From acc1c8f7f7f79e751053e267bd4d29c77b251f48 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 20 Jun 2024 18:53:15 +0100 Subject: [PATCH 01/94] chore: 1st attempt at automatic devnet deployment --- .github/workflows/devnet-deploys.yml | 69 + .gitmodules | 4 + barretenberg/cpp/pil/avm/kernel.pil | 8 +- barretenberg/cpp/scripts/compile_avm.sh | 21 +- barretenberg/cpp/scripts/rebuild_avm.sh | 11 + barretenberg/cpp/src/barretenberg/bb/main.cpp | 76 +- .../relations/generated/avm/alu.hpp | 406 ++-- .../relations/generated/avm/binary.hpp | 28 +- .../relations/generated/avm/conversion.hpp | 2 +- .../relations/generated/avm/declare_views.hpp | 8 +- .../relations/generated/avm/keccakf1600.hpp | 2 +- .../relations/generated/avm/kernel.hpp | 62 +- .../relations/generated/avm/main.hpp | 577 ++--- .../relations/generated/avm/mem.hpp | 84 +- .../relations/generated/avm/pedersen.hpp | 2 +- .../relations/generated/avm/poseidon2.hpp | 2 +- .../relations/generated/avm/sha256.hpp | 2 +- .../stdlib_circuit_builders/mock_circuits.hpp | 1 - .../vm/generated/avm_circuit_builder.cpp | 41 +- .../vm/generated/avm_circuit_builder.hpp | 16 +- .../barretenberg/vm/generated/avm_flavor.hpp | 76 +- .../barretenberg/vm/generated/avm_prover.cpp | 22 +- .../vm/generated/avm_verifier.cpp | 16 +- bb-pilcom/.gitignore | 1 + bb-pilcom/Cargo.lock | 1880 +++++++++++++++++ bb-pilcom/Cargo.toml | 28 + bb-pilcom/bb-pil-backend/Cargo.toml | 16 + .../bb-pil-backend/src/circuit_builder.rs | 374 ++++ .../bb-pil-backend/src/composer_builder.rs | 210 ++ bb-pilcom/bb-pil-backend/src/file_writer.rs | 58 + .../bb-pil-backend/src/flavor_builder.rs | 629 ++++++ bb-pilcom/bb-pil-backend/src/lib.rs | 11 + .../bb-pil-backend/src/lookup_builder.rs | 369 ++++ .../bb-pil-backend/src/permutation_builder.rs | 254 +++ .../bb-pil-backend/src/prover_builder.rs | 331 +++ .../bb-pil-backend/src/relation_builder.rs | 562 +++++ bb-pilcom/bb-pil-backend/src/utils.rs | 145 ++ .../bb-pil-backend/src/verifier_builder.rs | 286 +++ bb-pilcom/bb-pil-backend/src/vm_builder.rs | 236 +++ bb-pilcom/bootstrap.sh | 3 + bb-pilcom/cli/Cargo.toml | 26 + bb-pilcom/cli/README.md | 3 + bb-pilcom/cli/src/main.rs | 52 + bb-pilcom/powdr | 1 + docs/docs/migration_notes.md | 13 +- iac/mainnet-fork/Dockerfile | 18 - iac/mainnet-fork/Earthfile | 29 + iac/mainnet-fork/nginx/nginx.conf | 1 + .../aztec/src/context/private_context.nr | 2 +- .../aztec/src/encrypted_logs/incoming_body.nr | 2 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 10 +- .../aztec-nr/aztec/src/note/utils.nr | 93 +- .../src/test/helpers/test_environment.nr | 4 +- .../crates/types/src/hash.nr | 19 +- yarn-project/Earthfile | 34 + .../aztec-node/src/aztec-node/server.ts | 8 +- yarn-project/aztec/terraform/node/main.tf | 14 +- .../aztec/terraform/node/variables.tf | 5 +- yarn-project/end-to-end/Earthfile | 3 + ...etwork.test.ts => e2e_p2p_network.test.ts} | 164 +- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- .../p2p-bootstrap/terraform/variables.tf | 8 +- yarn-project/p2p/src/client/index.ts | 10 +- .../p2p/src/client/p2p_client.test.ts | 1 - yarn-project/p2p/src/client/p2p_client.ts | 3 +- .../p2p/src/service/discV5_service.ts | 39 +- .../p2p/src/service/discv5_service.test.ts | 16 +- yarn-project/p2p/src/service/dummy_service.ts | 11 +- .../p2p/src/service/known_txs.test.ts | 42 - yarn-project/p2p/src/service/known_txs.ts | 56 - .../p2p/src/service/libp2p_service.ts | 153 +- yarn-project/p2p/src/service/peer_manager.ts | 199 +- yarn-project/p2p/src/service/service.ts | 21 +- 73 files changed, 6936 insertions(+), 1055 deletions(-) create mode 100644 .github/workflows/devnet-deploys.yml create mode 100755 barretenberg/cpp/scripts/rebuild_avm.sh create mode 100644 bb-pilcom/.gitignore create mode 100644 bb-pilcom/Cargo.lock create mode 100644 bb-pilcom/Cargo.toml create mode 100644 bb-pilcom/bb-pil-backend/Cargo.toml create mode 100644 bb-pilcom/bb-pil-backend/src/circuit_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/composer_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/file_writer.rs create mode 100644 bb-pilcom/bb-pil-backend/src/flavor_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/lib.rs create mode 100644 bb-pilcom/bb-pil-backend/src/lookup_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/permutation_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/prover_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/relation_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/utils.rs create mode 100644 bb-pilcom/bb-pil-backend/src/verifier_builder.rs create mode 100644 bb-pilcom/bb-pil-backend/src/vm_builder.rs create mode 100755 bb-pilcom/bootstrap.sh create mode 100644 bb-pilcom/cli/Cargo.toml create mode 100644 bb-pilcom/cli/README.md create mode 100644 bb-pilcom/cli/src/main.rs create mode 160000 bb-pilcom/powdr delete mode 100644 iac/mainnet-fork/Dockerfile create mode 100644 iac/mainnet-fork/Earthfile rename yarn-project/end-to-end/src/{flakey_e2e_p2p_network.test.ts => e2e_p2p_network.test.ts} (52%) delete mode 100644 yarn-project/p2p/src/service/known_txs.test.ts delete mode 100644 yarn-project/p2p/src/service/known_txs.ts diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml new file mode 100644 index 000000000000..a2b09291c1e8 --- /dev/null +++ b/.github/workflows/devnet-deploys.yml @@ -0,0 +1,69 @@ +name: Deploy to devnet +on: + push: + branches: [devnet] + +env: + DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} + GIT_COMMIT: ${{ github.sha }} + # TF Vars + TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol + TF_VAR_CHAIN_ID: 31337 + TF_VAR_BOOTNODE_1_PRIVATE_KEY: ${{ secrets.BOOTNODE_1_PRIVATE_KEY }} + TF_VAR_BOOTNODE_2_PRIVATE_KEY: ${{ secrets.BOOTNODE_2_PRIVATE_KEY }} + TF_VAR_SEQ_1_PUBLISHER_PRIVATE_KEY: ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} + TF_VAR_SEQ_2_PUBLISHER_PRIVATE_KEY: ${{ secrets.SEQ_2_PUBLISHER_PRIVATE_KEY }} + TF_VAR_DEPLOY_TAG: devnet + TF_VAR_API_KEY: ${{ secrets.FORK_API_KEY }} + +jobs: + setup: + uses: ./.github/workflows/setup-runner.yml + with: + username: master + runner_type: builder-x86 + secrets: inherit + + build: + runs-on: ${{ github.actor }}-x86 + steps: + - uses: actions/checkout@v4 + with: { ref: "${{ env.GIT_COMMIT }}" } + - uses: ./.github/ci-setup-action + with: + dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" + concurrency_key: build-release-artifacts-${{ github.actor }} + - name: "Build & Push images" + timeout-minutes: 40 + # Run the build steps for each image with version and arch, push to dockerhub + run: | + earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=devnet + + terraform_deploy: + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 + with: { ref: "${{ env.GIT_COMMIT }}" } + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.7.5 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-west-2 + + - name: Deploy Bootstrap Nodes + working-directory: ./yarn-project/aztec/terraform/node + run: | + terraform init -input=false -backend-config="key=devnet/aztec-node" + terraform apply -input=false -auto-approve + + - name: Deploy Aztec Nodes + working-directory: ./yarn-project/aztec/terraform/node + run: | + terraform init -input=false -backend-config="key=devnet/aztec-node" + terraform apply -input=false -auto-approve diff --git a/.gitmodules b/.gitmodules index f643e34f4ca5..9a73cfa279ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,7 @@ [submodule "barretenberg/sol/lib/openzeppelin-contracts"] path = barretenberg/sol/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "bb-pilcom/powdr"] + path = bb-pilcom/powdr + url = https://github.com/AztecProtocol/powdr + branch = avm-minimal diff --git a/barretenberg/cpp/pil/avm/kernel.pil b/barretenberg/cpp/pil/avm/kernel.pil index f7d402826ebb..dff09f08d77e 100644 --- a/barretenberg/cpp/pil/avm/kernel.pil +++ b/barretenberg/cpp/pil/avm/kernel.pil @@ -2,11 +2,11 @@ include "main.pil"; include "constants.pil"; namespace kernel(256); - pol public(/*idx=*/0) kernel_inputs; + pol public kernel_inputs; - pol public(/*idx=*/1) kernel_value_out; - pol public(/*idx=*/2) kernel_side_effect_out; - pol public(/*idx=*/3) kernel_metadata_out; + pol public kernel_value_out; + pol public kernel_side_effect_out; + pol public kernel_metadata_out; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6463): just use one col for both of these pol commit kernel_in_offset; diff --git a/barretenberg/cpp/scripts/compile_avm.sh b/barretenberg/cpp/scripts/compile_avm.sh index 01f422e229f6..6ecc8817ab24 100755 --- a/barretenberg/cpp/scripts/compile_avm.sh +++ b/barretenberg/cpp/scripts/compile_avm.sh @@ -1,23 +1,4 @@ #!/bin/bash -use_zsh_alias() { - # Run Zsh command, source .zshrc, and then execute the alias - zsh -i -c "$1" -} # Compile -use_zsh_alias "bb_pil pil/avm/avm_main.pil --name Avm" - -# Format generated folders -root_dir="src" - -# Find all directories named 'generate' under the specified root directory -find "$root_dir" -type d -name 'generate' | while read dir_path; do - echo "Processing directory: $dir_path" - - # Find all C/C++ source files in these directories and format them - find "$dir_path" -type f \( -iname '*.hpp' -o -iname '*.cpp' \) -exec clang-format -i {} + -done - - -# Build vm tests -cmake --build --preset clang16 --target vm_tests \ No newline at end of file +../../bb-pilcom/target/release/bb_pil pil/avm/main.pil --name Avm diff --git a/barretenberg/cpp/scripts/rebuild_avm.sh b/barretenberg/cpp/scripts/rebuild_avm.sh new file mode 100755 index 000000000000..b6fa11dfc23f --- /dev/null +++ b/barretenberg/cpp/scripts/rebuild_avm.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Rebuild +./scripts/compile_avm.sh + +# Format generated folders +git add **/generated/* +./format.sh staged + +# Build vm tests +cmake --build --preset clang16 --target vm_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index d62b3326310e..114e2f0caf2f 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -819,7 +819,7 @@ template bool verify_honk(const std::string& proof_path, } /** - * @brief Writes a verification key for an ACIR circuit to a file + * @brief Writes a Honk verification key for an ACIR circuit to a file * * Communication: * - stdout: The verification key is written to stdout as a byte array @@ -965,6 +965,74 @@ void prove_output_all(const std::string& bytecodePath, const std::string& witnes vinfo("vk as fields written to: ", vkFieldsOutputPath); } +/** + * @brief Creates a Honk proof for an ACIR circuit, outputs the proof and verification key in binary and 'field' format + * + * Communication: + * - Filesystem: The proof is written to the path specified by outputPath + * + * @param bytecodePath Path to the file containing the serialized circuit + * @param witnessPath Path to the file containing the serialized witness + * @param outputPath Directory into which we write the proof and verification key data + */ +template +void prove_honk_output_all(const std::string& bytecodePath, + const std::string& witnessPath, + const std::string& outputPath) +{ + using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + using VerificationKey = Flavor::VerificationKey; + + bool honk_recursion = false; + if constexpr (IsAnyOf) { + honk_recursion = true; + } + + auto constraint_system = get_constraint_system(bytecodePath, honk_recursion); + auto witness = get_witness(witnessPath); + + auto builder = acir_format::create_circuit(constraint_system, 0, witness, honk_recursion); + + auto num_extra_gates = builder.get_num_gates_added_to_ensure_nonzero_polynomials(); + size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates); + init_bn254_crs(srs_size); + + // Construct Honk proof + Prover prover{ builder }; + auto proof = prover.construct_proof(); + + // We have been given a directory, we will write the proof and verification key + // into the directory in both 'binary' and 'fields' formats + std::string vkOutputPath = outputPath + "/vk"; + std::string proofPath = outputPath + "/proof"; + std::string vkFieldsOutputPath = outputPath + "/vk_fields.json"; + std::string proofFieldsPath = outputPath + "/proof_fields.json"; + + VerificationKey vk( + prover.instance->proving_key); // uses a partial form of the proving key which only has precomputed entities + + // Write the 'binary' proof + write_file(proofPath, to_buffer(proof)); + vinfo("binary proof written to: ", proofPath); + + // Write the proof as fields + std::string proofJson = to_json(proof); + write_file(proofFieldsPath, { proofJson.begin(), proofJson.end() }); + vinfo("proof as fields written to: ", proofFieldsPath); + + // Write the vk as binary + auto serialized_vk = to_buffer(vk); + write_file(vkOutputPath, serialized_vk); + vinfo("vk written to: ", vkOutputPath); + + // Write the vk as fields + std::vector vk_data = vk.to_field_elements(); + auto vk_json = honk_vk_to_json(vk_data); + write_file(vkFieldsOutputPath, { vk_json.begin(), vk_json.end() }); + vinfo("vk as fields written to: ", vkFieldsOutputPath); +} + bool flag_present(std::vector& args, const std::string& flag) { return std::find(args.begin(), args.end(), flag) != args.end(); @@ -1027,6 +1095,12 @@ int main(int argc, char* argv[]) } else if (command == "prove_output_all") { std::string output_path = get_option(args, "-o", "./proofs"); prove_output_all(bytecode_path, witness_path, output_path); + } else if (command == "prove_ultra_honk_output_all") { + std::string output_path = get_option(args, "-o", "./proofs"); + prove_honk_output_all(bytecode_path, witness_path, output_path); + } else if (command == "prove_mega_honk_output_all") { + std::string output_path = get_option(args, "-o", "./proofs"); + prove_honk_output_all(bytecode_path, witness_path, output_path); } else if (command == "client_ivc_prove_output_all") { std::string output_path = get_option(args, "-o", "./proofs"); client_ivc_prove_output_all(bytecode_path, witness_path, output_path); diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp index eda58900a6eb..ff4313937703 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp @@ -326,7 +326,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = (alu_cf * (-alu_cf + FF(1))); + auto tmp = ((alu_cf * (-alu_cf + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -334,7 +334,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (alu_ff_tag * (-alu_ff_tag + FF(1))); + auto tmp = ((alu_ff_tag * (-alu_ff_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -342,7 +342,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (alu_u8_tag * (-alu_u8_tag + FF(1))); + auto tmp = ((alu_u8_tag * (-alu_u8_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -350,7 +350,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (alu_u16_tag * (-alu_u16_tag + FF(1))); + auto tmp = ((alu_u16_tag * (-alu_u16_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -358,7 +358,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (alu_u32_tag * (-alu_u32_tag + FF(1))); + auto tmp = ((alu_u32_tag * (-alu_u32_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -366,7 +366,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (alu_u64_tag * (-alu_u64_tag + FF(1))); + auto tmp = ((alu_u64_tag * (-alu_u64_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -374,7 +374,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (alu_u128_tag * (-alu_u128_tag + FF(1))); + auto tmp = ((alu_u128_tag * (-alu_u128_tag + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -382,9 +382,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = - (alu_sel_alu * - ((((((alu_ff_tag + alu_u8_tag) + alu_u16_tag) + alu_u32_tag) + alu_u64_tag) + alu_u128_tag) - FF(1))); + auto tmp = ((alu_sel_alu * + ((((((alu_ff_tag + alu_u8_tag) + alu_u16_tag) + alu_u32_tag) + alu_u64_tag) + alu_u128_tag) - + FF(1))) - + FF(0)); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -403,17 +404,18 @@ template class aluImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = - (((alu_op_add + alu_op_sub) * ((((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - - alu_ia) + - (alu_ff_tag * alu_ic))) + - ((alu_op_add - alu_op_sub) * ((alu_cf * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })) - alu_ib))); + auto tmp = ((((alu_op_add + alu_op_sub) * + ((((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - + alu_ia) + + (alu_ff_tag * alu_ic))) + + ((alu_op_add - alu_op_sub) * ((alu_cf * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })) - alu_ib))) - + FF(0)); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -421,22 +423,23 @@ template class aluImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (((alu_op_add + alu_op_sub) * - (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) + - (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + - (alu_ff_tag * alu_ia)) - - alu_ic)) + - ((alu_ff_tag * (alu_op_add - alu_op_sub)) * alu_ib)); + auto tmp = ((((alu_op_add + alu_op_sub) * + (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) + + (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + + (alu_ff_tag * alu_ia)) - + alu_ic)) + + ((alu_ff_tag * (alu_op_add - alu_op_sub)) * alu_ib)) - + FF(0)); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -444,7 +447,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = ((alu_ff_tag * alu_op_mul) * ((alu_ia * alu_ib) - alu_ic)); + auto tmp = (((alu_ff_tag * alu_op_mul) * ((alu_ia * alu_ib) - alu_ic)) - FF(0)); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -452,15 +455,16 @@ template class aluImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = ((((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_op_mul) * - (((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - - (alu_ia * alu_ib))); + auto tmp = (((((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_op_mul) * + (((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - + (alu_ia * alu_ib))) - + FF(0)); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -469,12 +473,13 @@ template class aluImpl { Avm_DECLARE_VIEWS(16); auto tmp = - (alu_op_mul * (((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) - - (((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_ic))); + ((alu_op_mul * (((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) - + (((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_ic))) - + FF(0)); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -482,14 +487,15 @@ template class aluImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = ((alu_u128_tag * alu_op_mul) * - ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - ((((alu_u16_r3 + (alu_u16_r4 * FF(65536))) + (alu_u16_r5 * FF(4294967296UL))) + - (alu_u16_r6 * FF(281474976710656UL))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - alu_ia)); + auto tmp = (((alu_u128_tag * alu_op_mul) * + ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + ((((alu_u16_r3 + (alu_u16_r4 * FF(65536))) + (alu_u16_r5 * FF(4294967296UL))) + + (alu_u16_r6 * FF(281474976710656UL))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + alu_ia)) - + FF(0)); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -498,14 +504,15 @@ template class aluImpl { Avm_DECLARE_VIEWS(18); auto tmp = - ((alu_u128_tag * alu_op_mul) * - ((((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + - (alu_u16_r1_shift * FF(4294967296UL))) + - (alu_u16_r2_shift * FF(281474976710656UL))) + - ((((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + - (alu_u16_r6_shift * FF(281474976710656UL))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - alu_ib)); + (((alu_u128_tag * alu_op_mul) * + ((((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + + (alu_u16_r1_shift * FF(4294967296UL))) + + (alu_u16_r2_shift * FF(281474976710656UL))) + + ((((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + + (alu_u16_r6_shift * FF(281474976710656UL))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + alu_ib)) - + FF(0)); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -514,21 +521,22 @@ template class aluImpl { Avm_DECLARE_VIEWS(19); auto tmp = - ((alu_u128_tag * alu_op_mul) * - ((((alu_ia * ((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + - (alu_u16_r1_shift * FF(4294967296UL))) + - (alu_u16_r2_shift * FF(281474976710656UL)))) + - ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) * - (((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + - (alu_u16_r6_shift * FF(281474976710656UL)))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - (((alu_cf * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })) + - (((alu_u16_r7 + (alu_u16_r8 * FF(65536))) + (alu_u16_r9 * FF(4294967296UL))) + - (alu_u16_r10 * FF(281474976710656UL)))) * - FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - alu_ic)); + (((alu_u128_tag * alu_op_mul) * + ((((alu_ia * ((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + + (alu_u16_r1_shift * FF(4294967296UL))) + + (alu_u16_r2_shift * FF(281474976710656UL)))) + + ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) * + (((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + + (alu_u16_r6_shift * FF(281474976710656UL)))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + (((alu_cf * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })) + + (((alu_u16_r7 + (alu_u16_r8 * FF(65536))) + (alu_u16_r9 * FF(4294967296UL))) + + (alu_u16_r10 * FF(281474976710656UL)))) * + FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + alu_ic)) - + FF(0)); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -536,7 +544,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (alu_op_not * alu_ff_tag); + auto tmp = ((alu_op_not * alu_ff_tag) - FF(0)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -544,12 +552,12 @@ template class aluImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (alu_op_not * - ((alu_ia + alu_ic) - - ((((((alu_u8_tag * FF(256)) + (alu_u16_tag * FF(65536))) + (alu_u32_tag * FF(4294967296UL))) + - (alu_u64_tag * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u128_tag * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - FF(1)))); + auto tmp = ((alu_op_not * ((alu_ia + alu_ic) - ((((((alu_u8_tag * FF(256)) + (alu_u16_tag * FF(65536))) + + (alu_u32_tag * FF(4294967296UL))) + + (alu_u64_tag * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u128_tag * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -557,7 +565,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = ((alu_sel_cmp + alu_op_eq) * (alu_ic * (-alu_ic + FF(1)))); + auto tmp = (((alu_sel_cmp + alu_op_eq) * (alu_ic * (-alu_ic + FF(1)))) - FF(0)); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -566,9 +574,10 @@ template class aluImpl { Avm_DECLARE_VIEWS(23); auto tmp = - (alu_op_eq * - ((((alu_ia - alu_ib) * ((alu_ic * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - FF(1)) + - alu_ic)); + ((alu_op_eq * + ((((alu_ia - alu_ib) * ((alu_ic * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - FF(1)) + + alu_ic)) - + FF(0)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -594,7 +603,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (alu_p_a_borrow * (-alu_p_a_borrow + FF(1))); + auto tmp = ((alu_p_a_borrow * (-alu_p_a_borrow + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -602,10 +611,11 @@ template class aluImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = ((alu_p_sub_a_lo - - ((-alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + - (alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)); + auto tmp = (((alu_p_sub_a_lo - + ((-alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + + (alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * + ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)) - + FF(0)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -613,10 +623,11 @@ template class aluImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = ((alu_p_sub_a_hi - - ((-alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - - alu_p_a_borrow)) * - ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)); + auto tmp = (((alu_p_sub_a_hi - + ((-alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - + alu_p_a_borrow)) * + ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)) - + FF(0)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -624,7 +635,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (alu_p_b_borrow * (-alu_p_b_borrow + FF(1))); + auto tmp = ((alu_p_b_borrow * (-alu_p_b_borrow + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -632,10 +643,11 @@ template class aluImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = ((alu_p_sub_b_lo - - ((-alu_b_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + - (alu_p_b_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - alu_sel_cmp); + auto tmp = (((alu_p_sub_b_lo - + ((-alu_b_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + + (alu_p_b_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * + alu_sel_cmp) - + FF(0)); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -643,10 +655,11 @@ template class aluImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = ((alu_p_sub_b_hi - - ((-alu_b_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - - alu_p_b_borrow)) * - alu_sel_cmp); + auto tmp = (((alu_p_sub_b_hi - + ((-alu_b_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - + alu_p_b_borrow)) * + alu_sel_cmp) - + FF(0)); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -654,12 +667,13 @@ template class aluImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = ((alu_res_lo - - (((((alu_a_lo - alu_b_lo) - FF(1)) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * - ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + - (((alu_b_lo - alu_a_lo) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * - (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * - alu_sel_cmp); + auto tmp = (((alu_res_lo - + (((((alu_a_lo - alu_b_lo) - FF(1)) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + + (((alu_b_lo - alu_a_lo) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * + alu_sel_cmp) - + FF(0)); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -668,11 +682,12 @@ template class aluImpl { Avm_DECLARE_VIEWS(33); auto tmp = - ((alu_res_hi - - ((((alu_a_hi - alu_b_hi) - alu_borrow) * ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + - (((alu_b_hi - alu_a_hi) - alu_borrow) * - (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * - alu_sel_cmp); + (((alu_res_hi - + ((((alu_a_hi - alu_b_hi) - alu_borrow) * ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + + (((alu_b_hi - alu_a_hi) - alu_borrow) * + (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * + alu_sel_cmp) - + FF(0)); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -680,7 +695,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (((alu_cmp_rng_ctr_shift - alu_cmp_rng_ctr) + FF(1)) * alu_cmp_rng_ctr); + auto tmp = ((((alu_cmp_rng_ctr_shift - alu_cmp_rng_ctr) + FF(1)) * alu_cmp_rng_ctr) - FF(0)); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -688,7 +703,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = ((alu_cmp_rng_ctr_shift - FF(4)) * alu_sel_cmp); + auto tmp = (((alu_cmp_rng_ctr_shift - FF(4)) * alu_sel_cmp) - FF(0)); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -696,7 +711,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (alu_sel_rng_chk * (-alu_sel_rng_chk + FF(1))); + auto tmp = ((alu_sel_rng_chk * (-alu_sel_rng_chk + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -704,7 +719,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (alu_sel_rng_chk * alu_sel_cmp); + auto tmp = ((alu_sel_rng_chk * alu_sel_cmp) - FF(0)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -712,9 +727,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = ((alu_cmp_rng_ctr * - (((-alu_sel_rng_chk + FF(1)) * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - - alu_sel_rng_chk); + auto tmp = (((alu_cmp_rng_ctr * + (((-alu_sel_rng_chk + FF(1)) * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - + alu_sel_rng_chk) - + FF(0)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -773,7 +789,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = ((alu_a_lo_shift - alu_b_lo) * alu_sel_rng_chk_shift); + auto tmp = (((alu_a_lo_shift - alu_b_lo) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -781,7 +797,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = ((alu_a_hi_shift - alu_b_hi) * alu_sel_rng_chk_shift); + auto tmp = (((alu_a_hi_shift - alu_b_hi) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -789,7 +805,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = ((alu_b_lo_shift - alu_p_sub_a_lo) * alu_sel_rng_chk_shift); + auto tmp = (((alu_b_lo_shift - alu_p_sub_a_lo) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -797,7 +813,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = ((alu_b_hi_shift - alu_p_sub_a_hi) * alu_sel_rng_chk_shift); + auto tmp = (((alu_b_hi_shift - alu_p_sub_a_hi) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -805,7 +821,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = ((alu_p_sub_a_lo_shift - alu_p_sub_b_lo) * alu_sel_rng_chk_shift); + auto tmp = (((alu_p_sub_a_lo_shift - alu_p_sub_b_lo) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -813,7 +829,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = ((alu_p_sub_a_hi_shift - alu_p_sub_b_hi) * alu_sel_rng_chk_shift); + auto tmp = (((alu_p_sub_a_hi_shift - alu_p_sub_b_hi) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -821,7 +837,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = ((alu_p_sub_b_lo_shift - alu_res_lo) * alu_sel_rng_chk_shift); + auto tmp = (((alu_p_sub_b_lo_shift - alu_res_lo) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -829,7 +845,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = ((alu_p_sub_b_hi_shift - alu_res_hi) * alu_sel_rng_chk_shift); + auto tmp = (((alu_p_sub_b_hi_shift - alu_res_hi) * alu_sel_rng_chk_shift) - FF(0)); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -845,21 +861,22 @@ template class aluImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (alu_op_cast * - (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) + - (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + - (alu_ff_tag * alu_ia)) - - alu_ic)); + auto tmp = ((alu_op_cast * + (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) + + (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + + (alu_ff_tag * alu_ia)) - + alu_ic)) - + FF(0)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -867,7 +884,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = (alu_op_cast * (alu_a_lo_shift - alu_p_sub_a_lo)); + auto tmp = ((alu_op_cast * (alu_a_lo_shift - alu_p_sub_a_lo)) - FF(0)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -875,7 +892,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (alu_op_cast * (alu_a_hi_shift - alu_p_sub_a_hi)); + auto tmp = ((alu_op_cast * (alu_a_hi_shift - alu_p_sub_a_hi)) - FF(0)); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -883,7 +900,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (((alu_op_mul * alu_u128_tag) + alu_op_cast) * alu_sel_alu_shift); + auto tmp = ((((alu_op_mul * alu_u128_tag) + alu_op_cast) * alu_sel_alu_shift) - FF(0)); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -891,7 +908,8 @@ template class aluImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_lo - ((alu_two_pow_s - alu_b_lo) - FF(1)))); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_lo - ((alu_two_pow_s - alu_b_lo) - FF(1)))) - FF(0)); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -899,7 +917,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_hi - ((alu_two_pow_t_sub_s - alu_b_hi) - FF(1)))); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_hi - ((alu_two_pow_t_sub_s - alu_b_hi) - FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -907,7 +927,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_lo - ((alu_two_pow_t_sub_s - alu_b_lo) - FF(1)))); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_lo - ((alu_two_pow_t_sub_s - alu_b_lo) - FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -915,7 +937,8 @@ template class aluImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_hi - ((alu_two_pow_s - alu_b_hi) - FF(1)))); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_hi - ((alu_two_pow_s - alu_b_hi) - FF(1)))) - FF(0)); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -923,7 +946,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (alu_shift_lt_bit_len * (-alu_shift_lt_bit_len + FF(1))); + auto tmp = ((alu_shift_lt_bit_len * (-alu_shift_lt_bit_len + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -949,7 +972,8 @@ template class aluImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (((alu_b_hi * alu_two_pow_s) + alu_b_lo) - alu_ia)); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shr) * (((alu_b_hi * alu_two_pow_s) + alu_b_lo) - alu_ia)) - FF(0)); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -957,7 +981,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = (alu_op_shr * (alu_ic - (alu_b_hi * alu_shift_lt_bit_len))); + auto tmp = ((alu_op_shr * (alu_ic - (alu_b_hi * alu_shift_lt_bit_len))) - FF(0)); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -965,7 +989,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (((alu_b_hi * alu_two_pow_t_sub_s) + alu_b_lo) - alu_ia)); + auto tmp = + (((alu_shift_lt_bit_len * alu_op_shl) * (((alu_b_hi * alu_two_pow_t_sub_s) + alu_b_lo) - alu_ia)) - + FF(0)); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -973,7 +999,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = (alu_op_shl * (alu_ic - ((alu_b_lo * alu_two_pow_s) * alu_shift_lt_bit_len))); + auto tmp = ((alu_op_shl * (alu_ic - ((alu_b_lo * alu_two_pow_s) * alu_shift_lt_bit_len))) - FF(0)); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -989,7 +1015,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = (alu_op_div_a_lt_b * (-alu_op_div_a_lt_b + FF(1))); + auto tmp = ((alu_op_div_a_lt_b * (-alu_op_div_a_lt_b + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -997,7 +1023,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(67); - auto tmp = (alu_op_div_a_lt_b * (alu_a_lo - ((alu_ib - alu_ia) - FF(1)))); + auto tmp = ((alu_op_div_a_lt_b * (alu_a_lo - ((alu_ib - alu_ia) - FF(1)))) - FF(0)); tmp *= scaling_factor; std::get<67>(evals) += tmp; } @@ -1005,7 +1031,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(68); - auto tmp = (alu_op_div_a_lt_b * alu_ic); + auto tmp = ((alu_op_div_a_lt_b * alu_ic) - FF(0)); tmp *= scaling_factor; std::get<68>(evals) += tmp; } @@ -1013,7 +1039,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(69); - auto tmp = (alu_op_div_a_lt_b * (alu_ia - alu_remainder)); + auto tmp = ((alu_op_div_a_lt_b * (alu_ia - alu_remainder)) - FF(0)); tmp *= scaling_factor; std::get<69>(evals) += tmp; } @@ -1021,7 +1047,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(70); - auto tmp = (alu_op_div_std * (-alu_op_div_std + FF(1))); + auto tmp = ((alu_op_div_std * (-alu_op_div_std + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -1029,8 +1055,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(71); - auto tmp = - (alu_op_div_std * ((alu_ib - alu_divisor_lo) - (alu_divisor_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))); + auto tmp = ((alu_op_div_std * + ((alu_ib - alu_divisor_lo) - (alu_divisor_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))) - + FF(0)); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -1038,8 +1065,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = (alu_op_div_std * - ((alu_ic - alu_quotient_lo) - (alu_quotient_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))); + auto tmp = ((alu_op_div_std * + ((alu_ic - alu_quotient_lo) - (alu_quotient_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))) - + FF(0)); tmp *= scaling_factor; std::get<72>(evals) += tmp; } @@ -1057,10 +1085,12 @@ template class aluImpl { Avm_DECLARE_VIEWS(74); auto tmp = - (alu_op_div_std * - ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - (alu_a_lo + (alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))))); + ((alu_op_div_std * + ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * + FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + (alu_a_lo + (alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))))) - + FF(0)); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -1068,7 +1098,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(75); - auto tmp = (alu_op_div_std * (alu_b_hi - ((alu_ib - alu_remainder) - FF(1)))); + auto tmp = ((alu_op_div_std * (alu_b_hi - ((alu_ib - alu_remainder) - FF(1)))) - FF(0)); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -1076,7 +1106,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(76); - auto tmp = ((alu_cmp_rng_ctr_shift - FF(2)) * alu_op_div_std); + auto tmp = (((alu_cmp_rng_ctr_shift - FF(2)) * alu_op_div_std) - FF(0)); tmp *= scaling_factor; std::get<76>(evals) += tmp; } @@ -1084,7 +1114,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(77); - auto tmp = (alu_sel_rng_chk * alu_op_div_std); + auto tmp = ((alu_sel_rng_chk * alu_op_div_std) - FF(0)); tmp *= scaling_factor; std::get<77>(evals) += tmp; } @@ -1093,10 +1123,12 @@ template class aluImpl { Avm_DECLARE_VIEWS(78); auto tmp = - (alu_op_div_std * - ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - (alu_ia - alu_remainder))); + ((alu_op_div_std * + ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * + FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + (alu_ia - alu_remainder))) - + FF(0)); tmp *= scaling_factor; std::get<78>(evals) += tmp; } @@ -1104,7 +1136,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(79); - auto tmp = (alu_sel_div_rng_chk * (-alu_sel_div_rng_chk + FF(1))); + auto tmp = ((alu_sel_div_rng_chk * (-alu_sel_div_rng_chk + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<79>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp index 98260f373373..615e12a21c9d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp @@ -69,7 +69,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = (binary_sel_bin * (-binary_sel_bin + FF(1))); + auto tmp = ((binary_sel_bin * (-binary_sel_bin + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -77,7 +77,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = ((binary_op_id_shift - binary_op_id) * binary_mem_tag_ctr); + auto tmp = (((binary_op_id_shift - binary_op_id) * binary_mem_tag_ctr) - FF(0)); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -85,7 +85,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = (((binary_mem_tag_ctr_shift - binary_mem_tag_ctr) + FF(1)) * binary_mem_tag_ctr); + auto tmp = ((((binary_mem_tag_ctr_shift - binary_mem_tag_ctr) + FF(1)) * binary_mem_tag_ctr) - FF(0)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -93,9 +93,10 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = ((binary_mem_tag_ctr * - (((-binary_sel_bin + FF(1)) * (-binary_mem_tag_ctr_inv + FF(1))) + binary_mem_tag_ctr_inv)) - - binary_sel_bin); + auto tmp = (((binary_mem_tag_ctr * + (((-binary_sel_bin + FF(1)) * (-binary_mem_tag_ctr_inv + FF(1))) + binary_mem_tag_ctr_inv)) - + binary_sel_bin) - + FF(0)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -103,7 +104,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ia); + auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ia) - FF(0)); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -111,7 +112,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ib); + auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ib) - FF(0)); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -119,7 +120,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ic); + auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ic) - FF(0)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -127,7 +128,8 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (((binary_acc_ia - binary_ia_bytes) - (binary_acc_ia_shift * FF(256))) * binary_mem_tag_ctr); + auto tmp = + ((((binary_acc_ia - binary_ia_bytes) - (binary_acc_ia_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -135,7 +137,8 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (((binary_acc_ib - binary_ib_bytes) - (binary_acc_ib_shift * FF(256))) * binary_mem_tag_ctr); + auto tmp = + ((((binary_acc_ib - binary_ib_bytes) - (binary_acc_ib_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -143,7 +146,8 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (((binary_acc_ic - binary_ic_bytes) - (binary_acc_ic_shift * FF(256))) * binary_mem_tag_ctr); + auto tmp = + ((((binary_acc_ic - binary_ic_bytes) - (binary_acc_ic_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp index b83fb6bf7ac6..a51605c8f18d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp @@ -37,7 +37,7 @@ template class conversionImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = (conversion_sel_to_radix_le * (-conversion_sel_to_radix_le + FF(1))); + auto tmp = ((conversion_sel_to_radix_le * (-conversion_sel_to_radix_le + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index ef1db050b75d..9dd3eb86948a 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -4,6 +4,10 @@ using View = typename Accumulator::View; \ [[maybe_unused]] auto main_clk = View(new_term.main_clk); \ [[maybe_unused]] auto main_sel_first = View(new_term.main_sel_first); \ + [[maybe_unused]] auto kernel_kernel_inputs = View(new_term.kernel_kernel_inputs); \ + [[maybe_unused]] auto kernel_kernel_value_out = View(new_term.kernel_kernel_value_out); \ + [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ + [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ [[maybe_unused]] auto alu_a_hi = View(new_term.alu_a_hi); \ [[maybe_unused]] auto alu_a_lo = View(new_term.alu_a_lo); \ [[maybe_unused]] auto alu_b_hi = View(new_term.alu_b_hi); \ @@ -126,11 +130,7 @@ [[maybe_unused]] auto kernel_emit_unencrypted_log_write_offset = \ View(new_term.kernel_emit_unencrypted_log_write_offset); \ [[maybe_unused]] auto kernel_kernel_in_offset = View(new_term.kernel_kernel_in_offset); \ - [[maybe_unused]] auto kernel_kernel_inputs = View(new_term.kernel_kernel_inputs); \ - [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ [[maybe_unused]] auto kernel_kernel_out_offset = View(new_term.kernel_kernel_out_offset); \ - [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ - [[maybe_unused]] auto kernel_kernel_value_out = View(new_term.kernel_kernel_value_out); \ [[maybe_unused]] auto kernel_l1_to_l2_msg_exists_write_offset = \ View(new_term.kernel_l1_to_l2_msg_exists_write_offset); \ [[maybe_unused]] auto kernel_note_hash_exist_write_offset = View(new_term.kernel_note_hash_exist_write_offset); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp index 56e0a9e6a5d3..18989c0e836b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp @@ -37,7 +37,7 @@ template class keccakf1600Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = (keccakf1600_sel_keccakf1600 * (-keccakf1600_sel_keccakf1600 + FF(1))); + auto tmp = ((keccakf1600_sel_keccakf1600 * (-keccakf1600_sel_keccakf1600 + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp index a53770f6481b..e9e0d0e17489 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp @@ -98,8 +98,9 @@ template class kernelImpl { Avm_DECLARE_VIEWS(0); auto tmp = - ((-main_sel_last + FF(1)) * (kernel_note_hash_exist_write_offset_shift - - (kernel_note_hash_exist_write_offset + main_sel_op_note_hash_exists))); + (((-main_sel_last + FF(1)) * (kernel_note_hash_exist_write_offset_shift - + (kernel_note_hash_exist_write_offset + main_sel_op_note_hash_exists))) - + FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -107,8 +108,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = ((-main_sel_last + FF(1)) * (kernel_emit_note_hash_write_offset_shift - - (kernel_emit_note_hash_write_offset + main_sel_op_emit_note_hash))); + auto tmp = + (((-main_sel_last + FF(1)) * (kernel_emit_note_hash_write_offset_shift - + (kernel_emit_note_hash_write_offset + main_sel_op_emit_note_hash))) - + FF(0)); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -116,9 +119,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = ((-main_sel_last + FF(1)) * - (kernel_nullifier_exists_write_offset_shift - - (kernel_nullifier_exists_write_offset + (main_sel_op_nullifier_exists * main_ib)))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_nullifier_exists_write_offset_shift - + (kernel_nullifier_exists_write_offset + (main_sel_op_nullifier_exists * main_ib)))) - + FF(0)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -127,9 +131,10 @@ template class kernelImpl { Avm_DECLARE_VIEWS(3); auto tmp = - ((-main_sel_last + FF(1)) * - (kernel_nullifier_non_exists_write_offset_shift - - (kernel_nullifier_non_exists_write_offset + (main_sel_op_nullifier_exists * (-main_ib + FF(1)))))); + (((-main_sel_last + FF(1)) * + (kernel_nullifier_non_exists_write_offset_shift - + (kernel_nullifier_non_exists_write_offset + (main_sel_op_nullifier_exists * (-main_ib + FF(1)))))) - + FF(0)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -137,8 +142,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((-main_sel_last + FF(1)) * (kernel_emit_nullifier_write_offset_shift - - (kernel_emit_nullifier_write_offset + main_sel_op_emit_nullifier))); + auto tmp = + (((-main_sel_last + FF(1)) * (kernel_emit_nullifier_write_offset_shift - + (kernel_emit_nullifier_write_offset + main_sel_op_emit_nullifier))) - + FF(0)); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -146,9 +153,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = ((-main_sel_last + FF(1)) * - (kernel_l1_to_l2_msg_exists_write_offset_shift - - (kernel_l1_to_l2_msg_exists_write_offset + main_sel_op_l1_to_l2_msg_exists))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_l1_to_l2_msg_exists_write_offset_shift - + (kernel_l1_to_l2_msg_exists_write_offset + main_sel_op_l1_to_l2_msg_exists))) - + FF(0)); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -156,9 +164,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = ((-main_sel_last + FF(1)) * - (kernel_emit_unencrypted_log_write_offset_shift - - (kernel_emit_unencrypted_log_write_offset + main_sel_op_emit_unencrypted_log))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_emit_unencrypted_log_write_offset_shift - + (kernel_emit_unencrypted_log_write_offset + main_sel_op_emit_unencrypted_log))) - + FF(0)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -166,9 +175,10 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = - ((-main_sel_last + FF(1)) * (kernel_emit_l2_to_l1_msg_write_offset_shift - - (kernel_emit_l2_to_l1_msg_write_offset + main_sel_op_emit_l2_to_l1_msg))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_emit_l2_to_l1_msg_write_offset_shift - + (kernel_emit_l2_to_l1_msg_write_offset + main_sel_op_emit_l2_to_l1_msg))) - + FF(0)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -176,8 +186,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = ((-main_sel_last + FF(1)) * - (kernel_sload_write_offset_shift - (kernel_sload_write_offset + main_sel_op_sload))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_sload_write_offset_shift - (kernel_sload_write_offset + main_sel_op_sload))) - + FF(0)); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -185,8 +196,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = ((-main_sel_last + FF(1)) * - (kernel_sstore_write_offset_shift - (kernel_sstore_write_offset + main_sel_op_sstore))); + auto tmp = (((-main_sel_last + FF(1)) * + (kernel_sstore_write_offset_shift - (kernel_sstore_write_offset + main_sel_op_sstore))) - + FF(0)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp index 38835bdab220..1517e106ca72 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp @@ -307,7 +307,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = (main_l2_out_of_gas * (-main_l2_out_of_gas + FF(1))); + auto tmp = ((main_l2_out_of_gas * (-main_l2_out_of_gas + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -315,7 +315,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = (main_da_out_of_gas * (-main_da_out_of_gas + FF(1))); + auto tmp = ((main_da_out_of_gas * (-main_da_out_of_gas + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -323,8 +323,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = (main_sel_gas_accounting_active * - ((main_l2_gas_remaining_shift - main_l2_gas_remaining) + main_l2_gas_op_cost)); + auto tmp = ((main_sel_gas_accounting_active * + ((main_l2_gas_remaining_shift - main_l2_gas_remaining) + main_l2_gas_op_cost)) - + FF(0)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -332,8 +333,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = (main_sel_gas_accounting_active * - ((main_da_gas_remaining_shift - main_da_gas_remaining) + main_da_gas_op_cost)); + auto tmp = ((main_sel_gas_accounting_active * + ((main_da_gas_remaining_shift - main_da_gas_remaining) + main_da_gas_op_cost)) - + FF(0)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -341,7 +343,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((-main_sel_gas_accounting_active + FF(1)) * main_l2_gas_op_cost); + auto tmp = (((-main_sel_gas_accounting_active + FF(1)) * main_l2_gas_op_cost) - FF(0)); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -349,7 +351,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = ((-main_sel_gas_accounting_active + FF(1)) * main_da_gas_op_cost); + auto tmp = (((-main_sel_gas_accounting_active + FF(1)) * main_da_gas_op_cost) - FF(0)); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -357,10 +359,11 @@ template class mainImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (main_sel_gas_accounting_active * - ((((-(main_l2_out_of_gas * FF(2)) + FF(1)) * main_l2_gas_remaining_shift) - - (main_abs_l2_rem_gas_hi * FF(65536))) - - main_abs_l2_rem_gas_lo)); + auto tmp = ((main_sel_gas_accounting_active * + ((((-(main_l2_out_of_gas * FF(2)) + FF(1)) * main_l2_gas_remaining_shift) - + (main_abs_l2_rem_gas_hi * FF(65536))) - + main_abs_l2_rem_gas_lo)) - + FF(0)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -368,10 +371,11 @@ template class mainImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (main_sel_gas_accounting_active * - ((((-(main_da_out_of_gas * FF(2)) + FF(1)) * main_da_gas_remaining_shift) - - (main_abs_da_rem_gas_hi * FF(65536))) - - main_abs_da_rem_gas_lo)); + auto tmp = ((main_sel_gas_accounting_active * + ((((-(main_da_out_of_gas * FF(2)) + FF(1)) * main_da_gas_remaining_shift) - + (main_abs_da_rem_gas_hi * FF(65536))) - + main_abs_da_rem_gas_lo)) - + FF(0)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -379,7 +383,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (main_sel_op_sender * (-main_sel_op_sender + FF(1))); + auto tmp = ((main_sel_op_sender * (-main_sel_op_sender + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -387,7 +391,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (main_sel_op_address * (-main_sel_op_address + FF(1))); + auto tmp = ((main_sel_op_address * (-main_sel_op_address + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -395,7 +399,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))); + auto tmp = ((main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -403,7 +407,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))); + auto tmp = ((main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -411,7 +415,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = (main_sel_op_version * (-main_sel_op_version + FF(1))); + auto tmp = ((main_sel_op_version * (-main_sel_op_version + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -419,7 +423,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (main_sel_op_block_number * (-main_sel_op_block_number + FF(1))); + auto tmp = ((main_sel_op_block_number * (-main_sel_op_block_number + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -427,7 +431,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))); + auto tmp = ((main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -435,7 +439,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))); + auto tmp = ((main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -443,7 +447,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))); + auto tmp = ((main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -451,7 +455,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))); + auto tmp = ((main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -459,7 +463,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = (main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))); + auto tmp = ((main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -467,7 +471,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = (main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))); + auto tmp = ((main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -475,7 +479,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))); + auto tmp = ((main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -483,7 +487,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))); + auto tmp = ((main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -491,7 +495,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))); + auto tmp = ((main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -499,7 +503,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))); + auto tmp = ((main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -507,7 +511,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))); + auto tmp = ((main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -515,7 +519,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))); + auto tmp = ((main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -523,7 +527,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = (main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))); + auto tmp = ((main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -531,7 +535,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))); + auto tmp = ((main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -539,7 +543,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))); + auto tmp = ((main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -547,7 +551,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (main_sel_op_sload * (-main_sel_op_sload + FF(1))); + auto tmp = ((main_sel_op_sload * (-main_sel_op_sload + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -555,7 +559,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (main_sel_op_sstore * (-main_sel_op_sstore + FF(1))); + auto tmp = ((main_sel_op_sstore * (-main_sel_op_sstore + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -563,7 +567,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))); + auto tmp = ((main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -571,7 +575,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))); + auto tmp = ((main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -579,7 +583,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = (main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))); + auto tmp = ((main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -587,7 +591,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (main_sel_op_keccak * (-main_sel_op_keccak + FF(1))); + auto tmp = ((main_sel_op_keccak * (-main_sel_op_keccak + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -595,7 +599,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))); + auto tmp = ((main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -603,7 +607,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (main_sel_op_add * (-main_sel_op_add + FF(1))); + auto tmp = ((main_sel_op_add * (-main_sel_op_add + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -611,7 +615,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (main_sel_op_sub * (-main_sel_op_sub + FF(1))); + auto tmp = ((main_sel_op_sub * (-main_sel_op_sub + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -619,7 +623,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (main_sel_op_mul * (-main_sel_op_mul + FF(1))); + auto tmp = ((main_sel_op_mul * (-main_sel_op_mul + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -627,7 +631,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (main_sel_op_div * (-main_sel_op_div + FF(1))); + auto tmp = ((main_sel_op_div * (-main_sel_op_div + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -635,7 +639,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))); + auto tmp = ((main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -643,7 +647,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = (main_sel_op_not * (-main_sel_op_not + FF(1))); + auto tmp = ((main_sel_op_not * (-main_sel_op_not + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -651,7 +655,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (main_sel_op_eq * (-main_sel_op_eq + FF(1))); + auto tmp = ((main_sel_op_eq * (-main_sel_op_eq + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -659,7 +663,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (main_sel_op_and * (-main_sel_op_and + FF(1))); + auto tmp = ((main_sel_op_and * (-main_sel_op_and + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -667,7 +671,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (main_sel_op_or * (-main_sel_op_or + FF(1))); + auto tmp = ((main_sel_op_or * (-main_sel_op_or + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -675,7 +679,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (main_sel_op_xor * (-main_sel_op_xor + FF(1))); + auto tmp = ((main_sel_op_xor * (-main_sel_op_xor + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -683,7 +687,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (main_sel_op_cast * (-main_sel_op_cast + FF(1))); + auto tmp = ((main_sel_op_cast * (-main_sel_op_cast + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -691,7 +695,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (main_sel_op_lt * (-main_sel_op_lt + FF(1))); + auto tmp = ((main_sel_op_lt * (-main_sel_op_lt + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -699,7 +703,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (main_sel_op_lte * (-main_sel_op_lte + FF(1))); + auto tmp = ((main_sel_op_lte * (-main_sel_op_lte + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -707,7 +711,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (main_sel_op_shl * (-main_sel_op_shl + FF(1))); + auto tmp = ((main_sel_op_shl * (-main_sel_op_shl + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -715,7 +719,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = (main_sel_op_shr * (-main_sel_op_shr + FF(1))); + auto tmp = ((main_sel_op_shr * (-main_sel_op_shr + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -723,7 +727,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = (main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))); + auto tmp = ((main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -731,7 +735,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = (main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))); + auto tmp = ((main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -739,7 +743,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = (main_sel_op_jump * (-main_sel_op_jump + FF(1))); + auto tmp = ((main_sel_op_jump * (-main_sel_op_jump + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -747,7 +751,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = (main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))); + auto tmp = ((main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -755,7 +759,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = (main_sel_op_halt * (-main_sel_op_halt + FF(1))); + auto tmp = ((main_sel_op_halt * (-main_sel_op_halt + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -763,7 +767,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = (main_sel_op_external_call * (-main_sel_op_external_call + FF(1))); + auto tmp = ((main_sel_op_external_call * (-main_sel_op_external_call + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -771,7 +775,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); + auto tmp = ((main_sel_op_mov * (-main_sel_op_mov + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -779,7 +783,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); + auto tmp = ((main_sel_op_cmov * (-main_sel_op_cmov + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -787,7 +791,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = (main_op_err * (-main_op_err + FF(1))); + auto tmp = ((main_op_err * (-main_op_err + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -795,7 +799,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = (main_tag_err * (-main_tag_err + FF(1))); + auto tmp = ((main_tag_err * (-main_tag_err + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -803,7 +807,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = (main_id_zero * (-main_id_zero + FF(1))); + auto tmp = ((main_id_zero * (-main_id_zero + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -811,7 +815,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); + auto tmp = ((main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -819,7 +823,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); + auto tmp = ((main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -827,7 +831,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); + auto tmp = ((main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -835,7 +839,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(65); - auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); + auto tmp = ((main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<65>(evals) += tmp; } @@ -843,7 +847,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = (main_rwa * (-main_rwa + FF(1))); + auto tmp = ((main_rwa * (-main_rwa + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -851,7 +855,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(67); - auto tmp = (main_rwb * (-main_rwb + FF(1))); + auto tmp = ((main_rwb * (-main_rwb + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<67>(evals) += tmp; } @@ -859,7 +863,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(68); - auto tmp = (main_rwc * (-main_rwc + FF(1))); + auto tmp = ((main_rwc * (-main_rwc + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<68>(evals) += tmp; } @@ -867,7 +871,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(69); - auto tmp = (main_rwd * (-main_rwd + FF(1))); + auto tmp = ((main_rwd * (-main_rwd + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<69>(evals) += tmp; } @@ -875,7 +879,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(70); - auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); + auto tmp = ((main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -883,7 +887,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(71); - auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); + auto tmp = ((main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -891,7 +895,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); + auto tmp = ((main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<72>(evals) += tmp; } @@ -899,7 +903,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(73); - auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); + auto tmp = ((main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<73>(evals) += tmp; } @@ -907,7 +911,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(74); - auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); + auto tmp = ((((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -915,7 +919,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(75); - auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); + auto tmp = (((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)) - FF(0)); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -923,7 +927,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(76); - auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); + auto tmp = + (((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)) - FF(0)); tmp *= scaling_factor; std::get<76>(evals) += tmp; } @@ -931,7 +936,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(77); - auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); + auto tmp = ((((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<77>(evals) += tmp; } @@ -939,7 +944,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(78); - auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); + auto tmp = ((main_sel_op_fdiv * (main_r_in_tag - FF(6))) - FF(0)); tmp *= scaling_factor; std::get<78>(evals) += tmp; } @@ -947,7 +952,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(79); - auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); + auto tmp = ((main_sel_op_fdiv * (main_w_in_tag - FF(6))) - FF(0)); tmp *= scaling_factor; std::get<79>(evals) += tmp; } @@ -955,7 +960,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(80); - auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); + auto tmp = ((main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<80>(evals) += tmp; } @@ -963,16 +968,17 @@ template class mainImpl { { Avm_DECLARE_VIEWS(81); - auto tmp = (((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee) * - (-main_sel_q_kernel_lookup + FF(1))); + auto tmp = ((((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas) + + main_sel_op_transaction_fee) * + (-main_sel_q_kernel_lookup + FF(1))) - + FF(0)); tmp *= scaling_factor; std::get<81>(evals) += tmp; } @@ -981,12 +987,13 @@ template class mainImpl { Avm_DECLARE_VIEWS(82); auto tmp = - (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg) * - (-main_sel_q_kernel_output_lookup + FF(1))); + ((((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg) * + (-main_sel_q_kernel_output_lookup + FF(1))) - + FF(0)); tmp *= scaling_factor; std::get<82>(evals) += tmp; } @@ -994,7 +1001,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(83); - auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); + auto tmp = ((main_sel_op_jump * (main_pc_shift - main_ia)) - FF(0)); tmp *= scaling_factor; std::get<83>(evals) += tmp; } @@ -1002,8 +1009,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(84); - auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + - (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); + auto tmp = ((main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + + (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))) - + FF(0)); tmp *= scaling_factor; std::get<84>(evals) += tmp; } @@ -1012,7 +1020,8 @@ template class mainImpl { Avm_DECLARE_VIEWS(85); auto tmp = - (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); + ((main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<85>(evals) += tmp; } @@ -1020,7 +1029,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(86); - auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); + auto tmp = ((main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)) - FF(0)); tmp *= scaling_factor; std::get<86>(evals) += tmp; } @@ -1028,7 +1037,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(87); - auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); + auto tmp = ((main_sel_op_internal_call * (main_pc_shift - main_ia)) - FF(0)); tmp *= scaling_factor; std::get<87>(evals) += tmp; } @@ -1036,7 +1045,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(88); - auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); + auto tmp = ((main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)) - FF(0)); tmp *= scaling_factor; std::get<88>(evals) += tmp; } @@ -1044,7 +1053,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(89); - auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); + auto tmp = ((main_sel_op_internal_call * (main_rwb - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<89>(evals) += tmp; } @@ -1052,7 +1061,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(90); - auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); + auto tmp = ((main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<90>(evals) += tmp; } @@ -1061,7 +1070,8 @@ template class mainImpl { Avm_DECLARE_VIEWS(91); auto tmp = - (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); + ((main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<91>(evals) += tmp; } @@ -1069,7 +1079,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(92); - auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); + auto tmp = ((main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)) - FF(0)); tmp *= scaling_factor; std::get<92>(evals) += tmp; } @@ -1077,7 +1087,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(93); - auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); + auto tmp = ((main_sel_op_internal_return * (main_pc_shift - main_ia)) - FF(0)); tmp *= scaling_factor; std::get<93>(evals) += tmp; } @@ -1085,7 +1095,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(94); - auto tmp = (main_sel_op_internal_return * main_rwa); + auto tmp = ((main_sel_op_internal_return * main_rwa) - FF(0)); tmp *= scaling_factor; std::get<94>(evals) += tmp; } @@ -1093,7 +1103,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(95); - auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); + auto tmp = ((main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<95>(evals) += tmp; } @@ -1101,42 +1111,43 @@ template class mainImpl { { Avm_DECLARE_VIEWS(96); - auto tmp = - (((((main_sel_gas_accounting_active - - (((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + - main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) - - (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + - main_sel_op_internal_return)) - - main_sel_op_sload) - - main_sel_op_sstore) - - main_sel_mem_op_activate_gas); + auto tmp = ((((((main_sel_gas_accounting_active - + (((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + + main_sel_op_keccak) + + main_sel_op_pedersen)) + + ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas) + + main_sel_op_transaction_fee)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft))) - + (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + + main_sel_op_internal_return)) - + main_sel_op_sload) - + main_sel_op_sstore) - + main_sel_mem_op_activate_gas) - + FF(0)); tmp *= scaling_factor; std::get<96>(evals) += tmp; } @@ -1145,8 +1156,67 @@ template class mainImpl { Avm_DECLARE_VIEWS(97); auto tmp = - ((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * - (((((((main_sel_op_fdiv + + (((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * + (((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + + main_sel_op_pedersen)) + + ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas) + + main_sel_op_transaction_fee)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * + (main_pc_shift - (main_pc + FF(1)))) - + FF(0)); + tmp *= scaling_factor; + std::get<97>(evals) += tmp; + } + // Contribution 98 + { + Avm_DECLARE_VIEWS(98); + + auto tmp = + (((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + + FF(1)) * + (main_internal_return_ptr_shift - main_internal_return_ptr)) - + FF(0)); + tmp *= scaling_factor; + std::get<98>(evals) += tmp; + } + // Contribution 99 + { + Avm_DECLARE_VIEWS(99); + + auto tmp = + (((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))) - FF(0)); + tmp *= scaling_factor; + std::get<99>(evals) += tmp; + } + // Contribution 100 + { + Avm_DECLARE_VIEWS(100); + + auto tmp = + (((((((((main_sel_op_fdiv + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + main_sel_op_eq) + @@ -1173,64 +1243,9 @@ template class mainImpl { main_sel_op_l1_to_l2_msg_exists) + main_sel_op_emit_unencrypted_log) + main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * - (main_pc_shift - (main_pc + FF(1)))); - tmp *= scaling_factor; - std::get<97>(evals) += tmp; - } - // Contribution 98 - { - Avm_DECLARE_VIEWS(98); - - auto tmp = - ((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + - FF(1)) * - (main_internal_return_ptr_shift - main_internal_return_ptr)); - tmp *= scaling_factor; - std::get<98>(evals) += tmp; - } - // Contribution 99 - { - Avm_DECLARE_VIEWS(99); - - auto tmp = ((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))); - tmp *= scaling_factor; - std::get<99>(evals) += tmp; - } - // Contribution 100 - { - Avm_DECLARE_VIEWS(100); - - auto tmp = - ((((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * - (main_call_ptr - main_space_id)); + (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * + (main_call_ptr - main_space_id)) - + FF(0)); tmp *= scaling_factor; std::get<100>(evals) += tmp; } @@ -1238,7 +1253,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(101); - auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); + auto tmp = + (((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)) - FF(0)); tmp *= scaling_factor; std::get<101>(evals) += tmp; } @@ -1246,7 +1262,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(102); - auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); + auto tmp = ((((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<102>(evals) += tmp; } @@ -1270,7 +1286,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(105); - auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); + auto tmp = ((main_sel_mov_ia_to_ic * (main_ia - main_ic)) - FF(0)); tmp *= scaling_factor; std::get<105>(evals) += tmp; } @@ -1278,7 +1294,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(106); - auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); + auto tmp = ((main_sel_mov_ib_to_ic * (main_ib - main_ic)) - FF(0)); tmp *= scaling_factor; std::get<106>(evals) += tmp; } @@ -1286,7 +1302,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(107); - auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + auto tmp = (((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)) - FF(0)); tmp *= scaling_factor; std::get<107>(evals) += tmp; } @@ -1313,13 +1329,14 @@ template class mainImpl { Avm_DECLARE_VIEWS(109); auto tmp = - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) * - (main_alu_in_tag - main_r_in_tag)); + (((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) * + (main_alu_in_tag - main_r_in_tag)) - + FF(0)); tmp *= scaling_factor; std::get<109>(evals) += tmp; } @@ -1327,7 +1344,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(110); - auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); + auto tmp = ((main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)) - FF(0)); tmp *= scaling_factor; std::get<110>(evals) += tmp; } @@ -1335,7 +1352,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(111); - auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); + auto tmp = ((main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)) - FF(0)); tmp *= scaling_factor; std::get<111>(evals) += tmp; } @@ -1343,7 +1360,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(112); - auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); + auto tmp = ((main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)) - FF(0)); tmp *= scaling_factor; std::get<112>(evals) += tmp; } @@ -1351,7 +1368,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(113); - auto tmp = (main_sel_op_sender * (kernel_kernel_in_offset - FF(0))); + auto tmp = ((main_sel_op_sender * (kernel_kernel_in_offset - FF(0))) - FF(0)); tmp *= scaling_factor; std::get<113>(evals) += tmp; } @@ -1359,7 +1376,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(114); - auto tmp = (main_sel_op_address * (kernel_kernel_in_offset - FF(1))); + auto tmp = ((main_sel_op_address * (kernel_kernel_in_offset - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<114>(evals) += tmp; } @@ -1367,7 +1384,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(115); - auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(2))); + auto tmp = ((main_sel_op_storage_address * (kernel_kernel_in_offset - FF(2))) - FF(0)); tmp *= scaling_factor; std::get<115>(evals) += tmp; } @@ -1375,7 +1392,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(116); - auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))); + auto tmp = ((main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))) - FF(0)); tmp *= scaling_factor; std::get<116>(evals) += tmp; } @@ -1383,7 +1400,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(117); - auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))); + auto tmp = ((main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))) - FF(0)); tmp *= scaling_factor; std::get<117>(evals) += tmp; } @@ -1391,7 +1408,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(118); - auto tmp = (main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(40))); + auto tmp = ((main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(40))) - FF(0)); tmp *= scaling_factor; std::get<118>(evals) += tmp; } @@ -1399,7 +1416,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(119); - auto tmp = (main_sel_op_chain_id * (kernel_kernel_in_offset - FF(29))); + auto tmp = ((main_sel_op_chain_id * (kernel_kernel_in_offset - FF(29))) - FF(0)); tmp *= scaling_factor; std::get<119>(evals) += tmp; } @@ -1407,7 +1424,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(120); - auto tmp = (main_sel_op_version * (kernel_kernel_in_offset - FF(30))); + auto tmp = ((main_sel_op_version * (kernel_kernel_in_offset - FF(30))) - FF(0)); tmp *= scaling_factor; std::get<120>(evals) += tmp; } @@ -1415,7 +1432,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(121); - auto tmp = (main_sel_op_block_number * (kernel_kernel_in_offset - FF(31))); + auto tmp = ((main_sel_op_block_number * (kernel_kernel_in_offset - FF(31))) - FF(0)); tmp *= scaling_factor; std::get<121>(evals) += tmp; } @@ -1423,7 +1440,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(122); - auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))); + auto tmp = ((main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))) - FF(0)); tmp *= scaling_factor; std::get<122>(evals) += tmp; } @@ -1431,7 +1448,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(123); - auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))); + auto tmp = ((main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))) - FF(0)); tmp *= scaling_factor; std::get<123>(evals) += tmp; } @@ -1439,8 +1456,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(124); - auto tmp = (main_sel_op_note_hash_exists * - (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); + auto tmp = ((main_sel_op_note_hash_exists * + (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))) - + FF(0)); tmp *= scaling_factor; std::get<124>(evals) += tmp; } @@ -1448,7 +1466,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(125); - auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); + auto tmp = ((main_sel_first * kernel_note_hash_exist_write_offset) - FF(0)); tmp *= scaling_factor; std::get<125>(evals) += tmp; } @@ -1456,8 +1474,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(126); - auto tmp = (main_sel_op_emit_note_hash * - (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(176)))); + auto tmp = ((main_sel_op_emit_note_hash * + (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(176)))) - + FF(0)); tmp *= scaling_factor; std::get<126>(evals) += tmp; } @@ -1465,7 +1484,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(127); - auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); + auto tmp = ((main_sel_first * kernel_emit_note_hash_write_offset) - FF(0)); tmp *= scaling_factor; std::get<127>(evals) += tmp; } @@ -1473,10 +1492,11 @@ template class mainImpl { { Avm_DECLARE_VIEWS(128); - auto tmp = (main_sel_op_nullifier_exists * - (kernel_kernel_out_offset - - ((main_ib * (kernel_nullifier_exists_write_offset + FF(32))) + - ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(64)))))); + auto tmp = ((main_sel_op_nullifier_exists * + (kernel_kernel_out_offset - + ((main_ib * (kernel_nullifier_exists_write_offset + FF(32))) + + ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(64)))))) - + FF(0)); tmp *= scaling_factor; std::get<128>(evals) += tmp; } @@ -1484,7 +1504,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(129); - auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); + auto tmp = ((main_sel_first * kernel_nullifier_exists_write_offset) - FF(0)); tmp *= scaling_factor; std::get<129>(evals) += tmp; } @@ -1492,7 +1512,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(130); - auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); + auto tmp = ((main_sel_first * kernel_nullifier_non_exists_write_offset) - FF(0)); tmp *= scaling_factor; std::get<130>(evals) += tmp; } @@ -1500,8 +1520,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(131); - auto tmp = (main_sel_op_emit_nullifier * - (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(192)))); + auto tmp = ((main_sel_op_emit_nullifier * + (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(192)))) - + FF(0)); tmp *= scaling_factor; std::get<131>(evals) += tmp; } @@ -1509,7 +1530,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(132); - auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); + auto tmp = ((main_sel_first * kernel_emit_nullifier_write_offset) - FF(0)); tmp *= scaling_factor; std::get<132>(evals) += tmp; } @@ -1517,8 +1538,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(133); - auto tmp = (main_sel_op_l1_to_l2_msg_exists * - (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(96)))); + auto tmp = ((main_sel_op_l1_to_l2_msg_exists * + (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(96)))) - + FF(0)); tmp *= scaling_factor; std::get<133>(evals) += tmp; } @@ -1526,7 +1548,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(134); - auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); + auto tmp = ((main_sel_first * kernel_l1_to_l2_msg_exists_write_offset) - FF(0)); tmp *= scaling_factor; std::get<134>(evals) += tmp; } @@ -1534,8 +1556,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(135); - auto tmp = (main_sel_op_emit_unencrypted_log * - (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(210)))); + auto tmp = ((main_sel_op_emit_unencrypted_log * + (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(210)))) - + FF(0)); tmp *= scaling_factor; std::get<135>(evals) += tmp; } @@ -1543,7 +1566,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(136); - auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); + auto tmp = ((main_sel_first * kernel_emit_unencrypted_log_write_offset) - FF(0)); tmp *= scaling_factor; std::get<136>(evals) += tmp; } @@ -1551,8 +1574,9 @@ template class mainImpl { { Avm_DECLARE_VIEWS(137); - auto tmp = (main_sel_op_emit_l2_to_l1_msg * - (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(208)))); + auto tmp = ((main_sel_op_emit_l2_to_l1_msg * + (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(208)))) - + FF(0)); tmp *= scaling_factor; std::get<137>(evals) += tmp; } @@ -1560,7 +1584,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(138); - auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); + auto tmp = ((main_sel_first * kernel_emit_l2_to_l1_msg_write_offset) - FF(0)); tmp *= scaling_factor; std::get<138>(evals) += tmp; } @@ -1568,7 +1592,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(139); - auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(144)))); + auto tmp = + ((main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(144)))) - FF(0)); tmp *= scaling_factor; std::get<139>(evals) += tmp; } @@ -1576,7 +1601,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(140); - auto tmp = (main_sel_first * kernel_sload_write_offset); + auto tmp = ((main_sel_first * kernel_sload_write_offset) - FF(0)); tmp *= scaling_factor; std::get<140>(evals) += tmp; } @@ -1584,7 +1609,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(141); - auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(112)))); + auto tmp = + ((main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(112)))) - FF(0)); tmp *= scaling_factor; std::get<141>(evals) += tmp; } @@ -1592,7 +1618,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(142); - auto tmp = (main_sel_first * kernel_sstore_write_offset); + auto tmp = ((main_sel_first * kernel_sstore_write_offset) - FF(0)); tmp *= scaling_factor; std::get<142>(evals) += tmp; } @@ -1601,12 +1627,13 @@ template class mainImpl { Avm_DECLARE_VIEWS(143); auto tmp = - (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg) * - (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))); + ((((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg) * + (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))) - + FF(0)); tmp *= scaling_factor; std::get<143>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp index 8b1c6dcfe576..ea5a125887f0 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp @@ -126,7 +126,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = (mem_lastAccess * (-mem_lastAccess + FF(1))); + auto tmp = ((mem_lastAccess * (-mem_lastAccess + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -134,7 +134,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = (mem_last * (-mem_last + FF(1))); + auto tmp = ((mem_last * (-mem_last + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -142,7 +142,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = (mem_rw * (-mem_rw + FF(1))); + auto tmp = ((mem_rw * (-mem_rw + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -150,7 +150,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = (mem_tag_err * (-mem_tag_err + FF(1))); + auto tmp = ((mem_tag_err * (-mem_tag_err + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -158,7 +158,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (mem_sel_op_a * (-mem_sel_op_a + FF(1))); + auto tmp = ((mem_sel_op_a * (-mem_sel_op_a + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -166,7 +166,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (mem_sel_op_b * (-mem_sel_op_b + FF(1))); + auto tmp = ((mem_sel_op_b * (-mem_sel_op_b + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -174,7 +174,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (mem_sel_op_c * (-mem_sel_op_c + FF(1))); + auto tmp = ((mem_sel_op_c * (-mem_sel_op_c + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -182,7 +182,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (mem_sel_op_d * (-mem_sel_op_d + FF(1))); + auto tmp = ((mem_sel_op_d * (-mem_sel_op_d + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -190,7 +190,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))); + auto tmp = ((mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -198,7 +198,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))); + auto tmp = ((mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -206,7 +206,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = (mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))); + auto tmp = ((mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -214,7 +214,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = (mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))); + auto tmp = ((mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -235,7 +235,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = (mem_sel_mem * (mem_sel_mem - FF(1))); + auto tmp = ((mem_sel_mem * (mem_sel_mem - FF(1))) - FF(0)); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -243,7 +243,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))); + auto tmp = ((((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -251,7 +251,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (main_sel_first * mem_sel_mem); + auto tmp = ((main_sel_first * mem_sel_mem) - FF(0)); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -259,7 +259,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = (((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))); + auto tmp = ((((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -302,7 +302,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = (main_sel_first * (-mem_lastAccess + FF(1))); + auto tmp = ((main_sel_first * (-mem_lastAccess + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -310,7 +310,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = ((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)); + auto tmp = (((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)) - FF(0)); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -318,11 +318,12 @@ template class memImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + - ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - - (mem_diff_hi * FF(4294967296UL))) - - (mem_diff_mid * FF(65536))) - - mem_diff_lo)); + auto tmp = ((mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + + ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - + (mem_diff_hi * FF(4294967296UL))) - + (mem_diff_mid * FF(65536))) - + mem_diff_lo)) - + FF(0)); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -330,7 +331,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)); + auto tmp = ((((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)) - FF(0)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -338,7 +339,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)); + auto tmp = ((((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)) - FF(0)); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -346,7 +347,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = ((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift); + auto tmp = (((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift) - FF(0)); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -364,8 +365,9 @@ template class memImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (((-mem_skip_check_tag + FF(1)) * (-mem_rw + FF(1))) * - (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)); + auto tmp = ((((-mem_skip_check_tag + FF(1)) * (-mem_rw + FF(1))) * + (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)) - + FF(0)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -373,7 +375,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = ((-mem_tag_err + FF(1)) * mem_one_min_inv); + auto tmp = (((-mem_tag_err + FF(1)) * mem_one_min_inv) - FF(0)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -381,7 +383,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = ((mem_skip_check_tag + mem_rw) * mem_tag_err); + auto tmp = (((mem_skip_check_tag + mem_rw) * mem_tag_err) - FF(0)); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -389,7 +391,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (mem_rw * (mem_w_in_tag - mem_tag)); + auto tmp = ((mem_rw * (mem_w_in_tag - mem_tag)) - FF(0)); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -397,7 +399,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (mem_rw * mem_tag_err); + auto tmp = ((mem_rw * mem_tag_err) - FF(0)); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -405,7 +407,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))); + auto tmp = ((mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))) - FF(0)); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -413,7 +415,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = (mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))); + auto tmp = ((mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))) - FF(0)); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -421,7 +423,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = (mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))); + auto tmp = ((mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))) - FF(0)); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -429,7 +431,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))); + auto tmp = ((mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))) - FF(0)); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -437,7 +439,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = (mem_sel_resolve_ind_addr_a * mem_rw); + auto tmp = ((mem_sel_resolve_ind_addr_a * mem_rw) - FF(0)); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -445,7 +447,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = (mem_sel_resolve_ind_addr_b * mem_rw); + auto tmp = ((mem_sel_resolve_ind_addr_b * mem_rw) - FF(0)); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -453,7 +455,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (mem_sel_resolve_ind_addr_c * mem_rw); + auto tmp = ((mem_sel_resolve_ind_addr_c * mem_rw) - FF(0)); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -461,7 +463,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = (mem_sel_resolve_ind_addr_d * mem_rw); + auto tmp = ((mem_sel_resolve_ind_addr_d * mem_rw) - FF(0)); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -469,7 +471,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = ((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err); + auto tmp = (((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err) - FF(0)); tmp *= scaling_factor; std::get<40>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp index d09722720e9e..eb73ea8dfdda 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp @@ -37,7 +37,7 @@ template class pedersenImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = (pedersen_sel_pedersen * (-pedersen_sel_pedersen + FF(1))); + auto tmp = ((pedersen_sel_pedersen * (-pedersen_sel_pedersen + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp index a758f8333b2b..1f6d384a3f72 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp @@ -37,7 +37,7 @@ template class poseidon2Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = (poseidon2_sel_poseidon_perm * (-poseidon2_sel_poseidon_perm + FF(1))); + auto tmp = ((poseidon2_sel_poseidon_perm * (-poseidon2_sel_poseidon_perm + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp index 189cbb7c699c..d77d4d69f672 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp @@ -37,7 +37,7 @@ template class sha256Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = (sha256_sel_sha256_compression * (-sha256_sel_sha256_compression + FF(1))); + auto tmp = ((sha256_sel_sha256_compression * (-sha256_sel_sha256_compression + FF(1))) - FF(0)); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 183d951f070a..5d5b3c03953a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -44,7 +44,6 @@ class MockCircuits { */ template static void add_arithmetic_gates(Builder& builder, const size_t num_gates = 4) { - // For good measure, include a gate with some public inputs for (size_t i = 0; i < num_gates; ++i) { FF a = FF::random_element(&engine); FF b = FF::random_element(&engine); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp index a0db02764b38..7d58df8071ae 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -20,6 +20,10 @@ template std::vector AvmFullRow::names() { return { "main_clk", "main_sel_first", + "kernel_kernel_inputs", + "kernel_kernel_value_out", + "kernel_kernel_side_effect_out", + "kernel_kernel_metadata_out", "alu_a_hi", "alu_a_lo", "alu_b_hi", @@ -140,11 +144,7 @@ template std::vector AvmFullRow::names() "kernel_emit_nullifier_write_offset", "kernel_emit_unencrypted_log_write_offset", "kernel_kernel_in_offset", - "kernel_kernel_inputs", - "kernel_kernel_metadata_out", "kernel_kernel_out_offset", - "kernel_kernel_side_effect_out", - "kernel_kernel_value_out", "kernel_l1_to_l2_msg_exists_write_offset", "kernel_note_hash_exist_write_offset", "kernel_nullifier_exists_write_offset", @@ -410,18 +410,20 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow { return os << field_to_string(row.main_clk) << "," << field_to_string(row.main_sel_first) << "," - << field_to_string(row.alu_a_hi) << "," << field_to_string(row.alu_a_lo) << "," - << field_to_string(row.alu_b_hi) << "," << field_to_string(row.alu_b_lo) << "," - << field_to_string(row.alu_borrow) << "," << field_to_string(row.alu_cf) << "," - << field_to_string(row.alu_clk) << "," << field_to_string(row.alu_cmp_rng_ctr) << "," - << field_to_string(row.alu_div_u16_r0) << "," << field_to_string(row.alu_div_u16_r1) << "," - << field_to_string(row.alu_div_u16_r2) << "," << field_to_string(row.alu_div_u16_r3) << "," - << field_to_string(row.alu_div_u16_r4) << "," << field_to_string(row.alu_div_u16_r5) << "," - << field_to_string(row.alu_div_u16_r6) << "," << field_to_string(row.alu_div_u16_r7) << "," - << field_to_string(row.alu_divisor_hi) << "," << field_to_string(row.alu_divisor_lo) << "," - << field_to_string(row.alu_ff_tag) << "," << field_to_string(row.alu_ia) << "," - << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) << "," - << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," + << field_to_string(row.kernel_kernel_inputs) << "," << field_to_string(row.kernel_kernel_value_out) << "," + << field_to_string(row.kernel_kernel_side_effect_out) << "," + << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.alu_a_hi) << "," + << field_to_string(row.alu_a_lo) << "," << field_to_string(row.alu_b_hi) << "," + << field_to_string(row.alu_b_lo) << "," << field_to_string(row.alu_borrow) << "," + << field_to_string(row.alu_cf) << "," << field_to_string(row.alu_clk) << "," + << field_to_string(row.alu_cmp_rng_ctr) << "," << field_to_string(row.alu_div_u16_r0) << "," + << field_to_string(row.alu_div_u16_r1) << "," << field_to_string(row.alu_div_u16_r2) << "," + << field_to_string(row.alu_div_u16_r3) << "," << field_to_string(row.alu_div_u16_r4) << "," + << field_to_string(row.alu_div_u16_r5) << "," << field_to_string(row.alu_div_u16_r6) << "," + << field_to_string(row.alu_div_u16_r7) << "," << field_to_string(row.alu_divisor_hi) << "," + << field_to_string(row.alu_divisor_lo) << "," << field_to_string(row.alu_ff_tag) << "," + << field_to_string(row.alu_ia) << "," << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) + << "," << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," << field_to_string(row.alu_op_cast) << "," << field_to_string(row.alu_op_cast_prev) << "," << field_to_string(row.alu_op_div) << "," << field_to_string(row.alu_op_div_a_lt_b) << "," << field_to_string(row.alu_op_div_std) << "," << field_to_string(row.alu_op_eq) << "," @@ -473,11 +475,8 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << field_to_string(row.kernel_emit_note_hash_write_offset) << "," << field_to_string(row.kernel_emit_nullifier_write_offset) << "," << field_to_string(row.kernel_emit_unencrypted_log_write_offset) << "," - << field_to_string(row.kernel_kernel_in_offset) << "," << field_to_string(row.kernel_kernel_inputs) << "," - << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.kernel_kernel_out_offset) - << "," << field_to_string(row.kernel_kernel_side_effect_out) << "," - << field_to_string(row.kernel_kernel_value_out) << "," - << field_to_string(row.kernel_l1_to_l2_msg_exists_write_offset) << "," + << field_to_string(row.kernel_kernel_in_offset) << "," << field_to_string(row.kernel_kernel_out_offset) + << "," << field_to_string(row.kernel_l1_to_l2_msg_exists_write_offset) << "," << field_to_string(row.kernel_note_hash_exist_write_offset) << "," << field_to_string(row.kernel_nullifier_exists_write_offset) << "," << field_to_string(row.kernel_nullifier_non_exists_write_offset) << "," diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 83e3cd74b16d..b8f8a1079010 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -87,6 +87,10 @@ namespace bb { template struct AvmFullRow { FF main_clk{}; FF main_sel_first{}; + FF kernel_kernel_inputs{}; + FF kernel_kernel_value_out{}; + FF kernel_kernel_side_effect_out{}; + FF kernel_kernel_metadata_out{}; FF alu_a_hi{}; FF alu_a_lo{}; FF alu_b_hi{}; @@ -207,11 +211,7 @@ template struct AvmFullRow { FF kernel_emit_nullifier_write_offset{}; FF kernel_emit_unencrypted_log_write_offset{}; FF kernel_kernel_in_offset{}; - FF kernel_kernel_inputs{}; - FF kernel_kernel_metadata_out{}; FF kernel_kernel_out_offset{}; - FF kernel_kernel_side_effect_out{}; - FF kernel_kernel_value_out{}; FF kernel_l1_to_l2_msg_exists_write_offset{}; FF kernel_note_hash_exist_write_offset{}; FF kernel_nullifier_exists_write_offset{}; @@ -570,6 +570,10 @@ class AvmCircuitBuilder { for (size_t i = 0; i < rows.size(); i++) { polys.main_clk[i] = rows[i].main_clk; polys.main_sel_first[i] = rows[i].main_sel_first; + polys.kernel_kernel_inputs[i] = rows[i].kernel_kernel_inputs; + polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; + polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; + polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; polys.alu_a_hi[i] = rows[i].alu_a_hi; polys.alu_a_lo[i] = rows[i].alu_a_lo; polys.alu_b_hi[i] = rows[i].alu_b_hi; @@ -690,11 +694,7 @@ class AvmCircuitBuilder { polys.kernel_emit_nullifier_write_offset[i] = rows[i].kernel_emit_nullifier_write_offset; polys.kernel_emit_unencrypted_log_write_offset[i] = rows[i].kernel_emit_unencrypted_log_write_offset; polys.kernel_kernel_in_offset[i] = rows[i].kernel_kernel_in_offset; - polys.kernel_kernel_inputs[i] = rows[i].kernel_kernel_inputs; - polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; polys.kernel_kernel_out_offset[i] = rows[i].kernel_kernel_out_offset; - polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; - polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; polys.kernel_l1_to_l2_msg_exists_write_offset[i] = rows[i].kernel_l1_to_l2_msg_exists_write_offset; polys.kernel_note_hash_exist_write_offset[i] = rows[i].kernel_note_hash_exist_write_offset; polys.kernel_nullifier_exists_write_offset[i] = rows[i].kernel_nullifier_exists_write_offset; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 41cae773d42d..283812ece0f1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -256,6 +256,10 @@ class AvmFlavor { template class WitnessEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, + kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, alu_a_hi, alu_a_lo, alu_b_hi, @@ -376,11 +380,7 @@ class AvmFlavor { kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, - kernel_kernel_inputs, - kernel_kernel_metadata_out, kernel_kernel_out_offset, - kernel_kernel_side_effect_out, - kernel_kernel_value_out, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, @@ -642,7 +642,11 @@ class AvmFlavor { RefVector get_wires() { - return { alu_a_hi, + return { kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, + alu_a_hi, alu_a_lo, alu_b_hi, alu_b_lo, @@ -762,11 +766,7 @@ class AvmFlavor { kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, - kernel_kernel_inputs, - kernel_kernel_metadata_out, kernel_kernel_out_offset, - kernel_kernel_side_effect_out, - kernel_kernel_value_out, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, @@ -1033,6 +1033,10 @@ class AvmFlavor { DEFINE_FLAVOR_MEMBERS(DataType, main_clk, main_sel_first, + kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1153,11 +1157,7 @@ class AvmFlavor { kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, - kernel_kernel_inputs, - kernel_kernel_metadata_out, kernel_kernel_out_offset, - kernel_kernel_side_effect_out, - kernel_kernel_value_out, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, @@ -1486,6 +1486,10 @@ class AvmFlavor { { return { main_clk, main_sel_first, + kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1606,11 +1610,7 @@ class AvmFlavor { kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, - kernel_kernel_inputs, - kernel_kernel_metadata_out, kernel_kernel_out_offset, - kernel_kernel_side_effect_out, - kernel_kernel_value_out, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, @@ -1939,6 +1939,10 @@ class AvmFlavor { { return { main_clk, main_sel_first, + kernel_kernel_inputs, + kernel_kernel_value_out, + kernel_kernel_side_effect_out, + kernel_kernel_metadata_out, alu_a_hi, alu_a_lo, alu_b_hi, @@ -2059,11 +2063,7 @@ class AvmFlavor { kernel_emit_nullifier_write_offset, kernel_emit_unencrypted_log_write_offset, kernel_kernel_in_offset, - kernel_kernel_inputs, - kernel_kernel_metadata_out, kernel_kernel_out_offset, - kernel_kernel_side_effect_out, - kernel_kernel_value_out, kernel_l1_to_l2_msg_exists_write_offset, kernel_note_hash_exist_write_offset, kernel_nullifier_exists_write_offset, @@ -2686,7 +2686,7 @@ class AvmFlavor { } } - [[nodiscard]] size_t get_polynomial_size() const { return alu_a_hi.size(); } + [[nodiscard]] size_t get_polynomial_size() const { return kernel_kernel_inputs.size(); } /** * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which * represents one row in the execution trace. @@ -2748,6 +2748,10 @@ class AvmFlavor { { Base::main_clk = "MAIN_CLK"; Base::main_sel_first = "MAIN_SEL_FIRST"; + Base::kernel_kernel_inputs = "KERNEL_KERNEL_INPUTS"; + Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; + Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; + Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; Base::alu_a_hi = "ALU_A_HI"; Base::alu_a_lo = "ALU_A_LO"; Base::alu_b_hi = "ALU_B_HI"; @@ -2868,11 +2872,7 @@ class AvmFlavor { Base::kernel_emit_nullifier_write_offset = "KERNEL_EMIT_NULLIFIER_WRITE_OFFSET"; Base::kernel_emit_unencrypted_log_write_offset = "KERNEL_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET"; Base::kernel_kernel_in_offset = "KERNEL_KERNEL_IN_OFFSET"; - Base::kernel_kernel_inputs = "KERNEL_KERNEL_INPUTS"; - Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; Base::kernel_kernel_out_offset = "KERNEL_KERNEL_OUT_OFFSET"; - Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; - Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; Base::kernel_l1_to_l2_msg_exists_write_offset = "KERNEL_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET"; Base::kernel_note_hash_exist_write_offset = "KERNEL_NOTE_HASH_EXIST_WRITE_OFFSET"; Base::kernel_nullifier_exists_write_offset = "KERNEL_NULLIFIER_EXISTS_WRITE_OFFSET"; @@ -3150,6 +3150,10 @@ class AvmFlavor { public: uint32_t circuit_size; + Commitment kernel_kernel_inputs; + Commitment kernel_kernel_value_out; + Commitment kernel_kernel_side_effect_out; + Commitment kernel_kernel_metadata_out; Commitment alu_a_hi; Commitment alu_a_lo; Commitment alu_b_hi; @@ -3270,11 +3274,7 @@ class AvmFlavor { Commitment kernel_emit_nullifier_write_offset; Commitment kernel_emit_unencrypted_log_write_offset; Commitment kernel_kernel_in_offset; - Commitment kernel_kernel_inputs; - Commitment kernel_kernel_metadata_out; Commitment kernel_kernel_out_offset; - Commitment kernel_kernel_side_effect_out; - Commitment kernel_kernel_value_out; Commitment kernel_l1_to_l2_msg_exists_write_offset; Commitment kernel_note_hash_exist_write_offset; Commitment kernel_nullifier_exists_write_offset; @@ -3552,6 +3552,10 @@ class AvmFlavor { circuit_size = deserialize_from_buffer(proof_data, num_frs_read); size_t log_n = numeric::get_msb(circuit_size); + kernel_kernel_inputs = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + kernel_kernel_value_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + kernel_kernel_side_effect_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + kernel_kernel_metadata_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_lo = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_b_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3676,11 +3680,7 @@ class AvmFlavor { kernel_emit_unencrypted_log_write_offset = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_in_offset = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - kernel_kernel_inputs = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - kernel_kernel_metadata_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_out_offset = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - kernel_kernel_side_effect_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - kernel_kernel_value_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_l1_to_l2_msg_exists_write_offset = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_note_hash_exist_write_offset = @@ -3970,6 +3970,10 @@ class AvmFlavor { serialize_to_buffer(circuit_size, Transcript::proof_data); + serialize_to_buffer(kernel_kernel_inputs, Transcript::proof_data); + serialize_to_buffer(kernel_kernel_value_out, Transcript::proof_data); + serialize_to_buffer(kernel_kernel_side_effect_out, Transcript::proof_data); + serialize_to_buffer(kernel_kernel_metadata_out, Transcript::proof_data); serialize_to_buffer(alu_a_hi, Transcript::proof_data); serialize_to_buffer(alu_a_lo, Transcript::proof_data); serialize_to_buffer(alu_b_hi, Transcript::proof_data); @@ -4090,11 +4094,7 @@ class AvmFlavor { serialize_to_buffer(kernel_emit_nullifier_write_offset, Transcript::proof_data); serialize_to_buffer(kernel_emit_unencrypted_log_write_offset, Transcript::proof_data); serialize_to_buffer(kernel_kernel_in_offset, Transcript::proof_data); - serialize_to_buffer(kernel_kernel_inputs, Transcript::proof_data); - serialize_to_buffer(kernel_kernel_metadata_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_out_offset, Transcript::proof_data); - serialize_to_buffer(kernel_kernel_side_effect_out, Transcript::proof_data); - serialize_to_buffer(kernel_kernel_value_out, Transcript::proof_data); serialize_to_buffer(kernel_l1_to_l2_msg_exists_write_offset, Transcript::proof_data); serialize_to_buffer(kernel_note_hash_exist_write_offset, Transcript::proof_data); serialize_to_buffer(kernel_nullifier_exists_write_offset, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 2bdb385ef3f4..c6a7622629b5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -59,6 +59,10 @@ void AvmProver::execute_wire_commitments_round() // Commit to all polynomials (apart from logderivative inverse polynomials, which are committed to in the later // logderivative phase) + witness_commitments.kernel_kernel_inputs = commitment_key->commit(key->kernel_kernel_inputs); + witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); + witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); + witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); witness_commitments.alu_a_hi = commitment_key->commit(key->alu_a_hi); witness_commitments.alu_a_lo = commitment_key->commit(key->alu_a_lo); witness_commitments.alu_b_hi = commitment_key->commit(key->alu_b_hi); @@ -183,11 +187,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_emit_unencrypted_log_write_offset = commitment_key->commit(key->kernel_emit_unencrypted_log_write_offset); witness_commitments.kernel_kernel_in_offset = commitment_key->commit(key->kernel_kernel_in_offset); - witness_commitments.kernel_kernel_inputs = commitment_key->commit(key->kernel_kernel_inputs); - witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); witness_commitments.kernel_kernel_out_offset = commitment_key->commit(key->kernel_kernel_out_offset); - witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); - witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); witness_commitments.kernel_l1_to_l2_msg_exists_write_offset = commitment_key->commit(key->kernel_l1_to_l2_msg_exists_write_offset); witness_commitments.kernel_note_hash_exist_write_offset = @@ -402,6 +402,13 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.lookup_div_u16_7_counts = commitment_key->commit(key->lookup_div_u16_7_counts); // Send all commitments to the verifier + transcript->send_to_verifier(commitment_labels.kernel_kernel_inputs, witness_commitments.kernel_kernel_inputs); + transcript->send_to_verifier(commitment_labels.kernel_kernel_value_out, + witness_commitments.kernel_kernel_value_out); + transcript->send_to_verifier(commitment_labels.kernel_kernel_side_effect_out, + witness_commitments.kernel_kernel_side_effect_out); + transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, + witness_commitments.kernel_kernel_metadata_out); transcript->send_to_verifier(commitment_labels.alu_a_hi, witness_commitments.alu_a_hi); transcript->send_to_verifier(commitment_labels.alu_a_lo, witness_commitments.alu_a_lo); transcript->send_to_verifier(commitment_labels.alu_b_hi, witness_commitments.alu_b_hi); @@ -535,15 +542,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_emit_unencrypted_log_write_offset); transcript->send_to_verifier(commitment_labels.kernel_kernel_in_offset, witness_commitments.kernel_kernel_in_offset); - transcript->send_to_verifier(commitment_labels.kernel_kernel_inputs, witness_commitments.kernel_kernel_inputs); - transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, - witness_commitments.kernel_kernel_metadata_out); transcript->send_to_verifier(commitment_labels.kernel_kernel_out_offset, witness_commitments.kernel_kernel_out_offset); - transcript->send_to_verifier(commitment_labels.kernel_kernel_side_effect_out, - witness_commitments.kernel_kernel_side_effect_out); - transcript->send_to_verifier(commitment_labels.kernel_kernel_value_out, - witness_commitments.kernel_kernel_value_out); transcript->send_to_verifier(commitment_labels.kernel_l1_to_l2_msg_exists_write_offset, witness_commitments.kernel_l1_to_l2_msg_exists_write_offset); transcript->send_to_verifier(commitment_labels.kernel_note_hash_exist_write_offset, diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 32cb192f93a6..24a8b6c6f0b2 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -70,6 +70,14 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_inputs); + commitments.kernel_kernel_value_out = + transcript->template receive_from_prover(commitment_labels.kernel_kernel_value_out); + commitments.kernel_kernel_side_effect_out = + transcript->template receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); + commitments.kernel_kernel_metadata_out = + transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); commitments.alu_a_hi = transcript->template receive_from_prover(commitment_labels.alu_a_hi); commitments.alu_a_lo = transcript->template receive_from_prover(commitment_labels.alu_a_lo); commitments.alu_b_hi = transcript->template receive_from_prover(commitment_labels.alu_b_hi); @@ -233,16 +241,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_in_offset); - commitments.kernel_kernel_inputs = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_inputs); - commitments.kernel_kernel_metadata_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); commitments.kernel_kernel_out_offset = transcript->template receive_from_prover(commitment_labels.kernel_kernel_out_offset); - commitments.kernel_kernel_side_effect_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); - commitments.kernel_kernel_value_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_value_out); commitments.kernel_l1_to_l2_msg_exists_write_offset = transcript->template receive_from_prover(commitment_labels.kernel_l1_to_l2_msg_exists_write_offset); commitments.kernel_note_hash_exist_write_offset = diff --git a/bb-pilcom/.gitignore b/bb-pilcom/.gitignore new file mode 100644 index 000000000000..41bfb4401018 --- /dev/null +++ b/bb-pilcom/.gitignore @@ -0,0 +1 @@ +**/target/* \ No newline at end of file diff --git a/bb-pilcom/Cargo.lock b/bb-pilcom/Cargo.lock new file mode 100644 index 000000000000..d1179b177b9f --- /dev/null +++ b/bb-pilcom/Cargo.lock @@ -0,0 +1,1880 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "auto_enums" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1899bfcfd9340ceea3533ea157360ba8fa864354eccbceab58e1006ecab35393" +dependencies = [ + "derive_utils", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bb-pil-backend" +version = "0.1.0" +dependencies = [ + "itertools 0.10.5", + "log", + "num-bigint", + "num-integer", + "num-traits", + "powdr-ast", + "powdr-number", + "rand", +] + +[[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 = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "cc" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "clap" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "cli" +version = "0.1.0" +dependencies = [ + "bb-pil-backend", + "clap", + "itertools 0.10.5", + "log", + "num-bigint", + "num-integer", + "num-traits", + "powdr-ast", + "powdr-number", + "powdr-pil-analyzer", + "rand", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.66", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.66", +] + +[[package]] +name = "derive_utils" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61bb5a1014ce6dfc2a378578509abe775a5aa06bff584a547555d9efdb81b926" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "crypto-common", +] + +[[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 = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "ena" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +dependencies = [ + "log", +] + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ibig" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1fcc7f316b2c079dde77564a1360639c1a956a23fa96122732e416cb10717bb" +dependencies = [ + "cfg-if", + "num-traits", + "rand", + "serde", + "static_assertions", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lalrpop" +version = "0.19.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools 0.10.5", + "lalrpop-util", + "petgraph", + "regex", + "regex-syntax 0.6.29", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.2.6", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "powdr-ast" +version = "0.0.1" +dependencies = [ + "auto_enums", + "derive_more", + "itertools 0.11.0", + "num-traits", + "powdr-number", + "powdr-parser", + "powdr-parser-util", + "powdr-pil-analyzer", + "pretty_assertions", + "schemars", + "serde", + "serde_cbor", + "test-log", +] + +[[package]] +name = "powdr-number" +version = "0.0.1" +dependencies = [ + "ark-bn254", + "ark-ff", + "ark-serialize", + "csv", + "env_logger 0.10.2", + "ibig", + "num-bigint", + "num-traits", + "schemars", + "serde", + "serde_with", + "test-log", +] + +[[package]] +name = "powdr-parser" +version = "0.0.1" +dependencies = [ + "derive_more", + "env_logger 0.10.2", + "lalrpop", + "lalrpop-util", + "lazy_static", + "num-traits", + "powdr-ast", + "powdr-number", + "powdr-parser-util", + "pretty_assertions", + "similar", + "test-log", + "walkdir", +] + +[[package]] +name = "powdr-parser-util" +version = "0.0.1" +dependencies = [ + "codespan-reporting", + "env_logger 0.10.2", + "lalrpop-util", + "schemars", + "serde", + "test-log", +] + +[[package]] +name = "powdr-pil-analyzer" +version = "0.0.1" +dependencies = [ + "env_logger 0.10.2", + "itertools 0.10.5", + "lazy_static", + "num-traits", + "powdr-ast", + "powdr-number", + "powdr-parser", + "powdr-parser-util", + "pretty_assertions", + "test-log", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +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 = "pretty_assertions" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +dependencies = [ + "diff", + "yansi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags", +] + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "indexmap 1.9.3", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.66", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "serde_json" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "similar" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[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.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "test-log" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +dependencies = [ + "env_logger 0.11.3", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "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 = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] diff --git a/bb-pilcom/Cargo.toml b/bb-pilcom/Cargo.toml new file mode 100644 index 000000000000..5df0e982d9d1 --- /dev/null +++ b/bb-pilcom/Cargo.toml @@ -0,0 +1,28 @@ +[workspace] +resolver = "2" +members = [ + "cli", + "bb-pil-backend", + "powdr/ast", + "powdr/number", + "powdr/parser", + "powdr/parser-util", + "powdr/pil-analyzer" +] + +[workspace.package] +version = "0.0.1" +edition = "2021" +license = "MIT" +homepage = "https://powdr.org" +repository = "https://github.com/powdr-labs/powdr" + + +[workspace.dependencies] +bb-pil-backend = { path = "./bb-pil-backend" } +cli = { path = "./cli" } +powdr-ast = { path = "./powdr/ast" } +powdr-number = { path = "./powdr/number" } +powdr-parser = { path = "./powdr/parser" } +powdr-parser-util = { path = "./powdr/parser-util" } +powdr-pil-analyzer = { path = "./powdr/pil-analyzer" } diff --git a/bb-pilcom/bb-pil-backend/Cargo.toml b/bb-pilcom/bb-pil-backend/Cargo.toml new file mode 100644 index 000000000000..0904cd7f4454 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "bb-pil-backend" +version = "0.1.0" +authors = ["Aztec Labs"] +edition = "2021" + +[dependencies] +num-bigint = "0.4.3" + +powdr-number = { path = "../powdr/number" } +num-traits = "0.2.15" +num-integer = "0.1.45" +itertools = "^0.10" +log = "0.4.17" +rand = "0.8.5" +powdr-ast = { path = "../powdr/ast" } diff --git a/bb-pilcom/bb-pil-backend/src/circuit_builder.rs b/bb-pilcom/bb-pil-backend/src/circuit_builder.rs new file mode 100644 index 000000000000..1f93f0367e8e --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/circuit_builder.rs @@ -0,0 +1,374 @@ +use crate::{ + file_writer::BBFiles, + relation_builder::create_row_type, + utils::{get_relations_imports, map_with_newline, snake_case}, +}; + +pub trait CircuitBuilder { + fn create_circuit_builder_hpp( + &mut self, + name: &str, + relations: &[String], + permutations: &[String], + all_cols_without_inverses: &[String], + all_cols: &[String], + to_be_shifted: &[String], + all_cols_with_shifts: &[String], + ); + + fn create_circuit_builder_cpp(&mut self, name: &str, all_cols: &[String]); +} + +fn circuit_hpp_includes(name: &str, relations: &[String], permutations: &[String]) -> String { + let relation_imports = get_relations_imports(name, relations, permutations); + format!( + " + // AUTOGENERATED FILE + #pragma once + + #include +#ifndef __wasm__ + #include +#endif + + #include \"barretenberg/common/constexpr_utils.hpp\" + #include \"barretenberg/common/throw_or_abort.hpp\" + #include \"barretenberg/ecc/curves/bn254/fr.hpp\" + #include \"barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp\" + #include \"barretenberg/relations/generic_permutation/generic_permutation_relation.hpp\" + #include \"barretenberg/relations/generic_lookup/generic_lookup_relation.hpp\" + #include \"barretenberg/honk/proof_system/logderivative_library.hpp\" + + #include \"barretenberg/vm/generated/{name}_flavor.hpp\" + {relation_imports} +" + ) +} + +fn get_params() -> &'static str { + r#" + const FF gamma = FF::random_element(); + const FF beta = FF::random_element(); + bb::RelationParameters params{ + .eta = 0, + .beta = beta, + .gamma = gamma, + .public_input_delta = 0, + .lookup_grand_product_delta = 0, + .beta_sqr = 0, + .beta_cube = 0, + .eccvm_set_permutation_delta = 0, + }; + "# +} + +impl CircuitBuilder for BBFiles { + // Create circuit builder + // Generate some code that can read a commits.bin and constants.bin into data structures that bberg understands + fn create_circuit_builder_hpp( + &mut self, + name: &str, + relations: &[String], + permutations: &[String], + all_cols_without_inverses: &[String], + all_cols: &[String], + to_be_shifted: &[String], + all_cols_with_shifts: &[String], + ) { + let includes = circuit_hpp_includes(&snake_case(name), relations, permutations); + + let row_with_all_included = create_row_type(&format!("{name}Full"), all_cols_with_shifts); + + let num_polys = all_cols.len(); + let num_cols = all_cols.len() + to_be_shifted.len(); + + // Declare mapping transformations + let compute_polys_transformation = + |name: &String| format!("polys.{name}[i] = rows[i].{name};"); + let all_polys_transformation = + |name: &String| format!("polys.{name}_shift = Polynomial(polys.{name}.shifted());"); + let check_circuit_transformation = |relation_name: &String| { + format!( + "auto {relation_name} = [=]() {{ + return evaluate_relation.template operator()<{name}_vm::{relation_name}>(\"{relation_name}\", {name}_vm::get_relation_label_{relation_name}); + }}; + ", + name = name, + relation_name = relation_name + ) + }; + let check_lookup_transformation = |lookup_name: &String| { + let lookup_name_upper = lookup_name.to_uppercase(); + format!( + "auto {lookup_name} = [=]() {{ + return evaluate_logderivative.template operator()<{lookup_name}_relation>(\"{lookup_name_upper}\"); + }}; + " + ) + }; + + // When we are running natively, we want check circuit to run as futures; however, futures are not supported in wasm, so we must provide an + // alternative codepath that will execute the closures in serial + let emplace_future_transformation = |relation_name: &String| { + format!( + " + relation_futures.emplace_back(std::async(std::launch::async, {relation_name})); + " + ) + }; + + let execute_serial_transformation = |relation_name: &String| { + format!( + " + {relation_name}(); + " + ) + }; + + // Apply transformations + let compute_polys_assignemnt = + map_with_newline(all_cols_without_inverses, compute_polys_transformation); + let all_poly_shifts = map_with_newline(to_be_shifted, all_polys_transformation); + let check_circuit_for_each_relation = + map_with_newline(relations, check_circuit_transformation); + let check_circuit_for_each_lookup = + map_with_newline(permutations, check_lookup_transformation); + + // With futures + let emplace_future_relations = map_with_newline(relations, emplace_future_transformation); + let emplace_future_lookups = map_with_newline(permutations, emplace_future_transformation); + + // With threads + let serial_relations = map_with_newline(relations, execute_serial_transformation); + let serial_lookups = map_with_newline(permutations, execute_serial_transformation); + + let (params, lookup_check_closure) = if !permutations.is_empty() { + (get_params(), get_lookup_check_closure()) + } else { + ("", "".to_owned()) + }; + let relation_check_closure = if !relations.is_empty() { + get_relation_check_closure() + } else { + "".to_owned() + }; + + let circuit_hpp = format!(" +{includes} + +namespace bb {{ + +{row_with_all_included}; + +template std::ostream& operator<<(std::ostream& os, {name}FullRow const& row); + +class {name}CircuitBuilder {{ + public: + using Flavor = bb::{name}Flavor; + using FF = Flavor::FF; + using Row = {name}FullRow; + + // TODO: template + using Polynomial = Flavor::Polynomial; + using ProverPolynomials = Flavor::ProverPolynomials; + + static constexpr size_t num_fixed_columns = {num_cols}; + static constexpr size_t num_polys = {num_polys}; + std::vector rows; + + void set_trace(std::vector&& trace) {{ rows = std::move(trace); }} + + ProverPolynomials compute_polynomials() {{ + const auto num_rows = get_circuit_subgroup_size(); + ProverPolynomials polys; + + // Allocate mem for each column + for (auto& poly : polys.get_all()) {{ + poly = Polynomial(num_rows); + }} + + for (size_t i = 0; i < rows.size(); i++) {{ + {compute_polys_assignemnt} + }} + + {all_poly_shifts } + + return polys; + }} + + [[maybe_unused]] bool check_circuit() + {{ + {params} + + auto polys = compute_polynomials(); + const size_t num_rows = polys.get_polynomial_size(); + + {relation_check_closure} + + {lookup_check_closure} + + {check_circuit_for_each_relation} + + {check_circuit_for_each_lookup} + +#ifndef __wasm__ + + // Evaluate check circuit closures as futures + std::vector> relation_futures; + + {emplace_future_relations} + {emplace_future_lookups} + + + // Wait for lookup evaluations to complete + for (auto& future : relation_futures) {{ + int result = future.get(); + if (!result) {{ + return false; + }} + }} +#else + {serial_relations} + {serial_lookups} + +#endif + + return true; + }} + + + [[nodiscard]] size_t get_num_gates() const {{ return rows.size(); }} + + [[nodiscard]] size_t get_circuit_subgroup_size() const + {{ + const size_t num_rows = get_num_gates(); + const auto num_rows_log2 = static_cast(numeric::get_msb64(num_rows)); + size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1)); + return num_rows_pow2; + }} + + +}}; +}} + "); + + self.write_file( + &self.circuit, + &format!("{}_circuit_builder.hpp", snake_case(name)), + &circuit_hpp, + ); + } + + fn create_circuit_builder_cpp(&mut self, name: &str, all_cols: &[String]) { + let names_list = map_with_newline(all_cols, |name: &String| format!("\"{}\",", name)); + let stream_all_relations = map_with_newline(all_cols, |name: &String| { + format!("<< field_to_string(row.{}) << \",\"", name) + }); + let snake_name = snake_case(name); + + let circuit_cpp = format!( + " +#include \"barretenberg/vm/generated/{snake_name}_circuit_builder.hpp\" + +namespace bb {{ +namespace {{ + +template std::string field_to_string(const FF& ff) +{{ + std::ostringstream os; + os << ff; + std::string raw = os.str(); + auto first_not_zero = raw.find_first_not_of('0', 2); + std::string result = \"0x\" + (first_not_zero != std::string::npos ? raw.substr(first_not_zero) : \"0\"); + return result; +}} + +}} // namespace + +template std::vector {name}FullRow::names() {{ + return {{ + {names_list} + \"\" + }}; +}} + +template std::ostream& operator<<(std::ostream& os, {name}FullRow const& row) {{ + return os {stream_all_relations} + \"\"; +}} + +// Explicit template instantiation. +template std::ostream& operator<<(std::ostream& os, AvmFullRow const& row); +template std::vector AvmFullRow::names(); + +}} // namespace bb" + ); + + self.write_file( + &self.circuit, + &format!("{}_circuit_builder.cpp", snake_case(name)), + &circuit_cpp, + ); + } +} + +fn get_lookup_check_closure() -> String { + " + const auto evaluate_logderivative = [&](const std::string& lookup_name) { + + // Check the logderivative relation + bb::compute_logderivative_inverse< + Flavor, + LogDerivativeSettings>( + polys, params, num_rows); + + typename LogDerivativeSettings::SumcheckArrayOfValuesOverSubrelations + lookup_result; + + for (auto& r : lookup_result) { + r = 0; + } + for (size_t i = 0; i < num_rows; ++i) { + LogDerivativeSettings::accumulate(lookup_result, polys.get_row(i), params, 1); + } + for (auto r : lookup_result) { + if (r != 0) { + throw_or_abort(format(\"Lookup \", lookup_name, \" failed.\")); + return false; + } + } + return true; + }; + ".to_string() +} + +fn get_relation_check_closure() -> String { + " + const auto evaluate_relation = [&](const std::string& relation_name, + std::string (*debug_label)(int)) { + typename Relation::SumcheckArrayOfValuesOverSubrelations result; + for (auto& r : result) { + r = 0; + } + constexpr size_t NUM_SUBRELATIONS = result.size(); + + for (size_t i = 0; i < num_rows; ++i) { + Relation::accumulate(result, polys.get_row(i), {}, 1); + + bool x = true; + for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) { + if (result[j] != 0) { + std::string row_name = debug_label(static_cast(j)); + throw_or_abort( + format(\"Relation \", relation_name, \", subrelation index \", row_name, \" failed at row \", i)); + x = false; + } + } + if (!x) { + return false; + } + } + return true; + }; + ".to_string() +} diff --git a/bb-pilcom/bb-pil-backend/src/composer_builder.rs b/bb-pilcom/bb-pil-backend/src/composer_builder.rs new file mode 100644 index 000000000000..2cbd8576d1a5 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/composer_builder.rs @@ -0,0 +1,210 @@ +use crate::file_writer::BBFiles; +use crate::utils::snake_case; + +pub trait ComposerBuilder { + fn create_composer_cpp(&mut self, name: &str); + fn create_composer_hpp(&mut self, name: &str); +} + +impl ComposerBuilder for BBFiles { + fn create_composer_cpp(&mut self, name: &str) { + // Create a composer file, this is used to a prover and verifier for our flavour + let include_str = cpp_includes(&snake_case(name)); + + let composer_cpp = format!( + " +{include_str} + +namespace bb {{ + +using Flavor = {name}Flavor; +void {name}Composer::compute_witness(CircuitConstructor& circuit) +{{ + if (computed_witness) {{ + return; + }} + + auto polynomials = circuit.compute_polynomials(); + + for (auto [key_poly, prover_poly] : zip_view(proving_key->get_all(), polynomials.get_unshifted())) {{ + ASSERT(flavor_get_label(*proving_key, key_poly) == flavor_get_label(polynomials, prover_poly)); + key_poly = prover_poly; + }} + + computed_witness = true; +}} + +{name}Prover {name}Composer::create_prover(CircuitConstructor& circuit_constructor) +{{ + compute_proving_key(circuit_constructor); + compute_witness(circuit_constructor); + compute_commitment_key(circuit_constructor.get_circuit_subgroup_size()); + + {name}Prover output_state(proving_key, proving_key->commitment_key); + + return output_state; +}} + +{name}Verifier {name}Composer::create_verifier( + CircuitConstructor& circuit_constructor) +{{ + auto verification_key = compute_verification_key(circuit_constructor); + + {name}Verifier output_state(verification_key); + + auto pcs_verification_key = std::make_unique(); + + output_state.pcs_verification_key = std::move(pcs_verification_key); + + return output_state; +}} + +std::shared_ptr {name}Composer::compute_proving_key( + CircuitConstructor& circuit_constructor) +{{ + if (proving_key) {{ + return proving_key; + }} + + // Initialize proving_key + {{ + const size_t subgroup_size = circuit_constructor.get_circuit_subgroup_size(); + proving_key = std::make_shared(subgroup_size, 0); + }} + + proving_key->contains_recursive_proof = false; + + return proving_key; +}} + +std::shared_ptr {name}Composer::compute_verification_key( + CircuitConstructor& circuit_constructor) +{{ + if (verification_key) {{ + return verification_key; + }} + + if (!proving_key) {{ + compute_proving_key(circuit_constructor); + }} + + verification_key = + std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); + + return verification_key; +}} + +}} +"); + self.write_file( + &self.composer, + &format!("{}_composer.cpp", snake_case(name)), + &composer_cpp, + ); + } + + fn create_composer_hpp(&mut self, name: &str) { + let include_str = hpp_includes(&snake_case(name)); + + let composer_hpp = format!( + " +{include_str} + +namespace bb {{ +class {name}Composer {{ + public: + using Flavor = {name}Flavor; + using CircuitConstructor = {name}CircuitBuilder; + using ProvingKey = Flavor::ProvingKey; + using VerificationKey = Flavor::VerificationKey; + using PCS = Flavor::PCS; + using CommitmentKey = Flavor::CommitmentKey; + using VerifierCommitmentKey = Flavor::VerifierCommitmentKey; + + // TODO: which of these will we really need + static constexpr std::string_view NAME_STRING = \"{name}\"; + static constexpr size_t NUM_RESERVED_GATES = 0; + static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; + + std::shared_ptr proving_key; + std::shared_ptr verification_key; + + // The crs_factory holds the path to the srs and exposes methods to extract the srs elements + std::shared_ptr> crs_factory_; + + // The commitment key is passed to the prover but also used herein to compute the verfication key commitments + std::shared_ptr commitment_key; + + std::vector recursive_proof_public_input_indices; + bool contains_recursive_proof = false; + bool computed_witness = false; + + {name}Composer() + {{ + crs_factory_ = bb::srs::get_bn254_crs_factory(); + }} + + {name}Composer(std::shared_ptr p_key, std::shared_ptr v_key) + : proving_key(std::move(p_key)) + , verification_key(std::move(v_key)) + {{}} + + {name}Composer({name}Composer&& other) noexcept = default; + {name}Composer({name}Composer const& other) noexcept = default; + {name}Composer& operator=({name}Composer&& other) noexcept = default; + {name}Composer& operator=({name}Composer const& other) noexcept = default; + ~{name}Composer() = default; + + std::shared_ptr compute_proving_key(CircuitConstructor& circuit_constructor); + std::shared_ptr compute_verification_key(CircuitConstructor& circuit_constructor); + + void compute_witness(CircuitConstructor& circuit_constructor); + + {name}Prover create_prover(CircuitConstructor& circuit_constructor); + {name}Verifier create_verifier(CircuitConstructor& circuit_constructor); + + void add_table_column_selector_poly_to_proving_key(bb::polynomial& small, const std::string& tag); + + void compute_commitment_key(size_t circuit_size) + {{ + proving_key->commitment_key = std::make_shared(circuit_size); + }}; +}}; + +}} // namespace bb +" + ); + + self.write_file( + &self.composer, + &format!("{}_composer.hpp", snake_case(name)), + &composer_hpp, + ); + } +} + +fn cpp_includes(name: &str) -> String { + format!( + " +#include \"./{name}_composer.hpp\" +#include \"barretenberg/plonk_honk_shared/composer/composer_lib.hpp\" +#include \"barretenberg/plonk_honk_shared/composer/permutation_lib.hpp\" +#include \"barretenberg/vm/generated/{name}_circuit_builder.hpp\" +#include \"barretenberg/vm/generated/{name}_verifier.hpp\" +" + ) +} + +pub fn hpp_includes(name: &str) -> String { + format!( + " +#pragma once + +#include \"barretenberg/plonk_honk_shared/composer/composer_lib.hpp\" +#include \"barretenberg/srs/global_crs.hpp\" +#include \"barretenberg/vm/generated/{name}_circuit_builder.hpp\" +#include \"barretenberg/vm/generated/{name}_prover.hpp\" +#include \"barretenberg/vm/generated/{name}_verifier.hpp\" + " + ) +} diff --git a/bb-pilcom/bb-pil-backend/src/file_writer.rs b/bb-pilcom/bb-pil-backend/src/file_writer.rs new file mode 100644 index 000000000000..a4ed8e1e55e8 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/file_writer.rs @@ -0,0 +1,58 @@ +use std::fs::File; +use std::io::Write; + +pub struct BBFiles { + // Relative paths + pub file_name: String, + pub base: String, + pub rel: String, + pub circuit: String, + pub flavor: String, + pub composer: String, + pub prover: String, // path for both prover and verifier files +} + +impl BBFiles { + pub fn default(file_name: String) -> Self { + Self::new(file_name, None, None, None, None, None, None) + } + + #[allow(clippy::too_many_arguments)] + pub fn new( + file_name: String, + base: Option, + rel: Option, + circuit: Option, + flavor: Option, + composer: Option, + prover: Option, + ) -> Self { + let base = base.unwrap_or("src/barretenberg".to_owned()); + let rel = rel.unwrap_or("relations/generated".to_owned()); + let circuit = circuit.unwrap_or("vm/generated".to_owned()); + let flavor = flavor.unwrap_or("vm/generated".to_owned()); + let composer = composer.unwrap_or("vm/generated".to_owned()); + let prover = prover.unwrap_or("vm/generated".to_owned()); + + Self { + file_name, + + base, + rel, + circuit, + flavor, + composer, + prover, + } + } + + pub fn write_file(&self, folder: &str, filename: &str, contents: &String) { + // attempt to create dir + let base_path = format!("{}/{}", self.base, folder); + let _ = std::fs::create_dir_all(&base_path); + + let joined = format!("{}/{}", base_path, filename); + let mut file = File::create(joined).unwrap(); + file.write_all(contents.as_bytes()).unwrap(); + } +} diff --git a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs new file mode 100644 index 000000000000..dab4058bdfe2 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs @@ -0,0 +1,629 @@ +use crate::{ + file_writer::BBFiles, + utils::{get_relations_imports, map_with_newline, snake_case}, +}; + +pub trait FlavorBuilder { + #[allow(clippy::too_many_arguments)] + fn create_flavor_hpp( + &mut self, + name: &str, + relation_file_names: &[String], + lookups: &[String], + fixed: &[String], + witness: &[String], + all_cols: &[String], + to_be_shifted: &[String], + shifted: &[String], + all_cols_and_shifts: &[String], + ); +} + +/// Build the boilerplate for the flavor file +impl FlavorBuilder for BBFiles { + fn create_flavor_hpp( + &mut self, + name: &str, + relation_file_names: &[String], + lookups: &[String], + fixed: &[String], + witness: &[String], + all_cols: &[String], + to_be_shifted: &[String], + shifted: &[String], + all_cols_and_shifts: &[String], + ) { + let first_poly = &witness[0]; + let includes = flavor_includes(&snake_case(name), relation_file_names, lookups); + let num_precomputed = fixed.len(); + let num_witness = witness.len(); + let num_all = all_cols_and_shifts.len(); + + // Top of file boilerplate + let class_aliases = create_class_aliases(); + let relation_definitions = create_relation_definitions(name, relation_file_names, lookups); + let container_size_definitions = + container_size_definitions(num_precomputed, num_witness, num_all); + + // Entities classes + let precomputed_entities = create_precomputed_entities(fixed); + let witness_entities = create_witness_entities(witness); + let all_entities = + create_all_entities(all_cols, to_be_shifted, shifted, all_cols_and_shifts); + + let proving_and_verification_key = + create_proving_and_verification_key(name, lookups, to_be_shifted); + let polynomial_views = create_polynomial_views(first_poly); + + let commitment_labels_class = create_commitment_labels(all_cols); + + let verification_commitments = create_verifier_commitments(fixed); + + let transcript = generate_transcript(witness); + + let flavor_hpp = format!( + " +{includes} + +namespace bb {{ + +class {name}Flavor {{ + public: + {class_aliases} + + {container_size_definitions} + + {relation_definitions} + + static constexpr bool has_zero_row = true; + + private: + {precomputed_entities} + + {witness_entities} + + {all_entities} + + + {proving_and_verification_key} + + + {polynomial_views} + + {commitment_labels_class} + + {verification_commitments} + + {transcript} +}}; + +}} // namespace bb + + + " + ); + + self.write_file( + &self.flavor, + &format!("{}_flavor.hpp", snake_case(name)), + &flavor_hpp, + ); + } +} + +/// Imports located at the top of the flavor files +fn flavor_includes(name: &str, relation_file_names: &[String], lookups: &[String]) -> String { + let relation_imports = get_relations_imports(name, relation_file_names, lookups); + + format!( + "#pragma once + +#include \"barretenberg/commitment_schemes/kzg/kzg.hpp\" +#include \"barretenberg/ecc/curves/bn254/g1.hpp\" +#include \"barretenberg/flavor/relation_definitions.hpp\" +#include \"barretenberg/polynomials/barycentric.hpp\" +#include \"barretenberg/polynomials/univariate.hpp\" + +#include \"barretenberg/relations/generic_permutation/generic_permutation_relation.hpp\" + +#include \"barretenberg/flavor/flavor_macros.hpp\" +#include \"barretenberg/transcript/transcript.hpp\" +#include \"barretenberg/polynomials/evaluation_domain.hpp\" +#include \"barretenberg/polynomials/polynomial.hpp\" +#include \"barretenberg/flavor/flavor.hpp\" +{relation_imports} +" + ) +} + +/// Creates comma separated relations tuple file +fn create_relations_tuple(master_name: &str, relation_file_names: &[String]) -> String { + relation_file_names + .iter() + .map(|name| format!("{master_name}_vm::{name}")) + .collect::>() + .join(", ") +} + +/// Creates comma separated relations tuple file +fn create_lookups_tuple(lookups: &[String]) -> Option { + if lookups.is_empty() { + return None; + } + Some( + lookups + .iter() + .map(|lookup| format!("{}_relation", lookup.clone())) + .collect::>() + .join(", "), + ) +} + +/// Create Class Aliases +/// +/// Contains boilerplate defining key characteristics of the flavor class +fn create_class_aliases() -> &'static str { + r#" + using Curve = curve::BN254; + using G1 = Curve::Group; + using PCS = KZG; + + using FF = G1::subgroup_field; + using Polynomial = bb::Polynomial; + using PolynomialHandle = std::span; + using GroupElement = G1::element; + using Commitment = G1::affine_element; + using CommitmentHandle = G1::affine_element; + using CommitmentKey = bb::CommitmentKey; + using VerifierCommitmentKey = bb::VerifierCommitmentKey; + using RelationSeparator = FF; + "# +} + +/// Create relation definitions +/// +/// Contains all of the boilerplate code required to generate relation definitions. +/// We instantiate the Relations container, which contains a tuple of all of the separate relation file +/// definitions. +/// +/// We then also define some constants, making use of the preprocessor. +fn create_relation_definitions( + name: &str, + relation_file_names: &[String], + lookups: &[String], +) -> String { + // Relations tuple = ns::relation_name_0, ns::relation_name_1, ... ns::relation_name_n (comma speratated) + let comma_sep_relations = create_relations_tuple(name, relation_file_names); + let comma_sep_lookups: Option = create_lookups_tuple(lookups); + + // We only include the grand product relations if we are given lookups + let mut grand_product_relations = String::new(); + let mut all_relations = comma_sep_relations.to_string(); + if let Some(lookups) = comma_sep_lookups { + all_relations = all_relations + &format!(", {lookups}"); + grand_product_relations = format!("using GrandProductRelations = std::tuple<{lookups}>;"); + } + + format!(" + {grand_product_relations} + + using Relations = std::tuple<{all_relations}>; + + static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); + + // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` + // random polynomial e.g. For \\sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation + // length = 3 + static constexpr size_t BATCHED_RELATION_PARTIAL_LENGTH = MAX_PARTIAL_RELATION_LENGTH + 1; + static constexpr size_t NUM_RELATIONS = std::tuple_size_v; + + template + using ProtogalaxyTupleOfTuplesOfUnivariates = + decltype(create_protogalaxy_tuple_of_tuples_of_univariates()); + using SumcheckTupleOfTuplesOfUnivariates = decltype(create_sumcheck_tuple_of_tuples_of_univariates()); + using TupleOfArraysOfValues = decltype(create_tuple_of_arrays_of_values()); + ") +} + +/// Create the number of columns boilerplate for the flavor file +fn container_size_definitions( + num_precomputed: usize, + num_witness: usize, + num_all: usize, +) -> String { + format!(" + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = {num_precomputed}; + static constexpr size_t NUM_WITNESS_ENTITIES = {num_witness}; + static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; + // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for the unshifted and one for the shifted + static constexpr size_t NUM_ALL_ENTITIES = {num_all}; + + ") +} + +/// Returns a Ref Vector with the given name, +/// +/// The vector returned will reference the columns names given +/// Used in all entities declarations +fn return_ref_vector(name: &str, columns: &[String]) -> String { + let comma_sep = create_comma_separated(columns); + + format!("RefVector {name}() {{ return {{ {comma_sep} }}; }};") +} + +/// list -> "list[0], list[1], ... list[n-1]" +fn create_comma_separated(list: &[String]) -> String { + list.join(", ") +} + +/// Create Precomputed Entities +/// +/// Precomputed first contains a pointer view defining all of the precomputed columns +/// As-well as any polys conforming to tables / ids / permutations +fn create_precomputed_entities(fixed: &[String]) -> String { + let pointer_view = create_flavor_members(fixed); + + let selectors = return_ref_vector("get_selectors", fixed); + let sigma_polys = return_ref_vector("get_sigma_polynomials", &[]); + let id_polys = return_ref_vector("get_id_polynomials", &[]); + let table_polys = return_ref_vector("get_table_polynomials", &[]); + + format!( + " + template + class PrecomputedEntities : public PrecomputedEntitiesBase {{ + public: + using DataType = DataType_; + + {pointer_view} + + {selectors} + {sigma_polys} + {id_polys} + {table_polys} + }}; + " + ) +} + +fn create_witness_entities(witness: &[String]) -> String { + let pointer_view = create_flavor_members(witness); + + let wires = return_ref_vector("get_wires", witness); + + format!( + " + template + class WitnessEntities {{ + public: + + {pointer_view} + + {wires} + }}; + " + ) +} + +/// Creates container of all witness entities and shifts +fn create_all_entities( + all_cols: &[String], + to_be_shifted: &[String], + shifted: &[String], + all_cols_and_shifts: &[String], +) -> String { + let all_entities_flavor_members = create_flavor_members(all_cols_and_shifts); + + let wires = return_ref_vector("get_wires", all_cols_and_shifts); + let get_unshifted = return_ref_vector("get_unshifted", all_cols); + let get_to_be_shifted = return_ref_vector("get_to_be_shifted", to_be_shifted); + let get_shifted = return_ref_vector("get_shifted", shifted); + + format!( + " + template + class AllEntities {{ + public: + + {all_entities_flavor_members} + + + {wires} + {get_unshifted} + {get_to_be_shifted} + {get_shifted} + }}; + " + ) +} + +fn create_proving_and_verification_key( + flavor_name: &str, + lookups: &[String], + to_be_shifted: &[String], +) -> String { + let get_to_be_shifted = return_ref_vector("get_to_be_shifted", to_be_shifted); + let compute_logderivative_inverses = + create_compute_logderivative_inverses(flavor_name, lookups); + + format!(" + public: + class ProvingKey : public ProvingKeyAvm_, WitnessEntities, CommitmentKey> {{ + public: + // Expose constructors on the base class + using Base = ProvingKeyAvm_, WitnessEntities, CommitmentKey>; + using Base::Base; + + {get_to_be_shifted} + + {compute_logderivative_inverses} + }}; + + using VerificationKey = VerificationKey_, VerifierCommitmentKey>; + ") +} + +fn create_polynomial_views(first_poly: &String) -> String { + format!(" + + class AllValues : public AllEntities {{ + public: + using Base = AllEntities; + using Base::Base; + }}; + + /** + * @brief A container for the prover polynomials handles. + */ + class ProverPolynomials : public AllEntities {{ + public: + // Define all operations as default, except copy construction/assignment + ProverPolynomials() = default; + ProverPolynomials& operator=(const ProverPolynomials&) = delete; + ProverPolynomials(const ProverPolynomials& o) = delete; + ProverPolynomials(ProverPolynomials&& o) noexcept = default; + ProverPolynomials& operator=(ProverPolynomials&& o) noexcept = default; + ~ProverPolynomials() = default; + + ProverPolynomials(ProvingKey& proving_key) + {{ + for (auto [prover_poly, key_poly] : zip_view(this->get_unshifted(), proving_key.get_all())) {{ + ASSERT(flavor_get_label(*this, prover_poly) == flavor_get_label(proving_key, key_poly)); + prover_poly = key_poly.share(); + }} + for (auto [prover_poly, key_poly] : zip_view(this->get_shifted(), proving_key.get_to_be_shifted())) {{ + ASSERT(flavor_get_label(*this, prover_poly) == (flavor_get_label(proving_key, key_poly) + \"_shift\")); + prover_poly = key_poly.shifted(); + }} + }} + + [[nodiscard]] size_t get_polynomial_size() const {{ return {first_poly}.size(); }} + /** + * @brief Returns the evaluations of all prover polynomials at one point on the boolean hypercube, which + * represents one row in the execution trace. + */ + [[nodiscard]] AllValues get_row(size_t row_idx) const + {{ + AllValues result; + for (auto [result_field, polynomial] : zip_view(result.get_all(), this->get_all())) {{ + result_field = polynomial[row_idx]; + }} + return result; + }} + }}; + + class PartiallyEvaluatedMultivariates : public AllEntities {{ + public: + PartiallyEvaluatedMultivariates() = default; + PartiallyEvaluatedMultivariates(const size_t circuit_size) + {{ + // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + for (auto& poly : get_all()) {{ + poly = Polynomial(circuit_size / 2); + }} + }} + }}; + + /** + * @brief A container for univariates used during Protogalaxy folding and sumcheck. + * @details During folding and sumcheck, the prover evaluates the relations on these univariates. + */ + template + using ProverUnivariates = AllEntities>; + + /** + * @brief A container for univariates used during Protogalaxy folding and sumcheck with some of the computation + * optimistically ignored + * @details During folding and sumcheck, the prover evaluates the relations on these univariates. + */ + template + using OptimisedProverUnivariates = AllEntities>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + */ + using ExtendedEdges = ProverUnivariates; + + /** + * @brief A container for the witness commitments. + * + */ + using WitnessCommitments = WitnessEntities; + + ") +} + +fn create_flavor_members(entities: &[String]) -> String { + let pointer_list = create_comma_separated(entities); + + format!( + "DEFINE_FLAVOR_MEMBERS(DataType, {pointer_list})", + pointer_list = pointer_list + ) +} + +fn create_labels(all_ents: &[String]) -> String { + let mut labels = String::new(); + for name in all_ents { + labels.push_str(&format!( + "Base::{name} = \"{}\"; + ", + name.to_uppercase() + )); + } + labels +} + +fn create_commitment_labels(all_ents: &[String]) -> String { + let labels = create_labels(all_ents); + + format!( + " + class CommitmentLabels: public AllEntities {{ + private: + using Base = AllEntities; + + public: + CommitmentLabels() : AllEntities() + {{ + {labels} + }}; + }}; + " + ) +} + +/// Create the compute_logderivative_inverses function +/// +/// If we do not have any lookups, we do not need to include this round +fn create_compute_logderivative_inverses(flavor_name: &str, lookups: &[String]) -> String { + if lookups.is_empty() { + return "".to_string(); + } + + let compute_inverse_transformation = |lookup_name: &String| { + format!("bb::compute_logderivative_inverse<{flavor_name}Flavor, {lookup_name}_relation>(prover_polynomials, relation_parameters, this->circuit_size);") + }; + + let compute_inverses = map_with_newline(lookups, compute_inverse_transformation); + + format!( + " + void compute_logderivative_inverses(const RelationParameters& relation_parameters) + {{ + ProverPolynomials prover_polynomials = ProverPolynomials(*this); + + {compute_inverses} + }} + " + ) +} + +fn create_key_dereference(fixed: &[String]) -> String { + let deref_transformation = |name: &String| format!("{name} = verification_key->{name};"); + + map_with_newline(fixed, deref_transformation) +} + +fn create_verifier_commitments(fixed: &[String]) -> String { + let key_dereference = create_key_dereference(fixed); + + format!( + " + class VerifierCommitments : public AllEntities {{ + private: + using Base = AllEntities; + + public: + VerifierCommitments(const std::shared_ptr& verification_key) + {{ + {key_dereference} + }} + }}; +" + ) +} + +fn generate_transcript(witness: &[String]) -> String { + // Transformations + let declaration_transform = |c: &_| format!("Commitment {c};"); + let deserialize_transform = |name: &_| { + format!( + "{name} = deserialize_from_buffer(Transcript::proof_data, num_frs_read);", + ) + }; + let serialize_transform = + |name: &_| format!("serialize_to_buffer({name}, Transcript::proof_data);"); + + // Perform Transformations + let declarations = map_with_newline(witness, declaration_transform); + let deserialize_wires = map_with_newline(witness, deserialize_transform); + let serialize_wires = map_with_newline(witness, serialize_transform); + + format!(" + class Transcript : public NativeTranscript {{ + public: + uint32_t circuit_size; + + {declarations} + + std::vector> sumcheck_univariates; + std::array sumcheck_evaluations; + std::vector zm_cq_comms; + Commitment zm_cq_comm; + Commitment zm_pi_comm; + + Transcript() = default; + + Transcript(const std::vector& proof) + : NativeTranscript(proof) + {{}} + + void deserialize_full_transcript() + {{ + size_t num_frs_read = 0; + circuit_size = deserialize_from_buffer(proof_data, num_frs_read); + size_t log_n = numeric::get_msb(circuit_size); + + {deserialize_wires} + + for (size_t i = 0; i < log_n; ++i) {{ + sumcheck_univariates.emplace_back( + deserialize_from_buffer>( + Transcript::proof_data, num_frs_read)); + }} + sumcheck_evaluations = deserialize_from_buffer>( + Transcript::proof_data, num_frs_read); + for (size_t i = 0; i < log_n; ++i) {{ + zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); + }} + zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); + zm_pi_comm = deserialize_from_buffer(proof_data, num_frs_read); + }} + + void serialize_full_transcript() + {{ + size_t old_proof_length = proof_data.size(); + Transcript::proof_data.clear(); + size_t log_n = numeric::get_msb(circuit_size); + + serialize_to_buffer(circuit_size, Transcript::proof_data); + + {serialize_wires} + + for (size_t i = 0; i < log_n; ++i) {{ + serialize_to_buffer(sumcheck_univariates[i], Transcript::proof_data); + }} + serialize_to_buffer(sumcheck_evaluations, Transcript::proof_data); + for (size_t i = 0; i < log_n; ++i) {{ + serialize_to_buffer(zm_cq_comms[i], proof_data); + }} + serialize_to_buffer(zm_cq_comm, proof_data); + serialize_to_buffer(zm_pi_comm, proof_data); + + // sanity check to make sure we generate the same length of proof as before. + ASSERT(proof_data.size() == old_proof_length); + }} + }}; + ") +} diff --git a/bb-pilcom/bb-pil-backend/src/lib.rs b/bb-pilcom/bb-pil-backend/src/lib.rs new file mode 100644 index 000000000000..7644c13d1b57 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/lib.rs @@ -0,0 +1,11 @@ +mod circuit_builder; +mod composer_builder; +mod file_writer; +mod flavor_builder; +pub mod lookup_builder; +pub mod permutation_builder; +mod prover_builder; +mod relation_builder; +mod utils; +mod verifier_builder; +pub mod vm_builder; diff --git a/bb-pilcom/bb-pil-backend/src/lookup_builder.rs b/bb-pilcom/bb-pil-backend/src/lookup_builder.rs new file mode 100644 index 000000000000..50016404a3f3 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/lookup_builder.rs @@ -0,0 +1,369 @@ +use crate::{ + file_writer::BBFiles, + utils::{create_get_const_entities, create_get_nonconst_entities, snake_case}, +}; +use itertools::Itertools; +use powdr_ast::{ + analyzed::{AlgebraicExpression, Analyzed, Identity, IdentityKind}, + parsed::SelectedExpressions, +}; +use powdr_number::FieldElement; + +use crate::utils::sanitize_name; + +#[derive(Debug)] +/// Lookup +/// +/// Contains the information required to produce a lookup relation +/// Lookup object and lookup side object are very similar in structure, however they are duplicated for +/// readability. +pub struct Lookup { + /// the name given to the inverse helper column + pub attribute: Option, + /// The name of the counts polynomial that stores the number of times a lookup is read + pub counts_poly: String, + /// the left side of the lookup + pub left: LookupSide, + /// the right side of the lookup + pub right: LookupSide, +} + +#[derive(Debug)] +/// LookupSide +/// +/// One side of a two sided lookup relationship +pub struct LookupSide { + /// -> Option - the selector for the lookup ( on / off toggle ) + selector: Option, + /// The columns involved in this side of the lookup + cols: Vec, +} + +pub trait LookupBuilder { + /// Takes in an AST and works out what lookup relations are needed + /// Note: returns the name of the inverse columns, such that they can be added to the prover in subsequent steps + fn create_lookup_files( + &self, + name: &str, + analyzed: &Analyzed, + ) -> Vec; +} + +impl LookupBuilder for BBFiles { + fn create_lookup_files( + &self, + project_name: &str, + analyzed: &Analyzed, + ) -> Vec { + let lookups: Vec<&Identity>> = analyzed + .identities + .iter() + .filter(|identity| matches!(identity.kind, IdentityKind::Plookup)) + .collect(); + let new_lookups = lookups + .iter() + .map(|lookup| Lookup { + attribute: lookup.attribute.clone().map(|att| att.to_lowercase()), + counts_poly: format!( + "{}_counts", + lookup.attribute.clone().unwrap().to_lowercase() + ), + left: get_lookup_side(&lookup.left), + right: get_lookup_side(&lookup.right), + }) + .collect_vec(); + + create_lookups(self, project_name, &new_lookups); + new_lookups + } +} + +/// The attributes of a lookup contain the name of the inverse, we collect all of these to create the inverse column +pub fn get_inverses_from_lookups(lookups: &[Lookup]) -> Vec { + lookups + .iter() + .map(|lookup| lookup.attribute.clone().unwrap()) + .collect() +} + +pub fn get_counts_from_lookups(lookups: &[Lookup]) -> Vec { + lookups + .iter() + .map(|lookup| lookup.counts_poly.clone()) + .collect() +} + +/// Write the lookup settings files to disk +fn create_lookups(bb_files: &BBFiles, project_name: &str, lookups: &Vec) { + for lookup in lookups { + let lookup_settings = create_lookup_settings_file(lookup); + + let folder = format!("{}/{}", bb_files.rel, &snake_case(project_name)); + let file_name = format!( + "{}{}", + lookup.attribute.clone().unwrap_or("NONAME".to_owned()), + ".hpp".to_owned() + ); + bb_files.write_file(&folder, &file_name, &lookup_settings); + } +} + +/// All relation types eventually get wrapped in the relation type +/// This function creates the export for the relation type so that it can be added to the flavor +fn create_relation_exporter(lookup_name: &str) -> String { + let settings_name = format!("{}_lookup_settings", lookup_name); + let lookup_export = format!("template using {lookup_name}_relation = GenericLookupRelation<{settings_name}, FF_>;"); + let relation_export = format!( + "template using {lookup_name} = GenericLookup<{settings_name}, FF_>;" + ); + + format!( + " + {lookup_export} + {relation_export} + " + ) +} + +fn lookup_settings_includes() -> &'static str { + r#" + #pragma once + + #include "barretenberg/relations/generic_lookup/generic_lookup_relation.hpp" + + #include + #include + "# +} + +fn create_lookup_settings_file(lookup: &Lookup) -> String { + let columns_per_set = lookup.left.cols.len(); + let lookup_name = lookup + .attribute + .clone() + .expect("Inverse column name must be provided within lookup attribute - #[]"); + let counts_poly_name = lookup.counts_poly.to_owned(); + + // NOTE: https://github.com/AztecProtocol/aztec-packages/issues/3879 + // Settings are not flexible enough to combine inverses + + let lhs_selector = lookup + .left + .selector + .clone() + .expect("Left hand side selector for lookup required"); + let rhs_selector = lookup + .right + .selector + .clone() + .expect("Right hand side selector for lookup required"); + let lhs_cols = lookup.left.cols.clone(); + let rhs_cols = lookup.right.cols.clone(); + + assert!( + lhs_cols.len() == rhs_cols.len(), + "Lookup columns lhs must be the same length as rhs" + ); + + // 0. The polynomial containing the inverse products -> taken from the attributes + // 1. The polynomial with the counts! + // 2. lhs selector + // 3. rhs selector + // 4.. + columns per set. lhs cols + // 4 + columns per set.. . rhs cols + let mut lookup_entities: Vec = [ + lookup_name.clone(), + counts_poly_name.clone(), + lhs_selector.clone(), + rhs_selector.clone(), + ] + .to_vec(); + + lookup_entities.extend(lhs_cols); + lookup_entities.extend(rhs_cols); + + // NOTE: these are hardcoded as 1 for now until more optimizations are required + let read_terms = 1; + let write_terms = 1; + let lookup_tuple_size = columns_per_set; + + // NOTE: hardcoded until optimizations required + let inverse_degree = 4; + let read_term_degree = 0; + let write_term_degree = 0; + let read_term_types = "{0}"; + let write_term_types = "{0}"; + + let lookup_settings_includes = lookup_settings_includes(); + let inverse_polynomial_is_computed_at_row = + create_inverse_computed_at(&lhs_selector, &rhs_selector); + let compute_inverse_exists = create_compute_inverse_exist(&lhs_selector, &rhs_selector); + let const_entities = create_get_const_entities(&lookup_entities); + let nonconst_entities = create_get_nonconst_entities(&lookup_entities); + let relation_exporter = create_relation_exporter(&lookup_name); + + format!( + " + {lookup_settings_includes} + + namespace bb {{ + + /** + * @brief This class contains an example of how to set LookupSettings classes used by the + * GenericLookupRelationImpl class to specify a scaled lookup + * + * @details To create your own lookup: + * 1) Create a copy of this class and rename it + * 2) Update all the values with the ones needed for your lookup + * 3) Update \"DECLARE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS\" and \"DEFINE_LOOKUP_IMPLEMENTATIONS_FOR_ALL_SETTINGS\" to + * include the new settings + * 4) Add the relation with the chosen settings to Relations in the flavor (for example,\"` + * using Relations = std::tuple>;)` + * + */ + class {lookup_name}_lookup_settings {{ + public: + /** + * @brief The number of read terms (how many lookups we perform) in each row + * + */ + static constexpr size_t READ_TERMS = {read_terms}; + /** + * @brief The number of write terms (how many additions to the lookup table we make) in each row + * + */ + static constexpr size_t WRITE_TERMS = {write_terms}; + + /** + * @brief The type of READ_TERM used for each read index (basic and scaled) + * + */ + static constexpr size_t READ_TERM_TYPES[READ_TERMS] = {read_term_types}; + + /** + * @brief They type of WRITE_TERM used for each write index + * + */ + static constexpr size_t WRITE_TERM_TYPES[WRITE_TERMS] = {write_term_types}; + + /** + * @brief How many values represent a single lookup object. This value is used by the automatic read term + * implementation in the relation in case the lookup is a basic or scaled tuple and in the write term if it's a + * basic tuple + * + */ + static constexpr size_t LOOKUP_TUPLE_SIZE = {lookup_tuple_size}; + + /** + * @brief The polynomial degree of the relation telling us if the inverse polynomial value needs to be computed + * + */ + static constexpr size_t INVERSE_EXISTS_POLYNOMIAL_DEGREE = {inverse_degree}; + + /** + * @brief The degree of the read term if implemented arbitrarily. This value is not used by basic and scaled read + * terms, but will cause compilation error if not defined + * + */ + static constexpr size_t READ_TERM_DEGREE = {read_term_degree}; + + /** + * @brief The degree of the write term if implemented arbitrarily. This value is not used by the basic write + * term, but will cause compilation error if not defined + * + */ + + static constexpr size_t WRITE_TERM_DEGREE = {write_term_degree}; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial exists at this index. + * Otherwise the value needs to be set to zero. + * + * @details If this is true then the lookup takes place in this row + * + */ + {inverse_polynomial_is_computed_at_row} + + /** + * @brief Subprocedure for computing the value deciding if the inverse polynomial value needs to be checked in this + * row + * + * @tparam Accumulator Type specified by the lookup relation + * @tparam AllEntities Values/Univariates of all entities row + * @param in Value/Univariate of all entities at row/edge + * @return Accumulator + */ + {compute_inverse_exists} + + /** + * @brief Get all the entities for the lookup when need to update them + * + * @details The generic structure of this tuple is described in ./generic_lookup_relation.hpp . The following is + description for the current case: + The entities are returned as a tuple of references in the following order (this is for ): + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that specifies how many times the lookup table entry at this row has been looked up + * - READ_TERMS entities/polynomials that enable individual lookup operations + * - The entity/polynomial that enables adding an entry to the lookup table in this row + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the basic tuple being looked up as the first read term + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the previous accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the shifts in the second read term (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing the current accumulators in the second read term + (scaled tuple) + * - LOOKUP_TUPLE_SIZE entities/polynomials representing basic tuples added to the table + * + * @return All the entities needed for the lookup + */ + {const_entities} + + /** + * @brief Get all the entities for the lookup when we only need to read them + * @details Same as in get_const_entities, but nonconst + * + * @return All the entities needed for the lookup + */ + {nonconst_entities} + }}; + + {relation_exporter} + }} + " + ) +} + +fn create_inverse_computed_at(lhs_selector: &String, rhs_selector: &String) -> String { + let lhs_computed_selector = format!("in.{lhs_selector}"); + let rhs_computed_selector = format!("in.{rhs_selector}"); + format!(" + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) {{ + return ({lhs_computed_selector } == 1 || {rhs_computed_selector} == 1); + }}") +} + +fn create_compute_inverse_exist(lhs_selector: &String, rhs_selector: &String) -> String { + let lhs_computed_selector = format!("in.{lhs_selector}"); + let rhs_computed_selector = format!("in.{rhs_selector}"); + format!(" + template static inline auto compute_inverse_exists(const AllEntities& in) {{ + using View = typename Accumulator::View; + const auto is_operation = View({lhs_computed_selector}); + const auto is_table_entry = View({rhs_computed_selector}); + return (is_operation + is_table_entry - is_operation * is_table_entry); + }}") +} + +fn get_lookup_side( + def: &SelectedExpressions>, +) -> LookupSide { + let get_name = |expr: &AlgebraicExpression| match expr { + AlgebraicExpression::Reference(a_ref) => sanitize_name(&a_ref.name), + _ => panic!("Expected reference"), + }; + + LookupSide { + selector: def.selector.as_ref().map(get_name), + cols: def.expressions.iter().map(get_name).collect_vec(), + } +} diff --git a/bb-pilcom/bb-pil-backend/src/permutation_builder.rs b/bb-pilcom/bb-pil-backend/src/permutation_builder.rs new file mode 100644 index 000000000000..b9dbeb0130e7 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/permutation_builder.rs @@ -0,0 +1,254 @@ +use crate::{ + file_writer::BBFiles, + utils::{create_get_const_entities, create_get_nonconst_entities, snake_case}, +}; +use itertools::Itertools; +use powdr_ast::{ + analyzed::{AlgebraicExpression, Analyzed, Identity, IdentityKind}, + parsed::SelectedExpressions, +}; +use powdr_number::FieldElement; + +use crate::utils::sanitize_name; + +#[derive(Debug)] +/// Permutation +/// +/// Contains the information required to produce a permutation relation +pub struct Permutation { + /// -> Attribute - the name given to the inverse helper column + pub attribute: Option, + /// -> PermSide - the left side of the permutation + pub left: PermutationSide, + /// -> PermSide - the right side of the permutation + pub right: PermutationSide, +} + +#[derive(Debug)] +/// PermSide +/// +/// One side of a two sided permutation relationship +pub struct PermutationSide { + /// -> Option - the selector for the permutation ( on / off toggle ) + selector: Option, + /// The columns involved in this side of the permutation + cols: Vec, +} + +pub trait PermutationBuilder { + /// Takes in an AST and works out what permutation relations are needed + /// Note: returns the name of the inverse columns, such that they can be added to he prover in subsequent steps + fn create_permutation_files( + &self, + name: &str, + analyzed: &Analyzed, + ) -> Vec; +} + +impl PermutationBuilder for BBFiles { + fn create_permutation_files( + &self, + project_name: &str, + analyzed: &Analyzed, + ) -> Vec { + let perms: Vec<&Identity>> = analyzed + .identities + .iter() + .filter(|identity| matches!(identity.kind, IdentityKind::Permutation)) + .collect(); + let new_perms = perms + .iter() + .map(|perm| Permutation { + attribute: perm.attribute.clone().map(|att| att.to_lowercase()), + left: get_perm_side(&perm.left), + right: get_perm_side(&perm.right), + }) + .collect_vec(); + + create_permutations(self, project_name, &new_perms); + new_perms + } +} + +/// The attributes of a permutation contain the name of the inverse, we collect all of these to create the inverse column +pub fn get_inverses_from_permutations(permutations: &[Permutation]) -> Vec { + permutations + .iter() + .map(|perm| perm.attribute.clone().unwrap()) + .collect() +} + +/// Write the permutation settings files to disk +fn create_permutations(bb_files: &BBFiles, project_name: &str, permutations: &Vec) { + for permutation in permutations { + let perm_settings = create_permutation_settings_file(permutation); + + let folder = format!("{}/{}", bb_files.rel, &snake_case(project_name)); + let file_name = format!( + "{}{}", + permutation.attribute.clone().unwrap_or("NONAME".to_owned()), + ".hpp".to_owned() + ); + bb_files.write_file(&folder, &file_name, &perm_settings); + } +} + +/// All relation types eventually get wrapped in the relation type +/// This function creates the export for the relation type so that it can be added to the flavor +fn create_relation_exporter(permutation_name: &str) -> String { + let settings_name = format!("{}_permutation_settings", permutation_name); + let permutation_export = format!("template using {permutation_name}_relation = GenericPermutationRelation<{settings_name}, FF_>;"); + let relation_export = format!("template using {permutation_name} = GenericPermutation<{settings_name}, FF_>;"); + + format!( + " + {permutation_export} + {relation_export} + " + ) +} + +fn permutation_settings_includes() -> &'static str { + r#" + #pragma once + + #include "barretenberg/relations/generic_permutation/generic_permutation_relation.hpp" + + #include + #include + "# +} + +fn create_permutation_settings_file(permutation: &Permutation) -> String { + log::trace!("Permutation: {:?}", permutation); + let columns_per_set = permutation.left.cols.len(); + // TODO(md): In the future we will need to condense off the back of this - combining those with the same inverse column + let permutation_name = permutation + .attribute + .clone() + .expect("Inverse column name must be provided using attribute syntax"); + + // This also will need to work for both sides of this ! + let lhs_selector = permutation + .left + .selector + .clone() + .expect("At least one selector must be provided"); + // If a rhs selector is not present, then we use the rhs selector -- TODO(md): maybe we want the default to be always on? + let rhs_selector = permutation + .right + .selector + .clone() + .unwrap_or(lhs_selector.clone()); + + let lhs_cols = permutation.left.cols.clone(); + let rhs_cols = permutation.right.cols.clone(); + + // 0. The polynomial containing the inverse products -> taken from the attributes + // 1. The polynomial enabling the relation (the selector) + // 2. lhs selector + // 3. rhs selector + // 4.. + columns per set. lhs cols + // 4 + columns per set.. . rhs cols + let mut perm_entities: Vec = [ + permutation_name.clone(), + lhs_selector.clone(), + lhs_selector.clone(), + rhs_selector.clone(), + ] + .to_vec(); + + perm_entities.extend(lhs_cols); + perm_entities.extend(rhs_cols); + + let permutation_settings_includes = permutation_settings_includes(); + + let inverse_computed_at = create_inverse_computed_at(&lhs_selector, &rhs_selector); + let const_entities = create_get_const_entities(&perm_entities); + let nonconst_entities = create_get_nonconst_entities(&perm_entities); + let relation_exporter = create_relation_exporter(&permutation_name); + + format!( + " + {permutation_settings_includes} + + namespace bb {{ + + class {permutation_name}_permutation_settings {{ + public: + // This constant defines how many columns are bundled together to form each set. + constexpr static size_t COLUMNS_PER_SET = {columns_per_set}; + + /** + * @brief If this method returns true on a row of values, then the inverse polynomial at this index. Otherwise the + * value needs to be set to zero. + * + * @details If this is true then permutation takes place in this row + */ + {inverse_computed_at} + + /** + * @brief Get all the entities for the permutation when we don't need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + {const_entities} + + /** + * @brief Get all the entities for the permutation when need to update them + * + * @details The entities are returned as a tuple of references in the following order: + * - The entity/polynomial used to store the product of the inverse values + * - The entity/polynomial that switches on the subrelation of the permutation relation that ensures correctness of + * the inverse polynomial + * - The entity/polynomial that enables adding a tuple-generated value from the first set to the logderivative sum + * subrelation + * - The entity/polynomial that enables adding a tuple-generated value from the second set to the logderivative sum + * subrelation + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the first set (N.B. ORDER IS IMPORTANT!) + * - A sequence of COLUMNS_PER_SET entities/polynomials that represent the second set (N.B. ORDER IS IMPORTANT!) + * + * @return All the entities needed for the permutation + */ + {nonconst_entities} + }}; + + {relation_exporter} + }} + " + ) +} + +fn create_inverse_computed_at(lhs_selector: &String, rhs_selector: &String) -> String { + let lhs_computed_selector = format!("in.{lhs_selector}"); + let rhs_computed_selector = format!("in.{rhs_selector}"); + format!(" + template static inline auto inverse_polynomial_is_computed_at_row(const AllEntities& in) {{ + return ({lhs_computed_selector } == 1 || {rhs_computed_selector} == 1); + }}") +} + +fn get_perm_side( + def: &SelectedExpressions>, +) -> PermutationSide { + let get_name = |expr: &AlgebraicExpression| match expr { + AlgebraicExpression::Reference(a_ref) => sanitize_name(&a_ref.name), + _ => panic!("Expected reference"), + }; + + PermutationSide { + selector: def.selector.as_ref().map(get_name), + cols: def.expressions.iter().map(get_name).collect_vec(), + } +} diff --git a/bb-pilcom/bb-pil-backend/src/prover_builder.rs b/bb-pilcom/bb-pil-backend/src/prover_builder.rs new file mode 100644 index 000000000000..be412cf0d579 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/prover_builder.rs @@ -0,0 +1,331 @@ +use crate::file_writer::BBFiles; +use crate::utils::{map_with_newline, snake_case}; + +pub trait ProverBuilder { + fn create_prover_hpp(&mut self, name: &str); + + fn create_prover_cpp( + &mut self, + name: &str, + commitment_polys: &[String], + lookup_names: &[String], + ); +} + +impl ProverBuilder for BBFiles { + fn create_prover_hpp(&mut self, name: &str) { + let include_str = includes_hpp(&snake_case(name)); + + let prover_hpp = format!(" + {include_str} + namespace bb {{ + + class {name}Prover {{ + + using Flavor = {name}Flavor; + using FF = Flavor::FF; + using PCS = Flavor::PCS; + using PCSCommitmentKey = Flavor::CommitmentKey; + using ProvingKey = Flavor::ProvingKey; + using Polynomial = Flavor::Polynomial; + using ProverPolynomials = Flavor::ProverPolynomials; + using CommitmentLabels = Flavor::CommitmentLabels; + using Transcript = Flavor::Transcript; + + public: + explicit {name}Prover(std::shared_ptr input_key, std::shared_ptr commitment_key); + + void execute_preamble_round(); + void execute_wire_commitments_round(); + void execute_log_derivative_inverse_round(); + void execute_relation_check_rounds(); + void execute_zeromorph_rounds(); + + HonkProof export_proof(); + HonkProof construct_proof(); + + std::shared_ptr transcript = std::make_shared(); + + std::vector public_inputs; + + bb::RelationParameters relation_parameters; + + std::shared_ptr key; + + // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). + ProverPolynomials prover_polynomials; + + CommitmentLabels commitment_labels; + typename Flavor::WitnessCommitments witness_commitments; + + Polynomial quotient_W; + + SumcheckOutput sumcheck_output; + + std::shared_ptr commitment_key; + + using ZeroMorph = ZeroMorphProver_; + + private: + HonkProof proof; + }}; + + }} // namespace bb + + "); + self.write_file( + &self.prover, + &format!("{}_prover.hpp", snake_case(name)), + &prover_hpp, + ); + } + + /// Create the prover cpp file + /// + /// Committed polys are included as we manually unroll all commitments, as we do not commit to everything + fn create_prover_cpp( + &mut self, + name: &str, + commitment_polys: &[String], + lookup_names: &[String], + ) { + let include_str = includes_cpp(&snake_case(name)); + + let polynomial_commitment_phase = create_commitments_phase(commitment_polys); + + let (call_log_derivative_phase, log_derivative_inverse_phase): (String, String) = + if lookup_names.is_empty() { + ("".to_owned(), "".to_owned()) + } else { + ( + "execute_log_derivative_inverse_round();".to_owned(), + create_log_derivative_inverse_round(lookup_names), + ) + }; + + let prover_cpp = format!(" + {include_str} + + namespace bb {{ + + using Flavor = {name}Flavor; + using FF = Flavor::FF; + + /** + * Create {name}Prover from proving key, witness and manifest. + * + * @param input_key Proving key. + * @param input_manifest Input manifest + * + * @tparam settings Settings class. + * */ + {name}Prover::{name}Prover(std::shared_ptr input_key, + std::shared_ptr commitment_key) + : key(input_key) + , commitment_key(commitment_key) + {{ + for (auto [prover_poly, key_poly] : zip_view(prover_polynomials.get_unshifted(), key->get_all())) {{ + ASSERT(bb::flavor_get_label(prover_polynomials, prover_poly) == + bb::flavor_get_label(*key, key_poly)); + prover_poly = key_poly.share(); + }} + for (auto [prover_poly, key_poly] : zip_view(prover_polynomials.get_shifted(), key->get_to_be_shifted())) {{ + ASSERT(bb::flavor_get_label(prover_polynomials, prover_poly) == + bb::flavor_get_label(*key, key_poly) + \"_shift\"); + prover_poly = key_poly.shifted(); + }} + }} + + + /** + * @brief Add circuit size, public input size, and public inputs to transcript + * + */ + void {name}Prover::execute_preamble_round() + {{ + const auto circuit_size = static_cast(key->circuit_size); + + transcript->send_to_verifier(\"circuit_size\", circuit_size); + }} + + /** + * @brief Compute commitments to all of the witness wires (apart from the logderivative inverse wires) + * + */ + void {name}Prover::execute_wire_commitments_round() + {{ + + {polynomial_commitment_phase} + + }} + + void {name}Prover::execute_log_derivative_inverse_round() + {{ + + {log_derivative_inverse_phase} + }} + + /** + * @brief Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all evaluations at u being calculated. + * + */ + void {name}Prover::execute_relation_check_rounds() + {{ + using Sumcheck = SumcheckProver; + + auto sumcheck = Sumcheck(key->circuit_size, transcript); + + FF alpha = transcript->template get_challenge(\"Sumcheck:alpha\"); + std::vector gate_challenges(numeric::get_msb(key->circuit_size)); + + for (size_t idx = 0; idx < gate_challenges.size(); idx++) {{ + gate_challenges[idx] = transcript->template get_challenge(\"Sumcheck:gate_challenge_\" + std::to_string(idx)); + }} + sumcheck_output = sumcheck.prove(prover_polynomials, relation_parameters, alpha, gate_challenges); + }} + + + /** + * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck + * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. + * + * */ + void {name}Prover::execute_zeromorph_rounds() + {{ + ZeroMorph::prove(prover_polynomials.get_unshifted(), + prover_polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript); + + }} + + + HonkProof {name}Prover::export_proof() + {{ + proof = transcript->proof_data; + return proof; + }} + + HonkProof {name}Prover::construct_proof() + {{ + // Add circuit size public input size and public inputs to transcript. + execute_preamble_round(); + + // Compute wire commitments + execute_wire_commitments_round(); + + // Compute sorted list accumulator and commitment + {call_log_derivative_phase} + + // Fiat-Shamir: alpha + // Run sumcheck subprotocol. + execute_relation_check_rounds(); + + // Fiat-Shamir: rho, y, x, z + // Execute Zeromorph multilinear PCS + execute_zeromorph_rounds(); + + return export_proof(); + }} + + }} // namespace bb + + + "); + + self.write_file( + &self.prover, + &format!("{}_prover.cpp", snake_case(name)), + &prover_cpp, + ); + } +} + +fn includes_hpp(name: &str) -> String { + format!( + " +#pragma once +#include \"barretenberg/commitment_schemes/zeromorph/zeromorph.hpp\" +#include \"barretenberg/plonk/proof_system/types/proof.hpp\" +#include \"barretenberg/relations/relation_parameters.hpp\" +#include \"barretenberg/sumcheck/sumcheck_output.hpp\" +#include \"barretenberg/transcript/transcript.hpp\" + +#include \"barretenberg/vm/generated/{name}_flavor.hpp\" + + " + ) +} + +fn includes_cpp(name: &str) -> String { + format!( + " + + #include \"{name}_prover.hpp\" + #include \"barretenberg/commitment_schemes/claim.hpp\" + #include \"barretenberg/commitment_schemes/commitment_key.hpp\" + #include \"barretenberg/honk/proof_system/logderivative_library.hpp\" + #include \"barretenberg/honk/proof_system/permutation_library.hpp\" + #include \"barretenberg/plonk_honk_shared/library/grand_product_library.hpp\" + #include \"barretenberg/polynomials/polynomial.hpp\" + #include \"barretenberg/relations/lookup_relation.hpp\" + #include \"barretenberg/relations/permutation_relation.hpp\" + #include \"barretenberg/sumcheck/sumcheck.hpp\" + " + ) +} + +/// Commitment Transform +/// +/// Produces code to perform kzg commitment, then stores in the witness_commitments struct +fn commitment_transform(name: &String) -> String { + format!("witness_commitments.{name} = commitment_key->commit(key->{name});") +} + +/// Send to Verifier Transform +/// +/// Sends commitment produces in commitment_transform to the verifier +fn send_to_verifier_transform(name: &String) -> String { + format!("transcript->send_to_verifier(commitment_labels.{name}, witness_commitments.{name});") +} + +fn create_commitments_phase(polys_to_commit_to: &[String]) -> String { + let all_commit_operations = map_with_newline(polys_to_commit_to, commitment_transform); + let send_to_verifier_operations = + map_with_newline(polys_to_commit_to, send_to_verifier_transform); + + format!( + " + // Commit to all polynomials (apart from logderivative inverse polynomials, which are committed to in the later logderivative phase) + {all_commit_operations} + + // Send all commitments to the verifier + {send_to_verifier_operations} + " + ) +} + +fn create_log_derivative_inverse_round(lookup_operations: &[String]) -> String { + let all_commit_operations = map_with_newline(lookup_operations, commitment_transform); + let send_to_verifier_operations = + map_with_newline(lookup_operations, send_to_verifier_transform); + + format!( + " + auto [beta, gamm] = transcript->template get_challenges(\"beta\", \"gamma\"); + relation_parameters.beta = beta; + relation_parameters.gamma = gamm; + + key->compute_logderivative_inverses(relation_parameters); + + // Commit to all logderivative inverse polynomials + {all_commit_operations} + + // Send all commitments to the verifier + {send_to_verifier_operations} + " + ) +} diff --git a/bb-pilcom/bb-pil-backend/src/relation_builder.rs b/bb-pilcom/bb-pil-backend/src/relation_builder.rs new file mode 100644 index 000000000000..cfae7c85092a --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/relation_builder.rs @@ -0,0 +1,562 @@ +use itertools::Itertools; +use powdr_ast::analyzed::AlgebraicBinaryOperation; +use powdr_ast::analyzed::AlgebraicExpression; +use powdr_ast::analyzed::AlgebraicUnaryOperation; +use powdr_ast::analyzed::Identity; +use powdr_ast::analyzed::{ + AlgebraicBinaryOperator, AlgebraicExpression as Expression, AlgebraicUnaryOperator, + IdentityKind, +}; +use powdr_ast::parsed::SelectedExpressions; +use std::collections::HashMap; +use std::collections::HashSet; +use std::path::Path; + +use powdr_number::{BigUint, DegreeType, FieldElement}; + +use crate::file_writer::BBFiles; +use crate::utils::{capitalize, map_with_newline, snake_case}; + +/// Returned back to the vm builder from the create_relations call +pub struct RelationOutput { + /// A list of the names of the created relations + pub relations: Vec, + /// A list of the names of all of the 'used' shifted polys + pub shifted_polys: Vec, +} + +/// Each created bb Identity is passed around with its degree so as needs to be manually +/// provided for sumcheck +type BBIdentity = (DegreeType, String); + +pub trait RelationBuilder { + /// Create Relations + /// + /// Takes in the ast ( for relations ), groups each of them by file, and then + /// calls 'create relation' for each + /// + /// Relation output is passed back to the caller as the prover requires both: + /// - The shifted polys + /// - The names of the relations files created + fn create_relations( + &self, + root_name: &str, + identities: &[Identity>], + ) -> RelationOutput; + + /// Create Relation + /// + /// Name and root name are required to determine the file path, e.g. it will be in the bberg/relations/generated + /// followed by /root_name/name + /// - root name should be the name provided with the --name flag + /// - name will be a pil namespace + /// + /// - Identities are the identities that will be used to create the relations, they are generated within create_relations + /// - row_type contains all of the columns that the relations namespace touches. + fn create_relation( + &self, + root_name: &str, + name: &str, + sub_relations: &[String], + identities: &[BBIdentity], + row_type: &str, + labels_lookup: String, + ); + + /// Declare views + /// + /// Declare views is a macro that generates a reference for each of the columns + /// This reference will be a span into a sumcheck related object, it must be declared for EACH sub-relation + /// as the sumcheck object is sensitive to the degree of the relation. + fn create_declare_views(&self, name: &str, all_cols_and_shifts: &[String]); +} + +impl RelationBuilder for BBFiles { + fn create_relations( + &self, + file_name: &str, + analyzed_identities: &[Identity>], + ) -> RelationOutput { + // Group relations per file + let grouped_relations: HashMap>>> = + group_relations_per_file(analyzed_identities); + let mut relations = grouped_relations.keys().cloned().collect_vec(); + relations.sort(); + + // Contains all of the rows in each relation, will be useful for creating composite builder types + let mut all_rows: HashMap = HashMap::new(); + let mut shifted_polys: Vec = Vec::new(); + + // ----------------------- Create the relation files ----------------------- + for (relation_name, analyzed_idents) in grouped_relations.iter() { + let IdentitiesOutput { + subrelations, + identities, + collected_cols, + collected_shifts, + expression_labels, + } = create_identities(file_name, analyzed_idents); + + // TODO: This can probably be moved into the create_identities function + let row_type = create_row_type(&capitalize(relation_name), &collected_cols); + + // Aggregate all shifted polys + shifted_polys.extend(collected_shifts); + // Aggregate all rows + all_rows.insert(relation_name.to_owned(), row_type.clone()); + + let labels_lookup = create_relation_labels(relation_name, expression_labels); + self.create_relation( + file_name, + relation_name, + &subrelations, + &identities, + &row_type, + labels_lookup, + ); + } + + shifted_polys.sort(); + relations.sort(); + + RelationOutput { + relations, + shifted_polys, + } + } + + fn create_relation( + &self, + root_name: &str, + name: &str, + sub_relations: &[String], + identities: &[BBIdentity], + row_type: &str, + labels_lookup: String, + ) { + let includes = relation_includes(); + let class_boilerplate = relation_class_boilerplate(name, sub_relations, identities); + let export = get_export(name); + + let relations = format!( + "{includes} +namespace bb::{root_name}_vm {{ + +{row_type}; + +{labels_lookup} + +{class_boilerplate} + +{export} + + }}" + ); + + self.write_file( + &format!("{}/{}", &self.rel, snake_case(root_name)), + &format!("{}.hpp", snake_case(name)), + &relations, + ); + } + + fn create_declare_views(&self, name: &str, all_cols_and_shifts: &[String]) { + let view_transformation = + |name: &String| format!("[[maybe_unused]] auto {name} = View(new_term.{name}); \\"); + let make_view_per_row = map_with_newline(all_cols_and_shifts, view_transformation); + + let declare_views = format!( + " + #define {name}_DECLARE_VIEWS(index) \\ + using Accumulator = typename std::tuple_element::type; \\ + using View = typename Accumulator::View; \\ + {make_view_per_row} + + + " + ); + + self.write_file( + &format!("{}/{}", &self.rel, snake_case(name)), + "declare_views.hpp", + &declare_views, + ); + } +} + +/// Group relations per file +/// +/// The compiler returns all relations in one large vector, however we want to distinguish +/// which files .pil files the relations belong to for later code gen +/// +/// Say we have two files foo.pil and bar.pil +/// foo.pil contains the following relations: +/// - foo1 +/// - foo2 +/// bar.pil contains the following relations: +/// - bar1 +/// - bar2 +/// +/// This function will return a hashmap with the following structure: +/// { +/// "foo": [foo1, foo2], +/// "bar": [bar1, bar2] +/// } +/// +/// This allows us to generate a relation.hpp file containing ONLY the relations for that .pil file +fn group_relations_per_file( + identities: &[Identity>], +) -> HashMap>>> { + identities.iter().cloned().into_group_map_by(|identity| { + identity + .source + .file_name + .as_ref() + .and_then(|file_name| Path::new(file_name.as_ref()).file_stem()) + .map(|stem| stem.to_string_lossy().into_owned()) + .unwrap_or_default() + .replace(".pil", "") + }) +} + +fn relation_class_boilerplate( + name: &str, + sub_relations: &[String], + identities: &[BBIdentity], +) -> String { + // We add one to all degrees because we have an extra scaling factor + let degrees = identities.iter().map(|(d, _)| d + 1).collect(); + let degree_boilerplate = get_degree_boilerplate(degrees); + let relation_code = get_relation_code(sub_relations); + format!( + "template class {name}Impl {{ + public: + using FF = FF_; + + {degree_boilerplate} + + {relation_code} +}};", + ) +} + +fn get_export(name: &str) -> String { + format!( + "template using {name} = Relation<{name}Impl>;", + name = name + ) +} + +fn get_relation_code(ids: &[String]) -> String { + let mut relation_code = r#" + template + void static accumulate( + ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor + ){ + + "# + .to_owned(); + for id in ids { + relation_code.push_str(&format!("{}\n", id)); + } + relation_code.push_str("}\n"); + relation_code +} + +fn get_degree_boilerplate(degrees: Vec) -> String { + let num_degrees = degrees.len(); + + let mut degree_boilerplate = format!( + "static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{{\n" + ); + for degree in °rees { + degree_boilerplate.push_str(&format!(" {},\n", degree)); + } + degree_boilerplate.push_str("};"); + + degree_boilerplate +} + +// The include statements required for a new relation file +fn relation_includes() -> &'static str { + r#" +#pragma once +#include "../../relation_parameters.hpp" +#include "../../relation_types.hpp" +#include "./declare_views.hpp" +"# +} + +// Each vm will need to have a row which is a combination of all of the witness columns +pub(crate) fn create_row_type(name: &str, all_rows: &[String]) -> String { + let row_transformation = |row: &_| format!(" FF {row} {{}};"); + let all_annotated = map_with_newline(all_rows, row_transformation); + + format!( + "template struct {name}Row {{ + {} + + [[maybe_unused]] static std::vector names(); + }}", + all_annotated, + ) +} + +fn create_identity( + expression: &SelectedExpressions>, + collected_cols: &mut HashSet, + collected_public_identities: &mut HashSet, +) -> Option { + // We want to read the types of operators and then create the appropiate code + + if let Some(expr) = &expression.selector { + let x = craft_expression(expr, collected_cols, collected_public_identities); + log::trace!("expression {:?}", x); + Some(x) + } else { + None + } +} + +// TODO: replace the preamble with a macro so the code looks nicer +fn create_subrelation(index: usize, preamble: String, identity: &mut BBIdentity) -> String { + // \\\ + let id = &identity.1; + + format!( + "//Contribution {index} + {{\n{preamble} + + auto tmp = {id}; + tmp *= scaling_factor; + std::get<{index}>(evals) += tmp; +}}", + ) +} + +fn craft_expression( + expr: &Expression, + // TODO: maybe make state? + collected_cols: &mut HashSet, + collected_public_identities: &mut HashSet, +) -> BBIdentity { + let var_name = match expr { + Expression::Number(n) => { + let number: BigUint = n.to_arbitrary_integer(); + if number.bit_len() < 32 { + return (1, format!("FF({})", number)); + } + if number.bit_len() < 64 { + return (1, format!("FF({}UL)", number)); + } + if number.bit_len() < 256 { + let bytes = number.to_be_bytes(); + let padding_len = 32 - bytes.len(); + + let mut padded_bytes = vec![0; padding_len]; + padded_bytes.extend_from_slice(&bytes); + + let mut chunks: Vec = padded_bytes + .chunks(8) + .map(|chunk| u64::from_be_bytes(chunk.try_into().unwrap())) + .collect(); + + chunks.resize(4, 0); + return ( + 1, + format!( + "FF(uint256_t{{{}UL, {}UL, {}UL, {}UL}})", + chunks[3], chunks[2], chunks[1], chunks[0], + ), + ); + } + unimplemented!("{:?}", expr); + } + Expression::Reference(polyref) => { + let mut poly_name = polyref.name.replace('.', "_").to_string(); + if polyref.next { + // NOTE: Naive algorithm to collect all shifted polys + poly_name = format!("{}_shift", poly_name); + } + collected_cols.insert(poly_name.clone()); + (1, poly_name) + } + Expression::BinaryOperation(AlgebraicBinaryOperation { + left: lhe, + op, + right: rhe, + }) => { + let (ld, lhs) = craft_expression(lhe, collected_cols, collected_public_identities); + let (rd, rhs) = craft_expression(rhe, collected_cols, collected_public_identities); + + let degree = std::cmp::max(ld, rd); + match op { + AlgebraicBinaryOperator::Add => match lhe.as_ref() { + // BBerg hack, we do not want a field on the lhs of an expression + Expression::Number(_) => (degree, format!("({} + {})", rhs, lhs)), + _ => (degree, format!("({} + {})", lhs, rhs)), + }, + AlgebraicBinaryOperator::Sub => match lhe.as_ref() { + // BBerg hack, we do not want a field on the lhs of an expression + Expression::Number(_) => (degree, format!("(-{} + {})", rhs, lhs)), + _ => (degree, format!("({} - {})", lhs, rhs)), + }, + AlgebraicBinaryOperator::Mul => match lhe.as_ref() { + // BBerg hack, we do not want a field on the lhs of an expression + Expression::Number(_) => (ld + rd, format!("({} * {})", rhs, lhs)), + _ => (ld + rd, format!("({} * {})", lhs, rhs)), + }, + _ => unimplemented!("{:?}", expr), + } + } + Expression::UnaryOperation(AlgebraicUnaryOperation { + op: operator, + expr: expression, + }) => match operator { + AlgebraicUnaryOperator::Minus => { + let (d, e) = + craft_expression(expression, collected_cols, collected_public_identities); + (d, format!("-{}", e)) + } + }, + // TODO: for now we do nothing with calls to public identities + // These probably can be implemented as some form of copy, however im not sure how we are going to process these down the line + Expression::PublicReference(name) => { + // We collect them for now to warn the user what is going on + collected_public_identities.insert(name.clone()); + (1, "FF(0)".to_string()) + } + // Note: challenges are not being used in our current pil construction + Expression::Challenge(_) => unimplemented!("{:?}", expr), + }; + var_name +} + +pub struct IdentitiesOutput { + subrelations: Vec, + identities: Vec, + collected_cols: Vec, + collected_shifts: Vec, + expression_labels: HashMap, +} + +pub(crate) fn create_identities( + file_name: &str, + identities: &[Identity>], +) -> IdentitiesOutput { + // We only want the expressions for now + // When we have a poly type, we only need the left side of it + let ids = identities + .iter() + .filter(|identity| identity.kind == IdentityKind::Polynomial) + .collect::>(); + + let mut identities = Vec::new(); + let mut subrelations = Vec::new(); + let mut expression_labels: HashMap = HashMap::new(); // Each relation can be given a label, this label can be assigned here + let mut collected_cols: HashSet = HashSet::new(); + let mut collected_public_identities: HashSet = HashSet::new(); + + // Collect labels for each identity + // TODO: shite + for (i, id) in ids.iter().enumerate() { + if let Some(label) = &id.attribute { + expression_labels.insert(i, label.clone()); + } + } + + let expressions = ids.iter().map(|id| id.left.clone()).collect::>(); + for (i, expression) in expressions.iter().enumerate() { + let relation_boilerplate = format!( + "{file_name}_DECLARE_VIEWS({i}); + ", + ); + + // TODO: collected pattern is shit + let mut identity = create_identity( + expression, + &mut collected_cols, + &mut collected_public_identities, + ) + .unwrap(); + let subrelation = create_subrelation(i, relation_boilerplate, &mut identity); + + identities.push(identity); + + subrelations.push(subrelation); + } + + // Print a warning to the user about usage of public identities + if !collected_public_identities.is_empty() { + log::warn!( + "Public Identities are not supported yet in codegen, however some were collected" + ); + log::warn!("Public Identities: {:?}", collected_public_identities); + } + + let mut collected_cols: Vec = collected_cols.drain().collect(); + let mut collected_shifts: Vec = collected_cols + .clone() + .iter() + .filter_map(|col| { + if col.ends_with("shift") { + Some(col.clone()) + } else { + None + } + }) + .collect(); + + collected_cols.sort(); + collected_shifts.sort(); + + IdentitiesOutput { + subrelations, + identities, + collected_cols, + collected_shifts, + expression_labels, + } +} + +/// Relation labels +/// +/// To view relation labels we create a sparse switch that contains all of the collected labels +/// Whenever there is a failure, we can lookup into this mapping +/// +/// Note: this mapping will never be that big, so we are quite naive in implementation +/// It should be able to be called from else where with relation_name::get_relation_label +fn create_relation_labels(relation_name: &str, labels: HashMap) -> String { + // Sort labels by the index + let label_transformation = |(index, label)| { + format!( + "case {index}: + return \"{label}\"; + " + ) + }; + + // Sort the labels by their index + let mut sorted_labels: Vec<(usize, String)> = labels.into_iter().collect(); + sorted_labels.sort_by(|a, b| a.0.cmp(&b.0)); + + let switch_statement: String = sorted_labels + .into_iter() + .map(label_transformation) + .collect::>() + .join("\n"); + + format!( + " + inline std::string get_relation_label_{relation_name}(int index) {{ + switch (index) {{ + {switch_statement} + }} + return std::to_string(index); + }} + " + ) +} diff --git a/bb-pilcom/bb-pil-backend/src/utils.rs b/bb-pilcom/bb-pil-backend/src/utils.rs new file mode 100644 index 000000000000..f84dfac2f1d9 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/utils.rs @@ -0,0 +1,145 @@ +use itertools::Itertools; + +/// Get Relations Imports +/// +/// We may have multiple relation files in the generated foler +/// This method will return all of the imports for the relation header files +pub fn get_relations_imports(name: &str, relations: &[String], permutations: &[String]) -> String { + let all_relations = flatten(&[relations.to_vec(), permutations.to_vec()]); + let transformation = |relation_name: &_| { + format!("#include \"barretenberg/relations/generated/{name}/{relation_name}.hpp\"") + }; + + map_with_newline(&all_relations, transformation) +} + +/// Sanitize Names +/// +/// Column titles that we get from pil contain . to distinguish which pil namespace they belong to +/// We need to replace these with _ to make them valid C++ identifiers +pub fn sanitize_name(string: &str) -> String { + string.replace(['.', '[', ']'], "_") +} + +/// Capitalize +pub fn capitalize(s: &str) -> String { + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +/// Map With Newline +/// This utility function is used all over the codegen pipeline +/// It takes a list, usually the names of columns in an execution trace and applies a string transformation "op" +/// to each element in the list +pub fn map_with_newline(list: &[String], op: Func) -> String +where + Func: Fn(&String) -> String, +{ + transform_map(list, op).join("\n") +} + +/// Collect Col +/// +/// Transforms columns from powdr representation ( where the witnesses are linked ) +/// Into a version where we just keep the columns +/// As this is all we are about +pub fn collect_col(list: &[String], op: Func) -> Vec +where + Func: Fn(&String) -> String, +{ + list.iter().map(op).collect::>() +} + +/// Transform Map +/// +/// Apply a transformation to a list of strings +pub fn transform_map(list: &[String], op: Func) -> Vec +where + Func: Fn(&String) -> String, +{ + list.iter().map(op).collect::>() +} + +/// Flatten +/// +/// Returns a flattened concatenation of the input arrays +pub fn flatten(list: &[Vec]) -> Vec { + let arr = list.iter().cloned(); + arr.into_iter().flatten().collect() +} + +/// Create Forward As Tuple +/// +/// Helper function to create a forward as tuple cpp statement +pub fn create_forward_as_tuple(settings: &[String]) -> String { + let adjusted = settings.iter().map(|col| format!("in.{col}")).join(",\n"); + format!( + " + return std::forward_as_tuple( + {} + ); + ", + adjusted + ) +} + +// TODO: may make sense to move the below around a bit +pub fn create_get_const_entities(settings: &[String]) -> String { + let forward = create_forward_as_tuple(settings); + format!( + " + template static inline auto get_const_entities(const AllEntities& in) {{ + {forward} + }} + " + ) +} + +pub fn create_get_nonconst_entities(settings: &[String]) -> String { + let forward = create_forward_as_tuple(settings); + format!( + " + template static inline auto get_nonconst_entities(AllEntities& in) {{ + {forward} + }} + " + ) +} + +/// Snake Case +/// +/// Transform camel case string into snake case, such as: RedFlower --> red_flower +pub fn snake_case(input: &str) -> String { + let mut result = String::new(); + + // Handle the first character + if input.is_empty() { + return result; // Empty input + } + let mut first_char = input.chars().next().unwrap(); + if first_char.is_uppercase() { + first_char = first_char.to_ascii_lowercase(); + } + result.push(first_char); + + // Process remaining characters + for ch in input.chars().skip(1) { + if ch.is_uppercase() { + result.push('_'); + result.push(ch.to_ascii_lowercase()); + } else { + result.push(ch); + } + } + + result +} + +pub fn sort_cols(cols: &[String]) -> Vec { + let mut cols = cols.to_vec(); + cols.sort(); + cols +} diff --git a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs new file mode 100644 index 000000000000..710b9cafadc7 --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs @@ -0,0 +1,286 @@ +use crate::{ + file_writer::BBFiles, + utils::{map_with_newline, snake_case}, +}; + +pub trait VerifierBuilder { + fn create_verifier_cpp( + &mut self, + name: &str, + witness: &[String], + inverses: &[String], + public_cols: &[(String, usize)], + ); + + fn create_verifier_hpp(&mut self, name: &str, public_cols: &[(String, usize)]); +} + +impl VerifierBuilder for BBFiles { + fn create_verifier_cpp( + &mut self, + name: &str, + witness: &[String], + inverses: &[String], + public_cols: &[(String, usize)], + ) { + let include_str = includes_cpp(&snake_case(name)); + + let wire_transformation = |n: &String| { + format!( + "commitments.{n} = transcript->template receive_from_prover(commitment_labels.{n});" + ) + }; + let wire_commitments = map_with_newline(witness, wire_transformation); + + let has_public_input_columns = !public_cols.is_empty(); + let has_inverses = !inverses.is_empty(); + + let get_inverse_challenges = if has_inverses { + " + auto [beta, gamm] = transcript->template get_challenges(\"beta\", \"gamma\"); + relation_parameters.beta = beta; + relation_parameters.gamma = gamm; + " + .to_string() + } else { + "".to_owned() + }; + + let verify_proof_function_declaration: String = if has_public_input_columns { + format!("bool {name}Verifier::verify_proof(const HonkProof& proof, const std::vector>& public_inputs)") + } else { + format!("bool {name}Verifier::verify_proof(const HonkProof& proof)") + }; + + let public_inputs_column_transformation = + |public_inputs_column_name: &String, idx: usize| { + format!( + " + FF {public_inputs_column_name}_evaluation = evaluate_public_input_column(public_inputs[{idx}], circuit_size, multivariate_challenge); + if ({public_inputs_column_name}_evaluation != claimed_evaluations.{public_inputs_column_name}) {{ + return false; + }} + " + ) + }; + + let (public_inputs_check, evaluate_public_inputs) = if has_public_input_columns { + let inputs_check = public_cols + .iter() + .map(|(col_name, idx)| public_inputs_column_transformation(col_name, *idx)) + .collect::(); + + let evaluate_public_inputs = format!( + " + + using FF = {name}Flavor::FF; + + // Evaluate the given public input column over the multivariate challenge points + [[maybe_unused]] inline FF evaluate_public_input_column(const std::vector& points, const size_t circuit_size, std::vector challenges) {{ + + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6361): we pad the points to the circuit size in order to get the correct evaluation. + // This is not efficient, and will not be valid in production. + std::vector new_points(circuit_size, 0); + std::copy(points.begin(), points.end(), new_points.data()); + + Polynomial polynomial(new_points); + return polynomial.evaluate_mle(challenges); + }} + " + ); + + (inputs_check, evaluate_public_inputs) + } else { + ("".to_owned(), "".to_owned()) + }; + + let inverse_commitments = map_with_newline(inverses, wire_transformation); + + let ver_cpp = format!(" +{include_str} + + namespace bb {{ + + + {name}Verifier::{name}Verifier(std::shared_ptr verifier_key) + : key(verifier_key) + {{}} + + {name}Verifier::{name}Verifier({name}Verifier&& other) noexcept + : key(std::move(other.key)) + , pcs_verification_key(std::move(other.pcs_verification_key)) + {{}} + + {name}Verifier& {name}Verifier::operator=({name}Verifier&& other) noexcept + {{ + key = other.key; + pcs_verification_key = (std::move(other.pcs_verification_key)); + commitments.clear(); + return *this; + }} + + {evaluate_public_inputs} + + + /** + * @brief This function verifies an {name} Honk proof for given program settings. + * + */ + {verify_proof_function_declaration} + {{ + using Flavor = {name}Flavor; + using FF = Flavor::FF; + using Commitment = Flavor::Commitment; + // using PCS = Flavor::PCS; + // using ZeroMorph = ZeroMorphVerifier_; + using VerifierCommitments = Flavor::VerifierCommitments; + using CommitmentLabels = Flavor::CommitmentLabels; + + RelationParameters relation_parameters; + + transcript = std::make_shared(proof); + + VerifierCommitments commitments {{ key }}; + CommitmentLabels commitment_labels; + + const auto circuit_size = transcript->template receive_from_prover(\"circuit_size\"); + + if (circuit_size != key->circuit_size) {{ + return false; + }} + + // Get commitments to VM wires + {wire_commitments} + + {get_inverse_challenges} + + // Get commitments to inverses + {inverse_commitments} + + // Execute Sumcheck Verifier + const size_t log_circuit_size = numeric::get_msb(circuit_size); + auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); + + FF alpha = transcript->template get_challenge(\"Sumcheck:alpha\"); + + auto gate_challenges = std::vector(log_circuit_size); + for (size_t idx = 0; idx < log_circuit_size; idx++) {{ + gate_challenges[idx] = transcript->template get_challenge(\"Sumcheck:gate_challenge_\" + std::to_string(idx)); + }} + + auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = + sumcheck.verify(relation_parameters, alpha, gate_challenges); + + // If Sumcheck did not verify, return false + if (sumcheck_verified.has_value() && !sumcheck_verified.value()) {{ + return false; + }} + + // Public columns evaluation checks + {public_inputs_check} + + // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the + // unrolled protocol. + // NOTE: temporarily disabled - facing integration issues + // auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), + // commitments.get_to_be_shifted(), + // claimed_evaluations.get_unshifted(), + // claimed_evaluations.get_shifted(), + // multivariate_challenge, + // transcript); + + // auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); + // return sumcheck_verified.value() && verified; + return sumcheck_verified.value(); + }} + + + }} // namespace bb + + + "); + + self.write_file( + &self.prover, + &format!("{}_verifier.cpp", snake_case(name)), + &ver_cpp, + ); + } + + fn create_verifier_hpp(&mut self, name: &str, public_cols: &[(String, usize)]) { + let include_str = include_hpp(&snake_case(name)); + + // If there are public input columns, then the generated verifier must take them in as an argument for the verify_proof + let verify_proof = if !public_cols.is_empty() { + "bool verify_proof(const HonkProof& proof, const std::vector>& public_inputs);" + .to_string() + } else { + "bool verify_proof(const HonkProof& proof);".to_owned() + }; + + let ver_hpp = format!( + " +{include_str} + + namespace bb {{ + class {name}Verifier {{ + using Flavor = {name}Flavor; + using FF = Flavor::FF; + using Commitment = Flavor::Commitment; + using VerificationKey = Flavor::VerificationKey; + using VerifierCommitmentKey = Flavor::VerifierCommitmentKey; + using Transcript = Flavor::Transcript; + + public: + explicit {name}Verifier(std::shared_ptr verifier_key = nullptr); + {name}Verifier({name}Verifier&& other) noexcept; + {name}Verifier(const {name}Verifier& other) = delete; + + {name}Verifier& operator=(const {name}Verifier& other) = delete; + {name}Verifier& operator=({name}Verifier&& other) noexcept; + + {verify_proof} + + std::shared_ptr key; + std::map commitments; + std::shared_ptr pcs_verification_key; + std::shared_ptr transcript; + }}; + + }} // namespace bb + + + " + ); + + self.write_file( + &self.prover, + &format!("{}_verifier.hpp", snake_case(name)), + &ver_hpp, + ); + } +} + +fn include_hpp(name: &str) -> String { + format!( + " +#pragma once +#include \"barretenberg/plonk/proof_system/types/proof.hpp\" +#include \"barretenberg/sumcheck/sumcheck.hpp\" +#include \"barretenberg/vm/generated/{name}_flavor.hpp\" +#include \"barretenberg/vm/avm_trace/constants.hpp\" +" + ) +} + +fn includes_cpp(name: &str) -> String { + format!( + " + #include \"./{name}_verifier.hpp\" + #include \"barretenberg/commitment_schemes/zeromorph/zeromorph.hpp\" + #include \"barretenberg/numeric/bitop/get_msb.hpp\" + #include \"barretenberg/polynomials/polynomial.hpp\" + #include \"barretenberg/transcript/transcript.hpp\" + " + ) +} diff --git a/bb-pilcom/bb-pil-backend/src/vm_builder.rs b/bb-pilcom/bb-pil-backend/src/vm_builder.rs new file mode 100644 index 000000000000..8707ef40a45b --- /dev/null +++ b/bb-pilcom/bb-pil-backend/src/vm_builder.rs @@ -0,0 +1,236 @@ +use powdr_ast::analyzed::Analyzed; +use powdr_number::FieldElement; + +use crate::circuit_builder::CircuitBuilder; +use crate::composer_builder::ComposerBuilder; +use crate::file_writer::BBFiles; +use crate::flavor_builder::FlavorBuilder; +use crate::lookup_builder::get_counts_from_lookups; +use crate::lookup_builder::get_inverses_from_lookups; +use crate::lookup_builder::Lookup; +use crate::lookup_builder::LookupBuilder; +use crate::permutation_builder::get_inverses_from_permutations; +use crate::permutation_builder::Permutation; +use crate::permutation_builder::PermutationBuilder; +use crate::prover_builder::ProverBuilder; +use crate::relation_builder::RelationBuilder; +use crate::relation_builder::RelationOutput; +use crate::utils::collect_col; +use crate::utils::flatten; +use crate::utils::sanitize_name; +use crate::utils::sort_cols; +use crate::utils::transform_map; +use crate::verifier_builder::VerifierBuilder; + +/// All of the combinations of columns that are used in a bberg flavor file +struct ColumnGroups { + /// fixed or constant columns in pil -> will be found in vk + fixed: Vec, + /// witness or commit columns in pil -> will be found in proof + witness: Vec, + /// witness or commit columns in pil, with out the inverse columns + witnesses_without_inverses: Vec, + /// fixed + witness columns without lookup inverses + all_cols_without_inverses: Vec, + /// fixed + witness columns with lookup inverses + all_cols: Vec, + /// Columns that will not be shifted + unshifted: Vec, + /// Columns that will be shifted + to_be_shifted: Vec, + /// The shifts of the columns that will be shifted + shifted: Vec, + /// fixed + witness + shifted + all_cols_with_shifts: Vec, + /// Inverses from lookups and permuations + inverses: Vec, +} + +/// Analyzed to cpp +/// +/// Converts an analyzed pil AST into a set of cpp files that can be used to generate a proof +pub fn analyzed_to_cpp( + analyzed: &Analyzed, + fixed: &[String], + witness: &[String], + public: &[String], + name: Option, +) { + // Extract public inputs information. + let mut public_inputs: Vec<(String, usize)> = public + .iter() + .enumerate() + .map(|(i, name)| (sanitize_name(name), i)) + .collect(); + public_inputs.sort_by(|a, b| a.1.cmp(&b.1)); + + // Sort fixed and witness to ensure consistent ordering + let fixed = &sort_cols(fixed); + let witness = &sort_cols(witness); + + let file_name: &str = &name.unwrap_or("Example".to_owned()); + let mut bb_files = BBFiles::default(file_name.to_owned()); + + // Inlining step to remove the intermediate poly definitions + let mut analyzed_identities = analyzed.identities_with_inlined_intermediate_polynomials(); + analyzed_identities.sort_by(|a, b| a.id.cmp(&b.id)); + + // ----------------------- Handle Standard Relation Identities ----------------------- + // We collect all references to shifts as we traverse all identities and create relation files + let RelationOutput { + relations, + shifted_polys, + } = bb_files.create_relations(file_name, &analyzed_identities); + + // ----------------------- Handle Lookup / Permutation Relation Identities ----------------------- + let permutations = bb_files.create_permutation_files(file_name, analyzed); + let lookups = bb_files.create_lookup_files(file_name, analyzed); + + // TODO: hack - this can be removed with some restructuring + let shifted_polys: Vec = shifted_polys + .clone() + .iter() + .map(|s| s.replace("_shift", "")) + .collect(); + + // Collect all column names and determine if they need a shift or not + let ColumnGroups { + fixed, + witness, + witnesses_without_inverses, + all_cols, + all_cols_without_inverses, + unshifted: _unshifted, + to_be_shifted, + shifted, + all_cols_with_shifts, + inverses, + } = get_all_col_names( + fixed, + witness, + public, + &shifted_polys, + &permutations, + &lookups, + ); + + bb_files.create_declare_views(file_name, &all_cols_with_shifts); + + // ----------------------- Create the circuit builder file ----------------------- + bb_files.create_circuit_builder_hpp( + file_name, + &relations, + &inverses, + &all_cols_without_inverses, + &all_cols, + &to_be_shifted, + &all_cols_with_shifts, + ); + + bb_files.create_circuit_builder_cpp(file_name, &all_cols); + + // ----------------------- Create the flavor file ----------------------- + bb_files.create_flavor_hpp( + file_name, + &relations, + &inverses, + &fixed, + &witness, + &all_cols, + &to_be_shifted, + &shifted, + &all_cols_with_shifts, + ); + + // ----------------------- Create the composer files ----------------------- + bb_files.create_composer_cpp(file_name); + bb_files.create_composer_hpp(file_name); + + // ----------------------- Create the Verifier files ----------------------- + bb_files.create_verifier_cpp( + file_name, + &witnesses_without_inverses, + &inverses, + &public_inputs, + ); + bb_files.create_verifier_hpp(file_name, &public_inputs); + + // ----------------------- Create the Prover files ----------------------- + bb_files.create_prover_cpp(file_name, &witnesses_without_inverses, &inverses); + bb_files.create_prover_hpp(file_name); +} + +/// Get all col names +/// +/// In the flavor file, there are a number of different groups of columns that we need to keep track of +/// This function will return all of the columns in the following groups: +/// - fixed +/// - witness +/// - all_cols +/// - unshifted +/// - to_be_shifted +/// - all_cols_with_shifts +fn get_all_col_names( + fixed: &[String], + witness: &[String], + public: &[String], + to_be_shifted: &[String], + permutations: &[Permutation], + lookups: &[Lookup], +) -> ColumnGroups { + log::info!("Getting all column names"); + + // Transformations + let sanitize = |name: &String| sanitize_name(name).to_owned(); + let append_shift = |name: &String| format!("{}_shift", *name); + + let perm_inverses = get_inverses_from_permutations(permutations); + let lookup_inverses = get_inverses_from_lookups(lookups); + let lookup_counts = get_counts_from_lookups(lookups); + + // Gather sanitized column names + let fixed_names = collect_col(fixed, sanitize); + let witness_names = collect_col(witness, sanitize); + let public_names = collect_col(public, sanitize); + let inverses = flatten(&[perm_inverses, lookup_inverses]); + let witnesses_without_inverses = flatten(&[ + public_names.clone(), + witness_names.clone(), + lookup_counts.clone(), + ]); + let witnesses_with_inverses = flatten(&[ + public_names.clone(), + witness_names, + inverses.clone(), + lookup_counts, + ]); + + // Group columns by properties + let shifted = transform_map(to_be_shifted, append_shift); + let all_cols_without_inverses: Vec = + flatten(&[fixed_names.clone(), witnesses_without_inverses.clone()]); + let all_cols: Vec = flatten(&[fixed_names.clone(), witnesses_with_inverses.clone()]); + let unshifted: Vec = flatten(&[fixed_names.clone(), witnesses_with_inverses.clone()]) + .into_iter() + .filter(|name| !shifted.contains(name)) + .collect(); + + let all_cols_with_shifts: Vec = flatten(&[ + fixed_names.clone(), + witnesses_with_inverses.clone(), + shifted.clone(), + ]); + + ColumnGroups { + fixed: fixed_names, + witness: witnesses_with_inverses, + all_cols_without_inverses, + witnesses_without_inverses, + all_cols, + unshifted, + to_be_shifted: to_be_shifted.to_vec(), + shifted, + all_cols_with_shifts, + inverses, + } +} diff --git a/bb-pilcom/bootstrap.sh b/bb-pilcom/bootstrap.sh new file mode 100755 index 000000000000..ef8e4c9c117c --- /dev/null +++ b/bb-pilcom/bootstrap.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +cargo build --release \ No newline at end of file diff --git a/bb-pilcom/cli/Cargo.toml b/bb-pilcom/cli/Cargo.toml new file mode 100644 index 000000000000..6f717a88f5fa --- /dev/null +++ b/bb-pilcom/cli/Cargo.toml @@ -0,0 +1,26 @@ + +[package] +name = "cli" +version = "0.1.0" +authors = ["Aztec Labs"] +edition = "2021" + +[[bin]] +name = "bb_pil" +path = "src/main.rs" + +[dependencies] +clap = { version = "^4.3", features = ["derive"] } +num-bigint = "0.4.3" +bb-pil-backend ={ path = "../bb-pil-backend" } + +powdr-pil-analyzer ={ path = "../powdr/pil-analyzer" } +powdr-number = { path = "../powdr/number" } +num-traits = "0.2.15" +num-integer = "0.1.45" +itertools = "^0.10" +log = "0.4.17" +rand = "0.8.5" +powdr-ast = { path = "../powdr/ast" } + + diff --git a/bb-pilcom/cli/README.md b/bb-pilcom/cli/README.md new file mode 100644 index 000000000000..9c6fd860593c --- /dev/null +++ b/bb-pilcom/cli/README.md @@ -0,0 +1,3 @@ +## BBERG PIL CLI +A small wrapper around powdr pil that only implements the parts of powdr required for direct pil -> bberg codegen + diff --git a/bb-pilcom/cli/src/main.rs b/bb-pilcom/cli/src/main.rs new file mode 100644 index 000000000000..37f6b4cfd415 --- /dev/null +++ b/bb-pilcom/cli/src/main.rs @@ -0,0 +1,52 @@ +use std::{io, path::Path}; + +use bb_pil_backend::vm_builder::analyzed_to_cpp; +use clap::Parser; +use powdr_ast::analyzed::{Analyzed, FunctionValueDefinition, Symbol}; +use powdr_number::Bn254Field; +use powdr_pil_analyzer::analyze_file; + +#[derive(Parser)] +#[command(name = "bb-pil-cli", author, version, about, long_about = None)] +struct Cli { + /// Input file + file: String, + + /// Output directory for the PIL file, json file and fixed and witness column data. + #[arg(short, long)] + #[arg(default_value_t = String::from("."))] + output_directory: String, + + /// BBerg: Name of the output file for bberg + #[arg(long)] + name: Option, +} + +fn extract_col_name(cols: Vec<&(Symbol, Option)>) -> Vec { + // Note that function val def should be none + cols.iter() + .map(|(sym, _def)| sym.absolute_name.replace(".", "_")) + .collect() +} + +fn main() -> Result<(), io::Error> { + let args = Cli::parse(); + + let file_name = args.file; + let name = args.name; + + let analyzed: Analyzed = analyze_file(Path::new(&file_name)); + + let fixed = analyzed.constant_polys_in_source_order(); + let witness = analyzed.committed_polys_in_source_order(); + let public = analyzed.public_polys_in_source_order(); + + analyzed_to_cpp( + &analyzed, + &extract_col_name(fixed), + &extract_col_name(witness), + &extract_col_name(public), + name, + ); + Ok(()) +} diff --git a/bb-pilcom/powdr b/bb-pilcom/powdr new file mode 160000 index 000000000000..c3006c11819d --- /dev/null +++ b/bb-pilcom/powdr @@ -0,0 +1 @@ +Subproject commit c3006c11819d9b53fb183c9c12a10b83481bb631 diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 35a9d71ba0c1..6fed5c9c3b5f 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -61,13 +61,6 @@ These changes were done because having the note hash exposed allowed us to not h + } ``` - -## 0.43.0 - -### [Aztec.nr] break `token.transfer()` into `transfer` and `transferFrom` -Earlier we had just one function - `transfer()` which used authwits to handle the case where a contract/user wants to transfer funds on behalf of another user. -To reduce circuit sizes and proof times, we are breaking up `transfer` and introducing a dedicated `transferFrom()` function like in the ERC20 standard. - ### [Aztec.nr] `note_getter` returns `BoundedVec` The `get_notes` and `view_notes` function no longer return an array of options (i.e. `[Option, N_NOTES]`) but instead a `BoundedVec`. This better conveys the useful property the old array had of having all notes collapsed at the beginning of the array, which allows for powerful optimizations and gate count reduction when setting the `options.limit` value. @@ -96,6 +89,12 @@ To further reduce gate count, you can iterate over `options.limit` instead of `m + for i in 0..options.limit { ``` +## 0.43.0 + +### [Aztec.nr] break `token.transfer()` into `transfer` and `transferFrom` +Earlier we had just one function - `transfer()` which used authwits to handle the case where a contract/user wants to transfer funds on behalf of another user. +To reduce circuit sizes and proof times, we are breaking up `transfer` and introducing a dedicated `transferFrom()` function like in the ERC20 standard. + ### [Aztec.nr] `options.limit` has to be constant The `limit` parameter in `NoteGetterOptions` and `NoteViewerOptions` is now required to be a compile-time constant. This allows performing loops over this value, which leads to reduced circuit gate counts when setting a `limit` value. diff --git a/iac/mainnet-fork/Dockerfile b/iac/mainnet-fork/Dockerfile deleted file mode 100644 index c0240ccadc85..000000000000 --- a/iac/mainnet-fork/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM ubuntu:focal - -# Install nginx -RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections -RUN apt-get update && apt install -y git curl nginx - -# Copy nginx config -COPY . . -COPY nginx/gateway.conf /etc/nginx/gateway.conf -COPY nginx/nginx.conf /etc/nginx/nginx.conf - -# Install foundry -RUN ./scripts/install_foundry.sh -ENV PATH="./foundry/bin:${PATH}" - -# Run anvil and nginx -EXPOSE 80 -ENTRYPOINT ["sh", "-c", "./scripts/run_nginx_anvil.sh"] \ No newline at end of file diff --git a/iac/mainnet-fork/Earthfile b/iac/mainnet-fork/Earthfile new file mode 100644 index 000000000000..fb480d1801de --- /dev/null +++ b/iac/mainnet-fork/Earthfile @@ -0,0 +1,29 @@ +VERSION 0.8 + +build: + FROM ubuntu:focal + + # Install nginx + RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections + RUN apt-get update && apt install -y git curl nginx + + # Copy nginx config + COPY . . + COPY nginx/gateway.conf /etc/nginx/gateway.conf + COPY nginx/nginx.conf /etc/nginx/nginx.conf + + # Install foundry + RUN ./scripts/install_foundry.sh + ENV PATH="./foundry/bin:${PATH}" + + # Expose port 80 + EXPOSE 80 + + # Set entrypoint + ENTRYPOINT ["sh", "-c", "./scripts/run_nginx_anvil.sh"] + +export-mainnet-fork: + FROM +build + ARG DIST_TAG="aztec-dev" + ARG ARCH + SAVE IMAGE --push spypsy/mainnet-fork:${DIST_TAG}${ARCH:+-$ARCH} diff --git a/iac/mainnet-fork/nginx/nginx.conf b/iac/mainnet-fork/nginx/nginx.conf index 0deef80724e2..5e078c52cc82 100644 --- a/iac/mainnet-fork/nginx/nginx.conf +++ b/iac/mainnet-fork/nginx/nginx.conf @@ -10,6 +10,7 @@ http { # Basic Settings ## + client_max_body_size 20M; sendfile on; tcp_nopush on; tcp_nodelay on; 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 2bdc6b0a51fc..71d69f484a6c 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -5,7 +5,7 @@ use crate::{ messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash}, keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators}, - note::{note_interface::NoteInterface, utils::compute_note_hash_for_insertion}, + note::note_interface::NoteInterface, oracle::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 48c0f5bfd69f..871f5fd7771e 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -42,7 +42,7 @@ mod test { }; use crate::{ - note::{note_header::NoteHeader, note_interface::NoteInterface, utils::compute_note_hash_for_consumption}, + note::{note_header::NoteHeader, note_interface::NoteInterface}, event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand, context::PrivateContext }; diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 501decd69a9f..4a7a3a95e945 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -2,8 +2,7 @@ use dep::protocol_types::grumpkin_point::GrumpkinPoint; use crate::context::{PrivateContext, PublicContext}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption}, - note_emission::NoteEmission + utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission }; use crate::oracle::notes::{notify_created_note, notify_nullified_note}; @@ -18,7 +17,7 @@ pub fn create_note( let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed Note::set_header(note, header); - let inner_note_hash = compute_note_hash_for_insertion(*note); + let inner_note_hash = compute_inner_note_hash(*note); // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088 let serialized_note: [Field; N] = Note::serialize_content(*note); @@ -46,9 +45,8 @@ pub fn create_note_hash_from_public( let contract_address = (*context).this_address(); // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0 let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 }; - // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed - Note::set_header(note, header); - let inner_note_hash = compute_note_hash_for_insertion(*note); + note.set_header(header); + let inner_note_hash = compute_inner_note_hash(*note); context.push_new_note_hash(inner_note_hash); } diff --git a/noir-projects/aztec-nr/aztec/src/note/utils.nr b/noir-projects/aztec-nr/aztec/src/note/utils.nr index 6c00104d6113..59843201ffb4 100644 --- a/noir-projects/aztec-nr/aztec/src/note/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/note/utils.nr @@ -1,24 +1,14 @@ use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}}; use dep::protocol_types::{ - address::AztecAddress, - constants::{ - GENERATOR_INDEX__OUTER_NULLIFIER, GENERATOR_INDEX__UNIQUE_NOTE_HASH, - GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__INNER_NOTE_HASH + constants::GENERATOR_INDEX__INNER_NOTE_HASH, + hash::{ + pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash, + compute_siloed_nullifier as compute_siloed_nullifier_from_preimage }, - hash::pedersen_hash, utils::arr_copy_slice + utils::arr_copy_slice }; -fn compute_siloed_hash(contract_address: AztecAddress, unique_note_hash: Field) -> Field { - let inputs = [contract_address.to_field(), unique_note_hash]; - pedersen_hash(inputs, GENERATOR_INDEX__SILOED_NOTE_HASH) -} - -fn compute_unique_hash(nonce: Field, inner_note_hash: Field) -> Field { - let inputs = [nonce, inner_note_hash]; - pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH) -} - fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface { let header = note.get_header(); let note_hash = note.compute_note_content_hash(); @@ -29,29 +19,6 @@ fn compute_inner_note_hash(note: Note) -> Field where Note: NoteInte ) } -fn compute_unique_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { - let header = note_with_header.get_header(); - - let inner_note_hash = compute_inner_note_hash(note_with_header); - - compute_unique_hash(header.nonce, inner_note_hash) -} - -fn compute_siloed_note_hash(note_with_header: Note) -> Field where Note: NoteInterface { - let header = note_with_header.get_header(); - - let unique_note_hash = if (header.nonce == 0) { - // If nonce is zero, that means we are reading a public note. - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) - // Remove this once notes added from public also include nonces. - compute_inner_note_hash(note_with_header) - } else { - compute_unique_note_hash(note_with_header) - }; - - compute_siloed_hash(header.contract_address, unique_note_hash) -} - pub fn compute_siloed_nullifier( note_with_header: Note, context: &mut PrivateContext @@ -59,22 +26,27 @@ pub fn compute_siloed_nullifier( let header = note_with_header.get_header(); let (_, inner_nullifier) = note_with_header.compute_note_hash_and_nullifier(context); - let input = [header.contract_address.to_field(), inner_nullifier]; - pedersen_hash(input, GENERATOR_INDEX__OUTER_NULLIFIER) + compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier) } -pub fn compute_note_hash_for_insertion(note: Note) -> Field where Note: NoteInterface { - compute_inner_note_hash(note) +fn compute_note_hash_for_read_request_from_innter_and_nonce( + inner_note_hash: Field, + nonce: Field +) -> Field { + // TODO(#1386): This if-else can be nuked once we have nonces injected from public + if (nonce == 0) { + // If nonce is zero, that means we are reading a public note. + inner_note_hash + } else { + compute_unique_note_hash(nonce, inner_note_hash) + } } pub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface { - let header = note.get_header(); + let inner_note_hash = compute_inner_note_hash(note); + let nonce = note.get_header().nonce; - if (header.nonce != 0) { - compute_unique_note_hash(note) - } else { - compute_inner_note_hash(note) - } + compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce) } pub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface { @@ -84,15 +56,18 @@ pub fn compute_note_hash_for_consumption(note: Note) -> Field where // 2. The note was inserted in a previous transaction, and was inserted in public // 3. The note was inserted in a previous transaction, and was inserted in private + let inner_note_hash = compute_inner_note_hash(note); + if (header.note_hash_counter != 0) { // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address). - compute_inner_note_hash(note) + inner_note_hash } else { // If a note is not transient, that means we are reading a settled note (from tree) created in a // previous TX. So we need the siloed_note_hash which has already been hashed with // nonce and then contract address. This hash will match the existing leaf in the note hash // tree, so the kernel can just perform a membership check directly on this hash/leaf. - compute_siloed_note_hash(note) + let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce); + compute_siloed_note_hash(header.contract_address, unique_note_hash) // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is // "siloed" by contract address. When a note hash is computed solely for the purpose of // nullification, it is not strictly necessary to silo the note hash before computing @@ -105,27 +80,17 @@ pub fn compute_note_hash_for_consumption(note: Note) -> Field where } pub fn compute_note_hash_and_optionally_a_nullifier( - // docs:start:compute_note_hash_and_optionally_a_nullifier_args deserialize_content: fn([Field; N]) -> T, note_header: NoteHeader, compute_nullifier: bool, - serialized_note: [Field; S] // docs:end:compute_note_hash_and_optionally_a_nullifier_args + serialized_note: [Field; S] ) -> [Field; 4] where T: NoteInterface { let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0)); - // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed - T::set_header((&mut note), note_header); + note.set_header(note_header); let inner_note_hash = compute_inner_note_hash(note); - - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386) - // Should always be calling compute_unique_hash() once notes added from public also include nonces. - let unique_note_hash = if note_header.nonce != 0 { - compute_unique_hash(note_header.nonce, inner_note_hash) - } else { - inner_note_hash - }; - - let siloed_note_hash = compute_siloed_hash(note_header.contract_address, unique_note_hash); + let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, note_header.nonce); + let siloed_note_hash = compute_siloed_note_hash(note_header.contract_address, unique_note_hash); let inner_nullifier = if compute_nullifier { let (_, nullifier) = note.compute_note_hash_and_nullifier_without_context(); diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 142f6fd58f8f..4f2800b19fc9 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -14,7 +14,7 @@ use crate::hash::hash_args; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, - utils::{compute_note_hash_for_insertion, compute_note_hash_for_consumption} + utils::{compute_inner_note_hash, compute_note_hash_for_consumption} }; use crate::oracle::notes::notify_created_note; @@ -188,7 +188,7 @@ impl TestEnvironment { let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed Note::set_header(note, header); - let inner_note_hash = compute_note_hash_for_insertion(*note); + let inner_note_hash = compute_inner_note_hash(*note); // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088 let serialized_note: [Field; N] = Note::serialize_content(*note); 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 890d1ee3a601..561c3d1029be 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -45,20 +45,15 @@ pub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> ) } -fn compute_unique_note_hash(nonce: Field, note_hash: Field) -> Field { - pedersen_hash( - [ - nonce, - note_hash - ], - GENERATOR_INDEX__UNIQUE_NOTE_HASH - ) +pub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field { + let inputs = [nonce, inner_note_hash]; + pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH) } -pub fn compute_siloed_note_hash(address: AztecAddress, unique_note_hash: Field) -> Field { +pub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field { pedersen_hash( [ - address.to_field(), + app.to_field(), unique_note_hash ], GENERATOR_INDEX__SILOED_NOTE_HASH @@ -75,10 +70,10 @@ pub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: } } -pub fn compute_siloed_nullifier(address: AztecAddress, nullifier: Field) -> Field { +pub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field { pedersen_hash( [ - address.to_field(), + app.to_field(), nullifier ], GENERATOR_INDEX__OUTER_NULLIFIER diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index f39379e20a18..82f52d6e6ebc 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -161,6 +161,28 @@ aztec: CMD curl -fsSd '{\"jsonrpc\":\"2.0\",\"method\":\"pxe_getNodeInfo\",\"id\":1}' http://127.0.0.1:$port EXPOSE $port +aztec-faucet-build: + FROM +build + RUN yarn workspaces focus @aztec/aztec-faucet --production && yarn cache clean + RUN rm -rf \ + ../noir-projects \ + ../l1-contracts \ + ../barretenberg/ts/src \ + ../barretenberg/ts/dest/node-cjs \ + ../barretenberg/ts/dest/browser \ + aztec.js/dest/main.js \ + end-to-end \ + **/src \ + **/artifacts + SAVE ARTIFACT /usr/src /usr/src + +aztec-faucet: + FROM ubuntu:noble + RUN apt update && apt install nodejs curl -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + COPY +aztec-faucet/usr/src /usr/src + ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-faucet/dest/bin/index.js"] + LET port=8080 + # We care about creating a slimmed down e2e image because we have to serialize it from earthly to docker for running. end-to-end-prod: FROM +build @@ -219,6 +241,18 @@ export-aztec: FROM +aztec SAVE IMAGE aztecprotocol/aztec:$EARTHLY_GIT_HASH +export-aztec-arch: + FROM +aztec + ARG DIST_TAG="latest" + ARG ARCH + SAVE IMAGE --push aztecprotocol/aztec:${DIST_TAG}${ARCH:+-$ARCH} + +export-aztec-faucet: + FROM +aztec-faucet + ARG DIST_TAG="latest" + ARG ARCH + SAVE IMAGE --push aztecprotocol/aztec-faucet:${DIST_TAG}${ARCH:+-$ARCH} + export-end-to-end: ARG EARTHLY_GIT_HASH FROM +end-to-end diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 5ccbf6266c7c..da82aa420e79 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -122,7 +122,11 @@ export class AztecNodeService implements AztecNode { * @param config - The configuration to be used by the aztec node. * @returns - A fully synced Aztec Node for use in development/testing. */ - public static async createAndSync(config: AztecNodeConfig) { + public static async createAndSync( + config: AztecNodeConfig, + log = createDebugLogger('aztec:node'), + storeLog = createDebugLogger('aztec:node:lmdb'), + ) { const ethereumChain = createEthereumChain(config.rpcUrl, config.apiKey); //validate that the actual chain id matches that specified in configuration if (config.chainId !== ethereumChain.chainInfo.id) { @@ -131,8 +135,6 @@ export class AztecNodeService implements AztecNode { ); } - const log = createDebugLogger('aztec:node'); - const storeLog = createDebugLogger('aztec:node:lmdb'); const store = await initStoreForRollup( AztecLmdbStore.open(config.dataDirectory, false, storeLog), config.l1Contracts.rollupAddress, diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 3a205d1ff0b0..d627d416f0a0 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -234,31 +234,31 @@ resource "aws_ecs_task_definition" "aztec-node" { { "name": "ROLLUP_CONTRACT_ADDRESS", - "value": "${var.ROLLUP_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.rollup_contract_address}" }, { "name": "INBOX_CONTRACT_ADDRESS", - "value": "${var.INBOX_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.inbox_contract_address}" }, { "name": "OUTBOX_CONTRACT_ADDRESS", - "value": "${var.OUTBOX_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.outbox_contract_address}" }, { "name": "REGISTRY_CONTRACT_ADDRESS", - "value": "${var.REGISTRY_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.registry_contract_address}" }, { "name": "AVAILABILITY_ORACLE_CONTRACT_ADDRESS", - "value": "${var.AVAILABILITY_ORACLE_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.availability_oracle_contract_address}" }, { "name": "GAS_TOKEN_CONTRACT_ADDRESS", - "value": "${var.GAS_TOKEN_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.gas_token_contract_address}" }, { "name": "GAS_PORTAL_CONTRACT_ADDRESS", - "value": "${var.GAS_PORTAL_CONTRACT_ADDRESS}" + "value": "${data.terraform_remote_state.l1_contracts.outputs.gas_portal_contract_address}" }, { "name": "API_KEY", diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index 4463487e2c3b..2febb315fa9d 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -55,7 +55,7 @@ variable "SEQ_MIN_TX_PER_BLOCK" { variable "P2P_MIN_PEERS" { type = string - default = 50 + default = 5 } variable "P2P_MAX_PEERS" { @@ -85,5 +85,6 @@ variable "IMAGE_TAG" { } variable "FULL_IMAGE" { - type = string + type = string + default = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}" } diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index 10db3c25b4a8..2b3eda22113f 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -46,6 +46,9 @@ E2E_TEST: # Run our docker compose, ending whenever sandbox ends, filtering out noisy eth_getLogs RUN docker run -e HARDWARE_CONCURRENCY=$hardware_concurrency --rm aztecprotocol/end-to-end:$AZTEC_DOCKER_TAG $test || $allow_fail +e2e-p2p: + DO +E2E_TEST --test=./src/e2e_p2p_network.test.ts + e2e-2-pxes: DO +E2E_TEST --test=./src/e2e_2_pxes.test.ts diff --git a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts similarity index 52% rename from yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts rename to yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 84173febc0d9..42a5f26cb8bb 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -8,10 +8,13 @@ import { GrumpkinScalar, type SentTx, TxStatus, + createDebugLogger, + sleep, } from '@aztec/aztec.js'; import { type BootNodeConfig, BootstrapNode, createLibP2PPeerId } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; +import fs from 'fs'; import { mnemonicToAccount } from 'viem/accounts'; import { MNEMONIC } from './fixtures/fixtures.js'; @@ -30,21 +33,36 @@ interface NodeContext { account: AztecAddress; } +const PEER_ID_PRIVATE_KEYS = [ + '0802122002f651fd8653925529e3baccb8489b3af4d7d9db440cbf5df4a63ff04ea69683', + '08021220c3bd886df5fe5b33376096ad0dab3d2dc86ed2a361d5fde70f24d979dc73da41', + '080212206b6567ac759db5434e79495ec7458e5e93fe479a5b80713446e0bce5439a5655', + '08021220366453668099bdacdf08fab476ee1fced6bf00ddc1223d6c2ee626e7236fb526', +]; + describe('e2e_p2p_network', () => { let config: AztecNodeConfig; let logger: DebugLogger; let teardown: () => Promise; + let bootstrapNode: BootstrapNode; + let bootstrapNodeEnr: string; beforeEach(async () => { - ({ teardown, config, logger } = await setup(1)); + ({ teardown, config, logger } = await setup(0)); + bootstrapNode = await createBootstrapNode(); + bootstrapNodeEnr = bootstrapNode.getENR().encodeTxt(); }); afterEach(() => teardown()); + afterAll(() => { + for (let i = 0; i < NUM_NODES; i++) { + fs.rmSync(`./data-${i}`, { recursive: true, force: true }); + } + }); + it('should rollup txs from all peers', async () => { // create the bootstrap node for the network - const bootstrapNode = await createBootstrapNode(); - const bootstrapNodeEnr = bootstrapNode.getENR(); if (!bootstrapNodeEnr) { throw new Error('Bootstrap node ENR is not available'); } @@ -53,14 +71,29 @@ describe('e2e_p2p_network', () => { // should be set so that the only way for rollups to be built // is if the txs are successfully gossiped around the nodes. const contexts: NodeContext[] = []; + const nodes: AztecNodeService[] = []; for (let i = 0; i < NUM_NODES; i++) { - const node = await createNode(i + 1 + BOOT_NODE_UDP_PORT, bootstrapNodeEnr?.encodeTxt(), i); + const node = await createNode(i + 1 + BOOT_NODE_UDP_PORT, bootstrapNodeEnr, i); + nodes.push(node); + } + + // wait a bit for peers to discover each other + await sleep(2000); + + for (const node of nodes) { const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); contexts.push(context); } // now ensure that all txs were successfully mined - await Promise.all(contexts.flatMap(context => context.txs.map(tx => tx.wait()))); + await Promise.all( + contexts.flatMap((context, i) => + context.txs.map(async (tx, j) => { + logger.info(`Waiting for tx ${i}-${j}: ${await tx.getTxHash()} to be mined`); + return tx.wait(); + }), + ), + ); // shutdown all nodes. for (const context of contexts) { @@ -70,6 +103,61 @@ describe('e2e_p2p_network', () => { await bootstrapNode.stop(); }); + it('should re-discover stored peers without bootstrap node', async () => { + const contexts: NodeContext[] = []; + const nodes: AztecNodeService[] = []; + for (let i = 0; i < NUM_NODES; i++) { + const node = await createNode(i + 1 + BOOT_NODE_UDP_PORT, bootstrapNodeEnr, i, `./data-${i}`); + nodes.push(node); + } + // wait a bit for peers to discover each other + await sleep(3000); + + // stop bootstrap node + await bootstrapNode.stop(); + + // create new nodes from datadir + const newNodes: AztecNodeService[] = []; + + // stop all nodes + for (let i = 0; i < NUM_NODES; i++) { + const node = nodes[i]; + await node.stop(); + logger.info(`Node ${i} stopped`); + await sleep(1200); + const newNode = await createNode(i + 1 + BOOT_NODE_UDP_PORT, undefined, i, `./data-${i}`); + logger.info(`Node ${i} restarted`); + newNodes.push(newNode); + // const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); + // contexts.push(context); + } + + // wait a bit for peers to discover each other + await sleep(2000); + + for (const node of newNodes) { + const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); + contexts.push(context); + } + + // now ensure that all txs were successfully mined + await Promise.all( + contexts.flatMap((context, i) => + context.txs.map(async (tx, j) => { + logger.info(`Waiting for tx ${i}-${j}: ${await tx.getTxHash()} to be mined`); + return tx.wait(); + }), + ), + ); + + // shutdown all nodes. + // for (const context of contexts) { + for (const context of contexts) { + await context.node.stop(); + await context.pxeService.stop(); + } + }); + const createBootstrapNode = async () => { const peerId = await createLibP2PPeerId(); const bootstrapNode = new BootstrapNode(); @@ -87,7 +175,12 @@ describe('e2e_p2p_network', () => { }; // creates a P2P enabled instance of Aztec Node Service - const createNode = async (tcpListenPort: number, bootstrapNode: string, publisherAddressIndex: number) => { + const createNode = async ( + tcpListenPort: number, + bootstrapNode: string | undefined, + publisherAddressIndex: number, + dataDirectory?: string, + ) => { // We use different L1 publisher accounts in order to avoid duplicate tx nonces. We start from // publisherAddressIndex + 1 because index 0 was already used during test environment setup. const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: publisherAddressIndex + 1 }); @@ -96,38 +189,21 @@ describe('e2e_p2p_network', () => { const newConfig: AztecNodeConfig = { ...config, + peerIdPrivateKey: PEER_ID_PRIVATE_KEYS[publisherAddressIndex], udpListenAddress: `0.0.0.0:${tcpListenPort}`, tcpListenAddress: `0.0.0.0:${tcpListenPort}`, tcpAnnounceAddress: `127.0.0.1:${tcpListenPort}`, udpAnnounceAddress: `127.0.0.1:${tcpListenPort}`, - bootstrapNodes: [bootstrapNode], minTxsPerBlock: NUM_TXS_PER_BLOCK, maxTxsPerBlock: NUM_TXS_PER_BLOCK, p2pEnabled: true, p2pBlockCheckIntervalMS: 1000, p2pL2QueueSize: 1, transactionProtocol: '', + dataDirectory, + bootstrapNodes: bootstrapNode ? [bootstrapNode] : [], }; - return await AztecNodeService.createAndSync(newConfig); - }; - - // submits a set of transactions to the provided Private eXecution Environment (PXE) - const submitTxsTo = async (pxe: PXEService, account: AztecAddress, numTxs: number) => { - const txs: SentTx[] = []; - for (let i = 0; i < numTxs; i++) { - const tx = getSchnorrAccount(pxe, Fr.random(), GrumpkinScalar.random(), Fr.random()).deploy(); - logger.info(`Tx sent with hash ${await tx.getTxHash()}`); - const receipt = await tx.getReceipt(); - expect(receipt).toEqual( - expect.objectContaining({ - status: TxStatus.PENDING, - error: '', - }), - ); - logger.info(`Receipt received for ${await tx.getTxHash()}`); - txs.push(tx); - } - return txs; + return await AztecNodeService.createAndSync(newConfig, createDebugLogger(`aztec:node-${tcpListenPort}`)); }; // creates an instance of the PXE and submit a given number of transactions to it. @@ -142,7 +218,7 @@ describe('e2e_p2p_network', () => { const completeAddress = CompleteAddress.fromSecretKeyAndPartialAddress(secretKey, Fr.random()); await pxeService.registerAccount(secretKey, completeAddress.partialAddress); - const txs = await submitTxsTo(pxeService, completeAddress.address, numTxs); + const txs = await submitTxsTo(pxeService, numTxs); return { txs, account: completeAddress.address, @@ -150,4 +226,36 @@ describe('e2e_p2p_network', () => { node, }; }; + + // submits a set of transactions to the provided Private eXecution Environment (PXE) + const submitTxsTo = async (pxe: PXEService, numTxs: number) => { + const txs: SentTx[] = []; + for (let i = 0; i < numTxs; i++) { + // const tx = getSchnorrAccount(pxe, Fr.random(), GrumpkinScalar.random(), Fr.random()).deploy(); + const accountManager = getSchnorrAccount(pxe, Fr.random(), GrumpkinScalar.random(), Fr.random()); + const deployMethod = await accountManager.getDeployMethod(); + await deployMethod.create({ + contractAddressSalt: accountManager.salt, + skipClassRegistration: true, + skipPublicDeployment: true, + universalDeploy: true, + }); + await deployMethod.prove({}); + const tx = deployMethod.send(); + + const txHash = await tx.getTxHash(); + + logger.info(`Tx sent with hash ${txHash}`); + const receipt = await tx.getReceipt(); + expect(receipt).toEqual( + expect.objectContaining({ + status: TxStatus.PENDING, + error: '', + }), + ); + logger.info(`Receipt received for ${txHash}`); + txs.push(tx); + } + return txs; + }; }); diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 7dbfed502b33..3536c88ee067 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = < { - let discv5Service; let p2pService; if (config.p2pEnabled) { @@ -40,7 +39,7 @@ export const createP2PClient = async ( config.tcpAnnounceAddress = tcpAnnounceAddress; } else { throw new Error( - `Invalid announceTcpAddress provided: ${splitTcpAnnounceAddress}. Expected format: :`, + `Invalid announceTcpAddress provided: ${configTcpAnnounceAddress}. Expected format: :`, ); } } @@ -59,11 +58,10 @@ export const createP2PClient = async ( // Create peer discovery service const peerId = await createLibP2PPeerId(config.peerIdPrivateKey); - discv5Service = new DiscV5Service(peerId, config); - p2pService = await LibP2PService.new(config, discv5Service, peerId, txPool); + const discoveryService = new DiscV5Service(peerId, config); + p2pService = await LibP2PService.new(config, discoveryService, peerId, txPool, store); } else { p2pService = new DummyP2PService(); - discv5Service = new DummyPeerDiscoveryService(); } return new P2PClient(store, l2BlockSource, txPool, p2pService); }; diff --git a/yarn-project/p2p/src/client/p2p_client.test.ts b/yarn-project/p2p/src/client/p2p_client.test.ts index 91c0a5561f01..6726df9aeaa5 100644 --- a/yarn-project/p2p/src/client/p2p_client.test.ts +++ b/yarn-project/p2p/src/client/p2p_client.test.ts @@ -37,7 +37,6 @@ describe('In-Memory P2P Client', () => { start: jest.fn(), stop: jest.fn(), propagateTx: jest.fn(), - settledTxs: jest.fn(), }; blockSource = new MockBlockSource(); diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index fe3c58db6024..96401b356850 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -194,7 +194,7 @@ export class P2PClient implements P2P { this.log.debug('Stopped block downloader'); await this.runningPromise; this.setCurrentState(P2PClientState.STOPPED); - this.log.info('P2P client stopped...'); + this.log.info('P2P client stopped.'); } /** @@ -278,7 +278,6 @@ export class P2PClient implements P2P { for (const block of blocks) { const txHashes = block.body.txEffects.map(txEffect => txEffect.txHash); await this.txPool.deleteTxs(txHashes); - this.p2pService.settledTxs(txHashes); } } diff --git a/yarn-project/p2p/src/service/discV5_service.ts b/yarn-project/p2p/src/service/discV5_service.ts index 8838c180b2fc..557a431e19b7 100644 --- a/yarn-project/p2p/src/service/discV5_service.ts +++ b/yarn-project/p2p/src/service/discV5_service.ts @@ -1,9 +1,8 @@ import { createDebugLogger } from '@aztec/foundation/log'; -import { RunningPromise } from '@aztec/foundation/running-promise'; import { sleep } from '@aztec/foundation/sleep'; import { Discv5, type Discv5EventEmitter } from '@chainsafe/discv5'; -import { type ENR, SignableENR } from '@chainsafe/enr'; +import { ENR, SignableENR } from '@chainsafe/enr'; import type { PeerId } from '@libp2p/interface'; import { multiaddr } from '@multiformats/multiaddr'; import EventEmitter from 'events'; @@ -14,6 +13,8 @@ import { type PeerDiscoveryService, PeerDiscoveryState } from './service.js'; export const AZTEC_ENR_KEY = 'aztec_network'; +const delayBeforeStart = 2000; // 2sec + export enum AztecENR { devnet = 0x01, testnet = 0x02, @@ -33,11 +34,12 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService /** This instance's ENR */ private enr: SignableENR; - private runningPromise: RunningPromise; - private currentState = PeerDiscoveryState.STOPPED; private bootstrapNodes: string[]; + private bootstrapNodePeerIds: PeerId[] = []; + + private startTime = 0; constructor(private peerId: PeerId, config: P2PConfig, private logger = createDebugLogger('aztec:discv5_service')) { super(); @@ -83,18 +85,17 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService const multiAddrUdp = await enr.getFullMultiaddr('udp'); this.logger.debug(`ENR multiaddr: ${multiAddrTcp?.toString()}, ${multiAddrUdp?.toString()}`); }); - - this.runningPromise = new RunningPromise(async () => { - await this.discv5.findRandomNode(); - }, config.p2pPeerCheckIntervalMS); } public async start(): Promise { + // Do this conversion once since it involves an async function call + this.bootstrapNodePeerIds = await Promise.all(this.bootstrapNodes.map(enr => ENR.decodeTxt(enr).peerId())); if (this.currentState === PeerDiscoveryState.RUNNING) { throw new Error('DiscV5Service already started'); } this.logger.info('Starting DiscV5'); await this.discv5.start(); + this.startTime = Date.now(); this.logger.info('DiscV5 started'); this.currentState = PeerDiscoveryState.RUNNING; @@ -110,12 +111,25 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService this.logger.error(`Error adding bootnode ENRs: ${e}`); } } + } + + public async runRandomNodesQuery(): Promise { + if (this.currentState !== PeerDiscoveryState.RUNNING) { + throw new Error('DiscV5Service not running'); + } // First, wait some time before starting the peer discovery // reference: https://github.com/ChainSafe/lodestar/issues/3423 - await sleep(2000); + const msSinceStart = Date.now() - this.startTime; + if (Date.now() - this.startTime <= delayBeforeStart) { + await sleep(delayBeforeStart - msSinceStart); + } - this.runningPromise.start(); + try { + await this.discv5.findRandomNode(); + } catch (err) { + this.logger.error(`Error running discV5 random node query: ${err}`); + } } public getAllPeers(): ENR[] { @@ -134,8 +148,11 @@ export class DiscV5Service extends EventEmitter implements PeerDiscoveryService return this.currentState; } + public isBootstrapPeer(peerId: PeerId): boolean { + return this.bootstrapNodePeerIds.some(node => node.equals(peerId)); + } + public async stop(): Promise { - await this.runningPromise.stop(); await this.discv5.stop(); this.currentState = PeerDiscoveryState.STOPPED; } diff --git a/yarn-project/p2p/src/service/discv5_service.test.ts b/yarn-project/p2p/src/service/discv5_service.test.ts index dd5a58b9aae1..67442f0a87ee 100644 --- a/yarn-project/p2p/src/service/discv5_service.test.ts +++ b/yarn-project/p2p/src/service/discv5_service.test.ts @@ -1,3 +1,5 @@ +import { sleep } from '@aztec/foundation/sleep'; + import { jest } from '@jest/globals'; import type { PeerId } from '@libp2p/interface'; import { SemVer } from 'semver'; @@ -8,7 +10,7 @@ import { createLibP2PPeerId } from './libp2p_service.js'; import { PeerDiscoveryState } from './service.js'; const waitForPeers = (node: DiscV5Service, expectedCount: number): Promise => { - const timeout = 5_000; + const timeout = 7_000; return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { reject(new Error(`Timeout: Failed to connect to ${expectedCount} peers within ${timeout} ms`)); @@ -67,7 +69,17 @@ describe('Discv5Service', () => { const node2 = await createNode(basePort); await node1.start(); await node2.start(); - await waitForPeers(node2, 2); + await Promise.all([ + waitForPeers(node2, 2), + (async () => { + await sleep(2000); // wait for peer discovery to be able to start + for (let i = 0; i < 5; i++) { + await node1.runRandomNodesQuery(); + await node2.runRandomNodesQuery(); + await sleep(100); + } + })(), + ]); const node1Peers = await Promise.all(node1.getAllPeers().map(async peer => (await peer.peerId()).toString())); const node2Peers = await Promise.all(node2.getAllPeers().map(async peer => (await peer.peerId()).toString())); diff --git a/yarn-project/p2p/src/service/dummy_service.ts b/yarn-project/p2p/src/service/dummy_service.ts index cd1ed8d0d41a..aeeedb1f03d1 100644 --- a/yarn-project/p2p/src/service/dummy_service.ts +++ b/yarn-project/p2p/src/service/dummy_service.ts @@ -1,5 +1,6 @@ -import { type Tx, type TxHash } from '@aztec/circuit-types'; +import type { Tx, TxHash } from '@aztec/circuit-types'; +import type { PeerId } from '@libp2p/interface'; import EventEmitter from 'events'; import { type P2PService, type PeerDiscoveryService, PeerDiscoveryState } from './service.js'; @@ -66,6 +67,14 @@ export class DummyPeerDiscoveryService extends EventEmitter implements PeerDisco return []; } + public runRandomNodesQuery(): Promise { + return Promise.resolve(); + } + + public isBootstrapPeer(_: PeerId): boolean { + return false; + } + public getStatus(): PeerDiscoveryState { return this.currentState; } diff --git a/yarn-project/p2p/src/service/known_txs.test.ts b/yarn-project/p2p/src/service/known_txs.test.ts deleted file mode 100644 index 7c93b0853203..000000000000 --- a/yarn-project/p2p/src/service/known_txs.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { randomTxHash } from '@aztec/circuit-types'; - -import { expect } from '@jest/globals'; -import type { Ed25519PeerId, PeerId } from '@libp2p/interface'; -import { mock } from 'jest-mock-extended'; - -import { KnownTxLookup } from './known_txs.js'; - -const createMockPeerId = (peerId: string): PeerId => { - return mock({ - toString: () => peerId, - }); -}; - -describe('Known Txs', () => { - it('Returns false when a peer has not seen a tx', () => { - const knownTxs = new KnownTxLookup(); - - const peer = createMockPeerId('Peer 1'); - const txHash = randomTxHash(); - - expect(knownTxs.hasPeerSeenTx(peer, txHash.toString())).toEqual(false); - }); - - it('Returns true when a peer has seen a tx', () => { - const knownTxs = new KnownTxLookup(); - - const peer = createMockPeerId('Peer 1'); - const peer2 = createMockPeerId('Peer 2'); - const txHash = randomTxHash(); - - knownTxs.addPeerForTx(peer, txHash.toString()); - - expect(knownTxs.hasPeerSeenTx(peer, txHash.toString())).toEqual(true); - expect(knownTxs.hasPeerSeenTx(peer2, txHash.toString())).toEqual(false); - - knownTxs.addPeerForTx(peer2, txHash.toString()); - - expect(knownTxs.hasPeerSeenTx(peer, txHash.toString())).toEqual(true); - expect(knownTxs.hasPeerSeenTx(peer2, txHash.toString())).toEqual(true); - }); -}); diff --git a/yarn-project/p2p/src/service/known_txs.ts b/yarn-project/p2p/src/service/known_txs.ts deleted file mode 100644 index d25c866aebec..000000000000 --- a/yarn-project/p2p/src/service/known_txs.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { type PeerId } from '@libp2p/interface'; - -/** - * Keeps a record of which Peers have 'seen' which transactions. - */ -export class KnownTxLookup { - private lookup: { [key: string]: { [key: string]: boolean } } = {}; - - constructor() {} - - /** - * Inform this lookup that a peer has 'seen' a transaction. - * @param peerId - The peerId of the peer that has 'seen' the transaction. - * @param txHash - The thHash of the 'seen' transaction. - */ - public addPeerForTx(peerId: PeerId, txHash: string) { - const peerIdAsString = peerId.toString(); - const existingLookup = this.lookup[txHash]; - if (existingLookup === undefined) { - const newLookup: { [key: string]: boolean } = {}; - newLookup[peerIdAsString] = true; - this.lookup[txHash] = newLookup; - return; - } - existingLookup[peerIdAsString] = true; - } - - /** - * Determine if a peer has 'seen' a transaction. - * @param peerId - The peerId of the peer. - * @param txHash - The thHash of the transaction. - * @returns A boolean indicating if the transaction has been 'seen' by the peer. - */ - public hasPeerSeenTx(peerId: PeerId, txHash: string) { - const existingLookup = this.lookup[txHash]; - if (existingLookup === undefined) { - return false; - } - const peerIdAsString = peerId.toString(); - return !!existingLookup[peerIdAsString]; - } - - /** - * Updates the lookup from the result of settled txs - * These txs will be cleared out of the lookup. - * It is possible that some txs could still be gossiped for a - * short period of time meaning they come back into this lookup - * but this should be infrequent and cause no undesirable effects - * @param txHashes - The hashes of the newly settled transactions - */ - public handleSettledTxs(txHashes: string[]) { - for (const txHash of txHashes) { - delete this.lookup[txHash]; - } - } -} diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index 6ae680020d02..5164ebfcd64a 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -1,17 +1,16 @@ -import { type Tx, type TxHash } from '@aztec/circuit-types'; +import { type Tx } from '@aztec/circuit-types'; import { SerialQueue } from '@aztec/foundation/fifo'; import { createDebugLogger } from '@aztec/foundation/log'; -import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; +import { RunningPromise } from '@aztec/foundation/running-promise'; +import type { AztecKVStore } from '@aztec/kv-store'; -import { ENR } from '@chainsafe/enr'; import { type GossipsubEvents, gossipsub } from '@chainsafe/libp2p-gossipsub'; import { noise } from '@chainsafe/libp2p-noise'; import { yamux } from '@chainsafe/libp2p-yamux'; import { identify } from '@libp2p/identify'; -import type { PeerId, PubSub, Stream } from '@libp2p/interface'; +import type { PeerId, PubSub } from '@libp2p/interface'; import '@libp2p/kad-dht'; import { mplex } from '@libp2p/mplex'; -import { peerIdFromString } from '@libp2p/peer-id'; import { createFromJSON, createSecp256k1PeerId } from '@libp2p/peer-id-factory'; import { tcp } from '@libp2p/tcp'; import { type Libp2p, createLibp2p } from 'libp2p'; @@ -20,7 +19,6 @@ import { type P2PConfig } from '../config.js'; import { type TxPool } from '../tx_pool/index.js'; import { convertToMultiaddr } from '../util.js'; import { AztecDatastore } from './data_store.js'; -import { KnownTxLookup } from './known_txs.js'; import { PeerManager } from './peer_manager.js'; import type { P2PService, PeerDiscoveryService } from './service.js'; import { AztecTxMessageCreator, fromTxMessage } from './tx_messages.js'; @@ -30,7 +28,6 @@ export interface PubSubLibp2p extends Libp2p { pubsub: PubSub; }; } - /** * Create a libp2p peer ID from the private key if provided, otherwise creates a new random ID. * @param privateKey - Optional peer ID private key as hex string @@ -52,16 +49,14 @@ export async function createLibP2PPeerId(privateKey?: string): Promise { */ export class LibP2PService implements P2PService { private jobQueue: SerialQueue = new SerialQueue(); - private knownTxLookup: KnownTxLookup = new KnownTxLookup(); private messageCreator: AztecTxMessageCreator; private peerManager: PeerManager; + private discoveryRunningPromise?: RunningPromise; constructor( private config: P2PConfig, private node: PubSubLibp2p, private peerDiscoveryService: PeerDiscoveryService, - private protocolId: string, private txPool: TxPool, - private bootstrapPeerIds: PeerId[] = [], private logger = createDebugLogger('aztec:libp2p_service'), ) { this.messageCreator = new AztecTxMessageCreator(config.txGossipVersion); @@ -73,54 +68,42 @@ export class LibP2PService implements P2PService { * @returns An empty promise. */ public async start() { + // Check if service is already started if (this.node.status === 'started') { throw new Error('P2P service already started'); } + + // Log listen & announce addresses const { tcpListenAddress, tcpAnnounceAddress } = this.config; this.logger.info(`Starting P2P node on ${tcpListenAddress}`); - if (!tcpAnnounceAddress) { throw new Error('Announce address not provided.'); } - const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp'); - this.logger.info(`Announcing at ${announceTcpMultiaddr}`); - // handle discovered peers from external discovery service - this.peerDiscoveryService.on('peer:discovered', async (enr: ENR) => { - await this.addPeer(enr); - }); - - this.node.addEventListener('peer:connect', async evt => { - const peerId = evt.detail; - await this.handleNewConnection(peerId as PeerId); - }); - - this.node.addEventListener('peer:disconnect', async evt => { - const peerId = evt.detail; - if (this.isBootstrapPeer(peerId)) { - this.logger.info(`Disconnect from bootstrap peer ${peerId.toString()}`); - } else { - this.logger.info(`Disconnected from transaction peer ${peerId.toString()}`); - await this.peerManager.updateDiscoveryService(); - } - }); + // Start job queue, peer discovery service and libp2p node this.jobQueue.start(); await this.peerDiscoveryService.start(); await this.node.start(); this.logger.info(`Started P2P client with Peer ID ${this.node.peerId.toString()}`); - // Subscribe to standard topics by default + // Subscribe to standard GossipSub topics by default this.subscribeToTopic(this.messageCreator.getTopic()); - // add gossipsub listener + // add GossipSub listener this.node.services.pubsub.addEventListener('gossipsub:message', async e => { const { msg } = e.detail; this.logger.debug(`Received PUBSUB message.`); await this.jobQueue.put(() => this.handleNewGossipMessage(msg.topic, msg.data)); }); + + // Start running promise for peer discovery + this.discoveryRunningPromise = new RunningPromise(() => { + this.peerManager.discover(); + }, this.config.p2pPeerCheckIntervalMS); + this.discoveryRunningPromise.start(); } /** @@ -130,8 +113,12 @@ export class LibP2PService implements P2PService { public async stop() { this.logger.debug('Stopping job queue...'); await this.jobQueue.end(); + this.logger.debug('Stopping running promise...'); + await this.discoveryRunningPromise?.stop(); + this.logger.debug('Stopping peer discovery service...'); + await this.peerDiscoveryService.stop(); this.logger.debug('Stopping LibP2P...'); - await this.node.stop(); + await this.stopLibP2P(); this.logger.info('LibP2P service stopped'); } @@ -146,11 +133,14 @@ export class LibP2PService implements P2PService { peerDiscoveryService: PeerDiscoveryService, peerId: PeerId, txPool: TxPool, + store: AztecKVStore, ) { - const { tcpListenAddress, minPeerCount, maxPeerCount, transactionProtocol: protocolId } = config; + const { tcpListenAddress, tcpAnnounceAddress, minPeerCount, maxPeerCount } = config; const bindAddrTcp = convertToMultiaddr(tcpListenAddress, 'tcp'); + // We know tcpAnnounceAddress cannot be null here because we set it or throw when setting up the service. + const announceAddrTcp = convertToMultiaddr(tcpAnnounceAddress!, 'tcp'); - const datastore = new AztecDatastore(AztecLmdbStore.open()); + const datastore = new AztecDatastore(store); // The autonat service seems quite problematic in that using it seems to cause a lot of attempts // to dial ephemeral ports. I suspect that it works better if you can get the uPNPnat service to @@ -171,10 +161,19 @@ export class LibP2PService implements P2PService { peerId, addresses: { listen: [bindAddrTcp], + announce: [announceAddrTcp], }, transports: [ tcp({ maxConnections: config.maxPeerCount, + // socket option: the maximum length of the queue of pending connections + // https://nodejs.org/dist/latest-v18.x/docs/api/net.html#serverlisten + // it's not safe if we increase this number + backlog: 5, + closeServerOnMaxConnections: { + closeAbove: maxPeerCount ?? Infinity, + listenBelow: maxPeerCount ?? Infinity, + }, }), ], datastore, @@ -200,15 +199,7 @@ export class LibP2PService implements P2PService { }, }); - // extract bootstrap node peer IDs - let bootstrapPeerIds: PeerId[] = []; - if (config.bootstrapNodes.length) { - bootstrapPeerIds = await Promise.all( - config.bootstrapNodes.map(bootnodeEnr => ENR.decodeTxt(bootnodeEnr).peerId()), - ); - } - - return new LibP2PService(config, node, peerDiscoveryService, protocolId, txPool, bootstrapPeerIds); + return new LibP2PService(config, node, peerDiscoveryService, txPool); } /** @@ -260,71 +251,31 @@ export class LibP2PService implements P2PService { void this.jobQueue.put(() => Promise.resolve(this.sendTxToPeers(tx))); } - /** - * Handles the settling of a new batch of transactions. - * @param txHashes - The hashes of the newly settled transactions. - */ - public settledTxs(txHashes: TxHash[]): void { - this.knownTxLookup.handleSettledTxs(txHashes.map(x => x.toString())); - } - - private async addPeer(enr: ENR) { - const peerMultiAddr = await enr.getFullMultiaddr('tcp'); - if (!peerMultiAddr) { - // No TCP address, can't connect - return; - } - const peerIdStr = peerMultiAddr.getPeerId(); - - if (!peerIdStr) { - this.logger.debug(`Peer ID not found in discovered node's multiaddr: ${peerMultiAddr}`); - return; - } - - // check if peer is already known - const peerId = peerIdFromString(peerIdStr); - const hasPeer = await this.node.peerStore.has(peerId); - - // add to peer store if not already known - if (!hasPeer) { - this.logger.info(`Discovered peer ${peerIdStr}. Adding to libp2p peer list`); - let stream: Stream | undefined; - try { - stream = await this.node.dialProtocol(peerMultiAddr, this.protocolId); - } catch (err) { - this.logger.debug(`Failed to dial peer ${peerIdStr}: ${err}`); - } finally { - if (stream) { - await stream.close(); - } - } - } - } - - private async handleNewConnection(peerId: PeerId) { - if (this.isBootstrapPeer(peerId)) { - this.logger.info(`Connected to bootstrap peer ${peerId.toString()}`); - } else { - this.logger.info(`Connected to transaction peer ${peerId.toString()}`); - await this.peerManager.updateDiscoveryService(); - } - } - private async processTxFromPeer(tx: Tx): Promise { const txHash = tx.getTxHash(); const txHashString = txHash.toString(); - this.logger.debug(`Received tx ${txHashString} from external peer.`); + this.logger.verbose(`Received tx ${txHashString} from external peer.`); await this.txPool.addTxs([tx]); } private async sendTxToPeers(tx: Tx) { const { data: txData } = this.messageCreator.createTxMessage(tx); - this.logger.debug(`Sending tx ${tx.getTxHash().toString()} to peers`); + this.logger.verbose(`Sending tx ${tx.getTxHash().toString()} to peers`); const recipientsNum = await this.publishToTopic(this.messageCreator.getTopic(), txData); - this.logger.debug(`Sent tx ${tx.getTxHash().toString()} to ${recipientsNum} peers`); + this.logger.verbose(`Sent tx ${tx.getTxHash().toString()} to ${recipientsNum} peers`); } - private isBootstrapPeer(peer: PeerId) { - return this.bootstrapPeerIds.some(bootstrapPeer => bootstrapPeer.equals(peer)); + // Libp2p seems to hang sometimes if new peers are initiating connections. + private async stopLibP2P() { + const TIMEOUT_MS = 5000; // 5 seconds timeout + const timeout = new Promise((resolve, reject) => { + setTimeout(() => reject(new Error('Timeout during libp2p.stop()')), TIMEOUT_MS); + }); + try { + await Promise.race([this.node.stop(), timeout]); + this.logger.debug('Libp2p stopped'); + } catch (error) { + this.logger.error('Error during stop or timeout:', error); + } } } diff --git a/yarn-project/p2p/src/service/peer_manager.ts b/yarn-project/p2p/src/service/peer_manager.ts index 9e2993103d99..c81dab401247 100644 --- a/yarn-project/p2p/src/service/peer_manager.ts +++ b/yarn-project/p2p/src/service/peer_manager.ts @@ -1,26 +1,201 @@ import { createDebugLogger } from '@aztec/foundation/log'; +import { type ENR } from '@chainsafe/enr'; +import { type PeerId } from '@libp2p/interface'; +import { type Multiaddr } from '@multiformats/multiaddr'; import { type Libp2p } from 'libp2p'; import { type P2PConfig } from '../config.js'; -import { type PeerDiscoveryService, PeerDiscoveryState } from './service.js'; +import { type PeerDiscoveryService } from './service.js'; + +const MAX_DIAL_ATTEMPTS = 3; +const MAX_CACHED_PEERS = 100; + +type CachedPeer = { + peerId: PeerId; + enr: ENR; + multiaddrTcp: Multiaddr; + dialAttempts: number; +}; export class PeerManager { + private cachedPeers: Map = new Map(); constructor( private libP2PNode: Libp2p, - private discV5Node: PeerDiscoveryService, + private peerDiscoveryService: PeerDiscoveryService, private config: P2PConfig, private logger = createDebugLogger('aztec:p2p:peer_manager'), - ) {} - - async updateDiscoveryService() { - const peerCount = this.libP2PNode.getPeers().length; - if (peerCount >= this.config.maxPeerCount && this.discV5Node.getStatus() === PeerDiscoveryState.RUNNING) { - this.logger.debug('Max peer count reached, stopping discovery service'); - await this.discV5Node.stop(); - } else if (peerCount <= this.config.minPeerCount && this.discV5Node.getStatus() === PeerDiscoveryState.STOPPED) { - this.logger.debug('Min peer count reached, starting discovery service'); - await this.discV5Node.start(); + ) { + // Handle new established connections + this.libP2PNode.addEventListener('peer:connect', evt => { + const peerId = evt.detail; + if (this.peerDiscoveryService.isBootstrapPeer(peerId)) { + this.logger.debug(`Connected to bootstrap peer ${peerId.toString()}`); + } else { + this.logger.debug(`Connected to transaction peer ${peerId.toString()}`); + } + }); + + // Handle lost connections + this.libP2PNode.addEventListener('peer:disconnect', evt => { + const peerId = evt.detail; + if (this.peerDiscoveryService.isBootstrapPeer(peerId)) { + this.logger.debug(`Disconnected from bootstrap peer ${peerId.toString()}`); + } else { + this.logger.debug(`Disconnected from transaction peer ${peerId.toString()}`); + } + }); + + // Handle Discovered peers + this.peerDiscoveryService.on('peer:discovered', async (enr: ENR) => { + await this.handleDiscoveredPeer(enr); + }); + } + + /** + * Discovers peers. + */ + public discover() { + // Get current connections + const connections = this.libP2PNode.getConnections(); + + // Calculate how many connections we're looking to make + const peersToConnect = this.config.maxPeerCount - connections.length; + + this.logger.debug( + `Connections: ${connections.length}, Peers to connect: ${peersToConnect}, maxPeerCount: ${this.config.maxPeerCount}, cachedPeers: ${this.cachedPeers.size}`, + ); + + // Exit if no peers to connect + if (peersToConnect <= 0) { + return; + } + + const cachedPeersToDial: CachedPeer[] = []; + + const pendingDials = new Set( + this.libP2PNode + .getDialQueue() + .map(pendingDial => pendingDial.peerId?.toString()) + .filter(Boolean) as string[], + ); + + for (const [id, peerData] of this.cachedPeers.entries()) { + // if already dialling or connected to, remove from cache + if (pendingDials.has(id) || connections.some(conn => conn.remotePeer.equals(peerData.peerId))) { + this.cachedPeers.delete(id); + } else { + // cachedPeersToDial.set(id, enr); + cachedPeersToDial.push(peerData); + } + } + + // reverse to dial older entries first + cachedPeersToDial.reverse(); + + for (const peer of cachedPeersToDial) { + this.cachedPeers.delete(peer.peerId.toString()); + void this.dialPeer(peer); + } + + // if we need more peers, start randomNodesQuery + if (peersToConnect > 0) { + this.logger.debug('Running random nodes query'); + void this.peerDiscoveryService.runRandomNodesQuery(); + } + } + + /** + * Handles a discovered peer. + * @param enr - The discovered peer's ENR. + */ + private async handleDiscoveredPeer(enr: ENR) { + // TODO: Will be handling peer scoring here + + // check if peer is already connected + const [peerId, multiaddrTcp] = await Promise.all([enr.peerId(), enr.getFullMultiaddr('tcp')]); + + this.logger.debug(`Handling discovered peer ${peerId.toString()}, ${multiaddrTcp?.toString()}`); + + // throw if no tcp addr in multiaddr + if (!multiaddrTcp) { + this.logger.debug(`No TCP address in discovered node's multiaddr: ${enr.toString()}`); + return; + } + const connections = this.libP2PNode.getConnections(); + if (connections.some(conn => conn.remotePeer.equals(peerId))) { + this.logger.debug(`Already connected to peer ${peerId.toString()}`); + return; + } + + // check if peer is already in cache + const id = peerId.toString(); + if (this.cachedPeers.has(id)) { + this.logger.debug(`Already in cache ${id}`); + return; + } + + // create cached peer object + const cachedPeer: CachedPeer = { + peerId, + enr, + multiaddrTcp, + dialAttempts: 0, + }; + + // Determine if we should dial immediately or not + if (this.shouldDialPeer()) { + this.logger.debug(`Dialing peer ${id}`); + void this.dialPeer(cachedPeer); + } else { + this.logger.debug(`Caching peer ${id}`); + this.cachedPeers.set(id, cachedPeer); + // Prune set of cached peers + this.pruneCachedPeers(); + } + } + + async dialPeer(peer: CachedPeer) { + const id = peer.peerId.toString(); + await this.libP2PNode.peerStore.merge(peer.peerId, { multiaddrs: [peer.multiaddrTcp] }); + + this.logger.debug(`Dialing peer ${id}`); + try { + await this.libP2PNode.dial(peer.multiaddrTcp); + } catch { + this.logger.debug(`Failed to dial peer ${id}`); + peer.dialAttempts++; + if (peer.dialAttempts < MAX_DIAL_ATTEMPTS) { + this.cachedPeers.set(id, peer); + } else { + this.cachedPeers.delete(id); + } + } + } + + private shouldDialPeer(): boolean { + const connections = this.libP2PNode.getConnections().length; + this.logger.debug(`Connections: ${connections}, maxPeerCount: ${this.config.maxPeerCount}`); + if (connections >= this.config.maxPeerCount) { + this.logger.debug('Not dialing peer, maxPeerCount reached'); + return false; + } + return true; + } + + private pruneCachedPeers() { + let peersToDelete = this.cachedPeers.size - MAX_CACHED_PEERS; + if (peersToDelete <= 0) { + return; + } + + // Remove the oldest peers + for (const key of this.cachedPeers.keys()) { + this.cachedPeers.delete(key); + peersToDelete--; + if (peersToDelete <= 0) { + break; + } } } } diff --git a/yarn-project/p2p/src/service/service.ts b/yarn-project/p2p/src/service/service.ts index 5d3389af54df..f9933dd3b346 100644 --- a/yarn-project/p2p/src/service/service.ts +++ b/yarn-project/p2p/src/service/service.ts @@ -1,6 +1,7 @@ -import type { Tx, TxHash } from '@aztec/circuit-types'; +import type { Tx } from '@aztec/circuit-types'; import type { ENR } from '@chainsafe/enr'; +import type { PeerId } from '@libp2p/interface'; import type EventEmitter from 'events'; export enum PeerDiscoveryState { @@ -29,12 +30,6 @@ export interface P2PService { * @param tx - The transaction to be propagated. */ propagateTx(tx: Tx): void; - - /** - * Called upon receipt of settled transactions. - * @param txHashes - The hashes of the settled transactions. - */ - settledTxs(txHashes: TxHash[]): void; } /** @@ -57,6 +52,18 @@ export interface PeerDiscoveryService extends EventEmitter { */ getAllPeers(): ENR[]; + /** + * Runs findRandomNode query. + */ + runRandomNodesQuery(): Promise; + + /** + * Checks if the given peer is a bootstrap peer. + * @param peerId - The peer ID to check. + * @returns True if the peer is a bootstrap peer. + */ + isBootstrapPeer(peerId: PeerId): boolean; + /** * Event emitted when a new peer is discovered. */ From d3b6a297680cdfc4f2bbd02bb18b091cbbe2fcaf Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 21 Jun 2024 07:42:16 +0000 Subject: [PATCH 02/94] fix FULL_IMAGE var --- yarn-project/aztec/terraform/node/main.tf | 4 ++-- yarn-project/aztec/terraform/node/variables.tf | 9 --------- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- yarn-project/p2p-bootstrap/terraform/variables.tf | 5 ----- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index d627d416f0a0..9a3627e9b695 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -165,7 +165,7 @@ resource "aws_ecs_task_definition" "aztec-node" { [ { "name": "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}", - "image": "${var.FULL_IMAGE}", + "image": "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}", "command": ["start", "--node", "--archiver", "--sequencer", "--prover"], "essential": true, "memoryReservation": 3776, @@ -591,7 +591,7 @@ resource "aws_ecs_task_definition" "aztec-proving-agent" { [ { "name": "${var.DEPLOY_TAG}-aztec-proving-agent-group-${count.index + 1}", - "image": "${var.FULL_IMAGE}", + "image": "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}", "command": ["start", "--prover"], "essential": true, "memoryReservation": 98304, diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index 2febb315fa9d..fc2ee4e2f862 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -79,12 +79,3 @@ variable "PROVING_ENABLED" { type = bool default = true } - -variable "IMAGE_TAG" { - type = string -} - -variable "FULL_IMAGE" { - type = string - default = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.IMAGE_TAG}" -} diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 3536c88ee067..63a7b079ac0e 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = < Date: Fri, 21 Jun 2024 12:16:45 +0000 Subject: [PATCH 03/94] fix missing vars --- .../aztec/terraform/node/variables.tf | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index fc2ee4e2f862..4090d722f152 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -64,7 +64,18 @@ variable "P2P_MAX_PEERS" { } variable "P2P_ENABLED" { - type = bool + type = bool + default = true +} + +variable "PROVING_ENABLED" { + type = bool + default = true +} + +variable "AGENTS_PER_SEQUENCER" { + type = string + default = 4 } variable "AVAILABILITY_ORACLE_CONTRACT_ADDRESS" { type = string } @@ -74,8 +85,4 @@ variable "INBOX_CONTRACT_ADDRESS" { type = string } variable "OUTBOX_CONTRACT_ADDRESS" { type = string } variable "GAS_TOKEN_CONTRACT_ADDRESS" { type = string } variable "GAS_PORTAL_CONTRACT_ADDRESS" { type = string } -variable "AGENTS_PER_SEQUENCER" { type = string } -variable "PROVING_ENABLED" { - type = bool - default = true -} + From 1a45de71320f129a3339206c76d1c748ecc7443a Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 21 Jun 2024 12:45:36 +0000 Subject: [PATCH 04/94] rm contract address vars --- yarn-project/aztec/terraform/node/variables.tf | 9 --------- 1 file changed, 9 deletions(-) diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index 4090d722f152..f761cfee2e75 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -77,12 +77,3 @@ variable "AGENTS_PER_SEQUENCER" { type = string default = 4 } - -variable "AVAILABILITY_ORACLE_CONTRACT_ADDRESS" { type = string } -variable "ROLLUP_CONTRACT_ADDRESS" { type = string } -variable "REGISTRY_CONTRACT_ADDRESS" { type = string } -variable "INBOX_CONTRACT_ADDRESS" { type = string } -variable "OUTBOX_CONTRACT_ADDRESS" { type = string } -variable "GAS_TOKEN_CONTRACT_ADDRESS" { type = string } -variable "GAS_PORTAL_CONTRACT_ADDRESS" { type = string } - From 368cb6ea1b85fd1ab4921d445322de9b3ec1b81a Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 21 Jun 2024 14:06:47 +0000 Subject: [PATCH 05/94] fix deploy p2p --- .github/workflows/devnet-deploys.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index a2b09291c1e8..47d2c6f5b6fe 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -57,9 +57,9 @@ jobs: aws-region: us-west-2 - name: Deploy Bootstrap Nodes - working-directory: ./yarn-project/aztec/terraform/node + working-directory: ./yarn-project/p2p-bootstrap/terraform run: | - terraform init -input=false -backend-config="key=devnet/aztec-node" + terraform init -input=false -backend-config="key=devnet/p2p-bootstrap" terraform apply -input=false -auto-approve - name: Deploy Aztec Nodes From d38fe6ef205cab1d5816312b73550f60f7aa4477 Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 24 Jun 2024 08:24:08 +0000 Subject: [PATCH 06/94] fix ecs name --- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 63a7b079ac0e..7dbfed502b33 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = < Date: Mon, 24 Jun 2024 12:34:05 +0000 Subject: [PATCH 07/94] hardcode fork url --- yarn-project/ethereum/src/testnet.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/yarn-project/ethereum/src/testnet.ts b/yarn-project/ethereum/src/testnet.ts index c6e28871a3ef..6b28b99bc8b7 100644 --- a/yarn-project/ethereum/src/testnet.ts +++ b/yarn-project/ethereum/src/testnet.ts @@ -2,7 +2,9 @@ import { type Chain } from 'viem'; import { type EthereumChain } from './ethereum_chain.js'; -const { DEPLOY_TAG = 'aztec-dev', CHAIN_ID = 31337 } = process.env; +// TODO: restore DEPLOY_TAG +// Temporarily hardcoding DEPLOY_TAG to 'aztec-dev' until mainnet fork is also deployed via devnet flow +const { /* DEPLOY_TAG = 'aztec-dev', */ CHAIN_ID = 31337 } = process.env; export const createTestnetChain = (apiKey: string) => { const chain: Chain = { @@ -16,10 +18,12 @@ export const createTestnetChain = (apiKey: string) => { }, rpcUrls: { default: { - http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], + // http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], + http: [`https://aztec-dev-mainnet-fork.aztec.network:8545/${apiKey}`], }, public: { - http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], + // http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], + http: [`https://aztec-dev-mainnet-fork.aztec.network:8545/${apiKey}`], }, }, }; From 80253eb34a0461cc6b7ac985f9d021666b8fdf22 Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 24 Jun 2024 13:53:43 +0000 Subject: [PATCH 08/94] force new deployments --- yarn-project/aztec/terraform/node/main.tf | 1 + yarn-project/p2p-bootstrap/terraform/main.tf | 1 + 2 files changed, 2 insertions(+) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 9a3627e9b695..251d0d279c90 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -357,6 +357,7 @@ resource "aws_ecs_service" "aztec-node" { deployment_maximum_percent = 100 deployment_minimum_healthy_percent = 0 platform_version = "1.4.0" + force_new_deployment = true network_configuration { diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 7dbfed502b33..30a9520f63cc 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -174,6 +174,7 @@ resource "aws_ecs_service" "p2p-bootstrap" { deployment_maximum_percent = 100 deployment_minimum_healthy_percent = 0 platform_version = "1.4.0" + force_new_deployment = true network_configuration { subnets = [ From 16fe39becacf08bc5070ff5bd9bb6045e80ab3ce Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 24 Jun 2024 14:26:05 +0000 Subject: [PATCH 09/94] hardcode aztec-dev in tf file --- yarn-project/aztec/terraform/node/main.tf | 2 +- yarn-project/ethereum/src/testnet.ts | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 251d0d279c90..2af04bd4731b 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -205,7 +205,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "ETHEREUM_HOST", - "value": "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" + "value": "https://aztec-dev-mainnet-fork.aztec.network:8545/${var.API_KEY}" }, { "name": "DATA_DIRECTORY", diff --git a/yarn-project/ethereum/src/testnet.ts b/yarn-project/ethereum/src/testnet.ts index 6b28b99bc8b7..c6e28871a3ef 100644 --- a/yarn-project/ethereum/src/testnet.ts +++ b/yarn-project/ethereum/src/testnet.ts @@ -2,9 +2,7 @@ import { type Chain } from 'viem'; import { type EthereumChain } from './ethereum_chain.js'; -// TODO: restore DEPLOY_TAG -// Temporarily hardcoding DEPLOY_TAG to 'aztec-dev' until mainnet fork is also deployed via devnet flow -const { /* DEPLOY_TAG = 'aztec-dev', */ CHAIN_ID = 31337 } = process.env; +const { DEPLOY_TAG = 'aztec-dev', CHAIN_ID = 31337 } = process.env; export const createTestnetChain = (apiKey: string) => { const chain: Chain = { @@ -18,12 +16,10 @@ export const createTestnetChain = (apiKey: string) => { }, rpcUrls: { default: { - // http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], - http: [`https://aztec-dev-mainnet-fork.aztec.network:8545/${apiKey}`], + http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], }, public: { - // http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], - http: [`https://aztec-dev-mainnet-fork.aztec.network:8545/${apiKey}`], + http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], }, }, }; From 4ed2e5b4b017c59aca3b8a18aeb70c169c344f60 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 25 Jun 2024 13:38:36 +0000 Subject: [PATCH 10/94] separate node - prover terraforms --- .github/workflows/devnet-deploys.yml | 6 + yarn-project/aztec/terraform/node/main.tf | 314 +----------------- yarn-project/aztec/terraform/prover/main.tf | 247 ++++++++++++++ .../aztec/terraform/prover/variables.tf | 17 + 4 files changed, 274 insertions(+), 310 deletions(-) create mode 100644 yarn-project/aztec/terraform/prover/main.tf create mode 100644 yarn-project/aztec/terraform/prover/variables.tf diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 47d2c6f5b6fe..6ce952dec315 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -67,3 +67,9 @@ jobs: run: | terraform init -input=false -backend-config="key=devnet/aztec-node" terraform apply -input=false -auto-approve + + - name: Deploy Provers + working-directory: ./yarn-project/aztec/terraform/prover + run: | + terraform init -input=false -backend-config="key=devnet/prover" + terraform apply -input=false -auto-approve diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 2af04bd4731b..a1a52ffeb410 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -62,6 +62,10 @@ locals { agents_per_sequencer = var.AGENTS_PER_SEQUENCER } +output "node_count" { + value = local.node_count +} + resource "aws_cloudwatch_log_group" "aztec-node-log-group" { count = local.node_count name = "/fargate/service/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}" @@ -115,20 +119,6 @@ resource "aws_efs_file_system" "node_data_store" { } } -# resource "aws_efs_mount_target" "private_az1" { -# count = local.node_count -# file_system_id = aws_efs_file_system.node_data_store[count.index].id -# subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id -# security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] -# } - -# resource "aws_efs_mount_target" "private_az2" { -# count = local.node_count -# file_system_id = aws_efs_file_system.node_data_store[count.index].id -# subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id -# security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id] -# } - resource "aws_efs_mount_target" "public_az1" { count = local.node_count file_system_id = aws_efs_file_system.node_data_store[count.index].id @@ -374,19 +364,6 @@ resource "aws_ecs_service" "aztec-node" { container_port = 80 } - - # load_balancer { - # target_group_arn = aws_lb_target_group.aztec-node-tcp[count.index].arn - # container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - # container_port = var.NODE_P2P_TCP_PORT + count.index - # } - - # load_balancer { - # target_group_arn = aws_lb_target_group.aztec-node-udp[count.index].arn - # container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - # container_port = var.NODE_P2P_UDP_PORT + count.index - # } - service_registries { registry_arn = aws_service_discovery_service.aztec-node[count.index].arn container_name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" @@ -437,23 +414,6 @@ resource "aws_lb_listener_rule" "api" { } } -# resource "aws_lb_target_group" "aztec-node-tcp" { -# count = local.node_count -# name = "${var.DEPLOY_TAG}-node-${count.index + 1}-p2p-tcp-target" -# port = var.NODE_P2P_TCP_PORT + count.index -# protocol = "TCP" -# target_type = "ip" -# vpc_id = data.terraform_remote_state.setup_iac.outputs.vpc_id - -# health_check { -# protocol = "TCP" -# interval = 10 -# healthy_threshold = 2 -# unhealthy_threshold = 2 -# port = var.NODE_P2P_TCP_PORT + count.index -# } -# } - resource "aws_security_group_rule" "allow-node-tcp-in" { count = local.node_count type = "ingress" @@ -474,40 +434,6 @@ resource "aws_security_group_rule" "allow-node-tcp-out" { security_group_id = data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id } -# resource "aws_lb_listener" "aztec-node-tcp-listener" { -# count = local.node_count -# load_balancer_arn = data.terraform_remote_state.aztec-network_iac.outputs.nlb_arn -# port = var.NODE_P2P_TCP_PORT + count.index -# protocol = "TCP" - -# tags = { -# name = "aztec-node-${count.index}-tcp-listener" -# } - -# default_action { -# type = "forward" -# target_group_arn = aws_lb_target_group.aztec-node-tcp[count.index].arn -# } -# } - - -# resource "aws_lb_target_group" "aztec-node-udp" { -# count = local.node_count -# name = "${var.DEPLOY_TAG}-node-${count.index + 1}-p2p-udp-target" -# port = var.NODE_P2P_UDP_PORT + count.index -# protocol = "UDP" -# target_type = "ip" -# vpc_id = data.terraform_remote_state.setup_iac.outputs.vpc_id - -# health_check { -# protocol = "TCP" -# interval = 10 -# healthy_threshold = 2 -# unhealthy_threshold = 2 -# port = var.NODE_P2P_TCP_PORT + count.index -# } -# } - resource "aws_security_group_rule" "allow-node-udp-in" { type = "ingress" from_port = var.NODE_P2P_UDP_PORT @@ -525,235 +451,3 @@ resource "aws_security_group_rule" "allow-node-udp-out" { cidr_blocks = ["0.0.0.0/0"] security_group_id = data.terraform_remote_state.aztec-network_iac.outputs.p2p_security_group_id } - -# resource "aws_lb_listener" "aztec-node-udp-listener" { -# count = local.node_count -# load_balancer_arn = data.terraform_remote_state.aztec-network_iac.outputs.nlb_arn -# port = var.NODE_P2P_UDP_PORT + count.index -# protocol = "UDP" - -# tags = { -# name = "aztec-node-${count.index}-udp-listener" -# } - -# default_action { -# type = "forward" -# target_group_arn = aws_lb_target_group.aztec-node-udp[count.index].arn -# } -# } - - - -// Configuration for proving agents - -resource "aws_cloudwatch_log_group" "aztec-proving-agent-log-group" { - count = local.node_count - name = "/fargate/service/${var.DEPLOY_TAG}/aztec-proving-agent-group-${count.index + 1}" - retention_in_days = 14 -} - -resource "aws_service_discovery_service" "aztec-proving-agent" { - count = local.node_count - name = "${var.DEPLOY_TAG}-aztec-proving-agent-group-${count.index + 1}" - - health_check_custom_config { - failure_threshold = 1 - } - dns_config { - namespace_id = data.terraform_remote_state.setup_iac.outputs.local_service_discovery_id - dns_records { - ttl = 60 - type = "A" - } - dns_records { - ttl = 60 - type = "SRV" - } - routing_policy = "MULTIVALUE" - } - # Terraform just fails if this resource changes and you have registered instances. - provisioner "local-exec" { - when = destroy - command = "${path.module}/servicediscovery-drain.sh ${self.id}" - } -} - -# Define task definitions for each node. -resource "aws_ecs_task_definition" "aztec-proving-agent" { - count = local.node_count - family = "${var.DEPLOY_TAG}-aztec-proving-agent-group-${count.index + 1}" - requires_compatibilities = ["FARGATE"] - network_mode = "awsvpc" - cpu = "16384" - memory = "98304" - execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn - task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn - container_definitions = < Date: Tue, 25 Jun 2024 13:51:38 +0000 Subject: [PATCH 11/94] add data resources --- yarn-project/aztec/terraform/prover/main.tf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/yarn-project/aztec/terraform/prover/main.tf b/yarn-project/aztec/terraform/prover/main.tf index bcd684aa7937..d7745fc09d1b 100644 --- a/yarn-project/aztec/terraform/prover/main.tf +++ b/yarn-project/aztec/terraform/prover/main.tf @@ -11,6 +11,24 @@ terraform { } } +data "terraform_remote_state" "setup_iac" { + backend = "s3" + config = { + bucket = "aztec-terraform" + key = "setup/setup-iac" + region = "eu-west-2" + } +} + +data "terraform_remote_state" "aztec2_iac" { + backend = "s3" + config = { + bucket = "aztec-terraform" + key = "aztec2/iac" + region = "eu-west-2" + } +} + data "terraform_remote_state" "aztec-network_iac" { backend = "s3" config = { From 7e20a58ec52d65f4f7d54875cc48d472cf6e17d3 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 08:22:51 +0000 Subject: [PATCH 12/94] add provider block --- yarn-project/aztec/terraform/prover/main.tf | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn-project/aztec/terraform/prover/main.tf b/yarn-project/aztec/terraform/prover/main.tf index d7745fc09d1b..a9034ad7bc7c 100644 --- a/yarn-project/aztec/terraform/prover/main.tf +++ b/yarn-project/aztec/terraform/prover/main.tf @@ -11,6 +11,11 @@ terraform { } } +# Define provider and region +provider "aws" { + region = "eu-west-2" +} + data "terraform_remote_state" "setup_iac" { backend = "s3" config = { From b88a3eaf316ca2d1487bb92a59a52b45ec6ea42d Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 14:04:13 +0000 Subject: [PATCH 13/94] merge with master --- .circleci/config.yml | 10 - .devcontainer/scripts/onCreateCommand.sh | 4 +- .devcontainer/scripts/postAttachCommand.sh | 2 +- .github/workflows/devnet-deploys.yml | 2 +- .github/workflows/publish-docs.yml | 39 + .github/workflows/vm_full_tests.yml | 7 +- CODEOWNERS | 36 +- barretenberg/.gitrepo | 4 +- .../gen_inner_proof_inputs_ultra_honk.sh | 2 +- barretenberg/cpp/pil/avm/binary.pil | 4 +- .../cpp/pil/avm/{ => fixed}/byte_lookup.pil | 1 - barretenberg/cpp/pil/avm/{ => fixed}/gas.pil | 7 +- barretenberg/cpp/pil/avm/fixed/powers.pil | 9 + barretenberg/cpp/pil/avm/main.pil | 15 +- barretenberg/cpp/pil/avm/mem.pil | 8 +- .../benchmark/ipa_bench/ipa.bench.cpp | 2 +- .../relations_bench/relations.bench.cpp | 6 +- .../ultra_bench/ultra_honk_rounds.bench.cpp | 2 +- .../ultra_circuit_builder.test.cpp | 17 + .../commitment_schemes/ipa/ipa.fuzzer.cpp | 7 +- .../commitment_schemes/ipa/ipa.hpp | 12 +- .../commitment_schemes/ipa/ipa.test.cpp | 28 +- .../commitment_schemes/kzg/kzg.hpp | 14 +- .../commitment_schemes/kzg/kzg.test.cpp | 18 +- .../commitment_schemes/shplonk/shplonk.hpp | 104 +- .../shplonk/shplonk.test.cpp | 29 +- .../commitment_schemes/verification_key.hpp | 4 +- .../zeromorph/zeromorph.hpp | 172 +- .../zeromorph/zeromorph.test.cpp | 336 +-- .../eccvm/eccvm_composer.test.cpp | 6 +- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 60 +- .../src/barretenberg/eccvm/eccvm_prover.cpp | 90 +- .../src/barretenberg/eccvm/eccvm_prover.hpp | 2 +- .../eccvm/eccvm_transcript.test.cpp | 22 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 103 +- .../eccvm_recursive_verifier.cpp | 107 +- .../eccvm_recursive_verifier.test.cpp | 1 - .../verifier_commitment_key.hpp | 6 +- .../verifier_commitment_key.test.cpp | 2 +- .../plonk/composer/composer_lib.hpp | 75 + .../plonk_honk_shared/CMakeLists.txt | 2 +- .../composer/composer_lib.hpp | 90 +- .../composer/composer_lib.test.cpp | 75 +- .../protogalaxy/decider_verifier.cpp | 17 +- .../protogalaxy/protogalaxy.test.cpp | 114 +- .../protogalaxy/protogalaxy_prover.hpp | 1 - .../protogalaxy/protogalaxy_prover_impl.hpp | 7 +- .../relations/databus_lookup_relation.hpp | 16 +- .../relations/generated/avm/declare_views.hpp | 2 +- .../relations/generated/avm/gas.hpp | 69 + .../generated/avm/lookup_pow_2_0.hpp | 4 +- .../generated/avm/lookup_pow_2_1.hpp | 4 +- .../relations/generated/avm/mem.hpp | 6 +- .../relations/generated/avm/powers.hpp | 49 + .../relations/logderiv_lookup_relation.hpp | 207 ++ .../relations/lookup_relation.hpp | 224 -- .../ultra_relation_consistency.test.cpp | 79 - .../srs/factories/crs_factory.hpp | 4 +- .../srs/factories/file_crs_factory.cpp | 4 +- .../srs/factories/file_crs_factory.hpp | 8 +- .../srs/factories/mem_bn254_crs_factory.cpp | 4 +- .../srs/factories/mem_crs_factory.test.cpp | 2 +- .../factories/mem_grumpkin_crs_factory.cpp | 2 +- .../client_ivc_recursive_verifier.cpp | 6 + .../client_ivc_recursive_verifier.test.cpp | 4 + .../verifier/decider_recursive_verifier.cpp | 17 +- .../verifier/goblin_recursive_verifier.cpp | 12 +- .../protogalaxy_recursive_verifier.cpp | 17 +- .../verifier/ultra_recursive_verifier.cpp | 39 +- .../honk_recursion/verifier/verifier.test.cpp | 2 +- .../grand_product_library.test.cpp | 133 - .../stdlib_circuit_builders/mega_flavor.hpp | 143 +- .../stdlib_circuit_builders/mock_circuits.hpp | 29 + .../plookup_tables/plookup_tables.cpp | 18 +- .../plookup_tables/types.hpp | 76 +- .../stdlib_circuit_builders/ultra_flavor.hpp | 164 +- .../ultra_recursive_flavor.hpp | 12 +- .../sumcheck/instance/prover_instance.hpp | 5 +- .../instance/prover_instance.test.cpp | 89 - .../barretenberg/sumcheck/sumcheck.test.cpp | 1 - .../translator_vm/translator_prover.cpp | 32 +- .../translator_vm/translator_prover.hpp | 2 +- .../translator_vm/translator_verifier.cpp | 24 +- .../translator_recursive_verifier.cpp | 26 +- .../ultra_honk/decider_prover.cpp | 23 +- .../ultra_honk/decider_prover.hpp | 5 +- .../ultra_honk/mega_transcript.test.cpp | 9 +- .../barretenberg/ultra_honk/oink_prover.cpp | 31 +- .../barretenberg/ultra_honk/oink_verifier.cpp | 17 +- .../ultra_honk/relation_correctness.test.cpp | 56 +- .../barretenberg/ultra_honk/sumcheck.test.cpp | 8 +- ..._composer.test.cpp => ultra_honk.test.cpp} | 132 +- .../ultra_honk/ultra_transcript.test.cpp | 9 +- .../ultra_honk/ultra_verifier.cpp | 20 +- .../vm/avm_trace/avm_gas_trace.cpp | 15 +- .../vm/avm_trace/avm_gas_trace.hpp | 113 +- .../vm/avm_trace/avm_mem_trace.cpp | 2 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 2168 +++++++---------- .../barretenberg/vm/avm_trace/avm_trace.hpp | 62 +- .../barretenberg/vm/avm_trace/fixed_gas.cpp | 23 + .../barretenberg/vm/avm_trace/fixed_gas.hpp | 36 + .../vm/avm_trace/fixed_powers.cpp | 25 + .../vm/avm_trace/fixed_powers.hpp | 32 + .../vm/generated/avm_circuit_builder.cpp | 54 +- .../vm/generated/avm_circuit_builder.hpp | 23 +- .../barretenberg/vm/generated/avm_flavor.hpp | 22 +- .../barretenberg/vm/generated/avm_prover.cpp | 24 +- .../barretenberg/vm/generated/avm_prover.hpp | 6 +- .../vm/generated/avm_verifier.cpp | 11 +- .../vm/tests/avm_arithmetic.test.cpp | 39 +- .../vm/tests/avm_bitwise.test.cpp | 19 +- .../barretenberg/vm/tests/avm_cast.test.cpp | 23 +- .../vm/tests/avm_comparison.test.cpp | 21 +- .../vm/tests/avm_control_flow.test.cpp | 19 +- .../vm/tests/avm_execution.test.cpp | 347 +-- .../barretenberg/vm/tests/avm_gas.test.cpp | 3 +- .../vm/tests/avm_indirect_mem.test.cpp | 19 +- .../vm/tests/avm_inter_table.test.cpp | 19 +- .../barretenberg/vm/tests/avm_kernel.test.cpp | 5 +- .../vm/tests/avm_mem_opcodes.test.cpp | 29 +- .../barretenberg/vm/tests/avm_memory.test.cpp | 20 +- .../barretenberg/vm/tests/helpers.test.cpp | 12 +- .../barretenberg/vm/tests/helpers.test.hpp | 2 + barretenberg/ts/src/types/fields.ts | 2 +- boxes/boxes/react/package.json | 1 - boxes/boxes/react/src/contracts/src/main.nr | 6 +- boxes/boxes/react/webpack.config.js | 1 - boxes/boxes/vanilla/package.json | 1 - boxes/boxes/vanilla/src/contracts/src/main.nr | 6 +- boxes/boxes/vanilla/webpack.config.js | 1 - boxes/contract-only/package.json | 1 - boxes/yarn.lock | 9 - build-images/Earthfile | 14 +- cspell.json | 12 +- docker-compose.yml | 139 +- docs/.gitignore | 1 + docs/docs/aztec/_category_.json | 2 +- docs/docs/getting_started.md | 42 +- docs/docs/getting_started/codespaces.md | 25 + docs/docs/getting_started/manual_install.md | 77 + .../how_to_compile_contract.md | 2 +- .../writing_contracts/authwit.md | 8 +- .../common_patterns/index.md | 2 +- .../writing_contracts/initializers.md | 2 +- .../docs/reference/sandbox_reference/index.md | 20 - .../sandbox_reference/sandbox-reference.md | 61 - .../aztecjs-getting-started.md | 2 +- .../advanced/_category_.json | 2 +- .../contract_tutorials/counter_contract.md} | 36 +- .../crowdfunding_contract.md | 2 +- .../private_voting_contract.md | 5 +- .../contract_tutorials/token_contract.md | 2 +- docs/docs/vision.mdx | 2 +- docs/sidebars.js | 9 - .../aztec/aztec-node-dashboard.json | 576 +++++ .../aztec/protocol-circuits-dashboard.json | 747 ++++++ grafana_dashboards/default.yml | 11 + noir-projects/Dockerfile.test | 4 +- noir-projects/Earthfile | 5 +- noir-projects/aztec-nr/.gitrepo | 4 +- noir-projects/aztec-nr/authwit/src/account.nr | 7 +- noir-projects/aztec-nr/authwit/src/auth.nr | 35 +- .../aztec-nr/authwit/src/cheatcodes.nr | 44 + noir-projects/aztec-nr/authwit/src/lib.nr | 1 + .../aztec/src/context/call_interfaces.nr | 59 +- .../aztec/src/context/private_context.nr | 40 +- .../src/context/unconstrained_context.nr | 22 +- .../aztec-nr/aztec/src/encrypted_logs.nr | 1 + .../encrypted_event_emission.nr | 45 + .../encrypted_logs/encrypted_note_emission.nr | 4 +- .../aztec/src/encrypted_logs/header.nr | 2 +- .../aztec/src/encrypted_logs/incoming_body.nr | 50 +- .../aztec/src/encrypted_logs/outgoing_body.nr | 2 +- .../aztec/src/encrypted_logs/payload.nr | 60 +- .../aztec/src/event/event_interface.nr | 11 +- .../aztec/src/keys/point_to_symmetric_key.nr | 2 +- .../aztec-nr/aztec/src/keys/public_keys.nr | 3 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 6 +- .../oracle/enqueue_public_function_call.nr | 1 + .../aztec-nr/aztec/src/oracle/logs_traits.nr | 25 +- .../aztec-nr/aztec/src/oracle/notes.nr | 3 +- .../aztec-nr/aztec/src/test/helpers.nr | 2 +- .../aztec/src/test/helpers/cheatcodes.nr | 94 +- .../src/test/helpers/test_environment.nr | 87 +- .../src/test/helpers/{types.nr => utils.nr} | 51 +- .../src/easy_private_uint.nr | 6 +- .../aztec-nr/value-note/src/utils.nr | 4 +- noir-projects/noir-contracts/Nargo.toml | 1 + .../app_subscription_contract/src/main.nr | 6 +- .../auth_wit_test_contract/Nargo.toml | 9 + .../auth_wit_test_contract/src/main.nr | 14 + .../contracts/avm_test_contract/src/main.nr | 6 +- .../contracts/card_game_contract/src/cards.nr | 4 +- .../contracts/child_contract/src/main.nr | 4 +- .../contracts/counter_contract/src/main.nr | 24 +- .../crowdfunding_contract/src/main.nr | 16 +- .../delegated_on_contract/src/main.nr | 4 +- .../docs_example_contract/src/main.nr | 17 +- .../ecdsa_account_contract/src/main.nr | 15 +- .../contracts/escrow_contract/src/main.nr | 4 +- .../inclusion_proofs_contract/src/main.nr | 4 +- .../contracts/parent_contract/src/main.nr | 5 +- .../pending_note_hashes_contract/src/main.nr | 20 +- .../schnorr_account_contract/src/main.nr | 31 +- .../src/main.nr | 11 +- .../src/main.nr | 11 +- .../static_child_contract/src/main.nr | 6 +- .../contracts/test_contract/src/main.nr | 48 +- .../contracts/test_log_contract/src/main.nr | 99 +- .../token_blacklist_contract/src/main.nr | 12 +- .../contracts/token_contract/src/main.nr | 102 +- .../contracts/token_contract/src/test.nr | 9 + .../token_contract/src/test/access_control.nr | 52 + .../contracts/token_contract/src/test/burn.nr | 179 ++ .../token_contract/src/test/minting.nr | 239 ++ .../src/test/reading_constants.nr | 29 + .../token_contract/src/test/shielding.nr | 156 ++ .../src/test/transfer_private.nr | 131 + .../src/test/transfer_public.nr | 122 + .../token_contract/src/test/unshielding.nr | 89 + .../token_contract/src/test/utils.nr | 89 + .../crates/types/src/abis.nr | 1 + .../crates/types/src/abis/event_selector.nr | 70 + .../types/src/abis/public_call_stack_item.nr | 1 + .../crates/types/src/constants.nr | 19 +- .../crates/types/src/utils.nr | 3 +- noir/noir-repo/Cargo.lock | 1 + noir/noir-repo/aztec_macros/Cargo.toml | 2 +- noir/noir-repo/aztec_macros/src/lib.rs | 12 +- .../src/transforms/contract_interface.rs | 24 +- .../aztec_macros/src/transforms/events.rs | 488 ++-- .../src/transforms/note_interface.rs | 94 +- .../aztec_macros/src/utils/constants.rs | 1 - .../aztec_macros/src/utils/errors.rs | 6 + .../compiler/noirc_driver/src/abi_gen.rs | 5 +- .../src/hir/resolution/import.rs | 43 +- .../noirc_frontend/src/node_interner.rs | 9 + .../verify_honk_proof/Prover.toml | 2 +- .../verify_honk_proof/src/main.nr | 2 +- yarn-project/Earthfile | 9 +- yarn-project/accounts/package.json | 10 +- yarn-project/archiver/package.json | 11 +- .../archiver/src/archiver/archiver.test.ts | 3 + .../archiver/src/archiver/archiver.ts | 13 +- .../archiver/src/archiver/instrumentation.ts | 30 + .../archiver/kv_archiver_store/block_store.ts | 1 - yarn-project/archiver/src/index.ts | 3 + yarn-project/archiver/tsconfig.json | 3 + yarn-project/aztec-faucet/package.json | 10 +- yarn-project/aztec-node/package.json | 11 +- .../aztec-node/src/aztec-node/server.test.ts | 5 +- .../aztec-node/src/aztec-node/server.ts | 15 +- yarn-project/aztec-node/src/bin/index.ts | 3 +- yarn-project/aztec-node/tsconfig.json | 3 + yarn-project/aztec.js/package.json | 11 +- .../aztec.js/src/account/interface.ts | 29 +- yarn-project/aztec.js/src/account/wallet.ts | 9 +- .../src/fee/private_fee_payment_method.ts | 12 +- .../src/fee/public_fee_payment_method.ts | 33 +- yarn-project/aztec.js/src/index.ts | 3 +- .../aztec.js/src/rpc_clients/pxe_client.ts | 2 + yarn-project/aztec.js/src/utils/authwit.ts | 87 +- .../aztec.js/src/wallet/account_wallet.ts | 230 +- .../aztec.js/src/wallet/base_wallet.ts | 19 +- .../aztec.js/src/wallet/signerless_wallet.ts | 4 +- yarn-project/aztec.js/webpack.config.js | 1 - yarn-project/aztec/package.json | 11 +- .../aztec/src/cli/cmds/start_archiver.ts | 7 +- yarn-project/aztec/src/cli/cmds/start_node.ts | 7 +- .../aztec/src/cli/cmds/start_prover.ts | 22 +- yarn-project/aztec/src/sandbox.ts | 8 +- yarn-project/aztec/tsconfig.json | 3 + yarn-project/bb-prover/package.json | 11 +- .../bb-prover/src/avm_proving.test.ts | 37 +- yarn-project/bb-prover/src/bb/execute.ts | 20 +- yarn-project/bb-prover/src/instrumentation.ts | 149 ++ .../src/prover/bb_native_proof_creator.ts | 6 +- .../bb-prover/src/prover/bb_prover.ts | 74 +- yarn-project/bb-prover/src/stats.ts | 16 +- .../bb-prover/src/test/test_circuit_prover.ts | 30 +- yarn-project/bb-prover/tsconfig.json | 3 + yarn-project/builder/package.json | 10 +- .../src/contract-interface-gen/typescript.ts | 12 +- yarn-project/circuit-types/package.json | 10 +- .../src/logs/encrypted_l2_note_log.ts | 4 + .../src/logs/function_l2_logs.ts | 3 +- .../encrypted_note_log_incoming_body.test.ts | 7 +- .../encrypted_note_log_incoming_body.ts | 8 +- .../logs/l1_payload/l1_event_payload.test.ts | 3 +- .../src/logs/l1_payload/l1_event_payload.ts | 23 +- .../src/logs/l1_payload/l1_note_payload.ts | 7 +- .../src/logs/l1_payload/tagged_log.test.ts | 3 +- .../src/logs/l1_payload/tagged_log.ts | 28 +- .../circuit-types/src/logs/tx_l2_logs.ts | 53 +- yarn-project/circuit-types/src/mocks.ts | 70 +- .../circuit-types/src/notes/extended_note.ts | 6 +- .../circuit-types/src/tx/processed_tx.ts | 23 +- yarn-project/circuit-types/src/tx/tx.ts | 38 +- yarn-project/circuits.js/package.json | 10 +- yarn-project/circuits.js/src/constants.gen.ts | 19 +- .../contract_address.test.ts.snap | 2 +- .../circuits.js/src/keys/derivation.test.ts | 2 +- .../circuits.js/src/structs/avm/avm.ts | 9 + .../src/structs/complete_address.test.ts | 4 +- .../src/structs/contract_storage_read.ts | 33 +- .../contract_storage_update_request.ts | 15 +- .../src/structs/public_call_stack_item.ts | 17 +- yarn-project/cli/package.json | 10 +- yarn-project/cli/src/cmds/add_note.ts | 4 +- yarn-project/cli/src/inspect.ts | 2 +- yarn-project/end-to-end/package.json | 12 +- .../src/composed/e2e_aztec_js_browser.test.ts | 6 +- .../composed/integration_l1_publisher.test.ts | 3 +- .../end-to-end/src/e2e_authwit.test.ts | 171 +- .../end-to-end/src/e2e_avm_simulator.test.ts | 2 +- .../e2e_blacklist_token_contract/burn.test.ts | 12 +- .../transfer_private.test.ts | 12 +- .../unshielding.test.ts | 6 +- .../src/e2e_cross_chain_messaging.test.ts | 9 +- .../end-to-end/src/e2e_event_logs.test.ts | 29 +- .../end-to-end/src/e2e_fees/failures.test.ts | 131 +- .../src/e2e_lending_contract.test.ts | 19 +- .../end-to-end/src/e2e_p2p_network.test.ts | 7 +- .../end-to-end/src/e2e_prover/full.test.ts | 4 +- .../deposits.test.ts | 22 +- .../src/e2e_token_contract/burn.test.ts | 12 +- .../transfer_private.test.ts | 67 +- .../transfer_public.test.ts | 39 +- .../e2e_token_contract/unshielding.test.ts | 6 +- .../src/fixtures/snapshot_manager.ts | 7 +- yarn-project/end-to-end/src/fixtures/utils.ts | 10 +- yarn-project/end-to-end/src/shared/browser.ts | 4 +- .../end-to-end/src/shared/uniswap_l1_l2.ts | 136 +- yarn-project/end-to-end/tsconfig.json | 3 + yarn-project/end-to-end/webpack.config.js | 1 - yarn-project/entrypoints/package.json | 10 +- .../entrypoints/src/dapp_entrypoint.ts | 10 +- yarn-project/ethereum/package.json | 10 +- yarn-project/foundation/.prettierrc.json | 2 +- yarn-project/foundation/package.json | 10 +- yarn-project/foundation/src/abi/abi.ts | 3 +- yarn-project/foundation/src/abi/index.ts | 3 +- .../foundation/src/abi/note_selector.ts | 73 + .../src/crypto/random/randomness_singleton.ts | 4 +- .../src/json-rpc/server/json_rpc_server.ts | 4 +- yarn-project/foundation/src/log/logger.ts | 43 +- .../src/serialize/buffer_reader.test.ts | 68 + .../foundation/src/serialize/buffer_reader.ts | 16 + yarn-project/key-store/package.json | 10 +- yarn-project/key-store/src/key_store.test.ts | 30 +- yarn-project/kv-store/package.json | 10 +- yarn-project/merkle-tree/package.json | 10 +- .../snapshots/indexed_tree_snapshot.test.ts | 8 +- yarn-project/noir-contracts.js/package.json | 10 +- .../noir-protocol-circuits-types/package.json | 10 +- .../noir-protocol-circuits-types/src/index.ts | 2 +- .../src/type_conversion.ts | 4 +- yarn-project/p2p-bootstrap/package.json | 10 +- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- yarn-project/p2p/package.json | 11 +- .../p2p/src/tx_pool/aztec_kv_tx_pool.test.ts | 3 +- .../p2p/src/tx_pool/aztec_kv_tx_pool.ts | 15 +- .../p2p/src/tx_pool/instrumentation.ts | 58 + .../p2p/src/tx_pool/memory_tx_pool.test.ts | 4 +- .../p2p/src/tx_pool/memory_tx_pool.ts | 9 +- yarn-project/p2p/tsconfig.json | 3 + yarn-project/package.common.json | 14 +- yarn-project/package.json | 3 +- yarn-project/protocol-contracts/package.json | 10 +- yarn-project/prover-client/package.json | 11 +- .../prover-client/src/mocks/test_context.ts | 9 +- .../src/orchestrator/orchestrator.ts | 201 +- .../orchestrator_failures.test.ts | 5 +- .../orchestrator_lifecycle.test.ts | 5 +- .../orchestrator_workflow.test.ts | 3 +- .../src/test/bb_prover_base_rollup.test.ts | 3 +- .../src/test/bb_prover_full_rollup.test.ts | 3 +- .../src/test/bb_prover_parity.test.ts | 3 +- .../prover-client/src/tx-prover/tx-prover.ts | 25 +- yarn-project/prover-client/tsconfig.json | 3 + yarn-project/pxe/package.json | 10 +- .../src/database/deferred_note_dao.test.ts | 3 +- .../pxe/src/database/deferred_note_dao.ts | 5 +- .../src/database/incoming_note_dao.test.ts | 3 +- .../pxe/src/database/incoming_note_dao.ts | 7 +- .../src/database/outgoing_note_dao.test.ts | 3 +- .../pxe/src/database/outgoing_note_dao.ts | 5 +- yarn-project/pxe/src/index.ts | 1 + .../src/kernel_prover/kernel_prover.test.ts | 3 +- .../pxe/src/note_processor/note_processor.ts | 23 +- .../pxe/src/pxe_http/pxe_http_server.ts | 2 + .../pxe/src/pxe_service/pxe_service.ts | 10 +- yarn-project/scripts/package.json | 10 +- yarn-project/sequencer-client/package.json | 11 +- .../src/client/sequencer-client.ts | 10 +- .../src/sequencer/sequencer.test.ts | 2 + .../src/sequencer/sequencer.ts | 178 +- yarn-project/sequencer-client/tsconfig.json | 3 + yarn-project/simulator/package.json | 11 +- .../simulator/src/acvm/oracle/oracle.ts | 14 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 20 +- .../simulator/src/avm/avm_context.test.ts | 2 + .../src/avm/avm_execution_environment.test.ts | 3 + .../src/avm/avm_execution_environment.ts | 13 +- .../simulator/src/avm/avm_simulator.test.ts | 1044 ++++---- .../simulator/src/avm/avm_simulator.ts | 5 +- .../simulator/src/avm/fixtures/index.ts | 35 +- .../simulator/src/avm/journal/journal.test.ts | 774 +++--- .../simulator/src/avm/journal/journal.ts | 337 +-- .../src/avm/journal/nullifiers.test.ts | 22 +- .../simulator/src/avm/journal/nullifiers.ts | 43 +- .../src/avm/journal/public_storage.test.ts | 4 +- .../src/avm/journal/public_storage.ts | 10 + .../simulator/src/avm/journal/trace.test.ts | 294 --- .../simulator/src/avm/journal/trace.ts | 181 -- .../simulator/src/avm/journal/trace_types.ts | 91 - .../src/avm/opcodes/accrued_substate.test.ts | 457 ++-- .../src/avm/opcodes/accrued_substate.ts | 10 +- .../src/avm/opcodes/contract.test.ts | 51 +- .../src/avm/opcodes/external_calls.test.ts | 58 +- .../src/avm/opcodes/external_calls.ts | 52 +- .../simulator/src/avm/opcodes/storage.test.ts | 14 +- yarn-project/simulator/src/avm/test_utils.ts | 53 + .../src/client/client_execution_context.ts | 14 +- .../simulator/src/client/execution_result.ts | 3 +- .../src/client/private_execution.test.ts | 11 +- .../simulator/src/client/simulator.ts | 10 +- .../client/unconstrained_execution.test.ts | 2 + .../simulator/src/client/view_data_oracle.ts | 8 + yarn-project/simulator/src/mocks/fixtures.ts | 2 +- .../src/public/abstract_phase_manager.ts | 6 +- .../src/public/app_logic_phase_manager.ts | 1 + .../simulator/src/public/execution.ts | 58 +- yarn-project/simulator/src/public/executor.ts | 76 +- .../src/public/public_processor.test.ts | 31 +- .../simulator/src/public/public_processor.ts | 13 +- .../src/public/side_effect_trace.test.ts | 284 +++ .../simulator/src/public/side_effect_trace.ts | 323 +++ .../src/public/side_effect_trace_interface.ts | 41 + .../src/public/teardown_phase_manager.ts | 1 + .../src/public/transitional_adaptors.ts | 104 +- yarn-project/simulator/tsconfig.json | 3 + yarn-project/telemetry-client/.eslintrc.cjs | 1 + yarn-project/telemetry-client/package.json | 77 + .../telemetry-client/src/attributes.ts | 49 + yarn-project/telemetry-client/src/index.ts | 1 + yarn-project/telemetry-client/src/metrics.ts | 30 + yarn-project/telemetry-client/src/noop.ts | 83 + yarn-project/telemetry-client/src/otel.ts | 71 + yarn-project/telemetry-client/src/start.ts | 27 + .../telemetry-client/src/telemetry.ts | 180 ++ yarn-project/telemetry-client/tsconfig.json | 14 + yarn-project/txe/package.json | 13 +- yarn-project/txe/src/bin/index.ts | 15 +- yarn-project/txe/src/oracle/txe_oracle.ts | 453 +++- .../txe/src/txe_service/txe_service.ts | 184 +- .../txe/src/util/expected_failure_error.ts | 5 + .../util/txe_public_contract_data_source.ts | 63 + .../txe/src/util/txe_public_state_db.ts | 57 + yarn-project/types/package.json | 10 +- .../types/src/abi/contract_artifact.ts | 7 +- yarn-project/world-state/package.json | 10 +- yarn-project/yarn.lock | 370 ++- 463 files changed, 13089 insertions(+), 7990 deletions(-) rename barretenberg/cpp/pil/avm/{ => fixed}/byte_lookup.pil (99%) rename barretenberg/cpp/pil/avm/{ => fixed}/gas.pil (63%) create mode 100644 barretenberg/cpp/pil/avm/fixed/powers.pil create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp create mode 100644 barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp rename barretenberg/cpp/src/barretenberg/ultra_honk/{ultra_composer.test.cpp => ultra_honk.test.cpp} (88%) create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.hpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.cpp create mode 100644 barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.hpp create mode 100644 docs/docs/getting_started/codespaces.md create mode 100644 docs/docs/getting_started/manual_install.md rename docs/docs/{getting_started => tutorials}/aztecjs-getting-started.md (99%) rename docs/docs/{getting_started/aztecnr-getting-started.md => tutorials/contract_tutorials/counter_contract.md} (78%) create mode 100644 grafana_dashboards/aztec/aztec-node-dashboard.json create mode 100644 grafana_dashboards/aztec/protocol-circuits-dashboard.json create mode 100644 grafana_dashboards/default.yml create mode 100644 noir-projects/aztec-nr/authwit/src/cheatcodes.nr create mode 100644 noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr rename noir-projects/aztec-nr/aztec/src/test/helpers/{types.nr => utils.nr} (67%) create mode 100644 noir-projects/noir-contracts/contracts/auth_wit_test_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/auth_wit_test_contract/src/main.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/access_control.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/reading_constants.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr create mode 100644 noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr create mode 100644 yarn-project/archiver/src/archiver/instrumentation.ts create mode 100644 yarn-project/bb-prover/src/instrumentation.ts create mode 100644 yarn-project/foundation/src/abi/note_selector.ts create mode 100644 yarn-project/p2p/src/tx_pool/instrumentation.ts delete mode 100644 yarn-project/simulator/src/avm/journal/trace.test.ts delete mode 100644 yarn-project/simulator/src/avm/journal/trace.ts delete mode 100644 yarn-project/simulator/src/avm/journal/trace_types.ts create mode 100644 yarn-project/simulator/src/avm/test_utils.ts create mode 100644 yarn-project/simulator/src/public/side_effect_trace.test.ts create mode 100644 yarn-project/simulator/src/public/side_effect_trace.ts create mode 100644 yarn-project/simulator/src/public/side_effect_trace_interface.ts create mode 100644 yarn-project/telemetry-client/.eslintrc.cjs create mode 100644 yarn-project/telemetry-client/package.json create mode 100644 yarn-project/telemetry-client/src/attributes.ts create mode 100644 yarn-project/telemetry-client/src/index.ts create mode 100644 yarn-project/telemetry-client/src/metrics.ts create mode 100644 yarn-project/telemetry-client/src/noop.ts create mode 100644 yarn-project/telemetry-client/src/otel.ts create mode 100644 yarn-project/telemetry-client/src/start.ts create mode 100644 yarn-project/telemetry-client/src/telemetry.ts create mode 100644 yarn-project/telemetry-client/tsconfig.json create mode 100644 yarn-project/txe/src/util/expected_failure_error.ts create mode 100644 yarn-project/txe/src/util/txe_public_contract_data_source.ts create mode 100644 yarn-project/txe/src/util/txe_public_state_db.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index 8c3765900aa5..2322e6159b3b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -440,16 +440,6 @@ jobs: command: | should_release || exit 0 yarn-project/deploy_npm.sh latest - - run: - name: "Release canary to NPM: l1-contracts" - command: | - should_release || exit 0 - deploy_npm l1-contracts canary - - run: - name: "Release latest to NPM: l1-contracts" - command: | - should_release || exit 0 - deploy_npm l1-contracts latest - run: name: "Update aztec-up" command: | diff --git a/.devcontainer/scripts/onCreateCommand.sh b/.devcontainer/scripts/onCreateCommand.sh index 0f2f25affeed..c0970999305b 100755 --- a/.devcontainer/scripts/onCreateCommand.sh +++ b/.devcontainer/scripts/onCreateCommand.sh @@ -11,11 +11,11 @@ if ! grep -q "PXE_URL" ~/.bashrc; then fi if ! grep -q "alias sandbox" ~/.bashrc; then - echo "alias sandbox=\"npx create-aztec-app sandbox\"" >> ~/.bashrc + echo "alias sandbox=\"npx aztec-app sandbox\"" >> ~/.bashrc fi source ~/.bashrc -yes | npx create-aztec-app -t $TYPE -n $NAME -s +yes | npx aztec-app -t $TYPE -n $NAME -s mv $NAME/* $NAME/.* . rm -rf $NAME diff --git a/.devcontainer/scripts/postAttachCommand.sh b/.devcontainer/scripts/postAttachCommand.sh index 2ff4a39973bb..9eeff69f3502 100755 --- a/.devcontainer/scripts/postAttachCommand.sh +++ b/.devcontainer/scripts/postAttachCommand.sh @@ -5,7 +5,7 @@ NAME=$2 apt install gh gh codespace ports visibility 8080:public -c $CODESPACE_NAME -npx create-aztec-app sandbox start +npx aztec-app sandbox start r=$(tput sgr0) # Reset color bold=$(tput bold) # Bold text diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 6ce952dec315..80fa8aae0c2e 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -56,7 +56,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - - name: Deploy Bootstrap Nodes + - name: Deploy P2P Bootstrap Nodes working-directory: ./yarn-project/p2p-bootstrap/terraform run: | terraform init -input=false -backend-config="key=devnet/p2p-bootstrap" diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 11a065c8938d..e1abe1531d9b 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -29,3 +29,42 @@ jobs: - timeout-minutes: 25 run: earthly-ci --no-output ./docs/+deploy-prod --NETLIFY_AUTH_TOKEN=${{ secrets.NETLIFY_AUTH_TOKEN }} --NETLIFY_SITE_ID=${{ secrets.NETLIFY_SITE_ID }} --COMMIT_TAG=${{ inputs.tag }} + + pdf: + needs: setup + runs-on: master-x86 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} + path: aztec-packages + - name: Install Prince + run: | + curl https://www.princexml.com/download/prince-14.2-linux-generic-x86_64.tar.gz -O + tar zxf prince-14.2-linux-generic-x86_64.tar.gz + cd prince-14.2-linux-generic-x86_64 + yes "" | sudo ./install.sh + - name: Serve docs + run: | + cd aztec-packages/docs + yarn build + yarn serve & + - name: Checkout PDF repo + uses: actions/checkout@v3 + with: + token: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }} + repository: AztecProtocol/protocol-specs-pdf + path: protocol-specs-pdf + - name: Generate PDF + run: | + npx docusaurus-prince-pdf -u http://localhost:3000/protocol-specs/intro --output protocol-specs-pdf/protocol-specs.pdf + timeout-minutes: 4 + - name: Push to PDF repo + run: | + git config --global user.name AztecBot + git config --global user.email tech@aztecprotocol.com + cd protocol-specs-pdf + git add protocol-specs.pdf + git commit -m "chore: update protocol-specs.pdf" + git push origin main diff --git a/.github/workflows/vm_full_tests.yml b/.github/workflows/vm_full_tests.yml index 1e912a054384..e1e135b02018 100644 --- a/.github/workflows/vm_full_tests.yml +++ b/.github/workflows/vm_full_tests.yml @@ -55,6 +55,7 @@ jobs: concurrency_key: avm-full-tests-x86 - name: "AVM Full Tests" working-directory: ./barretenberg/cpp/ - timeout-minutes: 90 - # limit our parallelism to half our cores - run: earthly-ci --no-output +vm-full-test --hardware_concurrency=64 + timeout-minutes: 70 + run: | + sudo shutdown -P 70 # hack until core part of the scripts + earthly-ci --no-output +vm-full-test --hardware_concurrency=64 # limit our parallelism to half our cores diff --git a/CODEOWNERS b/CODEOWNERS index 1b8a6f2f1d27..9d8055da4cd6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,17 +1,31 @@ /build-images/ @charlielye -# Notify the AVM team of any changes to public oracle. -/yarn-project/simulator/src/public/public_execution_context.ts @Maddiaa0 @fcarreiro @dbanks12 - -# Notify the AVM team of changes to generated PIL code -barretenberg/cpp/src/barretenberg/**/generated/* @Maddiaa0 @jeanmon @IlyasRidhuan +# Notify the Noir team of any changes to ACIR serialization +/noir/noir-repo/acvm-repo/acir/codegen/* @TomAFrench @vezenovm @guipublic -# Notify the AVM team of any changes to public context or avm context. +##################################################### +# Notify the AVM team +# +# on changes to PIL code-generator +/bb-pilcom @Maddiaa0 @jeanmon @IlyasRidhuan @fcarreiro +# on changes to PIL code (AVM circuit) +/barretenberg/cpp/pil @Maddiaa0 @jeanmon @IlyasRidhuan @fcarreiro +# on changes to PIL-generated C++ +/barretenberg/cpp/src/barretenberg/**/generated @jeanmon @IlyasRidhuan @fcarreiro +# on changes to AVM trace (C++ witness generator) +/barretenberg/cpp/src/barretenberg/vm/avm_trace @jeanmon @IlyasRidhuan @fcarreiro +# on changes to public context in aztec-nr /noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @fcarreiro @dbanks12 -/noir-projects/aztec-nr/aztec/src/context/inputs/avm_context_inputs.nr @fcarreiro @dbanks12 /noir-projects/aztec-nr/aztec/src/context/public_context.nr @fcarreiro @dbanks12 -/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @fcarreiro @dbanks12 -/noir-projects/aztec-nr/aztec/src/context/interface.nr @fcarreiro @dbanks12 +# on changes to the AVM simulator and supporting modules +/yarn-project/simulator/src/avm @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/execution.ts @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/executor.ts @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/side_effect_trace.test.ts @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/side_effect_trace.ts @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/side_effect_trace_interface.ts @fcarreiro @dbanks12 +/yarn-project/simulator/src/public/transitional_adaptors.ts @fcarreiro @dbanks12 +# on changes to the AVM transpiler +/avm-transpiler/src @fcarreiro @dbanks12 +##################################################### -# Notify the Noir team of any changes to ACIR serialization -/noir/noir-repo/acvm-repo/acir/codegen/* @TomAFrench @vezenovm @guipublic diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index d2508be6360e..b994cf1a68cd 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 2d7b8b24571369e693e7e19470d7c85f0560368c - parent = 77761c670f2d516ab486de0f7bde036ff00ebd99 + commit = 947c5552eeb784dad1abb5ecebdb6a80880fec08 + parent = 94954131ea61bb6b58efe4e9f8b4e1f489f53fa9 method = merge cmdver = 0.4.6 diff --git a/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh index a013a7129b38..30548202ad3f 100755 --- a/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh +++ b/barretenberg/acir_tests/gen_inner_proof_inputs_ultra_honk.sh @@ -3,7 +3,7 @@ # BIN: to specify a different binary to test with (e.g. bb.js or bb.js-dev). set -eu -BIN=${BIN:-../cpp/build-debug/bin/bb} +BIN=${BIN:-../cpp/build/bin/bb} CRS_PATH=~/.bb-crs BRANCH=master VERBOSE=${VERBOSE:-} diff --git a/barretenberg/cpp/pil/avm/binary.pil b/barretenberg/cpp/pil/avm/binary.pil index 441f4c56bd19..c951481caf61 100644 --- a/barretenberg/cpp/pil/avm/binary.pil +++ b/barretenberg/cpp/pil/avm/binary.pil @@ -1,6 +1,4 @@ - -include "byte_lookup.pil"; -include "main.pil"; +include "fixed/byte_lookup.pil"; namespace binary(256); diff --git a/barretenberg/cpp/pil/avm/byte_lookup.pil b/barretenberg/cpp/pil/avm/fixed/byte_lookup.pil similarity index 99% rename from barretenberg/cpp/pil/avm/byte_lookup.pil rename to barretenberg/cpp/pil/avm/fixed/byte_lookup.pil index a91272a86e6d..1759bf838991 100644 --- a/barretenberg/cpp/pil/avm/byte_lookup.pil +++ b/barretenberg/cpp/pil/avm/fixed/byte_lookup.pil @@ -1,4 +1,3 @@ - namespace byte_lookup(256); // These columns are commited for now, but will be migrated to constant/fixed when // we support more *exotic* code generation options diff --git a/barretenberg/cpp/pil/avm/gas.pil b/barretenberg/cpp/pil/avm/fixed/gas.pil similarity index 63% rename from barretenberg/cpp/pil/avm/gas.pil rename to barretenberg/cpp/pil/avm/fixed/gas.pil index 0a1ed20bdb28..e366c85c67f4 100644 --- a/barretenberg/cpp/pil/avm/gas.pil +++ b/barretenberg/cpp/pil/avm/fixed/gas.pil @@ -5,4 +5,9 @@ namespace gas(256); // TODO(ISSUE_NUMBER): Constrain variable gas costs pol commit l2_gas_fixed_table; - pol commit da_gas_fixed_table; \ No newline at end of file + pol commit da_gas_fixed_table; + + // DUMMY RELATIONS to force creation of hpp. + sel_gas_cost - sel_gas_cost = 0; + l2_gas_fixed_table - l2_gas_fixed_table = 0; + da_gas_fixed_table - da_gas_fixed_table = 0; \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/fixed/powers.pil b/barretenberg/cpp/pil/avm/fixed/powers.pil new file mode 100644 index 000000000000..bc497eca04cc --- /dev/null +++ b/barretenberg/cpp/pil/avm/fixed/powers.pil @@ -0,0 +1,9 @@ +// This table should eventually be fixed. +// Contains 256 rows with the powers of 2 for 8-bit numbers. +// power_of_2 = 1 << clk; +namespace powers(256); + // clk will be the implicit power. + pol commit power_of_2; + + // DUMMY RELATION to force creation of hpp. + power_of_2 - power_of_2 = 0; \ No newline at end of file diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 36b2b6e2b97b..19e445d62907 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -3,7 +3,8 @@ include "alu.pil"; include "binary.pil"; include "constants.pil"; include "kernel.pil"; -include "gas.pil"; +include "fixed/gas.pil"; +include "fixed/powers.pil"; include "gadgets/conversion.pil"; include "gadgets/sha256.pil"; include "gadgets/poseidon2.pil"; @@ -139,9 +140,6 @@ namespace main(256); pol commit sel_rng_8; // Boolean selector for the 8-bit range check lookup pol commit sel_rng_16; // Boolean selector for the 16-bit range check lookup - //===== Lookup table powers of 2 ============================================= - pol commit table_pow_2; // Table of powers of 2 for 8-bit numbers. - //===== CONTROL FLOW ========================================================== // Program counter pol commit pc; @@ -487,6 +485,11 @@ namespace main(256); sel_gas_accounting_active - OPCODE_SELECTORS - SEL_ALL_CTRL_FLOW - sel_op_sload - sel_op_sstore - sel_mem_op_activate_gas = 0; // Program counter must increment if not jumping or returning + // TODO: support for muli-rows opcode in execution trace such as + // radix, hash gadgets operations. At the moment, we have to increment + // the pc in witness generation for all rows pertaining to the original + // opcode. This is misleading. Ultimately, we want the pc to be incremented + // just after the last row of a given opcode. #[PC_INCREMENT] (1 - sel_first) * (1 - sel_op_halt) * OPCODE_SELECTORS * (pc' - (pc + 1)) = 0; @@ -768,11 +771,11 @@ namespace main(256); // Lookup for 2**(ib) #[LOOKUP_POW_2_0] - alu.sel_shift_which {alu.ib, alu.two_pow_s} in sel_rng_8 {clk, table_pow_2}; + alu.sel_shift_which {alu.ib, alu.two_pow_s} in sel_rng_8 {clk, powers.power_of_2}; // Lookup for 2**(t-ib) #[LOOKUP_POW_2_1] - alu.sel_shift_which {alu.t_sub_s_bits , alu.two_pow_t_sub_s} in sel_rng_8 {clk, table_pow_2}; + alu.sel_shift_which {alu.t_sub_s_bits , alu.two_pow_t_sub_s} in sel_rng_8 {clk, powers.power_of_2}; //====== Inter-table Constraints (Range Checks) ============================================ // TODO: Investigate optimising these range checks. Handling non-FF elements should require less range checks. diff --git a/barretenberg/cpp/pil/avm/mem.pil b/barretenberg/cpp/pil/avm/mem.pil index a5aa3080f03b..0cb9d7c491ae 100644 --- a/barretenberg/cpp/pil/avm/mem.pil +++ b/barretenberg/cpp/pil/avm/mem.pil @@ -171,10 +171,14 @@ namespace mem(256); // instead of (r_in_tag - tag)^(-1) as this allows to store zero by default (i.e., when tag_err == 0). // The new column one_min_inv is set to 1 - (r_in_tag - tag)^(-1) when tag_err == 1 // but must be set to 0 when tags are matching and tag_err = 0 + // Relaxation: This relation is relaxed when skip_check_tag is enabled or for + // uninitialized memory, i.e. tag == 0. #[MEM_IN_TAG_CONSISTENCY_1] - (1 - skip_check_tag) * (1 - rw) * ((r_in_tag - tag) * (1 - one_min_inv) - tag_err) = 0; + tag * (1 - skip_check_tag) * (1 - rw) * ((r_in_tag - tag) * (1 - one_min_inv) - tag_err) = 0; + // TODO: Try to decrease the degree of the above relation, e.g., skip_check_tag might be consolidated + // with tag == 0 and rw == 1. #[MEM_IN_TAG_CONSISTENCY_2] - (1 - tag_err) * one_min_inv = 0; + tag * (1 - tag_err) * one_min_inv = 0; #[NO_TAG_ERR_WRITE_OR_SKIP] (skip_check_tag + rw) * tag_err = 0; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp index 2f4b2cd88f40..fac0f30f3b59 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ipa_bench/ipa.bench.cpp @@ -43,7 +43,7 @@ void ipa_open(State& state) noexcept auto prover_transcript = std::make_shared(); state.ResumeTiming(); // Compute proof - IPA::compute_opening_proof(ck, opening_pair, poly, prover_transcript); + IPA::compute_opening_proof(ck, { poly, opening_pair }, prover_transcript); // Store info for verifier prover_transcripts[static_cast(state.range(0)) - MIN_POLYNOMIAL_DEGREE_LOG2] = prover_transcript; opening_claims[static_cast(state.range(0)) - MIN_POLYNOMIAL_DEGREE_LOG2] = opening_claim; diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp index 6e7069f08ae2..f735d2cfb190 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp @@ -65,7 +65,7 @@ BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); -BENCHMARK(execute_relation_for_pg_univariates>); +BENCHMARK(execute_relation_for_pg_univariates>); BENCHMARK(execute_relation_for_pg_univariates>); // Goblin-Ultra only relations (PG prover combiner work) @@ -79,7 +79,7 @@ BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); -BENCHMARK(execute_relation_for_univariates>); +BENCHMARK(execute_relation_for_univariates>); BENCHMARK(execute_relation_for_univariates>); // Goblin-Ultra only relations (Sumcheck prover work) @@ -93,7 +93,7 @@ BENCHMARK(execute_relation_for_values>) BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); -BENCHMARK(execute_relation_for_values>); +BENCHMARK(execute_relation_for_values>); BENCHMARK(execute_relation_for_values>); // Goblin-Ultra only relations (verifier work) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp index 2d8cbe748e34..5625d4fddac3 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp @@ -60,7 +60,7 @@ BB_PROFILE static void test_round_inner(State& state, MegaProver& prover, size_t DeciderProver_ decider_prover(prover.instance, prover.transcript); time_if_index(RELATION_CHECK, [&] { decider_prover.execute_relation_check_rounds(); }); - time_if_index(ZEROMORPH, [&] { decider_prover.execute_zeromorph_rounds(); }); + time_if_index(ZEROMORPH, [&] { decider_prover.execute_pcs_rounds(); }); } BB_PROFILE static void test_round(State& state, size_t index) noexcept { diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp index 005a50ea156a..5d1eec577415 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_builder.test.cpp @@ -1,6 +1,7 @@ #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" #include @@ -104,6 +105,22 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) EXPECT_EQ(result, true); } +TEST(ultra_circuit_constructor, bad_lookup_failure) +{ + UltraCircuitBuilder builder; + MockCircuits::add_lookup_gates(builder); + + // Erroneously set a non-zero wire value to zero in one of the lookup gates + for (auto& wire_3_witness_idx : builder.blocks.lookup.w_o()) { + if (wire_3_witness_idx != builder.zero_idx) { + wire_3_witness_idx = builder.zero_idx; + break; + } + } + + EXPECT_FALSE(CircuitChecker::check(builder)); +} + TEST(ultra_circuit_constructor, base_case) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.fuzzer.cpp index cebb8c59c7af..df6c3ec3115c 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.fuzzer.cpp @@ -21,11 +21,10 @@ class ProxyCaller { public: template static void compute_opening_proof_internal(const std::shared_ptr>& ck, - const OpeningPair& opening_pair, - const Polynomial& polynomial, + const ProverOpeningClaim& opening_claim, const std::shared_ptr& transcript) { - IPA::compute_opening_proof_internal(ck, opening_pair, polynomial, transcript); + IPA::compute_opening_proof_internal(ck, opening_claim, transcript); } template static bool verify_internal(const std::shared_ptr>& vk, @@ -145,7 +144,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) } auto const opening_pair = OpeningPair{ x, poly.evaluate(x) }; auto const opening_claim = OpeningClaim{ opening_pair, ck->commit(poly) }; - ProxyCaller::compute_opening_proof_internal(ck, opening_pair, poly, transcript); + ProxyCaller::compute_opening_proof_internal(ck, { poly, opening_pair }, transcript); // Reset challenge indices transcript->reset_indices(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp index 288ad34b3ab9..0fcc7c65841d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.hpp @@ -130,10 +130,12 @@ template class IPA { */ template static void compute_opening_proof_internal(const std::shared_ptr& ck, - const OpeningPair& opening_pair, - const Polynomial& polynomial, + const ProverOpeningClaim& opening_claim, const std::shared_ptr& transcript) { + + Polynomial polynomial = opening_claim.polynomial; + // clang-format on auto poly_length = static_cast(polynomial.size()); @@ -184,6 +186,7 @@ template class IPA { // Step 5. // Compute vector b (vector of the powers of the challenge) + OpeningPair opening_pair = opening_claim.opening_pair; std::vector b_vec(poly_length); run_loop_in_parallel_if_effective( poly_length, @@ -603,11 +606,10 @@ template class IPA { * compute_opening_proof_internal \endlink. */ static void compute_opening_proof(const std::shared_ptr& ck, - const OpeningPair& opening_pair, - const Polynomial& polynomial, + const ProverOpeningClaim& opening_claim, const std::shared_ptr& transcript) { - compute_opening_proof_internal(ck, opening_pair, polynomial, transcript); + compute_opening_proof_internal(ck, opening_claim, transcript); } /** diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp index 4defedb4500a..db8a2597a5b2 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/ipa/ipa.test.cpp @@ -67,7 +67,7 @@ TEST_F(IPATest, OpenZeroPolynomial) // initialize empty prover transcript auto prover_transcript = std::make_shared(); - IPA::compute_opening_proof(this->ck(), opening_pair, poly, prover_transcript); + IPA::compute_opening_proof(this->ck(), { poly, opening_pair }, prover_transcript); // initialize verifier transcript from proof data auto verifier_transcript = std::make_shared(prover_transcript->proof_data); @@ -92,7 +92,7 @@ TEST_F(IPATest, OpenAtZero) // initialize empty prover transcript auto prover_transcript = std::make_shared(); - IPA::compute_opening_proof(this->ck(), opening_pair, poly, prover_transcript); + IPA::compute_opening_proof(this->ck(), { poly, opening_pair }, prover_transcript); // initialize verifier transcript from proof data auto verifier_transcript = std::make_shared(prover_transcript->proof_data); @@ -131,7 +131,7 @@ TEST_F(IPATest, ChallengesAreZero) auto new_random_vector = random_vector; new_random_vector[i] = Fr::zero(); transcript->initialize(new_random_vector); - EXPECT_ANY_THROW(IPA::compute_opening_proof_internal(this->ck(), opening_pair, poly, transcript)); + EXPECT_ANY_THROW(IPA::compute_opening_proof_internal(this->ck(), { poly, opening_pair }, transcript)); } // Fill out a vector of affine elements that the verifier receives from the prover with generators (we don't care // about them right now) @@ -181,7 +181,7 @@ TEST_F(IPATest, AIsZeroAfterOneRound) transcript->initialize(random_vector); // Compute opening proof - IPA::compute_opening_proof_internal(this->ck(), opening_pair, poly, transcript); + IPA::compute_opening_proof_internal(this->ck(), { poly, opening_pair }, transcript); // Reset indices transcript->reset_indices(); @@ -221,7 +221,7 @@ TEST_F(IPATest, Open) // initialize empty prover transcript auto prover_transcript = std::make_shared(); - IPA::compute_opening_proof(this->ck(), opening_pair, poly, prover_transcript); + IPA::compute_opening_proof(this->ck(), { poly, opening_pair }, prover_transcript); // initialize verifier transcript from proof data auto verifier_transcript = std::make_shared(prover_transcript->proof_data); @@ -295,22 +295,18 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( mle_opening_point, std::move(gemini_polynomials), r_challenge); + std::vector> opening_claims; + for (size_t l = 0; l < log_n; ++l) { std::string label = "Gemini:a_" + std::to_string(l); const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; prover_transcript->send_to_verifier(label, evaluation); + opening_claims.emplace_back(gemini_witnesses[l], gemini_opening_pairs[l]); } + opening_claims.emplace_back(gemini_witnesses[log_n], gemini_opening_pairs[log_n]); - const Fr nu_challenge = prover_transcript->template get_challenge("Shplonk:nu"); - auto batched_quotient_Q = - ShplonkProver::compute_batched_quotient(gemini_opening_pairs, gemini_witnesses, nu_challenge); - prover_transcript->send_to_verifier("Shplonk:Q", this->ck()->commit(batched_quotient_Q)); - - const Fr z_challenge = prover_transcript->template get_challenge("Shplonk:z"); - const auto [shplonk_opening_pair, shplonk_witness] = ShplonkProver::compute_partially_evaluated_batched_quotient( - gemini_opening_pairs, gemini_witnesses, std::move(batched_quotient_Q), nu_challenge, z_challenge); - - IPA::compute_opening_proof(this->ck(), shplonk_opening_pair, shplonk_witness, prover_transcript); + const auto opening_claim = ShplonkProver::prove(this->ck(), opening_claims, prover_transcript); + IPA::compute_opening_proof(this->ck(), opening_claim, prover_transcript); auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); @@ -321,7 +317,7 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) verifier_transcript); const auto shplonk_verifier_claim = - ShplonkVerifier::reduce_verification(this->vk(), gemini_verifier_claim, verifier_transcript); + ShplonkVerifier::reduce_verification(this->vk()->get_g1_identity(), gemini_verifier_claim, verifier_transcript); auto result = IPA::reduce_verify(this->vk(), shplonk_verifier_claim, verifier_transcript); EXPECT_EQ(result, true); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp index c763f3a2ecf4..a067b224fc6f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.hpp @@ -26,19 +26,19 @@ template class KZG { * @brief Computes the KZG commitment to an opening proof polynomial at a single evaluation point * * @param ck The commitment key which has a commit function, the srs and pippenger_runtime_state - * @param opening_pair OpeningPair = {r, v = p(r)} - * @param polynomial The witness whose opening proof needs to be computed + * @param opening_claim {p, (r, v = p(r))} where p is the witness polynomial whose opening proof needs to be + * computed * @param prover_transcript Prover transcript */ static void compute_opening_proof(std::shared_ptr ck, - const OpeningPair& opening_pair, - const Polynomial& polynomial, + const ProverOpeningClaim& opening_claim, const std::shared_ptr& prover_trancript) { - Polynomial quotient = polynomial; - quotient[0] -= opening_pair.evaluation; + Polynomial quotient = opening_claim.polynomial; + OpeningPair pair = opening_claim.opening_pair; + quotient[0] -= pair.evaluation; // Computes the coefficients for the quotient polynomial q(X) = (p(X) - v) / (X - r) through an FFT - quotient.factor_roots(opening_pair.challenge); + quotient.factor_roots(pair.challenge); auto quotient_commitment = ck->commit(quotient); // TODO(#479): for now we compute the KZG commitment directly to unify the KZG and IPA interfaces but in the // future we might need to adjust this to use the incoming alternative to work queue (i.e. variation of diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 5271e92b8901..5dd1fa892c4a 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -41,7 +41,7 @@ TYPED_TEST(KZGTest, single) auto prover_transcript = NativeTranscript::prover_init_empty(); - KZG::compute_opening_proof(this->ck(), opening_pair, witness, prover_transcript); + KZG::compute_opening_proof(this->ck(), { witness, opening_pair }, prover_transcript); auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); auto pairing_points = KZG::reduce_verify(opening_claim, verifier_transcript); @@ -130,27 +130,23 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( mle_opening_point, std::move(gemini_polynomials), r_challenge); + std::vector> opening_claims; for (size_t l = 0; l < log_n; ++l) { std::string label = "Gemini:a_" + std::to_string(l); const auto& evaluation = gemini_opening_pairs[l + 1].evaluation; prover_transcript->send_to_verifier(label, evaluation); + opening_claims.emplace_back(gemini_witnesses[l], gemini_opening_pairs[l]); } + opening_claims.emplace_back(gemini_witnesses[log_n], gemini_opening_pairs[log_n]); // Shplonk prover output: // - opening pair: (z_challenge, 0) // - witness: polynomial Q - Q_z - const Fr nu_challenge = prover_transcript->template get_challenge("Shplonk:nu"); - auto batched_quotient_Q = - ShplonkProver::compute_batched_quotient(gemini_opening_pairs, gemini_witnesses, nu_challenge); - prover_transcript->send_to_verifier("Shplonk:Q", this->ck()->commit(batched_quotient_Q)); - - const Fr z_challenge = prover_transcript->template get_challenge("Shplonk:z"); - const auto [shplonk_opening_pair, shplonk_witness] = ShplonkProver::compute_partially_evaluated_batched_quotient( - gemini_opening_pairs, gemini_witnesses, std::move(batched_quotient_Q), nu_challenge, z_challenge); + const auto opening_claim = ShplonkProver::prove(this->ck(), opening_claims, prover_transcript); // KZG prover: // - Adds commitment [W] to transcript - KZG::compute_opening_proof(this->ck(), shplonk_opening_pair, shplonk_witness, prover_transcript); + KZG::compute_opening_proof(this->ck(), opening_claim, prover_transcript); // Run the full verifier PCS protocol with genuine opening claims (genuine commitment, genuine evaluation) @@ -166,7 +162,7 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Shplonk verifier claim: commitment [Q] - [Q_z], opening point (z_challenge, 0) const auto shplonk_verifier_claim = - ShplonkVerifier::reduce_verification(this->vk(), gemini_verifier_claim, verifier_transcript); + ShplonkVerifier::reduce_verification(this->vk()->get_g1_identity(), gemini_verifier_claim, verifier_transcript); // KZG verifier: // aggregates inputs [Q] - [Q_z] and [W] into an 'accumulator' (can perform pairing check on result) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp index 74b3b500e797..9eac7b4a48c6 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.hpp @@ -20,24 +20,6 @@ */ namespace bb { -/** - * @brief Polynomial G(X) = Q(X) - ∑ₖ ẑₖ(r)⋅( Bₖ(X) − Tₖ(z) ), where Q(X) = ∑ₖ ( Bₖ(X) − Tₖ(X) ) / zₖ(X) - * - * @tparam Curve EC parameters - */ -template using OutputWitness = bb::Polynomial; - -/** - * @brief Prover output (claim=([G], r, 0), witness = G(X), proof = [Q]) - * that can be passed on to a univariate opening protocol. - * - * @tparam Curve EC parameters - */ -template struct ShplonkProverOutput { - OpeningPair opening_pair; // single opening pair (challenge, evaluation) - OutputWitness witness; // single polynomial G(X) -}; - /** * @brief Shplonk Prover * @@ -51,34 +33,31 @@ template class ShplonkProver_ { /** * @brief Compute batched quotient polynomial Q(X) = ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) * - * @param opening_pairs list of opening pairs (xⱼ, vⱼ) for a witness polynomial fⱼ(X), s.t. fⱼ(xⱼ) = vⱼ. - * @param witness_polynomials list of polynomials fⱼ(X). - * @param nu + * @param opening_claims list of prover opening claims {fⱼ(X), (xⱼ, vⱼ)} for a witness polynomial fⱼ(X), s.t. fⱼ(xⱼ) + * = vⱼ. + * @param nu batching challenge * @return Polynomial Q(X) */ - static Polynomial compute_batched_quotient(std::span> opening_pairs, - std::span witness_polynomials, - const Fr& nu) + static Polynomial compute_batched_quotient(std::span> opening_claims, const Fr& nu) { // Find n, the maximum size of all polynomials fⱼ(X) size_t max_poly_size{ 0 }; - for (const auto& poly : witness_polynomials) { - max_poly_size = std::max(max_poly_size, poly.size()); + for (const auto& claim : opening_claims) { + max_poly_size = std::max(max_poly_size, claim.polynomial.size()); } // Q(X) = ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) Polynomial Q(max_poly_size); Polynomial tmp(max_poly_size); Fr current_nu = Fr::one(); - for (size_t j = 0; j < opening_pairs.size(); ++j) { - // (Cⱼ, xⱼ, vⱼ) - const auto& [challenge, evaluation] = opening_pairs[j]; + for (const auto& claim : opening_claims) { - // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) - tmp = witness_polynomials[j]; - tmp[0] -= evaluation; - tmp.factor_roots(challenge); + // Compute individual claim quotient tmp = ( fⱼ(X) − vⱼ) / ( X − xⱼ ) + tmp = claim.polynomial; + tmp[0] -= claim.opening_pair.evaluation; + tmp.factor_roots(claim.opening_pair.challenge); + // Add the claim quotient to the batched quotient polynomial Q.add_scaled(tmp, current_nu); current_nu *= nu; } @@ -97,20 +76,19 @@ template class ShplonkProver_ { * @param z_challenge * @return Output{OpeningPair, Polynomial} */ - static ShplonkProverOutput compute_partially_evaluated_batched_quotient( - std::span> opening_pairs, - std::span witness_polynomials, - Polynomial&& batched_quotient_Q, + static ProverOpeningClaim compute_partially_evaluated_batched_quotient( + std::span> opening_claims, + Polynomial& batched_quotient_Q, const Fr& nu_challenge, const Fr& z_challenge) { - const size_t num_opening_pairs = opening_pairs.size(); + const size_t num_opening_claims = opening_claims.size(); // {ẑⱼ(r)}ⱼ , where ẑⱼ(r) = 1/zⱼ(r) = 1/(r - xⱼ) std::vector inverse_vanishing_evals; - inverse_vanishing_evals.reserve(num_opening_pairs); - for (const auto& pair : opening_pairs) { - inverse_vanishing_evals.emplace_back(z_challenge - pair.challenge); + inverse_vanishing_evals.reserve(num_opening_claims); + for (const auto& claim : opening_claims) { + inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge); } Fr::batch_invert(inverse_vanishing_evals); @@ -121,24 +99,44 @@ template class ShplonkProver_ { // G₀ = ∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ) Fr current_nu = Fr::one(); Polynomial tmp(G.size()); - for (size_t j = 0; j < num_opening_pairs; ++j) { - // (Cⱼ, xⱼ, vⱼ) - const auto& [challenge, evaluation] = opening_pairs[j]; - + size_t idx = 0; + for (const auto& claim : opening_claims) { // tmp = ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) - tmp = witness_polynomials[j]; - tmp[0] -= evaluation; - Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ ) + tmp = claim.polynomial; + tmp[0] -= claim.opening_pair.evaluation; + Fr scaling_factor = current_nu * inverse_vanishing_evals[idx]; // = ρʲ / ( r − xⱼ ) // G -= ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ ) G.add_scaled(tmp, -scaling_factor); current_nu *= nu_challenge; + idx++; } // Return opening pair (z, 0) and polynomial G(X) = Q(X) - Q_z(X) - return { .opening_pair = { .challenge = z_challenge, .evaluation = Fr::zero() }, .witness = std::move(G) }; + return { .polynomial = G, .opening_pair = { .challenge = z_challenge, .evaluation = Fr::zero() } }; }; + + /** + * @brief Returns a batched opening claim equivalent to a set of opening claims consisting of polynomials, each + * opened at a single point. + * + * @param commitment_key + * @param opening_claims + * @param transcript + * @return ProverOpeningClaim + */ + static ProverOpeningClaim prove(const std::shared_ptr>& commitment_key, + std::span> opening_claims, + auto& transcript) + { + const Fr nu = transcript->template get_challenge("Shplonk:nu"); + auto batched_quotient = compute_batched_quotient(opening_claims, nu); + auto batched_quotient_commitment = commitment_key->commit(batched_quotient); + transcript->send_to_verifier("Shplonk:Q", batched_quotient_commitment); + const Fr z = transcript->template get_challenge("Shplonk:z"); + return compute_partially_evaluated_batched_quotient(opening_claims, batched_quotient, nu, z); + } }; /** @@ -156,12 +154,12 @@ template class ShplonkVerifier_ { * @brief Recomputes the new claim commitment [G] given the proof and * the challenge r. No verification happens so this function always succeeds. * + * @param g1_identity the identity element for the Curve * @param claims list of opening claims (Cⱼ, xⱼ, vⱼ) for a witness polynomial fⱼ(X), s.t. fⱼ(xⱼ) = vⱼ. - * @param proof [Q(X)] = [ ∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( X − xⱼ ) ] * @param transcript * @return OpeningClaim */ - static OpeningClaim reduce_verification(std::shared_ptr vk, + static OpeningClaim reduce_verification(Commitment g1_identity, std::span> claims, auto& transcript) { @@ -227,7 +225,7 @@ template class ShplonkVerifier_ { scalars.emplace_back(-scaling_factor); } - commitments.emplace_back(GroupElement::one(builder)); + commitments.emplace_back(g1_identity); scalars.emplace_back(G_commitment_constant); // [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1] @@ -264,7 +262,7 @@ template class ShplonkVerifier_ { } // [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1] - G_commitment += vk->get_first_g1() * G_commitment_constant; + G_commitment += g1_identity * G_commitment_constant; } // Return opening pair (z, 0) and commitment [G] diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp index 359766165269..299ee846a2a4 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplonk.test.cpp @@ -22,8 +22,8 @@ TYPED_TEST(ShplonkTest, ShplonkSimple) using ShplonkProver = ShplonkProver_; using ShplonkVerifier = ShplonkVerifier_; using Fr = typename TypeParam::ScalarField; - using Polynomial = typename bb::Polynomial; - using OpeningPair = bb::OpeningPair; + using ProverOpeningClaim = ProverOpeningClaim; + using OpeningClaim = OpeningClaim; const size_t n = 16; @@ -43,32 +43,23 @@ TYPED_TEST(ShplonkTest, ShplonkSimple) const auto commitment2 = this->commit(poly2); // Aggregate polynomials and their opening pairs - std::vector opening_pairs = { { r1, eval1 }, { r2, eval2 } }; - std::vector polynomials = { poly1.share(), poly2.share() }; + std::vector prover_opening_claims = { { poly1, { r1, eval1 } }, { poly2, { r2, eval2 } } }; // Execute the shplonk prover functionality - const Fr nu_challenge = prover_transcript->template get_challenge("Shplonk:nu"); - auto batched_quotient_Q = ShplonkProver::compute_batched_quotient(opening_pairs, polynomials, nu_challenge); - prover_transcript->send_to_verifier("Shplonk:Q", this->ck()->commit(batched_quotient_Q)); - - const Fr z_challenge = prover_transcript->template get_challenge("Shplonk:z"); - const auto [prover_opening_pair, shplonk_prover_witness] = - ShplonkProver::compute_partially_evaluated_batched_quotient( - opening_pairs, polynomials, std::move(batched_quotient_Q), nu_challenge, z_challenge); - + const auto batched_opening_claim = ShplonkProver::prove(this->ck(), prover_opening_claims, prover_transcript); // An intermediate check to confirm the opening of the shplonk prover witness Q - this->verify_opening_pair(prover_opening_pair, shplonk_prover_witness); + this->verify_opening_pair(batched_opening_claim.opening_pair, batched_opening_claim.polynomial); // Aggregate polynomial commitments and their opening pairs - std::vector opening_claims; - opening_claims.emplace_back(OpeningClaim{ opening_pairs[0], commitment1 }); - opening_claims.emplace_back(OpeningClaim{ opening_pairs[1], commitment2 }); + std::vector verifier_opening_claims = { { { r1, eval1 }, commitment1 }, + { { r2, eval2 }, commitment2 } }; auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); // Execute the shplonk verifier functionality - const auto verifier_claim = ShplonkVerifier::reduce_verification(this->vk(), opening_claims, verifier_transcript); + const auto batched_verifier_claim = ShplonkVerifier::reduce_verification( + this->vk()->get_g1_identity(), verifier_opening_claims, verifier_transcript); - this->verify_opening_claim(verifier_claim, shplonk_prover_witness); + this->verify_opening_claim(batched_verifier_claim, batched_opening_claim.polynomial); } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp index 42fac7a1fab0..23fb76a95029 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp @@ -40,7 +40,7 @@ template <> class VerifierCommitmentKey { srs = srs::get_crs_factory()->get_verifier_crs(); }; - Commitment get_first_g1() { return srs->get_first_g1(); } + Commitment get_g1_identity() { return srs->get_g1_identity(); } /** * @brief verifies a pairing equation over 2 points using the verifier SRS @@ -93,7 +93,7 @@ template <> class VerifierCommitmentKey { srs = srs::get_crs_factory()->get_verifier_crs(num_points); } - Commitment get_first_g1() { return srs->get_first_g1(); } + Commitment get_g1_identity() { return srs->get_g1_identity(); } Commitment* get_monomial_points() { return srs->get_monomial_points(); } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index fe8947cbf01e..f6a77ba302c8 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -31,13 +31,13 @@ template inline std::vector powers_of_challenge(const FF challeng /** * @brief Prover for ZeroMorph multilinear PCS * - * @tparam PCS - The univariate PCS used inside ZeroMorph as a building block + * @tparam Curve - The curve used for arithmetising ZeroMorph */ -template class ZeroMorphProver_ { - using Curve = typename PCS::Curve; +template class ZeroMorphProver_ { using FF = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; using Polynomial = bb::Polynomial; + using OpeningClaim = ProverOpeningClaim; // TODO(#742): Set this N_max to be the number of G1 elements in the mocked zeromorph SRS once it's in place. // (Then, eventually, set it based on the real SRS). For now we set it to be larger then the Client IVC recursive @@ -65,7 +65,8 @@ template class ZeroMorphProver_ { * @param u_challenge Multivariate challenge u = (u_0, ..., u_{d-1}) * @return std::vector The quotients q_k */ - static std::vector compute_multilinear_quotients(Polynomial polynomial, std::span u_challenge) + static std::vector compute_multilinear_quotients(Polynomial& polynomial, + std::span u_challenge) { size_t log_N = numeric::get_msb(polynomial.size()); // The size of the multilinear challenge must equal the log of the polynomial size @@ -310,8 +311,8 @@ template class ZeroMorphProver_ { } /** - * @brief Prove a set of multilinear evaluation claims for unshifted polynomials f_i and to-be-shifted - * polynomials g_i + * @brief * @brief Returns a univariate opening claim equivalent to a set of multilinear evaluation claims for + * unshifted polynomials f_i and to-be-shifted polynomials g_i to be subsequently proved with a univariate PCS * * @param f_polynomials Unshifted polynomials * @param g_polynomials To-be-shifted polynomials (of which the shifts h_i were evaluated by sumcheck) @@ -319,17 +320,19 @@ template class ZeroMorphProver_ { * @param multilinear_challenge Multilinear challenge point u * @param commitment_key * @param transcript + * + * @todo https://github.com/AztecProtocol/barretenberg/issues/1030: document concatenation trick */ - static void prove(RefSpan f_polynomials, - RefSpan g_polynomials, - RefSpan f_evaluations, - RefSpan g_shift_evaluations, - std::span multilinear_challenge, - const std::shared_ptr>& commitment_key, - const std::shared_ptr& transcript, - RefSpan concatenated_polynomials = {}, - RefSpan concatenated_evaluations = {}, - const std::vector>& concatenation_groups = {}) + static OpeningClaim prove(RefSpan f_polynomials, + RefSpan g_polynomials, + RefSpan f_evaluations, + RefSpan g_shift_evaluations, + std::span multilinear_challenge, + const std::shared_ptr>& commitment_key, + const std::shared_ptr& transcript, + RefSpan concatenated_polynomials = {}, + RefSpan concatenated_evaluations = {}, + const std::vector>& concatenation_groups = {}) { // Generate batching challenge \rho and powers 1,...,\rho^{m-1} const FF rho = transcript->template get_challenge("rho"); @@ -428,22 +431,20 @@ template class ZeroMorphProver_ { // Compute batched degree-check and ZM-identity quotient polynomial pi auto pi_polynomial = compute_batched_evaluation_and_degree_check_polynomial(zeta_x, Z_x, z_challenge); - // Compute opening proof for x_challenge using the underlying univariate PCS - PCS::compute_opening_proof( - commitment_key, { .challenge = x_challenge, .evaluation = FF(0) }, pi_polynomial, transcript); + + // Returns the claim used to generate an opening proof for the univariate polynomial at x_challenge + return { pi_polynomial, { .challenge = x_challenge, .evaluation = FF(0) } }; } }; /** * @brief Verifier for ZeroMorph multilinear PCS * - * @tparam Curve + * @tparam Curve - The Curve used to arithmetise ZeroMorph */ -template class ZeroMorphVerifier_ { - using Curve = typename PCS::Curve; +template class ZeroMorphVerifier_ { using FF = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; - using VerifierAccumulator = typename PCS::VerifierAccumulator; public: /** @@ -458,7 +459,10 @@ template class ZeroMorphVerifier_ { * @param x_challenge * @return Commitment */ - static Commitment compute_C_zeta_x(Commitment C_q, std::vector& C_q_k, FF y_challenge, FF x_challenge) + static Commitment compute_C_zeta_x(const Commitment& C_q, + std::vector& C_q_k, + FF y_challenge, + FF x_challenge) { size_t log_N = C_q_k.size(); size_t N = 1 << log_N; @@ -510,7 +514,7 @@ template class ZeroMorphVerifier_ { * * @note The concatenation term arises from an implementation detail in the Translator and is not part of the * conventional ZM protocol - * @param first_g1 first element in the SRS + * @param g1_identity first element in the SRS * @param f_commitments Commitments to unshifted polynomials [f_i] * @param g_commitments Commitments to to-be-shifted polynomials [g_i] * @param C_q_k Commitments to q_k @@ -521,7 +525,7 @@ template class ZeroMorphVerifier_ { * @param concatenation_groups_commitments * @return Commitment */ - static Commitment compute_C_Z_x(Commitment first_g1, + static Commitment compute_C_Z_x(const Commitment& g1_identity, RefSpan f_commitments, RefSpan g_commitments, std::span C_q_k, @@ -544,7 +548,7 @@ template class ZeroMorphVerifier_ { // Add contribution: -v * x * \Phi_n(x) * [1]_1 scalars.emplace_back(FF(-1) * batched_evaluation * x_challenge * phi_n_x); - commitments.emplace_back(first_g1); + commitments.emplace_back(g1_identity); // Add contribution: x * \sum_{i=0}^{m-1} \rho^i*[f_i] auto rho_pow = FF(1); @@ -625,30 +629,24 @@ template class ZeroMorphVerifier_ { } /** - * @brief Compute the univariate opening claim used in the last step of Zeromorph to verify the univariate PCS - * evaluation. + * @brief Return the univariate opening claim used to verify, in a subsequent PCS, a set of multilinear evaluation + * claims for unshifted polynomials f_i and to-be-shifted polynomials g_i * - * @param unshifted_commitments - * @param to_be_shifted_commitments - * @param unshifted_evaluations - * @param shifted_evaluations - * @param multivariate_challenge - * @param first_g1 + * @param commitments Commitments to polynomials f_i and g_i (unshifted and to-be-shifted) + * @param claimed_evaluations Claimed evaluations v_i = f_i(u) and w_i = h_i(u) = g_i_shifted(u) + * @param multivariate_challenge Challenge point u * @param transcript - * @param concatenation_group_commitments - * @param concatenated_evaluations - * @return OpeningClaim + * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated */ - static OpeningClaim compute_univariate_evaluation_opening_claim( - RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - std::span multivariate_challenge, - Commitment first_g1, - auto& transcript, - const std::vector>& concatenation_group_commitments = {}, - RefSpan concatenated_evaluations = {}) + static OpeningClaim verify(RefSpan unshifted_commitments, + RefSpan to_be_shifted_commitments, + RefSpan unshifted_evaluations, + RefSpan shifted_evaluations, + std::span multivariate_challenge, + const Commitment& g1_identity, + auto& transcript, + const std::vector>& concatenation_group_commitments = {}, + RefSpan concatenated_evaluations = {}) { size_t log_N = multivariate_challenge.size(); FF rho = transcript->template get_challenge("rho"); @@ -689,7 +687,7 @@ template class ZeroMorphVerifier_ { auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); // Compute commitment C_{Z_x} - Commitment C_Z_x = compute_C_Z_x(first_g1, + Commitment C_Z_x = compute_C_Z_x(g1_identity, unshifted_commitments, to_be_shifted_commitments, C_q_k, @@ -714,82 +712,6 @@ template class ZeroMorphVerifier_ { return { .opening_pair = { .challenge = x_challenge, .evaluation = FF(0) }, .commitment = C_zeta_Z }; } - - /** - * @brief Verify a set of multilinear evaluation claims for unshifted polynomials f_i and to-be-shifted - * polynomials g_i - * - * @param commitments Commitments to polynomials f_i and g_i (unshifted and to-be-shifted) - * @param claimed_evaluations Claimed evaluations v_i = f_i(u) and w_i = h_i(u) = g_i_shifted(u) - * @param multivariate_challenge Challenge point u - * @param transcript - * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated - */ - static VerifierAccumulator verify(RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - std::span multivariate_challenge, - auto& transcript, - const std::vector>& concatenation_group_commitments = {}, - RefSpan concatenated_evaluations = {}) - { - Commitment first_g1; - - if constexpr (Curve::is_stdlib_type) { - auto builder = multivariate_challenge[0].get_context(); - first_g1 = Commitment::one(builder); - } else { - first_g1 = Commitment::one(); - } - auto opening_claim = compute_univariate_evaluation_opening_claim(unshifted_commitments, - to_be_shifted_commitments, - unshifted_evaluations, - shifted_evaluations, - multivariate_challenge, - first_g1, - transcript, - concatenation_group_commitments, - concatenated_evaluations); - return PCS::reduce_verify(opening_claim, transcript); - } - - /** - * @brief Verify a set of multilinear evaluation claims for unshifted polynomials f_i and to-be-shifted - * polynomials g_i. - * - * @details Identical purpose as the function above but used when the verification of the PCS evaluation protocol - * requires the verification key prior to the last step that is accumulated. - * - * @param commitments Commitments to polynomials f_i and g_i (unshifted and to-be-shifted) - * @param claimed_evaluations Claimed evaluations v_i = f_i(u) and w_i = h_i(u) = g_i_shifted(u) - * @param multivariate_challenge Challenge point u - * @param transcript - * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated - */ - static VerifierAccumulator verify(RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - std::span multivariate_challenge, - const std::shared_ptr>& vk, - auto& transcript, - const std::vector>& concatenation_group_commitments = {}, - RefSpan concatenated_evaluations = {}) - { - Commitment first_g1 = vk->get_first_g1(); - - auto opening_claim = compute_univariate_evaluation_opening_claim(unshifted_commitments, - to_be_shifted_commitments, - unshifted_evaluations, - shifted_evaluations, - multivariate_challenge, - first_g1, - transcript, - concatenation_group_commitments, - concatenated_evaluations); - return PCS::reduce_verify(vk, opening_claim, transcript); - } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 3fcb56aa3af4..122fcb1187fa 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -16,10 +16,42 @@ template class ZeroMorphTest : public CommitmentTest; - using ZeroMorphVerifier = ZeroMorphVerifier_; + using ZeroMorphProver = ZeroMorphProver_; + using ZeroMorphVerifier = ZeroMorphVerifier_; - // Evaluate Phi_k(x) = \sum_{i=0}^k x^i using the direct inefficent formula + using TupleOfConcatenationInputs = std::tuple>, + std::vector, + std::vector, + std::vector>>; + + /** + * @brief Data structure for encapsulating a set of multilinear polynomials used to test the protocol, their + * evaluations at the point that we want to create an evaluation proof for and + * their commitments. Alternatively, the polynomials and commitments can be the ones to-be-shifted, while the + * evaluations are for their shifted version. + * + */ + struct PolynomialsEvaluationsCommitments { + std::vector polynomials; + std::vector evaluations; + std::vector commitments; + }; + + /** + * @brief Data structure used to test the protocol's alternative for Goblin Translator. + * + */ + struct ConcatenationInputs { + std::vector> concatenation_groups; + std::vector concatenated_polynomials; + std::vector c_evaluations; + std::vector> concatenation_groups_commitments; + }; + + /** + * @brief Evaluate Phi_k(x) = \sum_{i=0}^k x^i using the direct inefficent formula + * + */ Fr Phi(Fr challenge, size_t subscript) { size_t length = 1 << subscript; @@ -37,152 +69,91 @@ template class ZeroMorphTest : public CommitmentTest u_challenge = this->random_evaluation_point(log_N); - // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) - std::vector f_polynomials; // unshifted polynomials - std::vector v_evaluations; - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(this->random_polynomial(N)); - f_polynomials[i][0] = Fr(0); // ensure f is "shiftable" - v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); - } - - // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i - std::vector g_polynomials; // to-be-shifted polynomials - std::vector h_polynomials; // shifts of the to-be-shifted polynomials - std::vector w_evaluations; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_polynomials.emplace_back(f_polynomials[i]); - h_polynomials.emplace_back(g_polynomials[i].shifted()); - w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); - // ASSERT_EQ(w_evaluations[i], g_polynomials[i].evaluate_mle(u_challenge, /* shift = */ true)); - } - - // Compute commitments [f_i] - std::vector f_commitments; - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_commitments.emplace_back(this->commit(f_polynomials[i])); - } - - // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) - std::vector g_commitments; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_commitments.emplace_back(f_commitments[i]); - } - - // Initialize an empty NativeTranscript - auto prover_transcript = NativeTranscript::prover_init_empty(); - - // Execute Prover protocol - ZeroMorphProver::prove(RefVector(f_polynomials), - RefVector(g_polynomials), - RefVector(v_evaluations), - RefVector(w_evaluations), - u_challenge, - this->commitment_key, - prover_transcript); + // Construct some random multilinear polynomials f_i, their commitments and their evaluations v_i = f_i(u) + PolynomialsEvaluationsCommitments unshifted_input = + polynomials_comms_and_evaluations(u_challenge, NUM_UNSHIFTED); - auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + // Construct polynomials and commitments from f_i that are to be shifted and compute their shifted evaluations + PolynomialsEvaluationsCommitments shifted_input = + to_be_shifted_polynomials_and_comms_and_shifted_evaluations(unshifted_input, u_challenge, NUM_SHIFTED); - VerifierAccumulator result; bool verified = false; - if constexpr (std::same_as>) { - // Execute Verifier protocol without the need for vk prior the final check - result = ZeroMorphVerifier::verify(RefVector(f_commitments), // unshifted - RefVector(g_commitments), // to-be-shifted - RefVector(v_evaluations), // unshifted - RefVector(w_evaluations), // shifted - u_challenge, - verifier_transcript); - verified = this->vk()->pairing_check(result[0], result[1]); + if (NUM_CONCATENATED == 0) { + verified = prove_and_verify(unshifted_input, shifted_input, u_challenge); } else { - // Execute Verifier protocol with vk - result = ZeroMorphVerifier::verify(RefVector(f_commitments), // unshifted - RefVector(g_commitments), // to-be-shifted - RefVector(v_evaluations), // unshifted - RefVector(w_evaluations), // shifted - u_challenge, - this->vk(), - verifier_transcript); - verified = result; + verified = + prove_and_verify_with_concatenation(unshifted_input, shifted_input, u_challenge, NUM_CONCATENATED); } - // The prover and verifier manifests should agree - EXPECT_EQ(prover_transcript->get_manifest(), verifier_transcript->get_manifest()); - return verified; } -}; - -template class ZeroMorphWithConcatenationTest : public CommitmentTest { - public: - using Curve = typename PCS::Curve; - using Fr = typename Curve::ScalarField; - using Polynomial = bb::Polynomial; - using Commitment = typename Curve::AffineElement; - using GroupElement = typename Curve::Element; - using VerifierAccumulator = typename PCS::VerifierAccumulator; - using ZeroMorphProver = ZeroMorphProver_; - using ZeroMorphVerifier = ZeroMorphVerifier_; - - // Evaluate Phi_k(x) = \sum_{i=0}^k x^i using the direct inefficent formula - Fr Phi(Fr challenge, size_t subscript) - { - size_t length = 1 << subscript; - auto result = Fr(0); - for (size_t idx = 0; idx < length; ++idx) { - result += challenge.pow(idx); - } - return result; - } /** - * @brief Construct and verify ZeroMorph proof of batched multilinear evaluation with shifts and concatenation - * @details The goal is to construct and verify a single batched multilinear evaluation proof for m polynomials f_i, - * l polynomials h_i and o groups of polynomials where each polynomial is concatenated from several shorter - * polynomials. It is assumed that the h_i are shifts of polynomials g_i (the "to-be-shifted" polynomials), which - * are a subset of the f_i. This is what is encountered in practice. We accomplish this using evaluations of h_i but - * commitments to only their unshifted counterparts g_i (which we get for "free" since commitments [g_i] are - * contained in the set of commitments [f_i]). - * + * @brief Generate some random multilinear polynomials and compute their evaluation at the set challenge as well as + * their commitments, returned as a tuple to be used in the subsequent protocol. */ - bool execute_zeromorph_protocol(size_t NUM_UNSHIFTED, size_t NUM_SHIFTED, size_t NUM_CONCATENATED) + PolynomialsEvaluationsCommitments polynomials_comms_and_evaluations(std::vector u_challenge, + size_t NUM_UNSHIFTED) { - bool verified = false; - size_t concatenation_index = 2; - size_t N = 64; - size_t MINI_CIRCUIT_N = N / concatenation_index; - size_t log_N = numeric::get_msb(N); - - auto u_challenge = this->random_evaluation_point(log_N); - // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) std::vector f_polynomials; // unshifted polynomials std::vector v_evaluations; + std::vector f_commitments; + size_t poly_length = 1 << u_challenge.size(); for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(this->random_polynomial(N)); + f_polynomials.emplace_back(this->random_polynomial(poly_length)); f_polynomials[i][0] = Fr(0); // ensure f is "shiftable" v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); + f_commitments.emplace_back(this->commit(f_polynomials[i])); } + return { f_polynomials, v_evaluations, f_commitments }; + } + + /** + * @brief Generate shifts of polynomials and compute their evaluation at the + * set challenge as well as their commitments, returned as a tuple to be used in the subsequent protocol. + */ + PolynomialsEvaluationsCommitments to_be_shifted_polynomials_and_comms_and_shifted_evaluations( + PolynomialsEvaluationsCommitments unshifted_inputs, std::vector u_challenge, size_t NUM_SHIFTED) + { + std::vector f_polynomials = unshifted_inputs.polynomials; + std::vector f_commitments = unshifted_inputs.commitments; - // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i std::vector g_polynomials; // to-be-shifted polynomials std::vector h_polynomials; // shifts of the to-be-shifted polynomials - std::vector w_evaluations; + std::vector w_evaluations; // shifted evaluations + std::vector g_commitments; + + // For testing purposes, pick the first NUM_SHIFTED polynomials to be shifted for (size_t i = 0; i < NUM_SHIFTED; ++i) { g_polynomials.emplace_back(f_polynomials[i]); h_polynomials.emplace_back(g_polynomials[i].shifted()); w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); - // ASSERT_EQ(w_evaluations[i], g_polynomials[i].evaluate_mle(u_challenge, /* shift = */ true)); + g_commitments.emplace_back(f_commitments[i]); } + return { g_polynomials, w_evaluations, g_commitments }; + } + + /** + * @brief Generate the tuple of concatenation inputs used to test Zeromorph special functionality that avoids high + * degrees in the Goblin Translator. + */ + ConcatenationInputs concatenation_inputs(std::vector u_challenge, size_t NUM_CONCATENATED) + { + + size_t concatenation_index = 2; + size_t N = 1 << u_challenge.size(); + size_t MINI_CIRCUIT_N = N / concatenation_index; // Polynomials "chunks" that are concatenated in the PCS std::vector> concatenation_groups; @@ -221,18 +192,6 @@ template class ZeroMorphWithConcatenationTest : public CommitmentTes c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(u_challenge)); } - // Compute commitments [f_i] - std::vector f_commitments; - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_commitments.emplace_back(this->commit(f_polynomials[i])); - } - - // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) - std::vector g_commitments; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_commitments.emplace_back(f_commitments[i]); - } - // Compute commitments of all polynomial chunks std::vector> concatenation_groups_commitments; for (size_t i = 0; i < NUM_CONCATENATED; ++i) { @@ -243,46 +202,100 @@ template class ZeroMorphWithConcatenationTest : public CommitmentTes concatenation_groups_commitments.emplace_back(concatenation_group_commitment); } - // Initialize an empty NativeTranscript + return { concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments }; + }; + + bool prove_and_verify(PolynomialsEvaluationsCommitments& unshifted, + PolynomialsEvaluationsCommitments& shifted, + std::vector u_challenge) + { auto prover_transcript = NativeTranscript::prover_init_empty(); // Execute Prover protocol - ZeroMorphProver::prove(RefVector(f_polynomials), // unshifted - RefVector(g_polynomials), // to-be-shifted - RefVector(v_evaluations), // unshifted - RefVector(w_evaluations), // shifted - u_challenge, - this->commitment_key, - prover_transcript, - RefVector(concatenated_polynomials), - RefVector(c_evaluations), - to_vector_of_ref_vectors(concatenation_groups)); + auto prover_opening_claim = ZeroMorphProver::prove(RefVector(unshifted.polynomials), // unshifted + RefVector(shifted.polynomials), // to-be shifted + RefVector(unshifted.evaluations), // unshifted + RefVector(shifted.evaluations), // shifted + u_challenge, + this->commitment_key, + prover_transcript); + + PCS::compute_opening_proof(this->commitment_key, prover_opening_claim, prover_transcript); auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + auto verifier_opening_claim = ZeroMorphVerifier::verify(RefVector(unshifted.commitments), // unshifted + RefVector(shifted.commitments), // to-be-shifted + RefVector(unshifted.evaluations), // unshifted + RefVector(shifted.evaluations), // shifted + u_challenge, + this->vk()->get_g1_identity(), + verifier_transcript); VerifierAccumulator result; + + bool verified = false; if constexpr (std::same_as>) { - // Execute Verifier protocol without the need for vk prior the final check - result = ZeroMorphVerifier::verify(RefVector(f_commitments), // unshifted - RefVector(g_commitments), // to-be-shifted - RefVector(v_evaluations), // unshifted - RefVector(w_evaluations), // shifted - u_challenge, - verifier_transcript, - to_vector_of_ref_vectors(concatenation_groups_commitments), - RefVector(c_evaluations)); + + result = PCS::reduce_verify(verifier_opening_claim, verifier_transcript); verified = this->vk()->pairing_check(result[0], result[1]); + } else { + // Execute Verifier protocol with vk + result = PCS::reduce_verify(this->vk(), verifier_opening_claim, verifier_transcript); + verified = result; + } + + // The prover and verifier manifests should agree + EXPECT_EQ(prover_transcript->get_manifest(), verifier_transcript->get_manifest()); + return verified; + }; + + bool prove_and_verify_with_concatenation(PolynomialsEvaluationsCommitments& unshifted, + PolynomialsEvaluationsCommitments& shifted, + std::vector u_challenge, + size_t NUM_CONCATENATED) + { + ConcatenationInputs concatenation = concatenation_inputs(u_challenge, NUM_CONCATENATED); + + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Execute Prover protocol + auto prover_opening_claim = + ZeroMorphProver::prove(RefVector(unshifted.polynomials), // unshifted + RefVector(shifted.polynomials), // to-be-shifted + RefVector(unshifted.evaluations), // unshifted + RefVector(shifted.evaluations), // shifted + u_challenge, + this->commitment_key, + prover_transcript, + RefVector(concatenation.concatenated_polynomials), + RefVector(concatenation.c_evaluations), + to_vector_of_ref_vectors(concatenation.concatenation_groups)); + PCS::compute_opening_proof(this->commitment_key, prover_opening_claim, prover_transcript); + + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + + auto verifier_opening_claim = + ZeroMorphVerifier::verify(RefVector(unshifted.commitments), // unshifted + RefVector(shifted.commitments), // to-be-shifted + RefVector(unshifted.evaluations), // unshifted + RefVector(shifted.evaluations), // shifted + u_challenge, + this->vk()->get_g1_identity(), + verifier_transcript, + to_vector_of_ref_vectors(concatenation.concatenation_groups_commitments), + RefVector(concatenation.c_evaluations)); + VerifierAccumulator result; + + bool verified = false; + if constexpr (std::same_as>) { + + result = PCS::reduce_verify(verifier_opening_claim, verifier_transcript); + verified = this->vk()->pairing_check(result[0], result[1]); } else { // Execute Verifier protocol with vk - result = ZeroMorphVerifier::verify(RefVector(f_commitments), // unshifted - RefVector(g_commitments), // to-be-shifted - RefVector(v_evaluations), // unshifted - RefVector(w_evaluations), // shifted - u_challenge, - this->vk(), - verifier_transcript, - to_vector_of_ref_vectors(concatenation_groups_commitments), - RefVector(c_evaluations)); + result = PCS::reduce_verify(this->vk(), verifier_opening_claim, verifier_transcript); + verified = result; } @@ -294,7 +307,6 @@ template class ZeroMorphWithConcatenationTest : public CommitmentTes using PCSTypes = ::testing::Types, IPA>; TYPED_TEST_SUITE(ZeroMorphTest, PCSTypes); -TYPED_TEST_SUITE(ZeroMorphWithConcatenationTest, PCSTypes); /** * @brief Test method for computing q_k given multilinear f @@ -307,8 +319,8 @@ TYPED_TEST_SUITE(ZeroMorphWithConcatenationTest, PCSTypes); TYPED_TEST(ZeroMorphTest, QuotientConstruction) { // Define some useful type aliases - using ZeroMorphProver = ZeroMorphProver_; using Curve = typename TypeParam::Curve; + using ZeroMorphProver = ZeroMorphProver_; using Fr = typename Curve::ScalarField; using Polynomial = bb::Polynomial; @@ -355,8 +367,8 @@ TYPED_TEST(ZeroMorphTest, QuotientConstruction) TYPED_TEST(ZeroMorphTest, BatchedLiftedDegreeQuotient) { // Define some useful type aliases - using ZeroMorphProver = ZeroMorphProver_; using Curve = typename TypeParam::Curve; + using ZeroMorphProver = ZeroMorphProver_; using Fr = typename Curve::ScalarField; using Polynomial = bb::Polynomial; @@ -400,8 +412,8 @@ TYPED_TEST(ZeroMorphTest, BatchedLiftedDegreeQuotient) TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZeta) { // Define some useful type aliases - using ZeroMorphProver = ZeroMorphProver_; using Curve = typename TypeParam::Curve; + using ZeroMorphProver = ZeroMorphProver_; using Fr = typename Curve::ScalarField; using Polynomial = bb::Polynomial; @@ -484,8 +496,8 @@ TYPED_TEST(ZeroMorphTest, PhiEvaluation) TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ) { // Define some useful type aliases - using ZeroMorphProver = ZeroMorphProver_; using Curve = typename TypeParam::Curve; + using ZeroMorphProver = ZeroMorphProver_; using Fr = typename Curve::ScalarField; using Polynomial = bb::Polynomial; @@ -565,7 +577,7 @@ TYPED_TEST(ZeroMorphTest, ProveAndVerifyBatchedWithShifts) * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation * */ -TYPED_TEST(ZeroMorphWithConcatenationTest, ProveAndVerify) +TYPED_TEST(ZeroMorphTest, ProveAndVerifyWithConcatenation) { size_t num_unshifted = 1; size_t num_shifted = 0; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp index cd2db6b71242..c3ae908ff71d 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp @@ -15,7 +15,7 @@ using namespace bb; -class ECCVMComposerTests : public ::testing::Test { +class ECCVMTests : public ::testing::Test { protected: void SetUp() override { srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); }; }; @@ -60,7 +60,7 @@ ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr) return builder; } -TEST_F(ECCVMComposerTests, BaseCase) +TEST_F(ECCVMTests, BaseCase) { ECCVMCircuitBuilder builder = generate_circuit(&engine); ECCVMProver prover(builder); @@ -71,7 +71,7 @@ TEST_F(ECCVMComposerTests, BaseCase) ASSERT_TRUE(verified); } -TEST_F(ECCVMComposerTests, EqFails) +TEST_F(ECCVMTests, EqFails) { auto builder = generate_circuit(&engine); // Tamper with the eq op such that the expected value is incorect diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 821de0707808..4a87e300d09c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -911,10 +911,6 @@ class ECCVMFlavor { std::array sumcheck_evaluations; std::vector zm_cq_comms; Commitment zm_cq_comm; - uint32_t ipa_poly_degree; - std::vector ipa_l_comms; - std::vector ipa_r_comms; - FF ipa_a_0_eval; Commitment translation_hack_comm; FF translation_eval_op; FF translation_eval_px; @@ -922,10 +918,11 @@ class ECCVMFlavor { FF translation_eval_z1; FF translation_eval_z2; FF hack_eval; - uint32_t translation_ipa_poly_degree; - std::vector translation_ipa_l_comms; - std::vector translation_ipa_r_comms; - FF translation_ipa_a_0_eval; + Commitment shplonk_q_comm; + uint32_t ipa_poly_degree; + std::vector ipa_l_comms; + std::vector ipa_r_comms; + FF ipa_a_0_eval; Transcript() = default; @@ -1129,17 +1126,6 @@ class ECCVMFlavor { } zm_cq_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); - ipa_poly_degree = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, - num_frs_read); - auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); - for (size_t i = 0; i < log_poly_degree; ++i) { - ipa_l_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - ipa_r_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read)); - } - ipa_a_0_eval = - NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); translation_hack_comm = NativeTranscript::template deserialize_from_buffer( NativeTranscript::proof_data, num_frs_read); translation_eval_op = @@ -1155,17 +1141,20 @@ class ECCVMFlavor { hack_eval = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - translation_ipa_poly_degree = NativeTranscript::template deserialize_from_buffer( - NativeTranscript::proof_data, num_frs_read); + shplonk_q_comm = NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read); + ipa_poly_degree = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, + num_frs_read); + + auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); for (size_t i = 0; i < log_poly_degree; ++i) { - translation_ipa_l_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( + ipa_l_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( NativeTranscript::proof_data, num_frs_read)); - translation_ipa_r_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( + ipa_r_comms.emplace_back(NativeTranscript::template deserialize_from_buffer( NativeTranscript::proof_data, num_frs_read)); } - translation_ipa_a_0_eval = + ipa_a_0_eval = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); } @@ -1284,15 +1273,6 @@ class ECCVMFlavor { } NativeTranscript::template serialize_to_buffer(zm_cq_comm, NativeTranscript::proof_data); - NativeTranscript::template serialize_to_buffer(ipa_poly_degree, NativeTranscript::proof_data); - - auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); - for (size_t i = 0; i < log_poly_degree; ++i) { - NativeTranscript::template serialize_to_buffer(ipa_l_comms[i], NativeTranscript::proof_data); - NativeTranscript::template serialize_to_buffer(ipa_r_comms[i], NativeTranscript::proof_data); - } - - NativeTranscript::template serialize_to_buffer(ipa_a_0_eval, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(translation_hack_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_op, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(translation_eval_px, NativeTranscript::proof_data); @@ -1301,16 +1281,16 @@ class ECCVMFlavor { NativeTranscript::template serialize_to_buffer(translation_eval_z2, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(hack_eval, NativeTranscript::proof_data); - NativeTranscript::template serialize_to_buffer(translation_ipa_poly_degree, NativeTranscript::proof_data); - log_poly_degree = static_cast(numeric::get_msb(translation_ipa_poly_degree)); + NativeTranscript::template serialize_to_buffer(shplonk_q_comm, NativeTranscript::proof_data); + + NativeTranscript::template serialize_to_buffer(ipa_poly_degree, NativeTranscript::proof_data); + auto log_poly_degree = static_cast(numeric::get_msb(ipa_poly_degree)); for (size_t i = 0; i < log_poly_degree; ++i) { - NativeTranscript::template serialize_to_buffer(translation_ipa_l_comms[i], - NativeTranscript::proof_data); - NativeTranscript::template serialize_to_buffer(translation_ipa_r_comms[i], - NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(ipa_l_comms[i], NativeTranscript::proof_data); + NativeTranscript::template serialize_to_buffer(ipa_r_comms[i], NativeTranscript::proof_data); } - serialize_to_buffer(translation_ipa_a_0_eval, proof_data); + serialize_to_buffer(ipa_a_0_eval, proof_data); ASSERT(NativeTranscript::proof_data.size() == old_proof_length); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 43cd7248f110..7d049b169707 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -1,12 +1,12 @@ #include "eccvm_prover.hpp" #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/common/ref_array.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" @@ -104,67 +104,74 @@ void ECCVMProver::execute_relation_check_rounds() } /** - * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck - * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. + * @brief Produce a univariate opening claim for the sumcheck multivariate evalutions and a batched univariate claim + * for the transcript polynomials (for the Translator consistency check). Reduce the two opening claims to a single one + * via Shplonk and produce an opening proof with the univariate PCS of choice (IPA when operating on Grumpkin). + * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled ZeroMorph + * protocol. * - * */ -void ECCVMProver::execute_zeromorph_rounds() -{ - ZeroMorph::prove(key->polynomials.get_unshifted(), - key->polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript); -} - -/** - * @brief Batch open the transcript polynomials as univariates for Translator consistency check - * TODO(#768): Find a better way to do this. See issue for details. - * - * @tparam Flavor */ -void ECCVMProver::execute_transcript_consistency_univariate_opening_round() +void ECCVMProver::execute_pcs_rounds() { - // Since IPA cannot currently handle polynomials for which the latter half of the coefficients are 0, we hackily - // batch the constant polynomial 1 in with the 5 transcript polynomials. See issue #768 for more details. + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphProver_; + using Shplonk = ShplonkProver_; + using OpeningClaim = ProverOpeningClaim; + + // Execute the ZeroMorph protocol to produce a univariate opening claim for the multilinear evaluations produced by + // Sumcheck + auto multivariate_to_univariate_opening_claim = + ZeroMorph::prove(key->polynomials.get_unshifted(), + key->polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript); + + // Batch open the transcript polynomials as univariates for Translator consistency check. Since IPA cannot + // currently handle polynomials for which the latter half of the coefficients are 0, we hackily + // batch the constant polynomial 1 in with the 5 transcript polynomials. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/768): fix IPA to avoid the need for the hack polynomial Polynomial hack(key->circuit_size); for (size_t idx = 0; idx < key->circuit_size; idx++) { hack[idx] = 1; } transcript->send_to_verifier("Translation:hack_commitment", commitment_key->commit(hack)); - // Get the challenge at which we evaluate the polynomials as univariates + // Get the challenge at which we evaluate all transcript polynomials as univariates evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); + // Evaluate the transcript polynomials at the challenge translation_evaluations.op = key->polynomials.transcript_op.evaluate(evaluation_challenge_x); translation_evaluations.Px = key->polynomials.transcript_Px.evaluate(evaluation_challenge_x); translation_evaluations.Py = key->polynomials.transcript_Py.evaluate(evaluation_challenge_x); translation_evaluations.z1 = key->polynomials.transcript_z1.evaluate(evaluation_challenge_x); translation_evaluations.z2 = key->polynomials.transcript_z2.evaluate(evaluation_challenge_x); - // Add the univariate evaluations to the transcript + // Add the univariate evaluations to the transcript so the verifier can reconstruct the batched evaluation transcript->send_to_verifier("Translation:op", translation_evaluations.op); transcript->send_to_verifier("Translation:Px", translation_evaluations.Px); transcript->send_to_verifier("Translation:Py", translation_evaluations.Py); transcript->send_to_verifier("Translation:z1", translation_evaluations.z1); transcript->send_to_verifier("Translation:z2", translation_evaluations.z2); - transcript->send_to_verifier("Translation:hack_evaluation", hack.evaluate(evaluation_challenge_x)); - // Get another challenge for batching the univariate claims + FF hack_evaluation = hack.evaluate(evaluation_challenge_x); + transcript->send_to_verifier("Translation:hack_evaluation", hack_evaluation); + + // Get another challenge for batching the univariates and evaluations FF ipa_batching_challenge = transcript->template get_challenge("Translation:ipa_batching_challenge"); // Collect the polynomials and evaluations to be batched RefArray univariate_polynomials{ key->polynomials.transcript_op, key->polynomials.transcript_Px, key->polynomials.transcript_Py, key->polynomials.transcript_z1, key->polynomials.transcript_z2, hack }; - std::array univariate_evaluations; - for (auto [eval, polynomial] : zip_view(univariate_evaluations, univariate_polynomials)) { - eval = polynomial.evaluate(evaluation_challenge_x); - } + std::array univariate_evaluations{ + translation_evaluations.op, translation_evaluations.Px, translation_evaluations.Py, + translation_evaluations.z1, translation_evaluations.z2, hack_evaluation + }; - // Construct the batched polynomial and batched evaluation + // Construct the batched polynomial and batched evaluation to produce the batched opening claim Polynomial batched_univariate{ key->circuit_size }; FF batched_evaluation{ 0 }; auto batching_scalar = FF(1); @@ -174,12 +181,17 @@ void ECCVMProver::execute_transcript_consistency_univariate_opening_round() batching_scalar *= ipa_batching_challenge; } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/922): We are doing another round of IPA here with - // exactly the same labels and no domain separation so if/when labels are going to matter we are clashing. - PCS::compute_opening_proof( - commitment_key, { evaluation_challenge_x, batched_evaluation }, batched_univariate, transcript); + std::array opening_claims = { multivariate_to_univariate_opening_claim, + { .polynomial = batched_univariate, + .opening_pair = { evaluation_challenge_x, batched_evaluation } } }; + + // Reduce the opening claims to a single opening claim via Shplonk + const OpeningClaim batched_opening_claim = Shplonk::prove(commitment_key, opening_claims, transcript); - // Get another challenge for batching the univariate claims + // Compute the opening proof for the batched opening claim with the univariate PCS + PCS::compute_opening_proof(commitment_key, batched_opening_claim, transcript); + + // Produce another challenge passed as input to the translator verifier translation_batching_challenge_v = transcript->template get_challenge("Translation:batching_challenge"); } @@ -203,9 +215,7 @@ HonkProof ECCVMProver::construct_proof() execute_relation_check_rounds(); - execute_zeromorph_rounds(); - - execute_transcript_consistency_univariate_opening_round(); + execute_pcs_rounds(); return export_proof(); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp index c6661069473b..52d243ca06c6 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.hpp @@ -35,7 +35,7 @@ class ECCVMProver { BB_PROFILE void execute_log_derivative_commitments_round(); BB_PROFILE void execute_grand_product_computation_round(); BB_PROFILE void execute_relation_check_rounds(); - BB_PROFILE void execute_zeromorph_rounds(); + BB_PROFILE void execute_pcs_rounds(); BB_PROFILE void execute_transcript_consistency_univariate_opening_round(); HonkProof export_proof(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 0b2e13a7850e..9eaedc9df93f 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -164,20 +164,6 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "ZM:x", "ZM:z"); round++; - manifest_expected.add_entry(round, "IPA:poly_degree_plus_1", frs_per_uint32); - manifest_expected.add_challenge(round, "IPA:generator_challenge"); - - for (size_t i = 0; i < log_n; ++i) { - round++; - std::string idx = std::to_string(log_n - i - 1); - manifest_expected.add_entry(round, "IPA:L_" + idx, frs_per_G); - manifest_expected.add_entry(round, "IPA:R_" + idx, frs_per_G); - std::string label = "IPA:round_challenge_" + idx; - manifest_expected.add_challenge(round, label); - } - - round++; - manifest_expected.add_entry(round, "IPA:a_0", frs_per_Fr); manifest_expected.add_entry(round, "Translation:hack_commitment", frs_per_G); manifest_expected.add_challenge(round, "Translation:evaluation_challenge_x"); @@ -190,6 +176,13 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "Translation:hack_evaluation", frs_per_Fr); manifest_expected.add_challenge(round, "Translation:ipa_batching_challenge"); + round++; + manifest_expected.add_challenge(round, "Shplonk:nu"); + + round++; + manifest_expected.add_entry(round, "Shplonk:Q", frs_per_G); + manifest_expected.add_challenge(round, "Shplonk:z"); + round++; manifest_expected.add_entry(round, "IPA:poly_degree_plus_1", frs_per_uint32); manifest_expected.add_challenge(round, "IPA:generator_challenge"); @@ -209,6 +202,7 @@ class ECCVMTranscriptTests : public ::testing::Test { return manifest_expected; } + ECCVMCircuitBuilder generate_trace(numeric::RNG* engine = nullptr) { std::shared_ptr op_queue = std::make_shared(); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 8cc715a97c5f..2c1e3d6dc571 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -1,4 +1,5 @@ #include "./eccvm_verifier.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" @@ -9,7 +10,9 @@ namespace bb { */ bool ECCVMVerifier::verify_proof(const HonkProof& proof) { - using ZeroMorph = ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; + using Shplonk = ShplonkVerifier_; RelationParameters relation_parameters; transcript = std::make_shared(proof); @@ -57,56 +60,58 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) return false; } - bool multivariate_opening_verified = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - key->pcs_verification_key, - transcript); + // Reduce the multivariate evaluation claims produced by sumcheck to a single univariate opening claim + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + key->pcs_verification_key->get_g1_identity(), + transcript); + // Execute transcript consistency univariate opening round - // TODO(#768): Find a better way to do this. See issue for details. - bool univariate_opening_verified = false; - { - auto hack_commitment = transcript->template receive_from_prover("Translation:hack_commitment"); - - FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); - - // Construct arrays of commitments and evaluations to be batched - const size_t NUM_UNIVARIATES = 6; - std::array transcript_commitments = { - commitments.transcript_op, commitments.transcript_Px, commitments.transcript_Py, - commitments.transcript_z1, commitments.transcript_z2, hack_commitment - }; - std::array transcript_evaluations = { - transcript->template receive_from_prover("Translation:op"), - transcript->template receive_from_prover("Translation:Px"), - transcript->template receive_from_prover("Translation:Py"), - transcript->template receive_from_prover("Translation:z1"), - transcript->template receive_from_prover("Translation:z2"), - transcript->template receive_from_prover("Translation:hack_evaluation") - }; - - // Get another challenge for batching the univariate claims - FF ipa_batching_challenge = transcript->template get_challenge("Translation:ipa_batching_challenge"); - - // Construct batched commitment and batched evaluation - auto batched_commitment = transcript_commitments[0]; - auto batched_transcript_eval = transcript_evaluations[0]; - auto batching_scalar = ipa_batching_challenge; - for (size_t idx = 1; idx < transcript_commitments.size(); ++idx) { - batched_commitment = batched_commitment + transcript_commitments[idx] * batching_scalar; - batched_transcript_eval += batching_scalar * transcript_evaluations[idx]; - batching_scalar *= ipa_batching_challenge; - } - - // Construct and verify batched opening claim - OpeningClaim batched_univariate_claim = { { evaluation_challenge_x, batched_transcript_eval }, - batched_commitment }; - univariate_opening_verified = - PCS::reduce_verify(key->pcs_verification_key, batched_univariate_claim, transcript); + auto hack_commitment = transcript->template receive_from_prover("Translation:hack_commitment"); + + FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); + + // Construct arrays of commitments and evaluations to be batched, the evaluations being received from the prover + const size_t NUM_UNIVARIATES = 6; + std::array transcript_commitments = { + commitments.transcript_op, commitments.transcript_Px, commitments.transcript_Py, + commitments.transcript_z1, commitments.transcript_z2, hack_commitment + }; + std::array transcript_evaluations = { + transcript->template receive_from_prover("Translation:op"), + transcript->template receive_from_prover("Translation:Px"), + transcript->template receive_from_prover("Translation:Py"), + transcript->template receive_from_prover("Translation:z1"), + transcript->template receive_from_prover("Translation:z2"), + transcript->template receive_from_prover("Translation:hack_evaluation") + }; + + // Get the batching challenge for commitments and evaluations + FF ipa_batching_challenge = transcript->template get_challenge("Translation:ipa_batching_challenge"); + + // Compute the batched commitment and batched evaluation for the univariate opening claim + auto batched_commitment = transcript_commitments[0]; + auto batched_transcript_eval = transcript_evaluations[0]; + auto batching_scalar = ipa_batching_challenge; + for (size_t idx = 1; idx < transcript_commitments.size(); ++idx) { + batched_commitment = batched_commitment + transcript_commitments[idx] * batching_scalar; + batched_transcript_eval += batching_scalar * transcript_evaluations[idx]; + batching_scalar *= ipa_batching_challenge; } - return sumcheck_verified.value() && multivariate_opening_verified && univariate_opening_verified; + std::array, 2> opening_claims = { multivariate_to_univariate_opening_claim, + { { evaluation_challenge_x, batched_transcript_eval }, + batched_commitment } }; + + // Construct and verify the combined opening claim + auto batched_opening_claim = + Shplonk::reduce_verification(key->pcs_verification_key->get_g1_identity(), opening_claims, transcript); + + bool batched_opening_verified = PCS::reduce_verify(key->pcs_verification_key, batched_opening_claim, transcript); + + return sumcheck_verified.value() && batched_opening_verified; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp index 7bef58336b1d..4ceb64781792 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp @@ -1,4 +1,5 @@ #include "./eccvm_recursive_verifier.hpp" +#include "barretenberg/commitment_schemes/shplonk/shplonk.hpp" #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" #include "barretenberg/transcript/transcript.hpp" @@ -18,7 +19,10 @@ ECCVMRecursiveVerifier_::ECCVMRecursiveVerifier_( // TODO(https://github.com/AztecProtocol/barretenberg/issues/1007): Finish this template void ECCVMRecursiveVerifier_::verify_proof(const HonkProof& proof) { - using ZeroMorph = ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; + using Shplonk = ShplonkVerifier_; + RelationParameters relation_parameters; StdlibProof stdlib_proof = bb::convert_proof_to_witness(builder, proof); @@ -71,57 +75,58 @@ template void ECCVMRecursiveVerifier_::verify_proof(co auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - // removed return bool - bool multivariate_opening_verified = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - key->pcs_verification_key, - transcript); - // Execute transcript consistency univariate opening round - // TODO(#768): Find a better way to do this. See issue for details. - bool univariate_opening_verified = false; - { - auto hack_commitment = transcript->template receive_from_prover("Translation:hack_commitment"); - - FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); - - // Construct arrays of commitments and evaluations to be batched - const size_t NUM_UNIVARIATES = 6; - std::array transcript_commitments = { - commitments.transcript_op, commitments.transcript_Px, commitments.transcript_Py, - commitments.transcript_z1, commitments.transcript_z2, hack_commitment - }; - std::array transcript_evaluations = { - transcript->template receive_from_prover("Translation:op"), - transcript->template receive_from_prover("Translation:Px"), - transcript->template receive_from_prover("Translation:Py"), - transcript->template receive_from_prover("Translation:z1"), - transcript->template receive_from_prover("Translation:z2"), - transcript->template receive_from_prover("Translation:hack_evaluation") - }; - - // Get another challenge for batching the univariate claims - FF ipa_batching_challenge = transcript->template get_challenge("Translation:ipa_batching_challenge"); - - // Construct batched commitment and batched evaluation - auto batched_commitment = transcript_commitments[0]; - auto batched_transcript_eval = transcript_evaluations[0]; - auto batching_scalar = ipa_batching_challenge; - for (size_t idx = 1; idx < transcript_commitments.size(); ++idx) { - batched_commitment = batched_commitment + transcript_commitments[idx] * batching_scalar; - batched_transcript_eval += batching_scalar * transcript_evaluations[idx]; - batching_scalar *= ipa_batching_challenge; - } - - // Construct and verify batched opening claim - OpeningClaim batched_univariate_claim = { { evaluation_challenge_x, batched_transcript_eval }, - batched_commitment }; - univariate_opening_verified = - PCS::reduce_verify(key->pcs_verification_key, batched_univariate_claim, transcript); + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + key->pcs_verification_key->get_g1_identity(), + transcript); + auto hack_commitment = transcript->template receive_from_prover("Translation:hack_commitment"); + + FF evaluation_challenge_x = transcript->template get_challenge("Translation:evaluation_challenge_x"); + + // Construct the vector of commitments (needs to be vector for the batch_mul) and array of evaluations to be batched + std::vector transcript_commitments = { commitments.transcript_op, commitments.transcript_Px, + commitments.transcript_Py, commitments.transcript_z1, + commitments.transcript_z2, hack_commitment }; + + std::vector transcript_evaluations = { transcript->template receive_from_prover("Translation:op"), + transcript->template receive_from_prover("Translation:Px"), + transcript->template receive_from_prover("Translation:Py"), + transcript->template receive_from_prover("Translation:z1"), + transcript->template receive_from_prover("Translation:z2"), + transcript->template receive_from_prover( + "Translation:hack_evaluation") }; + + // Get the batching challenge for commitments and evaluations + FF ipa_batching_challenge = transcript->template get_challenge("Translation:ipa_batching_challenge"); + + // Compute the batched commitment and batched evaluation for the univariate opening claim + auto batched_transcript_eval = transcript_evaluations[0]; + auto batching_scalar = ipa_batching_challenge; + + std::vector batching_challenges = { FF::one() }; + for (size_t idx = 1; idx < transcript_commitments.size(); ++idx) { + batched_transcript_eval += batching_scalar * transcript_evaluations[idx]; + batching_challenges.emplace_back(batching_scalar); + batching_scalar *= ipa_batching_challenge; } - ASSERT(sumcheck_verified && multivariate_opening_verified && univariate_opening_verified); + auto batched_commitment = Commitment::batch_mul(transcript_commitments, batching_challenges); + + // Construct and verify the combined opening claim + OpeningClaim batched_univariate_claim = { { evaluation_challenge_x, batched_transcript_eval }, + batched_commitment }; + + std::array, 2> opening_claims = { multivariate_to_univariate_opening_claim, + batched_univariate_claim }; + + auto batched_opening_claim = + Shplonk::reduce_verification(key->pcs_verification_key->get_g1_identity(), opening_claims, transcript); + + auto batched_opening_verified = PCS::reduce_verify(key->pcs_verification_key, batched_opening_claim, transcript); + + ASSERT(sumcheck_verified && batched_opening_verified); } template class ECCVMRecursiveVerifier_>; diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.test.cpp index 8be139c096ab..2d2c1fe93bf0 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.test.cpp @@ -76,7 +76,6 @@ template class ECCVMRecursiveTests : public ::testing { InnerBuilder builder = generate_circuit(&engine); InnerProver prover(builder); - info(builder.get_num_gates()); auto proof = prover.construct_proof(); auto verification_key = std::make_shared(prover.key); diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp index 8b2011d792f3..5dcb13ffacb9 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp @@ -25,7 +25,7 @@ template class VerifierCommitmentKey { VerifierCommitmentKey([[maybe_unused]] Builder* builder, size_t num_points, std::shared_ptr>& native_pcs_verification_key) - : first_g1(Commitment(native_pcs_verification_key->get_first_g1())) + : g1_identity(Commitment(native_pcs_verification_key->get_g1_identity())) { auto* native_points = native_pcs_verification_key->get_monomial_points(); @@ -34,11 +34,11 @@ template class VerifierCommitmentKey { } } - Commitment get_first_g1() { return first_g1; } + Commitment get_g1_identity() { return g1_identity; } std::vector get_monomial_points() { return monomial_points; } private: - Commitment first_g1; + Commitment g1_identity; std::vector monomial_points; }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.test.cpp index 66dc19302ea8..b9496e39ca4b 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.test.cpp @@ -25,7 +25,7 @@ template class RecursiveVeriferCommitmentKeyTest : public testi Builder builder; auto native_vk = std::make_shared(num_points); auto recursive_vk = std::make_shared(&builder, num_points, native_vk); - EXPECT_EQ(native_vk->get_first_g1(), recursive_vk->get_first_g1().get_value()); + EXPECT_EQ(native_vk->get_g1_identity(), recursive_vk->get_g1_identity().get_value()); auto* native_monomial_points = native_vk->get_monomial_points(); auto recursive_monomial_points = recursive_vk->get_monomial_points(); diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp index 0ca1c00e747d..88c518cb4b36 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp @@ -48,4 +48,79 @@ std::shared_ptr compute_verification_key_common( // silencing for now but need to figure out where to extract type of VerifierCrs from :-/ std::shared_ptr> const& vrs); +/** + * @brief Construct polynomials containing the sorted concatenation of the lookups and the lookup tables + * + * @tparam Flavor + * @param circuit + * @param dyadic_circuit_size + * @param additional_offset Additional space needed in polynomials to add randomness for zk (Plonk only) + * @return std::array + */ +template +std::array construct_sorted_list_polynomials(typename Flavor::CircuitBuilder& circuit, + const size_t dyadic_circuit_size, + size_t additional_offset = 0) +{ + using Polynomial = typename Flavor::Polynomial; + std::array sorted_polynomials; + // Initialise the sorted concatenated list polynomials for the lookup argument + for (auto& s_i : sorted_polynomials) { + s_i = Polynomial(dyadic_circuit_size); + } + + // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so + // that these entries are written into the last indices of the polynomials. The values on the first + // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the + // polynomial constructor. + size_t s_index = dyadic_circuit_size - (circuit.get_tables_size() + circuit.get_lookups_size()) - additional_offset; + ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + + for (auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + auto& lookup_gates = table.lookup_gates; + for (size_t i = 0; i < table.size(); ++i) { + if (table.use_twin_keys) { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + table.column_2[i].from_montgomery_form().data[0], + }, + { + table.column_3[i], + 0, + }, + }); + } else { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + 0, + }, + { + table.column_2[i], + table.column_3[i], + }, + }); + } + } + +#ifdef NO_TBB + std::sort(lookup_gates.begin(), lookup_gates.end()); +#else + std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); +#endif + + for (const auto& entry : lookup_gates) { + const auto components = entry.to_table_components(table.use_twin_keys); + sorted_polynomials[0][s_index] = components[0]; + sorted_polynomials[1][s_index] = components[1]; + sorted_polynomials[2][s_index] = components[2]; + sorted_polynomials[3][s_index] = table_index; + ++s_index; + } + } + return sorted_polynomials; +} + } // namespace bb::plonk diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt index d3024bcdbb18..7603c0f67759 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(plonk_honk_shared polynomials) \ No newline at end of file +barretenberg_module(plonk_honk_shared polynomials ultra_honk) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp index 7745a853c586..d4e75dc9e144 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/ref_array.hpp" #include "barretenberg/flavor/flavor.hpp" #include "barretenberg/polynomials/polynomial_store.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp" #include @@ -20,6 +21,7 @@ void construct_lookup_table_polynomials(RefArray // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments // | table randomness // ignored, as used for regular constraints and padding to the next power of 2. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace ASSERT(dyadic_circuit_size > circuit.get_tables_size() + additional_offset); size_t offset = dyadic_circuit_size - circuit.get_tables_size() - additional_offset; @@ -37,78 +39,40 @@ void construct_lookup_table_polynomials(RefArray } /** - * @brief Construct polynomials containing the sorted concatenation of the lookups and the lookup tables - * - * @tparam Flavor - * @param circuit - * @param dyadic_circuit_size - * @param additional_offset Additional space needed in polynomials to add randomness for zk (Plonk only) - * @return std::array + * @brief Construct polynomial whose value at index i is the number of times the table entry at that index has been + * read. + * @details Read counts are needed for the log derivative lookup argument. The table polynomials are constructed as a + * concatenation of basic 3-column tables. Similarly, the read counts polynomial is constructed as the concatenation of + * read counts for the individual tables. */ template -std::array construct_sorted_list_polynomials(typename Flavor::CircuitBuilder& circuit, - const size_t dyadic_circuit_size, - size_t additional_offset = 0) +void construct_lookup_read_counts(typename Flavor::Polynomial& read_counts, + typename Flavor::Polynomial& read_tags, + typename Flavor::CircuitBuilder& circuit, + size_t dyadic_circuit_size) { - using Polynomial = typename Flavor::Polynomial; - std::array sorted_polynomials; - // Initialise the sorted concatenated list polynomials for the lookup argument - for (auto& s_i : sorted_polynomials) { - s_i = Polynomial(dyadic_circuit_size); - } - - // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so - // that these entries are written into the last indices of the polynomials. The values on the first - // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the - // polynomial constructor. - size_t s_index = dyadic_circuit_size - (circuit.get_tables_size() + circuit.get_lookups_size()) - additional_offset; - ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace + size_t offset = dyadic_circuit_size - circuit.get_tables_size(); + size_t table_offset = offset; // offset of the present table in the table polynomials + // loop over all tables used in the circuit; each table contains data about the lookups made on it for (auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); - auto& lookup_gates = table.lookup_gates; - for (size_t i = 0; i < table.size(); ++i) { - if (table.use_twin_keys) { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - table.column_2[i].from_montgomery_form().data[0], - }, - { - table.column_3[i], - 0, - }, - }); - } else { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - 0, - }, - { - table.column_2[i], - table.column_3[i], - }, - }); - } - } + table.initialize_index_map(); + + for (auto& gate_data : table.lookup_gates) { + // convert lookup gate data to an array of three field elements, one for each of the 3 columns + auto table_entry = gate_data.to_table_components(table.use_twin_keys); -#ifdef NO_TBB - std::sort(lookup_gates.begin(), lookup_gates.end()); -#else - std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); -#endif + // find the index of the entry in the table + auto index_in_table = table.index_map[table_entry]; - for (const auto& entry : lookup_gates) { - const auto components = entry.to_sorted_list_components(table.use_twin_keys); - sorted_polynomials[0][s_index] = components[0]; - sorted_polynomials[1][s_index] = components[1]; - sorted_polynomials[2][s_index] = components[2]; - sorted_polynomials[3][s_index] = table_index; - ++s_index; + // increment the read count at the corresponding index in the full polynomial + size_t index_in_poly = table_offset + index_in_table; + read_counts[index_in_poly]++; + read_tags[index_in_poly] = 1; // tag is 1 if entry has been read 1 or more times } + table_offset += table.size(); // set the offset of the next table within the polynomials } - return sorted_polynomials; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp index 94219c72a480..33534bc958db 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/composer/composer_lib.test.cpp @@ -1,21 +1,78 @@ #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" -#include "barretenberg/common/slab_allocator.hpp" -#include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" + #include #include using namespace bb; class ComposerLibTests : public ::testing::Test { + public: + using Flavor = UltraFlavor; + using FF = typename Flavor::FF; + protected: + static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } +}; + +/** + * @brief A test to demonstrate that lookup read counts/tags are computed correctly for a simple 'hand-computable' case + * using the uint32 XOR table + * + */ +TEST_F(ComposerLibTests, LookupReadCounts) +{ + using Builder = UltraCircuitBuilder; using Flavor = UltraFlavor; using FF = typename Flavor::FF; - Flavor::CircuitBuilder circuit_constructor; - Flavor::ProvingKey proving_key = []() { - auto crs_factory = srs::factories::CrsFactory(); - auto crs = crs_factory.get_prover_crs(4); - return Flavor::ProvingKey(/*circuit_size=*/8, /*num_public_inputs=*/0); - }(); -}; \ No newline at end of file + using Polynomial = typename Flavor::Polynomial; + auto UINT32_XOR = plookup::MultiTableId::UINT32_XOR; + + Builder builder; + + // define some very simply inputs to XOR + FF left{ 1 }; + FF right{ 5 }; + + auto left_idx = builder.add_variable(left); + auto right_idx = builder.add_variable(right); + + // create a single lookup from the uint32 XOR table + auto accumulators = plookup::get_lookup_accumulators(UINT32_XOR, left, right, /*is_2_to_1_lookup*/ true); + builder.create_gates_from_plookup_accumulators(UINT32_XOR, accumulators, left_idx, right_idx); + + EXPECT_EQ(builder.lookup_tables.size(), 1); // we only used a single table + EXPECT_EQ(builder.lookup_tables[0].size(), 4096); // table has size 64*64 (6 bit operands) + + size_t circuit_size = 8192; + + Polynomial read_counts{ circuit_size }; + Polynomial read_tags{ circuit_size }; + + construct_lookup_read_counts(read_counts, read_tags, builder, circuit_size); + + // The table polys are constructed at the bottom of the trace, thus so to are the counts/tags + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1033): construct tables and counts at top of trace + size_t offset = circuit_size - builder.get_tables_size(); + + // The uint32 XOR lookup table is constructed for 6 bit operands via double for loop that iterates through the left + // operand externally (0 to 63) then the right operand internally (0 to 63). Computing (1 XOR 5) will thus result in + // 1 lookup from the (1*64 + 5)th index in the table and 5 lookups from the (0*64 + 0)th index (for the remaining 5 + // limbs that are all 0). The counts and tags at all other indices should be zero. + size_t idx = 0; + for (auto [count, tag] : zip_view(read_counts, read_tags)) { + if (idx == (0 + offset)) { + EXPECT_EQ(count, 5); + EXPECT_EQ(tag, 1); + } else if (idx == (69 + offset)) { + EXPECT_EQ(count, 1); + EXPECT_EQ(tag, 1); + } else { + EXPECT_EQ(count, 0); + EXPECT_EQ(tag, 0); + } + idx++; + } +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp index 43441174ecf9..5ae609a0e9a4 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp @@ -28,7 +28,8 @@ DeciderVerifier_::DeciderVerifier_() template bool DeciderVerifier_::verify_proof(const HonkProof& proof) { using PCS = typename Flavor::PCS; - using ZeroMorph = ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; transcript = std::make_shared(proof); @@ -48,12 +49,14 @@ template bool DeciderVerifier_::verify_proof(const Hon // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - transcript); + auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(), + transcript); + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 6c717c1d1266..da09210655f6 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -136,12 +136,10 @@ template class ProtoGalaxyTests : public testing::Test { instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); - if constexpr (IsGoblinFlavor) { - instance->proving_key.compute_logderivative_inverse(instance->relation_parameters); - } + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); for (auto& alpha : instance->alphas) { @@ -311,21 +309,94 @@ template class ProtoGalaxyTests : public testing::Test { } /** - * @brief Testing one valid round of folding followed by the decider. - * @brief For additional robustness we give one of the circuits more public inputs than the other + * @brief Testing one valid round of folding (plus decider) for two inhomogeneous circuits + * @details For robustness we fold circuits with different numbers/types of gates (but the same dyadic size) * */ - static void test_full_protogalaxy_simple() + static void test_protogalaxy_inhomogeneous() { - // Construct a first circuit with some public inputs - Builder builder1; - construct_circuit(builder1); - bb::MockCircuits::add_arithmetic_gates_with_public_inputs(builder1, /*num_gates=*/4); + auto check_fold_and_decide = [](Builder& circuit_1, Builder& circuit_2) { + // Construct the prover/verifier instances for each + TupleOfInstances instances; + construct_prover_and_verifier_instance(instances, circuit_1); + construct_prover_and_verifier_instance(instances, circuit_2); + + // Perform prover and verifier folding + auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); + check_accumulator_target_sum_manual(prover_accumulator, true); + + // Run decider + decide_and_verify(prover_accumulator, verifier_accumulator, true); + }; + + // One circuit has more arithmetic gates + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add some arithmetic gates + bb::MockCircuits::add_arithmetic_gates(builder1, /*num_gates=*/4); + + check_fold_and_decide(builder1, builder2); + } + + // One circuit has more arithmetic gates with public inputs + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add some arithmetic gates with public inputs to the first circuit + bb::MockCircuits::add_arithmetic_gates_with_public_inputs(builder1, /*num_gates=*/4); + + check_fold_and_decide(builder1, builder2); + } + + // One circuit has more lookup gates + { + // Construct two equivalent circuits + Builder builder1; + Builder builder2; + construct_circuit(builder1); + construct_circuit(builder2); + + // Add a different number of lookup gates to each circuit + bb::MockCircuits::add_lookup_gates(builder1, /*num_iterations=*/2); // 12 gates plus 4096 table + bb::MockCircuits::add_lookup_gates(builder2, /*num_iterations=*/1); // 6 gates plus 4096 table + + check_fold_and_decide(builder1, builder2); + } + } - // Construct a second circuit with no public inputs + /** + * @brief Ensure failure for a bad lookup gate in one of the circuits being folded + * + */ + static void test_protogalaxy_bad_lookup_failure() + { + // Construct two equivalent circuits + Builder builder1; Builder builder2; + construct_circuit(builder1); construct_circuit(builder2); + // Add a different number of lookup gates to each circuit + bb::MockCircuits::add_lookup_gates(builder1, /*num_iterations=*/2); // 12 gates plus 4096 table + bb::MockCircuits::add_lookup_gates(builder2, /*num_iterations=*/1); // 6 gates plus 4096 table + + // Erroneously set a non-zero wire value to zero in one of the lookup gates + for (auto& wire_3_witness_idx : builder1.blocks.lookup.w_o()) { + if (wire_3_witness_idx != builder1.zero_idx) { + wire_3_witness_idx = builder1.zero_idx; + break; + } + } + // Construct the prover/verifier instances for each TupleOfInstances instances; construct_prover_and_verifier_instance(instances, builder1); @@ -333,9 +404,11 @@ template class ProtoGalaxyTests : public testing::Test { // Perform prover and verifier folding auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); - check_accumulator_target_sum_manual(prover_accumulator, true); - decide_and_verify(prover_accumulator, verifier_accumulator, true); + // Expect failure in manual target sum check and decider + bool expected_result = false; + check_accumulator_target_sum_manual(prover_accumulator, expected_result); + decide_and_verify(prover_accumulator, verifier_accumulator, expected_result); } /** @@ -517,9 +590,9 @@ TYPED_TEST(ProtoGalaxyTests, CombineAlpha) TestFixture::test_combine_alpha(); } -TYPED_TEST(ProtoGalaxyTests, FullProtogalaxySimple) +TYPED_TEST(ProtoGalaxyTests, ProtogalaxyInhomogeneous) { - TestFixture::test_full_protogalaxy_simple(); + TestFixture::test_protogalaxy_inhomogeneous(); } TYPED_TEST(ProtoGalaxyTests, FullProtogalaxyTest) @@ -546,6 +619,11 @@ TYPED_TEST(ProtoGalaxyTests, TamperedAccumulatorPolynomial) TestFixture::test_tampered_accumulator_polynomial(); } +TYPED_TEST(ProtoGalaxyTests, BadLookupFailure) +{ + TestFixture::test_protogalaxy_bad_lookup_failure(); +} + // We only fold one instance currently due to significant compile time added by multiple instances TYPED_TEST(ProtoGalaxyTests, Fold1Instance) { diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp index 3091c0259e25..cbfbe35cbda6 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.hpp @@ -364,7 +364,6 @@ template class ProtoGalaxyProver_ { const FF& scaling_factor) { using Relation = std::tuple_element_t; - // WORKTODO: disable skipping for the combiner for now.. // Check if the relation is skippable to speed up accumulation if constexpr (!isSkippable) { // If not, accumulate normally diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp index f38ff10b3e11..36774b7c25fe 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover_impl.hpp @@ -187,7 +187,12 @@ FoldingResult ProtoGalaxyProver_proving_key.circuit_size == instances[idx + 1]->proving_key.circuit_size); + if (instances[idx]->proving_key.circuit_size != instances[idx + 1]->proving_key.circuit_size) { + info("ProtogalaxyProver: circuit size mismatch!"); + info("Instance ", idx, " size = ", instances[idx]->proving_key.circuit_size); + info("Instance ", idx + 1, " size = ", instances[idx + 1]->proving_key.circuit_size); + ASSERT(false); + } } preparation_round(); perturbator_round(); diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index 3c897ce39090..c0ec529cdd72 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -243,24 +243,24 @@ template class DatabusLookupRelationImpl { const auto inverses = View(BusData::inverses(in)); // Degree 1 const auto read_counts = View(BusData::read_counts(in)); // Degree 1 - const auto read_term = compute_read_term(in, params); // Degree 1 - const auto write_term = compute_write_term(in, params); // Degree 1 - const auto inverse_exists = compute_inverse_exists(in); // Degree 1 + const auto read_term = compute_read_term(in, params); // Degree 1 (2) + const auto write_term = compute_write_term(in, params); // Degree 1 (2) + const auto inverse_exists = compute_inverse_exists(in); // Degree 2 const auto read_selector = get_read_selector(in); // Degree 2 - const auto write_inverse = inverses * read_term; // Degree 2 - const auto read_inverse = inverses * write_term; // Degree 2 + const auto write_inverse = inverses * read_term; // Degree 2 (3) + const auto read_inverse = inverses * write_term; // Degree 2 (3) // Determine which pair of subrelations to update based on which bus column is being read constexpr size_t subrel_idx_1 = 2 * bus_idx; constexpr size_t subrel_idx_2 = 2 * bus_idx + 1; // Establish the correctness of the polynomial of inverses I. Note: inverses is computed so that the value is 0 - // if !inverse_exists. Degree 3 + // if !inverse_exists. Degree 3 (5) std::get(accumulator) += (read_term * write_term * inverses - inverse_exists) * scaling_factor; // Establish validity of the read. Note: no scaling factor here since this constraint is enforced across the - // entire trace, not on a per-row basis - std::get(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Degree 4 + // entire trace, not on a per-row basis. + std::get(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Deg 4 (5) } /** diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 9dd3eb86948a..2cdb82e6d1e2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -251,7 +251,6 @@ [[maybe_unused]] auto main_sel_rng_16 = View(new_term.main_sel_rng_16); \ [[maybe_unused]] auto main_sel_rng_8 = View(new_term.main_sel_rng_8); \ [[maybe_unused]] auto main_space_id = View(new_term.main_space_id); \ - [[maybe_unused]] auto main_table_pow_2 = View(new_term.main_table_pow_2); \ [[maybe_unused]] auto main_tag_err = View(new_term.main_tag_err); \ [[maybe_unused]] auto main_w_in_tag = View(new_term.main_w_in_tag); \ [[maybe_unused]] auto mem_addr = View(new_term.mem_addr); \ @@ -293,6 +292,7 @@ [[maybe_unused]] auto poseidon2_input = View(new_term.poseidon2_input); \ [[maybe_unused]] auto poseidon2_output = View(new_term.poseidon2_output); \ [[maybe_unused]] auto poseidon2_sel_poseidon_perm = View(new_term.poseidon2_sel_poseidon_perm); \ + [[maybe_unused]] auto powers_power_of_2 = View(new_term.powers_power_of_2); \ [[maybe_unused]] auto sha256_clk = View(new_term.sha256_clk); \ [[maybe_unused]] auto sha256_input = View(new_term.sha256_input); \ [[maybe_unused]] auto sha256_output = View(new_term.sha256_output); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp new file mode 100644 index 000000000000..7c69045c0014 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp @@ -0,0 +1,69 @@ + +#pragma once +#include "../../relation_parameters.hpp" +#include "../../relation_types.hpp" +#include "./declare_views.hpp" + +namespace bb::Avm_vm { + +template struct GasRow { + FF gas_da_gas_fixed_table{}; + FF gas_l2_gas_fixed_table{}; + FF gas_sel_gas_cost{}; + + [[maybe_unused]] static std::vector names(); +}; + +inline std::string get_relation_label_gas(int index) +{ + switch (index) {} + return std::to_string(index); +} + +template class gasImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 2, + 2, + 2, + }; + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + + // Contribution 0 + { + Avm_DECLARE_VIEWS(0); + + auto tmp = ((gas_sel_gas_cost - gas_sel_gas_cost) - FF(0)); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + // Contribution 1 + { + Avm_DECLARE_VIEWS(1); + + auto tmp = ((gas_l2_gas_fixed_table - gas_l2_gas_fixed_table) - FF(0)); + tmp *= scaling_factor; + std::get<1>(evals) += tmp; + } + // Contribution 2 + { + Avm_DECLARE_VIEWS(2); + + auto tmp = ((gas_da_gas_fixed_table - gas_da_gas_fixed_table) - FF(0)); + tmp *= scaling_factor; + std::get<2>(evals) += tmp; + } + } +}; + +template using gas = Relation>; + +} // namespace bb::Avm_vm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp index b042e72cf589..7ec3d3283b12 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_0.hpp @@ -140,7 +140,7 @@ class lookup_pow_2_0_lookup_settings { in.alu_ib, in.alu_two_pow_s, in.main_clk, - in.main_table_pow_2); + in.powers_power_of_2); } /** @@ -160,7 +160,7 @@ class lookup_pow_2_0_lookup_settings { in.alu_ib, in.alu_two_pow_s, in.main_clk, - in.main_table_pow_2); + in.powers_power_of_2); } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp index 0e3a413289c5..4101469c97f4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/lookup_pow_2_1.hpp @@ -140,7 +140,7 @@ class lookup_pow_2_1_lookup_settings { in.alu_t_sub_s_bits, in.alu_two_pow_t_sub_s, in.main_clk, - in.main_table_pow_2); + in.powers_power_of_2); } /** @@ -160,7 +160,7 @@ class lookup_pow_2_1_lookup_settings { in.alu_t_sub_s_bits, in.alu_two_pow_t_sub_s, in.main_clk, - in.main_table_pow_2); + in.powers_power_of_2); } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp index ea5a125887f0..6e4c4fdd982c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp @@ -112,7 +112,7 @@ template class memImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 4, 3, 4, 3, 4, 3, 3, - 3, 4, 4, 4, 4, 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 6, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, }; template @@ -365,7 +365,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = ((((-mem_skip_check_tag + FF(1)) * (-mem_rw + FF(1))) * + auto tmp = ((((mem_tag * (-mem_skip_check_tag + FF(1))) * (-mem_rw + FF(1))) * (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)) - FF(0)); tmp *= scaling_factor; @@ -375,7 +375,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (((-mem_tag_err + FF(1)) * mem_one_min_inv) - FF(0)); + auto tmp = (((mem_tag * (-mem_tag_err + FF(1))) * mem_one_min_inv) - FF(0)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp new file mode 100644 index 000000000000..7c43cb2db782 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp @@ -0,0 +1,49 @@ + +#pragma once +#include "../../relation_parameters.hpp" +#include "../../relation_types.hpp" +#include "./declare_views.hpp" + +namespace bb::Avm_vm { + +template struct PowersRow { + FF powers_power_of_2{}; + + [[maybe_unused]] static std::vector names(); +}; + +inline std::string get_relation_label_powers(int index) +{ + switch (index) {} + return std::to_string(index); +} + +template class powersImpl { + public: + using FF = FF_; + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + 2, + }; + + template + void static accumulate(ContainerOverSubrelations& evals, + const AllEntities& new_term, + [[maybe_unused]] const RelationParameters&, + [[maybe_unused]] const FF& scaling_factor) + { + + // Contribution 0 + { + Avm_DECLARE_VIEWS(0); + + auto tmp = ((powers_power_of_2 - powers_power_of_2) - FF(0)); + tmp *= scaling_factor; + std::get<0>(evals) += tmp; + } + } +}; + +template using powers = Relation>; + +} // namespace bb::Avm_vm \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp new file mode 100644 index 000000000000..92078db8e856 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp @@ -0,0 +1,207 @@ +#pragma once +#include +#include + +#include "barretenberg/common/constexpr_utils.hpp" +#include "barretenberg/honk/proof_system/logderivative_library.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/relations/relation_types.hpp" + +namespace bb { + +template class LogDerivLookupRelationImpl { + public: + using FF = FF_; + static constexpr size_t READ_TERMS = 1; + static constexpr size_t WRITE_TERMS = 1; + // 1 + polynomial degree of this relation + static constexpr size_t LENGTH = 5; // both subrelations are degree 4 + + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + LENGTH, // inverse construction sub-relation + LENGTH // log derivative lookup argument sub-relation + }; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1036): Scrutinize these adjustment factors. Counting + // degrees suggests the first subrelation should require an adjustment of 2. + static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ + 1, // inverse construction sub-relation + 1 // log derivative lookup argument sub-relation + }; + + static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; + + template inline static bool skip(const AllEntities& in) + { + // Ensure the input does not contain a lookup gate or data that is being read + return in.q_lookup.is_zero() && in.lookup_read_counts.is_zero(); + } + + /** + * @brief Does the provided row contain data relevant to table lookups; Used to determine whether the polynomial of + * inverses must be computed at a given row + * @details In order to avoid unnecessary computation, the polynomial of inverses I is only computed for rows at + * which the lookup relation is "active". It is active if either (1) the present row contains a lookup gate (i.e. + * q_lookup == 1), or (2) the present row contains table data that has been looked up in this circuit + * (lookup_read_tags == 1, or equivalently, if the row in consideration has index i, the data in polynomials table_i + * has been utlized in the circuit). + * + */ + template static bool operation_exists_at_row(const AllValues& row) + { + // is the row a lookup gate or does it contain table data that has been read at some point in this circuit + return (row.q_lookup == 1) || (row.lookup_read_tags == 1); + } + + // Get the inverse polynomial for this relation + template static auto& get_inverse_polynomial(AllEntities& in) { return in.lookup_inverses; } + + // Used in the inverse correctness subrelation; facilitates only computing inverses where necessary + template + static Accumulator compute_inverse_exists(const AllEntities& in) + { + using View = typename Accumulator::View; + + const auto row_has_write = View(in.lookup_read_tags); + const auto row_has_read = View(in.q_lookup); + return row_has_write + row_has_read - (row_has_write * row_has_read); + } + + template + static Accumulator lookup_read_counts(const AllEntities& in) + { + using View = typename Accumulator::View; + return Accumulator(View(in.lookup_read_counts)); + } + + // Compute table_1 + gamma + table_2 * eta + table_3 * eta_2 + table_4 * eta_3 + template + static Accumulator compute_write_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + using ParameterView = GetParameterView; + + static_assert(write_index < WRITE_TERMS); + + const auto& gamma = ParameterView(params.gamma); + const auto& eta = ParameterView(params.eta); + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); + + auto table_1 = View(in.table_1); + auto table_2 = View(in.table_2); + auto table_3 = View(in.table_3); + auto table_4 = View(in.table_4); + + return table_1 + gamma + table_2 * eta + table_3 * eta_two + table_4 * eta_three; + } + + template + static Accumulator compute_read_term(const AllEntities& in, const Parameters& params) + { + using View = typename Accumulator::View; + using ParameterView = GetParameterView; + + const auto& gamma = ParameterView(params.gamma); + const auto& eta = ParameterView(params.eta); + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); + + auto w_1 = View(in.w_l); + auto w_2 = View(in.w_r); + auto w_3 = View(in.w_o); + + auto w_1_shift = View(in.w_l_shift); + auto w_2_shift = View(in.w_r_shift); + auto w_3_shift = View(in.w_o_shift); + + auto table_index = View(in.q_o); + auto negative_column_1_step_size = View(in.q_r); + auto negative_column_2_step_size = View(in.q_m); + auto negative_column_3_step_size = View(in.q_c); + + // The wire values for lookup gates are accumulators structured in such a way that the differences w_i - + // step_size*w_i_shift result in values present in column i of a corresponding table. See the documentation in + // method get_lookup_accumulators() in for a detailed explanation. + auto derived_table_entry_1 = w_1 + gamma + negative_column_1_step_size * w_1_shift; + auto derived_table_entry_2 = w_2 + negative_column_2_step_size * w_2_shift; + auto derived_table_entry_3 = w_3 + negative_column_3_step_size * w_3_shift; + + // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. + // deg 2 or 3 + return derived_table_entry_1 + derived_table_entry_2 * eta + derived_table_entry_3 * eta_two + + table_index * eta_three; + } + + /** + * @brief Log-derivative style lookup argument for conventional lookups form tables with 3 or fewer columns + * @details The identity to be checked is of the form + * + * \sum{i=0}^{n-1} \frac{read_counts_i}{write_term_i} - \frac{q_lookup}{read_term_i} = 0 + * + * where write_term = table_col_1 + \gamma + table_col_2 * \eta_1 + table_col_3 * \eta_2 + table_index * \eta_3 + * and read_term = derived_table_entry_1 + \gamma + derived_table_entry_2 * \eta_1 + derived_table_entry_3 * \eta_2 + * + table_index * \eta_3, with derived_table_entry_i = w_i - col_step_size_i\cdot w_i_shift. (The table entries + * must be 'derived' from wire values in this way since the stored witnesses are actually successive accumulators, + * the differences of which are equal to entries in a table. This is an efficiency trick to avoid using additional + * gates to reconstruct full size values from the limbs contained in tables). + * + * In practice this identity is expressed in terms of polynomials by defining a polynomial of inverses I_i = + * \frac{1}{read_term_i\cdot write_term_i} then rewriting the above identity as + * + * (1) \sum{i=0}^{n-1} (read_counts_i\cdot I_i\cdot read_term_i) - (q_lookup\cdot I_i\cdot write_term_i) = 0 + * + * This requires a second subrelation to check that polynomial I was computed correctly. For all i, it must hold + * that + * + * (2) I_i\cdot read_term_i\cdot write_term_i - 1 = 0 + * + * Note that (1) is 'linearly dependent' in the sense that it holds only as a sum across the entire execution trace. + * (2) on the other hand holds independently at every row. Finally, note that to avoid unnecessary computation, we + * only compute I_i at indices where the relation is 'active', i.e. on rows which either contain a lookup gate or + * table data that has been read. For inactive rows i, we set I_i = 0. We can thus rewrite (2) as + * + * (2) I_i\cdot read_term_i\cdot write_term_i - is_active_i + * + * where is_active = q_lookup + read_tags - q_lookup\cdot read_tags + * + * and read_tags is a polynomial taking boolean values indicating whether the table entry at the corresponding row + * has been read or not. + * @note This relation utilizes functionality in the log-derivative library to compute the polynomial of inverses + * + */ + template + static void accumulate(ContainerOverSubrelations& accumulator, + const AllEntities& in, + const Parameters& params, + const FF& scaling_factor) + { + BB_OP_COUNT_TIME_NAME("Lookup::accumulate"); + using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + const auto inverses = View(in.lookup_inverses); // Degree 1 + const auto read_counts = View(in.lookup_read_counts); // Degree 1 + const auto read_selector = View(in.q_lookup); // Degree 1 + const auto inverse_exists = compute_inverse_exists(in); // Degree 2 + const auto read_term = compute_read_term(in, params); // Degree 2 (3) + const auto write_term = compute_write_term(in, params); // Degree 1 (2) + const auto write_inverse = inverses * read_term; // Degree 3 (4) + const auto read_inverse = inverses * write_term; // Degree 2 (3) + + // Establish the correctness of the polynomial of inverses I. Note: inverses is computed so that the value is 0 + // if !inverse_exists. + // Degrees: 2 (3) 1 (2) 1 1 + std::get<0>(accumulator) += (read_term * write_term * inverses - inverse_exists) * scaling_factor; // Deg 4 (6) + + // Establish validity of the read. Note: no scaling factor here since this constraint is 'linearly dependent, + // i.e. enforced across the entire trace, not on a per-row basis. + // Degrees: 1 2 (3) 1 3 (4) + std::get<1>(accumulator) += read_selector * read_inverse - read_counts * write_inverse; // Deg 4 (5) + } +}; + +template using LogDerivLookupRelation = Relation>; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp deleted file mode 100644 index 46b70df7cabf..000000000000 --- a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once -#include "barretenberg/relations/relation_types.hpp" - -namespace bb { - -/** - * @brief LookupRelationImpl defines the algebra for the lookup polynomial: - * - * ∏ (1 + β) ⋅ (q_lookup*f_k + γ) ⋅ (t_k + βt_{k+1} + γ(1 + β)) - * Z_lookup(g^j) = -------------------------------------------------------------------------- - * ∏ (s_k + βs_{k+1} + γ(1 + β)) - * - * - * The method `compute_numerator_term` computes polynomials f, t and incorporate them into terms that are ultimately - * needed to construct the grand product polynomial Z_lookup(X): Note 1: In the above, 't' is associated with table - * values (and is not to be confused with the quotient polynomial, also refered to as 't' elsewhere). Polynomial 's' is - * the sorted concatenation of the witnesses and the table values. - * - * @tparam FF parametrises the prime field class being used - */ -template class LookupRelationImpl { - public: - using FF = FF_; - - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ - 6, // grand product construction sub-relation - 3 // left-shiftable polynomial sub-relation - }; - - static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ - 4, // grand product construction sub-relation - 0 // left-shiftable polynomial sub-relation - }; - - /** - * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero - * - */ - template inline static bool skip([[maybe_unused]] const AllEntities& in) - { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/952): figure out why skip condition described in - // issue causes failures in acir tests. - return false; - } - - /** - * @brief Get the grand product polynomial object (either from the proving key or AllEntities depending on context) - * - * @param input - * @return auto& either std::span or Flavor::Polynomial depending on context - */ - inline static auto& get_grand_product_polynomial(auto& input) { return input.z_lookup; } - - /** - * @brief Get the shifted grand product polynomial object (either from the proving key or AllEntities depending on - * context) - * - * @param input - * @return auto& either std::span or Flavor::Polynomial depending on context - */ - inline static auto& get_shifted_grand_product_polynomial(auto& input) { return input.z_lookup_shift; } - - /** - * @brief Compute numerator term of the lookup relation: - * - * N_{index} = (1 + β) ⋅ ∏ (q_lookup*f_k + γ) ⋅ (t_k + βt_{k+1} + γ(1 + β)) - * - * @tparam AccumulatorTypes - * @param in - * @param relation_parameters - * @param index If calling this method over vector inputs, index >= 0 - */ - template - inline static Accumulator compute_grand_product_numerator(const AllEntities& in, const Parameters& params) - { - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& beta = ParameterView(params.beta); - const auto& gamma = ParameterView(params.gamma); - const auto& eta = ParameterView(params.eta); - const auto& eta_two = ParameterView(params.eta_two); - const auto& eta_three = ParameterView(params.eta_three); - - const auto one_plus_beta = beta + FF(1); - const auto gamma_by_one_plus_beta = gamma * one_plus_beta; - - auto w_1 = View(in.w_l); - auto w_2 = View(in.w_r); - auto w_3 = View(in.w_o); - - auto w_1_shift = View(in.w_l_shift); - auto w_2_shift = View(in.w_r_shift); - auto w_3_shift = View(in.w_o_shift); - - auto table_1 = View(in.table_1); - auto table_2 = View(in.table_2); - auto table_3 = View(in.table_3); - auto table_4 = View(in.table_4); - - auto table_1_shift = View(in.table_1_shift); - auto table_2_shift = View(in.table_2_shift); - auto table_3_shift = View(in.table_3_shift); - auto table_4_shift = View(in.table_4_shift); - - auto table_index = View(in.q_o); - auto column_1_step_size = View(in.q_r); - auto column_2_step_size = View(in.q_m); - auto column_3_step_size = View(in.q_c); - auto q_lookup = View(in.q_lookup); - - // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. - // deg 2 or 3 - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - - // t_1 + ηt_2 + η₂t_3 + η₃t_4 - // deg 1 or 2 - auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; - - // t_1_shift + ηt_2_shift + η₂t_3_shift + η₃t_4_shift - // deg 1 or 2 - auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; - - auto tmp = (q_lookup * wire_accum + gamma); // deg 3 or 4 - tmp *= (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 3 - tmp *= one_plus_beta; // deg 0 or 1 - return tmp; // deg 4 or 8 - } - - /** - * @brief Compute denominator term of the lookup relation: - * - * (s_k + βs_{k+1} + γ(1 + β)) - * - * @tparam AccumulatorTypes - * @param in - * @param relation_parameters - * @param index - */ - template - inline static Accumulator compute_grand_product_denominator(const AllEntities& in, const Parameters& params) - { - - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& beta = ParameterView(params.beta); - const auto& gamma = ParameterView(params.gamma); - - const auto one_plus_beta = beta + FF(1); - const auto gamma_by_one_plus_beta = gamma * one_plus_beta; // deg 0 or 2 - - // Contribution (1) - auto s_accum = View(in.sorted_accum); - auto s_accum_shift = View(in.sorted_accum_shift); - - auto tmp = (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 2 - return tmp; - } - - /** - * @brief Compute contribution of the lookup grand prod relation for a given edge (internal function) - * - * @details This the relation confirms faithful calculation of the lookup grand - * product polynomial Z_lookup. The contribution is - * z_lookup * (1 + β) * [q_lookup * f + γ] * (t_accum_k + βt_accum_{k+1} + γ(1 + β)) - - * z_lookup_shift * (s_accum_k + βs_accum_{k+1} + γ(1 + β)) - * where - * f = (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index, - * t_accum = table_1 + ηtable_2 + η²table_3 + η³table_4, and - * s_accum = s_1 + ηs_2 + η²s_3 + η³s_4. - * Note: Selectors q_2, q_m and q_c are repurposed as 'column step size' for lookup gates. - * - * @param evals transformed to `evals + C(in(X)...)*scaling_factor` - * @param in an std::array containing the fully extended Univariate edges. - * @param parameters contains beta, gamma, and public_input_delta, .... - * @param scaling_factor optional term to scale the evaluation before adding to evals. - */ - template - inline static void accumulate(ContainerOverSubrelations& accumulators, - const AllEntities& in, - const Parameters& params, - const FF& scaling_factor) - { - BB_OP_COUNT_TIME_NAME("Lookup::accumulate"); - { - using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; - using View = typename Accumulator::View; - using ParameterView = GetParameterView; - - const auto& grand_product_delta = ParameterView(params.lookup_grand_product_delta); - - auto z_lookup = View(in.z_lookup); - auto z_lookup_shift = View(in.z_lookup_shift); - - auto lagrange_first = View(in.lagrange_first); - auto lagrange_last = View(in.lagrange_last); - - const auto lhs = compute_grand_product_numerator(in, params); // deg 4 or 8 - const auto rhs = compute_grand_product_denominator(in, params); // deg 1 or 2 - - // (deg 5 or 9) - (deg 3 or 5) - const auto tmp = - lhs * (z_lookup + lagrange_first) - rhs * (z_lookup_shift + lagrange_last * grand_product_delta); - std::get<0>(accumulators) += tmp * scaling_factor; - }; - - { - using Accumulator = std::tuple_element_t<1, ContainerOverSubrelations>; - using View = typename Accumulator::View; - auto z_lookup_shift = View(in.z_lookup_shift); - auto lagrange_last = View(in.lagrange_last); - - // Contribution (2) - std::get<1>(accumulators) += (lagrange_last * z_lookup_shift) * scaling_factor; - }; - }; -}; - -template using LookupRelation = Relation>; - -} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 0406f82bcef8..b40b45da3c6f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -16,7 +16,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/poseidon2_external_relation.hpp" #include "barretenberg/relations/poseidon2_internal_relation.hpp" @@ -204,84 +203,6 @@ TEST_F(UltraRelationConsistency, UltraPermutationRelation) run_test(/*random_inputs=*/true); }; -TEST_F(UltraRelationConsistency, LookupRelation) -{ - const auto run_test = [](bool random_inputs) { - using Relation = LookupRelation; - using SumcheckArrayOfValuesOverSubrelations = typename Relation::SumcheckArrayOfValuesOverSubrelations; - - const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); - const auto& w_1 = input_elements.w_l; - const auto& w_2 = input_elements.w_r; - const auto& w_3 = input_elements.w_o; - - const auto& w_1_shift = input_elements.w_l_shift; - const auto& w_2_shift = input_elements.w_r_shift; - const auto& w_3_shift = input_elements.w_o_shift; - - const auto& table_1 = input_elements.table_1; - const auto& table_2 = input_elements.table_2; - const auto& table_3 = input_elements.table_3; - const auto& table_4 = input_elements.table_4; - - const auto& table_1_shift = input_elements.table_1_shift; - const auto& table_2_shift = input_elements.table_2_shift; - const auto& table_3_shift = input_elements.table_3_shift; - const auto& table_4_shift = input_elements.table_4_shift; - - const auto& s_accum = input_elements.sorted_accum; - const auto& s_accum_shift = input_elements.sorted_accum_shift; - const auto& z_lookup = input_elements.z_lookup; - const auto& z_lookup_shift = input_elements.z_lookup_shift; - - const auto& table_index = input_elements.q_o; - const auto& column_1_step_size = input_elements.q_r; - const auto& column_2_step_size = input_elements.q_m; - const auto& column_3_step_size = input_elements.q_c; - const auto& q_lookup = input_elements.q_lookup; - - const auto& lagrange_first = input_elements.lagrange_first; - const auto& lagrange_last = input_elements.lagrange_last; - - SumcheckArrayOfValuesOverSubrelations expected_values; - - const auto parameters = RelationParameters::get_random(); - - const auto eta = parameters.eta; - const auto eta_two = parameters.eta_two; - const auto eta_three = parameters.eta_three; - const auto beta = parameters.beta; - const auto gamma = parameters.gamma; - auto grand_product_delta = parameters.lookup_grand_product_delta; - - // Extract the extended edges for manual computation of relation contribution - auto one_plus_beta = FF::one() + beta; - auto gamma_by_one_plus_beta = gamma * one_plus_beta; - - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - - auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; - auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; - - // Contribution 1 - auto contribution_1 = (z_lookup + lagrange_first) * (q_lookup * wire_accum + gamma) * - (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta) * one_plus_beta; - contribution_1 -= (z_lookup_shift + lagrange_last * grand_product_delta) * - (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); - expected_values[0] = contribution_1; - - // Contribution 2 - auto contribution_2 = z_lookup_shift * lagrange_last; - expected_values[1] = contribution_2; - - validate_relation_execution(expected_values, input_elements, parameters); - }; - run_test(/*random_inputs=*/false); - run_test(/*random_inputs=*/true); -}; - TEST_F(UltraRelationConsistency, DeltaRangeConstraintRelation) { const auto run_test = [](bool random_inputs) { diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/crs_factory.hpp index 66e5e55f27d3..635bc3c0f5f8 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/crs_factory.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/crs_factory.hpp @@ -45,7 +45,7 @@ template <> class VerifierCrs { * @brief Returns the first G_1 element from the CRS, used by the Shplonk verifier to compute the final * commtiment. */ - virtual Curve::AffineElement get_first_g1() const = 0; + virtual Curve::AffineElement get_g1_identity() const = 0; }; template <> class VerifierCrs { @@ -62,7 +62,7 @@ template <> class VerifierCrs { * @brief Returns the first G_1 element from the CRS, used by the Shplonk verifier to compute the final * commtiment. */ - virtual Curve::AffineElement get_first_g1() const = 0; + virtual Curve::AffineElement get_g1_identity() const = 0; }; /** diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp index f082700e32f5..967e4e3612af 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.cpp @@ -18,7 +18,7 @@ FileVerifierCrs::FileVerifierCrs(std::string const& path, const si srs::IO::read_transcript_g2(g2_x, path); bb::pairing::precompute_miller_lines(bb::g2::one, precomputed_g2_lines[0]); bb::pairing::precompute_miller_lines(g2_x, precomputed_g2_lines[1]); - first_g1 = point_buf[0]; + g1_identity = point_buf[0]; } FileVerifierCrs::~FileVerifierCrs() @@ -33,7 +33,7 @@ FileVerifierCrs::FileVerifierCrs(std::string const& path, const monomials_ = scalar_multiplication::point_table_alloc(num_points); srs::IO::read_transcript_g1(monomials_.get(), num_points, path); scalar_multiplication::generate_pippenger_point_table(monomials_.get(), monomials_.get(), num_points); - first_g1 = monomials_[0]; + g1_identity = monomials_[0]; }; curve::Grumpkin::AffineElement* FileVerifierCrs::get_monomial_points() const diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp index 09dad29a1cbc..149d97940989 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/file_crs_factory.hpp @@ -62,10 +62,10 @@ template <> class FileVerifierCrs : public VerifierCrs class FileVerifierCrs : public VerifierCrs monomials_; }; diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp index 0c9767328a05..42ce7e2c30ea 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp @@ -28,10 +28,10 @@ class MemVerifierCrs : public VerifierCrs { g2::affine_element get_g2x() const { return g2_x; } pairing::miller_lines const* get_precomputed_g2_lines() const { return precomputed_g2_lines; } - g1::affine_element get_first_g1() const { return first_g1x; }; + g1::affine_element get_g1_identity() const { return g1_identityx; }; private: - g1::affine_element first_g1x; + g1::affine_element g1_identityx; g2::affine_element g2_x; pairing::miller_lines* precomputed_g2_lines; }; diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp index 190fa75cef1d..df243d73785c 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp @@ -68,7 +68,7 @@ TEST(reference_string, DISABLED_mem_grumpkin_file_consistency) auto file_verifier_crs = file_crs.get_verifier_crs(); auto mem_verifier_crs = file_crs.get_verifier_crs(); - EXPECT_EQ(mem_verifier_crs->get_first_g1(), file_verifier_crs->get_first_g1()); + EXPECT_EQ(mem_verifier_crs->get_g1_identity(), file_verifier_crs->get_g1_identity()); EXPECT_EQ(memcmp(file_verifier_crs->get_monomial_points(), mem_verifier_crs->get_monomial_points(), sizeof(Grumpkin::AffineElement) * 1024 * 2), diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp index 1001c9519a49..bbec0dccf0d0 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp @@ -26,7 +26,7 @@ class MemVerifierCrs : public VerifierCrs { virtual ~MemVerifierCrs() = default; Grumpkin::AffineElement* get_monomial_points() const override { return monomials_.get(); } size_t get_monomial_size() const override { return num_points; } - Grumpkin::AffineElement get_first_g1() const override { return monomials_[0]; }; + Grumpkin::AffineElement get_g1_identity() const override { return monomials_[0]; }; private: size_t num_points; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.cpp index 0286a7dbc945..055fa5ca299f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.cpp @@ -2,6 +2,12 @@ namespace bb::stdlib::recursion::honk { +/** + * @brief Performs recursive verification of the Client IVC proof. + * + * @todo (https://github.com/AztecProtocol/barretenberg/issues/934): Add logic for accumulating the pairing points + * produced by the verifiers (and potentially IPA accumulators for ECCVM verifier) + */ void ClientIVCRecursiveVerifier::verify(const ClientIVC::Proof& proof) { // Perform recursive folding verification diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.test.cpp index b7c5f01e5028..4be2ca259603 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/client_ivc_recursive_verifier.test.cpp @@ -88,6 +88,10 @@ TEST_F(ClientIVCRecursionTests, Basic) // Generate the recursive verification circuit verifier.verify(proof); + info("Recursive Verifier: num gates = ", builder->num_gates); + + EXPECT_EQ(builder->failed(), false) << builder->err(); + EXPECT_TRUE(CircuitChecker::check(*builder)); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp index 55d31e120966..44c083a544ca 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp @@ -15,7 +15,8 @@ std::array DeciderRecursiveVerifier_:: { using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; - using ZeroMorph = ::bb::ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ::bb::ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using Transcript = typename Flavor::Transcript; @@ -32,12 +33,14 @@ std::array DeciderRecursiveVerifier_:: // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - transcript); + auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(builder), + transcript); + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); return pairing_points; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/goblin_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/goblin_recursive_verifier.cpp index 692382da3a05..5ad5a1906212 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/goblin_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/goblin_recursive_verifier.cpp @@ -2,6 +2,12 @@ namespace bb::stdlib::recursion::honk { +/** + * @brief Runs the Goblin recursive verifier consisting of ECCVM, Translator and Merge verifiers. + * + * @todo https://github.com/AztecProtocol/barretenberg/issues/934: Add logic for accumulating the pairing points + * produced by the translator and merge verifier (and potentially IPA accumulators for ECCVM verifier) + */ void GoblinRecursiveVerifier::verify(const GoblinProof& proof) { // Run the ECCVM recursive verifier @@ -28,9 +34,7 @@ void GoblinRecursiveVerifier::verify(const GoblinProof& proof) }; translator_verifier.verify_translation(translation_evaluations); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1024): Perform recursive merge verification once it - // works with Ultra arithmetization - // MergeVerifier merge_verified{ builder }; - // [[maybe_unused]] auto merge_pairing_points = merge_verifier.verify_proof(proof.merge_proof); + MergeVerifier merge_verifier{ builder }; + merge_verifier.verify_proof(proof.merge_proof); } } // namespace bb::stdlib::recursion::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index daedb38fd71b..0a1b48068bd6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -53,17 +53,26 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst domain_separator + "_" + labels.return_data_read_counts); } - // Get challenge for sorted list batching and wire four memory records commitment + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "_eta", domain_separator + "_eta_two", domain_separator + "_eta_three"); - witness_commitments.sorted_accum = - transcript->template receive_from_prover(domain_separator + "_" + labels.sorted_accum); + + // Receive commitments to lookup argument polynomials + witness_commitments.lookup_read_counts = + transcript->template receive_from_prover(domain_separator + "_" + labels.lookup_read_counts); + witness_commitments.lookup_read_tags = + transcript->template receive_from_prover(domain_separator + "_" + labels.lookup_read_tags); + + // Receive commitments to wire 4 witness_commitments.w_4 = transcript->template receive_from_prover(domain_separator + "_" + labels.w_4); // Get permutation challenges and commitment to permutation and lookup grand products auto [beta, gamma] = transcript->template get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); + witness_commitments.lookup_inverses = transcript->template receive_from_prover( + domain_separator + "_" + commitment_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial if constexpr (IsGoblinFlavor) { witness_commitments.calldata_inverses = transcript->template receive_from_prover( @@ -74,8 +83,6 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst witness_commitments.z_perm = transcript->template receive_from_prover(domain_separator + "_" + labels.z_perm); - witness_commitments.z_lookup = - transcript->template receive_from_prover(domain_separator + "_" + labels.z_lookup); // Compute correction terms for grand products const FF public_input_delta = diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp index abb38ea241a6..f609464efec1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp @@ -40,7 +40,8 @@ std::array UltraRecursiveVerifier_::ve { using Sumcheck = ::bb::SumcheckVerifier; using PCS = typename Flavor::PCS; - using ZeroMorph = ::bb::ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ::bb::ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; using RelationParams = ::bb::RelationParameters; @@ -56,7 +57,8 @@ std::array UltraRecursiveVerifier_::ve transcript->template receive_from_prover("public_input_size"); transcript->template receive_from_prover("pub_inputs_offset"); - // For debugging purposes only + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1032): Uncomment these once it doesn't cause issues + // with the flows // ASSERT(static_cast(circuit_size.get_value()) == key->circuit_size); // ASSERT(static_cast(public_input_size.get_value()) == key->num_public_inputs); // ASSERT(static_cast(pub_inputs_offset.get_value()) == key->pub_inputs_offset); @@ -89,19 +91,25 @@ std::array UltraRecursiveVerifier_::ve transcript->template receive_from_prover(commitment_labels.return_data_read_counts); } - // Get challenge for sorted list batching and wire four memory records + // Get eta challenges; used in RAM/ROM memory records and log derivative lookup argument auto [eta, eta_two, eta_three] = transcript->template get_challenges("eta", "eta_two", "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - // Get commitments to sorted list accumulator and fourth wire - commitments.sorted_accum = transcript->template receive_from_prover(commitment_labels.sorted_accum); + // Get commitments to lookup argument polynomials and fourth wire + commitments.lookup_read_counts = + transcript->template receive_from_prover(commitment_labels.lookup_read_counts); + commitments.lookup_read_tags = + transcript->template receive_from_prover(commitment_labels.lookup_read_tags); commitments.w_4 = transcript->template receive_from_prover(commitment_labels.w_4); // Get permutation challenges auto [beta, gamma] = transcript->template get_challenges("beta", "gamma"); + commitments.lookup_inverses = + transcript->template receive_from_prover(commitment_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial if constexpr (IsGoblinFlavor) { commitments.calldata_inverses = @@ -121,7 +129,6 @@ std::array UltraRecursiveVerifier_::ve // Get commitment to permutation and lookup grand products commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); - commitments.z_lookup = transcript->template receive_from_prover(commitment_labels.z_lookup); // Execute Sumcheck Verifier and extract multivariate opening point u = (u_0, ..., u_{d-1}) and purported // multivariate evaluations at u @@ -138,14 +145,18 @@ std::array UltraRecursiveVerifier_::ve } auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - // Execute ZeroMorph multilinear PCS evaluation verifier - auto verifier_accumulator = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - transcript); - return verifier_accumulator; + + // Execute ZeroMorph to produce an opening claim subsequently verified by a univariate PCS + auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(builder), + transcript); + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); + + return pairing_points; } template class UltraRecursiveVerifier_>; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp index f8658a39fe3f..605b44b702f0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp @@ -227,7 +227,7 @@ template class RecursiveVerifierTest : public testing // Arbitrarily tamper with the proof to be verified inner_prover.transcript->deserialize_full_transcript(); - inner_prover.transcript->sorted_accum_comm = InnerCommitment::one() * InnerFF::random_element(); + inner_prover.transcript->z_perm_comm = InnerCommitment::one() * InnerFF::random_element(); inner_prover.transcript->serialize_full_transcript(); inner_proof = inner_prover.export_proof(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp index 9ab7c789f67b..0bf80a8db8cd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp @@ -146,134 +146,6 @@ template class GrandProductTests : public testing::Test { // Check consistency between locally computed z_perm and the one computed by the prover library EXPECT_EQ(prover_polynomials.z_perm, z_permutation_expected); }; - - /** - * @brief Check consistency of the computation of the lookup grand product polynomial z_lookup. - * @details This test compares a simple, unoptimized, easily readable calculation of the grand product z_lookup - * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization - * introduced into the calculation has not changed the result. - * @note This test does confirm the correctness of z_lookup, only that the two implementations yield an - * identical result. - */ - static void test_lookup_grand_product_construction() - { - using Flavor = UltraFlavor; - using ProverPolynomials = typename Flavor::ProverPolynomials; - - // Set a mock circuit size - static const size_t circuit_size = 8; - - // Construct a ProverPolynomials object with completely random polynomials - ProverPolynomials prover_polynomials; - for (auto& poly : prover_polynomials.get_unshifted()) { - poly = get_random_polynomial(circuit_size); - poly[0] = 0; // for shiftability - } - prover_polynomials.set_shifted(); - - // Get random challenges - auto beta = FF::random_element(); - auto gamma = FF::random_element(); - auto eta = FF::random_element(); - auto eta_two = FF::random_element(); - auto eta_three = FF::random_element(); - - RelationParameters params{ - .eta = eta, - .eta_two = eta_two, - .eta_three = eta_three, - .beta = beta, - .gamma = gamma, - .public_input_delta = 1, - .lookup_grand_product_delta = 1, - }; - - // Method 1: Compute z_lookup using the prover library method - constexpr size_t LOOKUP_RELATION_INDEX = 1; - using LHS = typename std::tuple_element::type; - using RHS = LookupRelation; - static_assert(std::same_as); - compute_grand_product(prover_polynomials, params); - - // Method 2: Compute the lookup grand product polynomial Z_lookup: - // - // ∏(1 + β) ⋅ ∏(q_lookup*f_k + γ) ⋅ ∏(t_k + βt_{k+1} + γ(1 + β)) - // Z_lookup(X_j) = ----------------------------------------------------------------- - // ∏(s_k + βs_{k+1} + γ(1 + β)) - // - // in a way that is simple to read (but inefficient). See prover library method for more details. - - std::array accumulators; - for (size_t i = 0; i < 4; ++i) { - accumulators[i] = Polynomial{ circuit_size }; - } - - // Step (1) - - auto wires = prover_polynomials.get_wires(); - auto tables = prover_polynomials.get_tables(); - auto sorted_batched = prover_polynomials.sorted_accum; - auto column_1_step_size = prover_polynomials.q_r; - auto column_2_step_size = prover_polynomials.q_m; - auto column_3_step_size = prover_polynomials.q_c; - auto lookup_index_selector = prover_polynomials.q_o; - auto lookup_selector = prover_polynomials.q_lookup; - - // Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k - const size_t block_mask = circuit_size - 1; - // Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω) - FF table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_two + tables[3][0] * eta_three; - for (size_t i = 0; i < circuit_size; ++i) { - size_t shift_idx = (i + 1) & block_mask; - - // f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index. - FF f_i = (wires[0][i] + wires[0][shift_idx] * column_1_step_size[i]) + - (wires[1][i] + wires[1][shift_idx] * column_2_step_size[i]) * eta + - (wires[2][i] + wires[2][shift_idx] * column_3_step_size[i]) * eta_two + - eta_three * lookup_index_selector[i]; - - // q_lookup * f + γ - accumulators[0][i] = lookup_selector[i] * f_i + gamma; - - // t = t_1 + ηt_2 + η²t_3 + η³t_4 - FF table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_two * tables[2][shift_idx] + - eta_three * tables[3][shift_idx]; - - // t + βt(Xω) + γ(1 + β) - accumulators[1][i] = table_i + table_i_plus_1 * beta + gamma * (FF::one() + beta); - - // (1 + β) - accumulators[2][i] = FF::one() + beta; - - // s + βs(Xω) + γ(1 + β) - accumulators[3][i] = sorted_batched[i] + beta * sorted_batched[shift_idx] + gamma * (FF::one() + beta); - - // Set t(X_i) for next iteration - table_i = table_i_plus_1; - } - - // Step (2) - for (auto& accum : accumulators) { - for (size_t i = 0; i < circuit_size - 1; ++i) { - accum[i + 1] *= accum[i]; - } - } - - // Step (3) - Polynomial z_lookup_expected(circuit_size); - z_lookup_expected[0] = FF::zero(); // Z_lookup_0 = 0 - - // Compute the numerator in accumulators[0]; The denominator is in accumulators[3] - for (size_t i = 0; i < circuit_size - 1; ++i) { - accumulators[0][i] *= accumulators[1][i] * accumulators[2][i]; - } - // Compute Z_lookup_i, i = [1, n-1] - for (size_t i = 0; i < circuit_size - 1; ++i) { - z_lookup_expected[i + 1] = accumulators[0][i] / accumulators[3][i]; - } - - EXPECT_EQ(prover_polynomials.z_lookup, z_lookup_expected); - }; }; using FieldTypes = testing::Types; @@ -283,8 +155,3 @@ TYPED_TEST(GrandProductTests, GrandProductPermutation) { TestFixture::template test_permutation_grand_product_construction(); } - -TYPED_TEST(GrandProductTests, GrandProductLookup) -{ - TestFixture::test_lookup_grand_product_construction(); -} diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 267c8643f4f1..45467f783253 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -13,7 +13,7 @@ #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/ecc_op_queue_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/poseidon2_external_relation.hpp" #include "barretenberg/relations/poseidon2_internal_relation.hpp" @@ -39,24 +39,23 @@ class MegaFlavor { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. - // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 58; + static constexpr size_t NUM_ALL_ENTITIES = 57; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 30; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 17; + static constexpr size_t NUM_WITNESS_ENTITIES = 18; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; - using GrandProductRelations = std::tuple, bb::LookupRelation>; + using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. template using Relations_ = std::tuple, bb::UltraPermutationRelation, - bb::LookupRelation, + bb::LogDerivLookupRelation, bb::DeltaRangeConstraintRelation, bb::EllipticRelation, bb::AuxiliaryRelation, @@ -66,8 +65,6 @@ class MegaFlavor { bb::Poseidon2InternalRelation>; using Relations = Relations_; - using LogDerivLookupRelation = bb::DatabusLookupRelation; - static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); @@ -179,19 +176,20 @@ class MegaFlavor { template class DerivedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - sorted_accum, // column 4 - z_perm, // column 5 - z_lookup, // column 6 - ecc_op_wire_1, // column 7 - ecc_op_wire_2, // column 8 - ecc_op_wire_3, // column 9 - ecc_op_wire_4, // column 10 - calldata, // column 11 - calldata_read_counts, // column 12 - calldata_inverses, // column 13 - return_data, // column 14 - return_data_read_counts, // column 15 - return_data_inverses); // column 16 + z_perm, // column 4 + lookup_inverses, // column 5 + lookup_read_counts, // column 6 + lookup_read_tags, // column 7 + ecc_op_wire_1, // column 8 + ecc_op_wire_2, // column 9 + ecc_op_wire_3, // column 10 + ecc_op_wire_4, // column 11 + calldata, // column 12 + calldata_read_counts, // column 13 + calldata_inverses, // column 14 + return_data, // column 15 + return_data_read_counts, // column 16 + return_data_inverses); // column 17 }; /** @@ -214,9 +212,10 @@ class MegaFlavor { this->w_r, this->w_o, this->w_4, - this->sorted_accum, this->z_perm, - this->z_lookup, + this->lookup_inverses, + this->lookup_read_counts, + this->lookup_read_tags, this->ecc_op_wire_1, this->ecc_op_wire_2, this->ecc_op_wire_3, @@ -232,18 +231,15 @@ class MegaFlavor { template class ShiftedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - table_1_shift, // column 0 - table_2_shift, // column 1 - table_3_shift, // column 2 - table_4_shift, // column 3 - w_l_shift, // column 4 - w_r_shift, // column 5 - w_o_shift, // column 6 - w_4_shift, // column 7 - sorted_accum_shift, // column 8 - z_perm_shift, // column 9 - z_lookup_shift // column 10 - ) + table_1_shift, // column 0 + table_2_shift, // column 1 + table_3_shift, // column 2 + table_4_shift, // column 3 + w_l_shift, // column 4 + w_r_shift, // column 5 + w_o_shift, // column 6 + w_4_shift, // column 7 + z_perm_shift) // column 8 }; public: @@ -281,8 +277,8 @@ class MegaFlavor { auto get_witness() { return WitnessEntities::get_all(); }; auto get_to_be_shifted() { - return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, - this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; + return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, + this->w_r, this->w_o, this->w_4, this->z_perm }; }; auto get_precomputed() { return PrecomputedEntities::get_all(); } auto get_shifted() { return ShiftedEntities::get_all(); }; @@ -351,44 +347,8 @@ class MegaFlavor { std::vector memory_read_records; std::vector memory_write_records; - std::array sorted_polynomials; ProverPolynomials polynomials; // storage for all polynomials evaluated by the prover - void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) - { - // Compute sorted witness-table accumulator - compute_sorted_list_accumulator(eta, eta_two, eta_three); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); - } - - /** - * @brief Construct sorted list accumulator polynomial 's'. - * - * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the - * sorted concatenated witness/table polynomials - * - * @param key proving key - * @param sorted_list_polynomials sorted concatenated witness/table polynomials - * @param eta random challenge - * @return Polynomial - */ - void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) - { - - auto& sorted_list_accumulator = polynomials.sorted_accum; - - // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < this->circuit_size; ++i) { - FF T0 = sorted_polynomials[3][i] * eta_three; - T0 += sorted_polynomials[2][i] * eta_two; - T0 += sorted_polynomials[1][i] * eta; - T0 += sorted_polynomials[0][i]; - sorted_list_accumulator[i] = T0; - } - } - /** * @brief Add plookup memory records to the fourth wire polynomial * @@ -398,7 +358,7 @@ class MegaFlavor { * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) + void add_ram_rom_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; @@ -422,14 +382,18 @@ class MegaFlavor { } /** - * @brief Compute the inverse polynomial used in the databus log derivative lookup argument + * @brief Compute the inverse polynomials used in the log derivative lookup relations * * @tparam Flavor * @param beta * @param gamma */ - void compute_logderivative_inverse(const RelationParameters& relation_parameters) + void compute_logderivative_inverses(const RelationParameters& relation_parameters) { + // Compute inverses for conventional lookups + compute_logderivative_inverse>( + this->polynomials, relation_parameters, this->circuit_size); + // Compute inverses for calldata reads DatabusLookupRelation::compute_logderivative_inverse( this->polynomials, relation_parameters, this->circuit_size); @@ -440,7 +404,7 @@ class MegaFlavor { } /** - * @brief Computes public_input_delta, lookup_grand_product_delta, the z_perm and z_lookup polynomials + * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters */ @@ -677,8 +641,9 @@ class MegaFlavor { w_o = "W_O"; w_4 = "W_4"; z_perm = "Z_PERM"; - z_lookup = "Z_LOOKUP"; - sorted_accum = "SORTED_ACCUM"; + lookup_inverses = "LOOKUP_INVERSES"; + lookup_read_counts = "LOOKUP_READ_COUNTS"; + lookup_read_tags = "LOOKUP_READ_TAGS"; ecc_op_wire_1 = "ECC_OP_WIRE_1"; ecc_op_wire_2 = "ECC_OP_WIRE_2"; ecc_op_wire_3 = "ECC_OP_WIRE_3"; @@ -768,9 +733,10 @@ class MegaFlavor { this->w_r = commitments.w_r; this->w_o = commitments.w_o; this->w_4 = commitments.w_4; - this->sorted_accum = commitments.sorted_accum; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->ecc_op_wire_1 = commitments.ecc_op_wire_1; this->ecc_op_wire_2 = commitments.ecc_op_wire_2; this->ecc_op_wire_3 = commitments.ecc_op_wire_3; @@ -811,10 +777,11 @@ class MegaFlavor { Commitment return_data_comm; Commitment return_data_read_counts_comm; Commitment return_data_inverses_comm; - Commitment sorted_accum_comm; Commitment w_4_comm; Commitment z_perm_comm; - Commitment z_lookup_comm; + Commitment lookup_inverses_comm; + Commitment lookup_read_counts_comm; + Commitment lookup_read_tags_comm; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; std::vector zm_cq_comms; @@ -867,10 +834,11 @@ class MegaFlavor { return_data_comm = deserialize_from_buffer(proof_data, num_frs_read); return_data_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); return_data_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); - sorted_accum_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_tags_comm = deserialize_from_buffer(proof_data, num_frs_read); w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - z_lookup_comm = deserialize_from_buffer(proof_data, num_frs_read); for (size_t i = 0; i < log_n; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, @@ -908,10 +876,11 @@ class MegaFlavor { serialize_to_buffer(return_data_comm, proof_data); serialize_to_buffer(return_data_read_counts_comm, proof_data); serialize_to_buffer(return_data_inverses_comm, proof_data); - serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(lookup_read_counts_comm, proof_data); + serialize_to_buffer(lookup_read_tags_comm, proof_data); serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - serialize_to_buffer(z_lookup_comm, proof_data); for (size_t i = 0; i < log_n; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp index 5d5b3c03953a..0682a8a44abf 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mock_circuits.hpp @@ -58,6 +58,35 @@ class MockCircuits { } } + /** + * @brief Add lookup gates using the uint32 XOR lookup table (table size 4096) + * @brief Each iteration adds 6 lookup gates and results in a minimum circuit size of 4096 + * + * @param builder + * @param num_gates + */ + template static void add_lookup_gates(Builder& builder, size_t num_iterations = 1) + { + auto UINT32_XOR = plookup::MultiTableId::UINT32_XOR; + + // Each iteration adds 6 lookup gates (due to six 6-bit limbs); the first adds a table of size 4096 + for (size_t i = 0; i < num_iterations; ++i) { + // define some arbitrary inputs to uint32 XOR + uint32_t left_value = engine.get_random_uint32(); + uint32_t right_value = engine.get_random_uint32(); + + fr left = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); + fr right = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); + + auto left_idx = builder.add_variable(left); + auto right_idx = builder.add_variable(right); + + // perform lookups from the uint32 XOR table + auto accumulators = plookup::get_lookup_accumulators(UINT32_XOR, left, right, /*is_2_to_1_lookup*/ true); + builder.create_gates_from_plookup_accumulators(UINT32_XOR, accumulators, left_idx, right_idx); + } + } + /** * @brief Populate a builder with a specified number of arithmetic gates; includes a PI * diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp index b897fc8c3093..0440eb17b9c5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.cpp @@ -143,14 +143,14 @@ const MultiTable& get_multitable(const MultiTableId id) /** * @brief Given a table ID and the key(s) for a key-value lookup, return the lookup accumulators - * @details In general the number of bits in key/value is greater than what can be efficiently supported in lookup - * tables. For this reason we actually perform lookups on the corresponding limbs. However, since we're interested in - * the full values and not the limbs, its convenient to structure the witnesses of lookup gates to store the former. - * This way we don't have to waste gates reaccumulating the limbs to compute the actual value of interest. The way to do - * this is to populate the wires with 'accumulator' values such that the first gate in the series contains the full - * accumulated values, and successive gates contain prior stages of the accumulator such that wire_i - r*wire_{i-1} = - * v_i, where r = num limb bits and v_i is a limb that explicitly appears in one of the lookup tables. See the detailed - * comment block below for more explanation. + * @details In general the number of bits in original key/value is greater than what can be efficiently supported in + * lookup tables. For this reason we actually perform lookups on the corresponding limbs. However, since we're + * interested in the original values and not the limbs, its convenient to structure the witnesses of lookup gates to + * store the former. This way we don't have to waste gates reaccumulating the limbs to compute the actual value of + * interest. The way to do this is to populate the wires with 'accumulator' values such that the first gate in the + * series contains the full accumulated values, and successive gates contain prior stages of the accumulator such that + * wire_i - r*wire_{i-1} = v_i, where r = num limb bits and v_i is a limb that explicitly appears in one of the lookup + * tables. See the detailed comment block below for more explanation. * * @param id * @param key_a @@ -176,7 +176,7 @@ ReadData get_lookup_accumulators(const MultiTableId id, std::vector column_3_raw_values; for (size_t i = 0; i < num_lookups; ++i) { - // compute the value(s) corresponding to the key(s) using on the i-th basic table query function + // compute the value(s) corresponding to the key(s) using the i-th basic table query function const auto values = multi_table.get_table_values[i]({ key_a_slices[i], key_b_slices[i] }); // store all query data in raw columns and key entry column_1_raw_values.emplace_back(key_a_slices[i]); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp index c41d4e94670e..259082820eb8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/plookup_tables/types.hpp @@ -122,8 +122,8 @@ enum MultiTableId { }; /** - * @brief Container for managing multiple BasicTables plus the data needed to combine basic table outputs (limbs) into - * accumulators. Does not store actual raw table data. + * @brief Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e.g. limbs) + * into accumulators. Does not store actual raw table data. * @details As a simple example, consider using lookups to compute XOR on uint32_t inputs. To do this we decompose the * inputs into 6 limbs and use a BasicTable for 6-bit XOR lookups. In this case the MultiTable simply manages 6 basic * tables, all of which are the XOR BasicTable. (In many cases all of the BasicTables managed by a MultiTable are @@ -213,7 +213,7 @@ struct MultiTable { // std::array value{ bb::fr(0), bb::fr(0) }; // bool operator<(const KeyEntry& other) const { return key < other.key; } -// std::array to_sorted_list_components(const bool use_two_keys) const +// std::array to_table_components(const bool use_two_keys) const // { // return { // key[0], @@ -248,7 +248,7 @@ struct MultiTable { // return (key.from_montgomery_form() < other.key.from_montgomery_form()); // } -// std::array to_sorted_list_components() const { return { key, values[0], values[0] }; } +// std::array to_table_components() const { return { key, values[0], values[0] }; } // } // BasicTableId id; @@ -268,6 +268,66 @@ struct MultiTable { // } +/** + * @brief A map from 'entry' to 'index' where entry is a row in a BasicTable and index is the row at which that entry + * exists in the table + * @details Such a map is needed to in order to construct read_counts (the polynomial containing the number of reads + * from each entry in a table) for the log-derivative lookup argument. A BasicTable essentially consists of 3 columns, + * and 'lookups' are recorded as rows in this table. The index at which this data exists in the table is not explicitly + * known at the time of lookup gate creation. This map can be used to construct read counts from the set of lookups that + * have been performed via an operation like read_counts[index_map[lookup_data]]++ + * + */ +struct LookupHashTable { + using FF = bb::fr; + using Key = std::array; // an entry in a lookup table + using Value = size_t; // the index of an entry in a lookup table + + // Define a simple hash on three field elements + struct HashFunction { + FF mult_const; + FF const_sqr; + + HashFunction() + : mult_const(FF(uint256_t(0x1337, 0x1336, 0x1335, 0x1334))) + , const_sqr(mult_const.sqr()) + {} + + size_t operator()(const Key& entry) const + { + FF result = entry[0] + mult_const * entry[1] + const_sqr * entry[2]; + return static_cast(result.reduce_once().data[0]); + } + }; + + std::unordered_map index_map; + + LookupHashTable() = default; + + // Initialize the entry-index map with the columns of a table + void initialize(std::vector& column_1, std::vector& column_2, std::vector& column_3) + { + for (size_t i = 0; i < column_1.size(); ++i) { + index_map[{ column_1[i], column_2[i], column_3[i] }] = i; + } + } + + // Given an entry in the table, return its index in the table + Value operator[](const Key& key) const + { + auto it = index_map.find(key); + if (it != index_map.end()) { + return it->second; + } else { + info("LookupHashTable: Key not found!"); + ASSERT(false); + return 0; + } + } + + bool operator==(const LookupHashTable& other) const = default; +}; + /** * @brief A basic table from which we can perform lookups (for example, an xor table) * @details Also stores the lookup gate data for all lookups performed on this table @@ -289,7 +349,8 @@ struct BasicTable { return key[0] < other.key[0] || ((key[0] == other.key[0]) && key[1] < other.key[1]); } - std::array to_sorted_list_components(const bool use_two_keys) const + // Express the key-value pair as the entries of a 3-column row in a table + std::array to_table_components(const bool use_two_keys) const { return { bb::fr(key[0]), @@ -313,6 +374,11 @@ struct BasicTable { std::vector column_3; std::vector lookup_gates; // wire data for all lookup gates created for lookups on this table + // Map from a table entry to its index in the table; used for constructing read counts + LookupHashTable index_map; + + void initialize_index_map() { index_map.initialize(column_1, column_2, column_3); } + std::array (*get_values_from_key)(const std::array); bool operator==(const BasicTable& other) const = default; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 909aa29d0d2f..6ca68d7037e7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -12,7 +12,7 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" @@ -36,23 +36,22 @@ class UltraFlavor { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. - // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 43; + static constexpr size_t NUM_ALL_ENTITIES = 42; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 7; + static constexpr size_t NUM_WITNESS_ENTITIES = 8; // Total number of folded polynomials, which is just all polynomials except the shifts static constexpr size_t NUM_FOLDED_ENTITIES = NUM_PRECOMPUTED_ENTITIES + NUM_WITNESS_ENTITIES; - using GrandProductRelations = std::tuple, bb::LookupRelation>; + using GrandProductRelations = std::tuple>; // define the tuple of Relations that comprise the Sumcheck relation // Note: made generic for use in MegaRecursive. template using Relations_ = std::tuple, bb::UltraPermutationRelation, - bb::LookupRelation, + bb::LogDerivLookupRelation, bb::DeltaRangeConstraintRelation, bb::EllipticRelation, bb::AuxiliaryRelation>; @@ -144,17 +143,18 @@ class UltraFlavor { template class WitnessEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - w_l, // column 0 - w_r, // column 1 - w_o, // column 2 - w_4, // column 3 - sorted_accum, // column 4 - z_perm, // column 5 - z_lookup) // column 6 + w_l, // column 0 + w_r, // column 1 + w_o, // column 2 + w_4, // column 3 + z_perm, // column 4 + lookup_inverses, // column 5 + lookup_read_counts, // column 6 + lookup_read_tags) // column 7 auto get_wires() { return RefArray{ w_l, w_r, w_o, w_4 }; }; - MSGPACK_FIELDS(w_l, w_r, w_o, w_4, sorted_accum, z_perm, z_lookup); + MSGPACK_FIELDS(w_l, w_r, w_o, w_4, z_perm, lookup_inverses, lookup_read_counts, lookup_read_tags); }; /** @@ -163,22 +163,20 @@ class UltraFlavor { template class ShiftedEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, - table_1_shift, // column 0 - table_2_shift, // column 1 - table_3_shift, // column 2 - table_4_shift, // column 3 - w_l_shift, // column 4 - w_r_shift, // column 5 - w_o_shift, // column 6 - w_4_shift, // column 7 - sorted_accum_shift, // column 8 - z_perm_shift, // column 9 - z_lookup_shift) // column 10 + table_1_shift, // column 0 + table_2_shift, // column 1 + table_3_shift, // column 2 + table_4_shift, // column 3 + w_l_shift, // column 4 + w_r_shift, // column 5 + w_o_shift, // column 6 + w_4_shift, // column 7 + z_perm_shift) // column 10 auto get_shifted() { - return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, w_r_shift, - w_o_shift, w_4_shift, sorted_accum_shift, z_perm_shift, z_lookup_shift }; + return RefArray{ table_1_shift, table_2_shift, table_3_shift, table_4_shift, w_l_shift, + w_r_shift, w_o_shift, w_4_shift, z_perm_shift }; }; }; @@ -203,7 +201,6 @@ class UltraFlavor { auto get_sigmas() { return RefArray{ this->sigma_1, this->sigma_2, this->sigma_3, this->sigma_4 }; }; auto get_ids() { return RefArray{ this->id_1, this->id_2, this->id_3, this->id_4 }; }; auto get_tables() { return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4 }; }; - // Gemini-specific getters. auto get_unshifted() { return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_all()); @@ -214,8 +211,8 @@ class UltraFlavor { auto get_witness() { return WitnessEntities::get_all(); }; auto get_to_be_shifted() { - return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, this->w_r, - this->w_o, this->w_4, this->sorted_accum, this->z_perm, this->z_lookup }; + return RefArray{ this->table_1, this->table_2, this->table_3, this->table_4, this->w_l, + this->w_r, this->w_o, this->w_4, this->z_perm }; }; auto get_shifted() { return ShiftedEntities::get_all(); }; }; @@ -240,7 +237,8 @@ class UltraFlavor { // Define all operations as default, except copy construction/assignment ProverPolynomials() = default; ProverPolynomials(size_t circuit_size) - { // Initialize all unshifted polynomials to the zero polynomial and initialize the shifted polys + { // Initialize all unshifted polynomials to the zero polynomial and initialize the + // shifted polys for (auto& poly : get_unshifted()) { poly = Polynomial{ circuit_size }; } @@ -285,57 +283,22 @@ class UltraFlavor { std::vector memory_read_records; std::vector memory_write_records; - std::array sorted_polynomials; ProverPolynomials polynomials; // storage for all polynomials evaluated by the prover - void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) - { - // Compute sorted witness-table accumulator - compute_sorted_list_accumulator(eta, eta_two, eta_three); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); - } - /** - * @brief Construct sorted list accumulator polynomial 's'. + * @brief Add RAM/ROM memory records to the fourth wire polynomial * - * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the - * sorted concatenated witness/table polynomials - * - * @param key proving key - * @param sorted_list_polynomials sorted concatenated witness/table polynomials - * @param eta random challenge - * @return Polynomial - */ - void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) - { - auto& sorted_list_accumulator = polynomials.sorted_accum; - - // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < this->circuit_size; ++i) { - FF T0 = sorted_polynomials[3][i] * eta_three; - T0 += sorted_polynomials[2][i] * eta_two; - T0 += sorted_polynomials[1][i] * eta; - T0 += sorted_polynomials[0][i]; - sorted_list_accumulator[i] = T0; - } - } - - /** - * @brief Add plookup memory records to the fourth wire polynomial - * - * @details This operation must be performed after the first three wires have been committed to, hence the - * dependence on the `eta` challenge. + * @details This operation must be performed after the first three wires have been + * committed to, hence the dependence on the `eta` challenge. * * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) + void add_ram_rom_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { - // The plookup memory record values are computed at the indicated indices as + // The memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; - // (See plookup_auxiliary_widget.hpp for details) + // (See the Auxiliary relation for details) auto wires = polynomials.get_wires(); // Compute read record values @@ -355,7 +318,21 @@ class UltraFlavor { } /** - * @brief Computes public_input_delta, lookup_grand_product_delta, the z_perm and z_lookup polynomials + * @brief Compute the inverse polynomial used in the log derivative lookup argument + * + * @tparam Flavor + * @param beta + * @param gamma + */ + void compute_logderivative_inverses(const RelationParameters& relation_parameters) + { + // Compute inverses for conventional lookups + compute_logderivative_inverse>( + this->polynomials, relation_parameters, this->circuit_size); + } + + /** + * @brief Computes public_input_delta and the permutation grand product polynomial * * @param relation_parameters */ @@ -403,7 +380,8 @@ class UltraFlavor { commitment = proving_key.commitment_key->commit(polynomial); } } - // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate up. + // TODO(https://github.com/AztecProtocol/barretenberg/issues/964): Clean the boilerplate + // up. VerificationKey(const uint64_t circuit_size, const uint64_t num_public_inputs, const uint64_t pub_inputs_offset, @@ -530,7 +508,8 @@ class UltraFlavor { PartiallyEvaluatedMultivariates() = default; PartiallyEvaluatedMultivariates(const size_t circuit_size) { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) + // Storage is only needed after the first partial evaluation, hence polynomials of + // size (n / 2) for (auto& poly : this->get_all()) { poly = Polynomial(circuit_size / 2); } @@ -574,8 +553,9 @@ class UltraFlavor { w_o = "W_O"; w_4 = "W_4"; z_perm = "Z_PERM"; - z_lookup = "Z_LOOKUP"; - sorted_accum = "SORTED_ACCUM"; + lookup_inverses = "LOOKUP_INVERSES"; + lookup_read_counts = "LOOKUP_READ_COUNTS"; + lookup_read_tags = "LOOKUP_READ_TAGS"; q_c = "Q_C"; q_l = "Q_L"; @@ -647,10 +627,11 @@ class UltraFlavor { this->w_l = commitments.w_l; this->w_r = commitments.w_r; this->w_o = commitments.w_o; - this->sorted_accum = commitments.sorted_accum; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->w_4 = commitments.w_4; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; } } }; @@ -671,10 +652,11 @@ class UltraFlavor { Commitment w_l_comm; Commitment w_r_comm; Commitment w_o_comm; - Commitment sorted_accum_comm; + Commitment lookup_read_counts_comm; + Commitment lookup_read_tags_comm; Commitment w_4_comm; Commitment z_perm_comm; - Commitment z_lookup_comm; + Commitment lookup_inverses_comm; std::vector> sumcheck_univariates; std::array sumcheck_evaluations; std::vector zm_cq_comms; @@ -704,8 +686,9 @@ class UltraFlavor { }; /** - * @brief Takes a FULL Ultra proof and deserializes it into the public member variables that compose the - * structure. Must be called in order to access the structure of the proof. + * @brief Takes a FULL Ultra proof and deserializes it into the public member variables + * that compose the structure. Must be called in order to access the structure of the + * proof. * */ void deserialize_full_transcript() @@ -723,10 +706,11 @@ class UltraFlavor { w_l_comm = deserialize_from_buffer(proof_data, num_frs_read); w_r_comm = deserialize_from_buffer(proof_data, num_frs_read); w_o_comm = deserialize_from_buffer(proof_data, num_frs_read); - sorted_accum_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_counts_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_read_tags_comm = deserialize_from_buffer(proof_data, num_frs_read); w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); + lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - z_lookup_comm = deserialize_from_buffer(proof_data, num_frs_read); for (size_t i = 0; i < log_n; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, @@ -740,8 +724,9 @@ class UltraFlavor { kzg_w_comm = deserialize_from_buffer(proof_data, num_frs_read); } /** - * @brief Serializes the structure variables into a FULL Ultra proof. Should be called only if - * deserialize_full_transcript() was called and some transcript variable was modified. + * @brief Serializes the structure variables into a FULL Ultra proof. Should be called + * only if deserialize_full_transcript() was called and some transcript variable was + * modified. * */ void serialize_full_transcript() @@ -758,10 +743,11 @@ class UltraFlavor { serialize_to_buffer(w_l_comm, proof_data); serialize_to_buffer(w_r_comm, proof_data); serialize_to_buffer(w_o_comm, proof_data); - serialize_to_buffer(sorted_accum_comm, proof_data); + serialize_to_buffer(lookup_read_counts_comm, proof_data); + serialize_to_buffer(lookup_read_tags_comm, proof_data); serialize_to_buffer(w_4_comm, proof_data); + serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - serialize_to_buffer(z_lookup_comm, proof_data); for (size_t i = 0; i < log_n; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index a73509fe0182..195097c2c7ff 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -11,7 +11,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" @@ -63,12 +62,12 @@ template class UltraRecursiveFlavor_ { // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS`. // Note: this number does not include the individual sorted list polynomials. - static constexpr size_t NUM_ALL_ENTITIES = 43; + static constexpr size_t NUM_ALL_ENTITIES = UltraFlavor::NUM_ALL_ENTITIES; // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying // assignment of witnesses. We again choose a neutral name. - static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = UltraFlavor::NUM_PRECOMPUTED_ENTITIES; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 7; + static constexpr size_t NUM_WITNESS_ENTITIES = UltraFlavor::NUM_WITNESS_ENTITIES; // define the tuple of Relations that comprise the Sumcheck relation using Relations = UltraFlavor::Relations_; @@ -238,10 +237,11 @@ template class UltraRecursiveFlavor_ { this->w_l = commitments.w_l; this->w_r = commitments.w_r; this->w_o = commitments.w_o; - this->sorted_accum = commitments.sorted_accum; + this->lookup_inverses = commitments.lookup_inverses; + this->lookup_read_counts = commitments.lookup_read_counts; + this->lookup_read_tags = commitments.lookup_read_tags; this->w_4 = commitments.w_4; this->z_perm = commitments.z_perm; - this->z_lookup = commitments.z_lookup; } } }; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index 3a5de3c3c5e2..d3a9d0bf8ee5 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -81,7 +81,10 @@ template class ProverInstance_ { construct_lookup_table_polynomials(proving_key.polynomials.get_tables(), circuit, dyadic_circuit_size); - proving_key.sorted_polynomials = construct_sorted_list_polynomials(circuit, dyadic_circuit_size); + construct_lookup_read_counts(proving_key.polynomials.lookup_read_counts, + proving_key.polynomials.lookup_read_tags, + circuit, + dyadic_circuit_size); std::span public_wires_source = proving_key.polynomials.w_r; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp deleted file mode 100644 index 4a8b5d367347..000000000000 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp +++ /dev/null @@ -1,89 +0,0 @@ - -#include "prover_instance.hpp" -#include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/srs/factories/file_crs_factory.hpp" -#include -using namespace bb; - -template class InstanceTests : public testing::Test { - using FF = typename Flavor::FF; - using Polynomial = bb::Polynomial; - using Builder = typename Flavor::CircuitBuilder; - - public: - /** - * @brief Get a random polynomial - * - * @param size - * @return Polynomial - */ - static constexpr Polynomial get_random_polynomial(size_t size) - { - Polynomial random_polynomial{ size }; - for (auto& coeff : random_polynomial) { - coeff = FF::random_element(); - } - return random_polynomial; - } - - static void populate_span(auto& polynomial_view, const auto& polynomial) - { - ASSERT(polynomial_view.size() <= polynomial.size()); - for (size_t idx = 0; idx < polynomial.size(); idx++) { - polynomial_view[idx] = polynomial[idx]; - } - }; - /** - * @brief Check consistency of the computation of the sorted list accumulator - * @details This test compares a simple, unoptimized, easily readable calculation of the sorted list accumulator - * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization - * introduced into the calculation has not changed the result. - * @note This test does confirm the correctness of the sorted list accumulator, only that the two implementations - * yield an identical result. - */ - static void test_sorted_list_accumulator_construction() - { - srs::init_crs_factory("../srs_db/ignition"); - - // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - Builder builder; - - auto a = 2; - builder.add_variable(a); - - builder.add_gates_to_ensure_all_polys_are_non_zero(); - builder.finalize_circuit(); - auto instance = ProverInstance_(builder); - - // Get random challenge eta - auto eta = FF::random_element(); - auto eta_two = FF::random_element(); - auto eta_three = FF::random_element(); - - auto sorted_list_polynomials = instance.proving_key.sorted_polynomials; - - // Method 1: computed sorted list accumulator polynomial using prover library method - instance.proving_key.compute_sorted_list_accumulator(eta, eta_two, eta_three); - auto sorted_list_accumulator = instance.proving_key.polynomials.sorted_accum; - - // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 - Polynomial sorted_list_accumulator_expected{ sorted_list_polynomials[0] }; - for (size_t i = 0; i < instance.proving_key.circuit_size; ++i) { - sorted_list_accumulator_expected[i] += sorted_list_polynomials[1][i] * eta + - sorted_list_polynomials[2][i] * eta_two + - sorted_list_polynomials[3][i] * eta_three; - } - - EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); - }; -}; - -using FlavorTypes = testing::Types; -TYPED_TEST_SUITE(InstanceTests, FlavorTypes); - -TYPED_TEST(InstanceTests, SortedListAccumulator) -{ - TestFixture::test_sorted_list_accumulator_construction(); -} diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp index 05c0938fa100..bfc9b0facac8 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.test.cpp @@ -3,7 +3,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index f0b7101086bf..0d103c302915 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -163,23 +163,27 @@ void TranslatorProver::execute_relation_check_rounds() } /** - * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck + * @brief Execute the ZeroMorph protocol to produce an opening claim for the multilinear evaluations produced by + * Sumcheck and then produce an opening proof with a univariate PCS * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. * * */ -void TranslatorProver::execute_zeromorph_rounds() +void TranslatorProver::execute_pcs_rounds() { - using ZeroMorph = ZeroMorphProver_; - ZeroMorph::prove(key->polynomials.get_unshifted_without_concatenated(), - key->polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted_without_concatenated(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript, - key->polynomials.get_concatenated_constraints(), - sumcheck_output.claimed_evaluations.get_concatenated_constraints(), - key->polynomials.get_concatenation_groups()); + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphProver_; + auto prover_opening_claim = + ZeroMorph::prove(key->polynomials.get_unshifted_without_concatenated(), + key->polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted_without_concatenated(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript, + key->polynomials.get_concatenated_constraints(), + sumcheck_output.claimed_evaluations.get_concatenated_constraints(), + key->polynomials.get_concatenation_groups()); + PCS::compute_opening_proof(commitment_key, prover_opening_claim, transcript); } HonkProof TranslatorProver::export_proof() @@ -208,7 +212,7 @@ HonkProof TranslatorProver::construct_proof() // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - execute_zeromorph_rounds(); + execute_pcs_rounds(); return export_proof(); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp index 62409ffbe8b0..d61e9dc23cd2 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.hpp @@ -36,7 +36,7 @@ class TranslatorProver { BB_PROFILE void execute_wire_and_sorted_constraints_commitments_round(); BB_PROFILE void execute_grand_product_computation_round(); BB_PROFILE void execute_relation_check_rounds(); - BB_PROFILE void execute_zeromorph_rounds(); + BB_PROFILE void execute_pcs_rounds(); HonkProof export_proof(); HonkProof construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index 53880bc0cf0b..cfae12f3a5c1 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -53,6 +53,10 @@ void TranslatorVerifier::put_translation_data_in_relation_parameters(const uint2 */ bool TranslatorVerifier::verify_proof(const HonkProof& proof) { + using Curve = typename Flavor::Curve; + using PCS = typename Flavor::PCS; + using ZeroMorph = ::bb::ZeroMorphVerifier_; + batching_challenge_v = transcript->template get_challenge("Translation:batching_challenge"); // Load the proof produced by the translator prover @@ -108,15 +112,17 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description ofthe // unrolled protocol. - auto pairing_points = - ZeroMorphVerifier_::verify(commitments.get_unshifted_without_concatenated(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted_without_concatenated(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - transcript, - commitments.get_concatenation_groups(), - claimed_evaluations.get_concatenated_constraints()); + + auto opening_claim = ZeroMorph::verify(commitments.get_unshifted_without_concatenated(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted_without_concatenated(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(), + transcript, + commitments.get_concatenation_groups(), + claimed_evaluations.get_concatenated_constraints()); + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); auto verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp index e22a831aa266..bf171d2c4a16 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp @@ -60,7 +60,8 @@ std::array TranslatorRecursiveVerifier_; using PCS = typename Flavor::PCS; - using ZeroMorph = ::bb::ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ::bb::ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; using CommitmentLabels = typename Flavor::CommitmentLabels; @@ -109,16 +110,19 @@ std::array TranslatorRecursiveVerifier_ void DeciderProver_::execute_relation_ch } /** - * @brief Execute the ZeroMorph protocol to prove the multilinear evaluations produced by Sumcheck + * @brief Execute the ZeroMorph protocol to produce an opening claim for the multilinear evaluations produced by + * Sumcheck and then produce an opening proof with a univariate PCS. * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. * * */ -template void DeciderProver_::execute_zeromorph_rounds() +template void DeciderProver_::execute_pcs_rounds() { - ZeroMorph::prove(accumulator->proving_key.polynomials.get_unshifted(), - accumulator->proving_key.polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript); + using ZeroMorph = ZeroMorphProver_; + auto prover_opening_claim = ZeroMorph::prove(accumulator->proving_key.polynomials.get_unshifted(), + accumulator->proving_key.polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript); + PCS::compute_opening_proof(commitment_key, prover_opening_claim, transcript); } template HonkProof DeciderProver_::export_proof() @@ -64,7 +67,7 @@ template HonkProof DeciderProver_::construct_proo // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - execute_zeromorph_rounds(); + execute_pcs_rounds(); return export_proof(); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp index 910bcd898e07..2a3902d9ad12 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_prover.hpp @@ -12,6 +12,7 @@ namespace bb { template class DeciderProver_ { using FF = typename Flavor::FF; + using Curve = typename Flavor::Curve; using Commitment = typename Flavor::Commitment; using CommitmentKey = typename Flavor::CommitmentKey; using ProvingKey = typename Flavor::ProvingKey; @@ -28,7 +29,7 @@ template class DeciderProver_ { const std::shared_ptr& transcript = std::make_shared()); BB_PROFILE void execute_relation_check_rounds(); - BB_PROFILE void execute_zeromorph_rounds(); + BB_PROFILE void execute_pcs_rounds(); HonkProof export_proof(); HonkProof construct_proof(); @@ -47,8 +48,6 @@ template class DeciderProver_ { std::shared_ptr commitment_key; - using ZeroMorph = ZeroMorphProver_; - private: HonkProof proof; }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index 4b9f122c966f..8dfc816e01a8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -65,15 +65,16 @@ class MegaTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; - manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_TAGS", frs_per_G); manifest_expected.add_entry(round, "W_4", frs_per_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; + manifest_expected.add_entry(round, "LOOKUP_INVERSES", frs_per_G); manifest_expected.add_entry(round, "CALLDATA_INVERSES", frs_per_G); manifest_expected.add_entry(round, "RETURN_DATA_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); - manifest_expected.add_entry(round, "Z_LOOKUP", frs_per_G); for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); @@ -242,7 +243,7 @@ TEST_F(MegaTranscriptTests, StructureTest) Flavor::Commitment one_group_val = Flavor::Commitment::one(); FF rand_val = FF::random_element(); - prover.transcript->sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + prover.transcript->z_perm_comm = one_group_val * rand_val; // choose random object to modify EXPECT_TRUE(verifier.verify_proof( prover.export_proof())); // we have not serialized it back to the proof so it should still be fine @@ -250,5 +251,5 @@ TEST_F(MegaTranscriptTests, StructureTest) EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it prover.transcript->deserialize_full_transcript(); - EXPECT_EQ(static_cast(prover.transcript->sorted_accum_comm), one_group_val * rand_val); + EXPECT_EQ(static_cast(prover.transcript->z_perm_comm), one_group_val * rand_val); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index f0c15496c951..6626b48623f3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -1,4 +1,5 @@ #include "barretenberg/ultra_honk/oink_prover.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" namespace bb { @@ -109,21 +110,25 @@ template void OinkProver::execute_wire_commitment */ template void OinkProver::execute_sorted_list_accumulator_round() { - + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - proving_key.compute_sorted_accumulator_polynomials( + proving_key.add_ram_rom_memory_records_to_wire_4( relation_parameters.eta, relation_parameters.eta_two, relation_parameters.eta_three); - // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire - // polynomial - witness_commitments.sorted_accum = commitment_key->commit(proving_key.polynomials.sorted_accum); + + // Commit to lookup argument polynomials and the finalized (i.e. with memory records) fourth wire polynomial + witness_commitments.lookup_read_counts = commitment_key->commit(proving_key.polynomials.lookup_read_counts); + witness_commitments.lookup_read_tags = commitment_key->commit(proving_key.polynomials.lookup_read_tags); witness_commitments.w_4 = commitment_key->commit(proving_key.polynomials.w_4); - transcript->send_to_verifier(domain_separator + commitment_labels.sorted_accum, witness_commitments.sorted_accum); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_read_counts, + witness_commitments.lookup_read_counts); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_read_tags, + witness_commitments.lookup_read_tags); transcript->send_to_verifier(domain_separator + commitment_labels.w_4, witness_commitments.w_4); } @@ -136,10 +141,16 @@ template void OinkProver::execute_log_derivative_ auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); relation_parameters.beta = beta; relation_parameters.gamma = gamma; - if constexpr (IsGoblinFlavor) { - // Compute and commit to the logderivative inverse used in DataBus - proving_key.compute_logderivative_inverse(relation_parameters); + // Compute the inverses used in log-derivative lookup relations + proving_key.compute_logderivative_inverses(relation_parameters); + + witness_commitments.lookup_inverses = commitment_key->commit(proving_key.polynomials.lookup_inverses); + transcript->send_to_verifier(domain_separator + commitment_labels.lookup_inverses, + witness_commitments.lookup_inverses); + + // If Mega, commit to the databus inverse polynomials and send + if constexpr (IsGoblinFlavor) { witness_commitments.calldata_inverses = commitment_key->commit(proving_key.polynomials.calldata_inverses); witness_commitments.return_data_inverses = commitment_key->commit(proving_key.polynomials.return_data_inverses); transcript->send_to_verifier(domain_separator + commitment_labels.calldata_inverses, @@ -158,10 +169,8 @@ template void OinkProver::execute_grand_product_c proving_key.compute_grand_product_polynomials(relation_parameters); witness_commitments.z_perm = commitment_key->commit(proving_key.polynomials.z_perm); - witness_commitments.z_lookup = commitment_key->commit(proving_key.polynomials.z_lookup); transcript->send_to_verifier(domain_separator + commitment_labels.z_perm, witness_commitments.z_perm); - transcript->send_to_verifier(domain_separator + commitment_labels.z_lookup, witness_commitments.z_lookup); } template typename Flavor::RelationSeparator OinkProver::generate_alphas_round() diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 69a2b20a57b7..0a5a1810e4c1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -87,15 +87,18 @@ template void OinkVerifier::execute_wire_commitme */ template void OinkVerifier::execute_sorted_list_accumulator_round() { - // Get challenge for sorted list batching and wire four memory records + // Get eta challenges auto [eta, eta_two, eta_three] = transcript->template get_challenges( domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); relation_parameters.eta = eta; relation_parameters.eta_two = eta_two; relation_parameters.eta_three = eta_three; - // Get commitments to sorted list accumulator and fourth wire - witness_comms.sorted_accum = - transcript->template receive_from_prover(domain_separator + comm_labels.sorted_accum); + + // Get commitments to lookup argument polynomials and fourth wire + witness_comms.lookup_read_counts = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_read_counts); + witness_comms.lookup_read_tags = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_read_tags); witness_comms.w_4 = transcript->template receive_from_prover(domain_separator + comm_labels.w_4); } @@ -109,6 +112,10 @@ template void OinkVerifier::execute_log_derivativ auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); relation_parameters.beta = beta; relation_parameters.gamma = gamma; + + witness_comms.lookup_inverses = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_inverses); + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomials if constexpr (IsGoblinFlavor) { witness_comms.calldata_inverses = @@ -137,8 +144,6 @@ template void OinkVerifier::execute_grand_product // Get commitment to permutation and lookup grand products witness_comms.z_perm = transcript->template receive_from_prover(domain_separator + comm_labels.z_perm); - witness_comms.z_lookup = - transcript->template receive_from_prover(domain_separator + comm_labels.z_lookup); } template typename Flavor::RelationSeparator OinkVerifier::generate_alphas_round() diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index b928a0bcd048..cedd1fd4bb2e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -4,7 +4,7 @@ #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/ecc_op_queue_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" +#include "barretenberg/relations/logderiv_lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" @@ -29,9 +29,8 @@ void ensure_non_zero(auto& polynomial) * @brief Check that a given relation is satified for a set of polynomials * * @tparam relation_idx Index into a tuple of provided relations - * @tparam Flavor */ -template void check_relation(auto circuit_size, auto& polynomials, auto params) +template void check_relation(auto circuit_size, auto& polynomials, auto params) { for (size_t i = 0; i < circuit_size; i++) { // Define the appropriate SumcheckArrayOfValuesOverSubrelations type for this relation and initialize to zero @@ -273,9 +272,10 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution @@ -285,18 +285,15 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) ensure_non_zero(proving_key.polynomials.q_elliptic); ensure_non_zero(proving_key.polynomials.q_aux); - // Construct the round for applying sumcheck relations and results for storing computed results - using Relations = typename Flavor::Relations; - auto& prover_polynomials = instance->proving_key.polynomials; auto params = instance->relation_parameters; // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); } TEST_F(UltraRelationCorrectnessTests, Mega) @@ -328,10 +325,10 @@ TEST_F(UltraRelationCorrectnessTests, Mega) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); - instance->proving_key.compute_logderivative_inverse(instance->relation_parameters); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution @@ -351,19 +348,18 @@ TEST_F(UltraRelationCorrectnessTests, Mega) ensure_non_zero(proving_key.polynomials.return_data_read_counts); ensure_non_zero(proving_key.polynomials.return_data_inverses); - // Construct the round for applying sumcheck relations and results for storing computed results - using Relations = typename Flavor::Relations; auto& prover_polynomials = instance->proving_key.polynomials; auto params = instance->relation_parameters; // Check that each relation is satisfied across each row of the prover polynomials - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_relation>(circuit_size, prover_polynomials, params); - check_linearly_dependent_relation>( - circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); + check_linearly_dependent_relation>(circuit_size, prover_polynomials, params); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index 5962b8ba212f..665538278c1b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -5,7 +5,6 @@ #include "barretenberg/relations/auxiliary_relation.hpp" #include "barretenberg/relations/delta_range_constraint_relation.hpp" #include "barretenberg/relations/elliptic_relation.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" @@ -157,9 +156,10 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key.compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, - instance->relation_parameters.eta_two, - instance->relation_parameters.eta_three); + instance->proving_key.add_ram_rom_memory_records_to_wire_4(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); + instance->proving_key.compute_logderivative_inverses(instance->relation_parameters); instance->proving_key.compute_grand_product_polynomials(instance->relation_parameters); auto prover_transcript = Transcript::prover_init_empty(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp similarity index 88% rename from barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp index b04bd0b7fd1e..31d0423fd99b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp @@ -48,7 +48,7 @@ void ensure_non_zero(auto& polynomial) ASSERT_TRUE(has_non_zero_coefficient); } -class UltraHonkComposerTests : public ::testing::Test { +class UltraHonkTests : public ::testing::Test { protected: static void SetUpTestSuite() { bb::srs::init_crs_factory("../srs_db/ignition"); } }; @@ -60,7 +60,7 @@ class UltraHonkComposerTests : public ::testing::Test { * to achieve non-zero polynomials * */ -TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) +TEST_F(UltraHonkTests, ANonZeroPolynomialIsAGoodPolynomial) { auto circuit_builder = UltraCircuitBuilder(); @@ -86,7 +86,7 @@ TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) * @brief Test proof construction/verification for a structured execution trace * */ -TEST_F(UltraHonkComposerTests, StructuredTrace) +TEST_F(UltraHonkTests, StructuredTrace) { auto builder = UltraCircuitBuilder(); size_t num_gates = 3; @@ -109,7 +109,7 @@ TEST_F(UltraHonkComposerTests, StructuredTrace) * @brief Test simple circuit with public inputs * */ -TEST_F(UltraHonkComposerTests, PublicInputs) +TEST_F(UltraHonkTests, PublicInputs) { auto builder = UltraCircuitBuilder(); size_t num_gates = 10; @@ -120,7 +120,7 @@ TEST_F(UltraHonkComposerTests, PublicInputs) prove_and_verify(builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, XorConstraint) +TEST_F(UltraHonkTests, XorConstraint) { auto circuit_builder = UltraCircuitBuilder(); @@ -147,7 +147,7 @@ TEST_F(UltraHonkComposerTests, XorConstraint) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) +TEST_F(UltraHonkTests, create_gates_from_plookup_accumulators) { auto circuit_builder = UltraCircuitBuilder(); @@ -207,7 +207,91 @@ TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, test_no_lookup_proof) +/** + * @brief Test various failure modes for the lookup relation via bad input polynomials + * + */ +TEST_F(UltraHonkTests, LookupFailure) +{ + // Construct a circuit with lookup and arithmetic gates + auto construct_circuit_with_lookups = []() { + UltraCircuitBuilder builder; + + MockCircuits::add_lookup_gates(builder); + MockCircuits::add_arithmetic_gates(builder); + + return builder; + }; + + auto prove_and_verify = [](auto& instance) { + UltraProver prover(instance); + auto verification_key = std::make_shared(instance->proving_key); + UltraVerifier verifier(verification_key); + auto proof = prover.construct_proof(); + return verifier.verify_proof(proof); + }; + + // Ensure the unaltered test circuit is valid + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + + EXPECT_TRUE(prove_and_verify(instance)); + } + + // Failure mode 1: bad read counts/tags + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Erroneously update the read counts/tags at an arbitrary index + // Note: updating only one or the other may not cause failure due to the design of the relation algebra. For + // example, the inverse is only computed if read tags is non-zero, otherwise the inverse at the row in question + // will be zero. So if read counts is incremented at some arbitrary index but read tags is not, the inverse will + // be 0 and the erroneous read_counts value will get multiplied by 0 in the relation. This is expected behavior. + polynomials.lookup_read_counts[25] = 1; + polynomials.lookup_read_tags[25] = 1; + + EXPECT_FALSE(prove_and_verify(instance)); + } + + // Failure mode 2: bad lookup gate wire value + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Find a lookup gate and alter one of the wire values + for (auto [q_lookup, wire_3] : zip_view(polynomials.q_lookup, polynomials.w_o)) { + if (!q_lookup.is_zero()) { + wire_3 += 1; + break; + } + } + + EXPECT_FALSE(prove_and_verify(instance)); + } + + // Failure mode 3: erroneous lookup gate + { + auto builder = construct_circuit_with_lookups(); + + auto instance = std::make_shared(builder); + auto& polynomials = instance->proving_key.polynomials; + + // Turn the lookup selector on for an arbitrary row where it is not already active + EXPECT_TRUE(polynomials.q_lookup[25] != 1); + polynomials.q_lookup[25] = 1; + + EXPECT_FALSE(prove_and_verify(instance)); + } +} + +TEST_F(UltraHonkTests, test_no_lookup_proof) { auto circuit_builder = UltraCircuitBuilder(); @@ -229,7 +313,7 @@ TEST_F(UltraHonkComposerTests, test_no_lookup_proof) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, test_elliptic_gate) +TEST_F(UltraHonkTests, test_elliptic_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -262,7 +346,7 @@ TEST_F(UltraHonkComposerTests, test_elliptic_gate) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation) +TEST_F(UltraHonkTests, non_trivial_tag_permutation) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -289,7 +373,7 @@ TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) +TEST_F(UltraHonkTests, non_trivial_tag_permutation_and_cycles) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::random_element(); @@ -326,7 +410,7 @@ TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, bad_tag_permutation) +TEST_F(UltraHonkTests, bad_tag_permutation) { { auto circuit_builder = UltraCircuitBuilder(); @@ -369,7 +453,7 @@ TEST_F(UltraHonkComposerTests, bad_tag_permutation) } } -TEST_F(UltraHonkComposerTests, sort_widget) +TEST_F(UltraHonkTests, sort_widget) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -386,7 +470,7 @@ TEST_F(UltraHonkComposerTests, sort_widget) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, sort_with_edges_gate) +TEST_F(UltraHonkTests, sort_with_edges_gate) { fr a = fr::one(); fr b = fr(2); @@ -476,7 +560,7 @@ TEST_F(UltraHonkComposerTests, sort_with_edges_gate) } } -TEST_F(UltraHonkComposerTests, range_constraint) +TEST_F(UltraHonkTests, range_constraint) { { auto circuit_builder = UltraCircuitBuilder(); @@ -545,7 +629,7 @@ TEST_F(UltraHonkComposerTests, range_constraint) } } -TEST_F(UltraHonkComposerTests, range_with_gates) +TEST_F(UltraHonkTests, range_with_gates) { auto circuit_builder = UltraCircuitBuilder(); auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); @@ -563,7 +647,7 @@ TEST_F(UltraHonkComposerTests, range_with_gates) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, range_with_gates_where_range_is_not_a_power_of_two) +TEST_F(UltraHonkTests, range_with_gates_where_range_is_not_a_power_of_two) { auto circuit_builder = UltraCircuitBuilder(); auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); @@ -581,7 +665,7 @@ TEST_F(UltraHonkComposerTests, range_with_gates_where_range_is_not_a_power_of_tw prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, sort_widget_complex) +TEST_F(UltraHonkTests, sort_widget_complex) { { @@ -607,7 +691,7 @@ TEST_F(UltraHonkComposerTests, sort_widget_complex) } } -TEST_F(UltraHonkComposerTests, sort_widget_neg) +TEST_F(UltraHonkTests, sort_widget_neg) { auto circuit_builder = UltraCircuitBuilder(); fr a = fr::one(); @@ -624,7 +708,7 @@ TEST_F(UltraHonkComposerTests, sort_widget_neg) prove_and_verify(circuit_builder, /*expected_result=*/false); } -TEST_F(UltraHonkComposerTests, composed_range_constraint) +TEST_F(UltraHonkTests, composed_range_constraint) { auto circuit_builder = UltraCircuitBuilder(); auto c = fr::random_element(); @@ -637,7 +721,7 @@ TEST_F(UltraHonkComposerTests, composed_range_constraint) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, non_native_field_multiplication) +TEST_F(UltraHonkTests, non_native_field_multiplication) { using fq = fq; auto circuit_builder = UltraCircuitBuilder(); @@ -693,7 +777,7 @@ TEST_F(UltraHonkComposerTests, non_native_field_multiplication) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, rom) +TEST_F(UltraHonkTests, rom) { auto circuit_builder = UltraCircuitBuilder(); @@ -734,7 +818,7 @@ TEST_F(UltraHonkComposerTests, rom) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, ram) +TEST_F(UltraHonkTests, ram) { auto circuit_builder = UltraCircuitBuilder(); @@ -797,7 +881,7 @@ TEST_F(UltraHonkComposerTests, ram) prove_and_verify(circuit_builder, /*expected_result=*/true); } -TEST_F(UltraHonkComposerTests, range_checks_on_duplicates) +TEST_F(UltraHonkTests, range_checks_on_duplicates) { auto circuit_builder = UltraCircuitBuilder(); @@ -836,7 +920,7 @@ TEST_F(UltraHonkComposerTests, range_checks_on_duplicates) // range constrained, do not break the set equivalence checks because of indices mismatch. // 2^14 is DEFAULT_PLOOKUP_RANGE_BITNUM i.e. the maximum size before a variable gets sliced // before range constraints are applied to it. -TEST_F(UltraHonkComposerTests, range_constraint_small_variable) +TEST_F(UltraHonkTests, range_constraint_small_variable) { auto circuit_builder = UltraCircuitBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index 952894e4a368..df541aeb2df5 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -58,13 +58,14 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; - manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_COUNTS", frs_per_G); + manifest_expected.add_entry(round, "LOOKUP_READ_TAGS", frs_per_G); manifest_expected.add_entry(round, "W_4", frs_per_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; + manifest_expected.add_entry(round, "LOOKUP_INVERSES", frs_per_G); manifest_expected.add_entry(round, "Z_PERM", frs_per_G); - manifest_expected.add_entry(round, "Z_LOOKUP", frs_per_G); for (size_t i = 0; i < NUM_SUBRELATIONS - 1; i++) { std::string label = "alpha_" + std::to_string(i); @@ -226,7 +227,7 @@ TEST_F(UltraTranscriptTests, StructureTest) Flavor::Commitment one_group_val = Flavor::Commitment::one(); FF rand_val = FF::random_element(); - prover.transcript->sorted_accum_comm = one_group_val * rand_val; // choose random object to modify + prover.transcript->z_perm_comm = one_group_val * rand_val; // choose random object to modify EXPECT_TRUE(verifier.verify_proof( prover.export_proof())); // we have not serialized it back to the proof so it should still be fine @@ -234,5 +235,5 @@ TEST_F(UltraTranscriptTests, StructureTest) EXPECT_FALSE(verifier.verify_proof(prover.export_proof())); // the proof is now wrong after serializing it prover.transcript->deserialize_full_transcript(); - EXPECT_EQ(static_cast(prover.transcript->sorted_accum_comm), one_group_val * rand_val); + EXPECT_EQ(static_cast(prover.transcript->z_perm_comm), one_group_val * rand_val); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 039591d2ba4b..942af05365b6 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -43,7 +43,8 @@ template bool UltraVerifier_::verify_proof(const HonkP { using FF = typename Flavor::FF; using PCS = typename Flavor::PCS; - using ZeroMorph = ZeroMorphVerifier_; + using Curve = typename Flavor::Curve; + using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; transcript = std::make_shared(proof); @@ -72,14 +73,17 @@ template bool UltraVerifier_::verify_proof(const HonkP return false; } - // Execute ZeroMorph rounds and check the pcs verifier accumulator returned. See + // Execute ZeroMorph rounds to produce an opening claim and verify it with a univariate PCS. See // https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. - auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), - commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, - transcript); + auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + Commitment::one(), + transcript); + auto pairing_points = PCS::reduce_verify(opening_claim, transcript); + auto pcs_verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return sumcheck_verified.value() && pcs_verified; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp index 4c8bb0f98726..59b0c41d9bac 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.cpp @@ -1,5 +1,10 @@ #include "barretenberg/vm/avm_trace/avm_gas_trace.hpp" + +#include +#include + #include "barretenberg/vm/avm_trace/avm_opcode.hpp" +#include "barretenberg/vm/avm_trace/fixed_gas.hpp" namespace bb::avm_trace { @@ -39,8 +44,9 @@ void AvmGasTraceBuilder::constrain_gas_lookup(uint32_t clk, OpCode opcode) gas_opcode_lookup_counter[opcode]++; // Get the gas prices for this opcode - uint32_t l2_gas_cost = GAS_COST_TABLE.at(opcode).l2_fixed_gas_cost; - uint32_t da_gas_cost = GAS_COST_TABLE.at(opcode).da_fixed_gas_cost; + const auto& GAS_COST_TABLE = FixedGasTable::get(); + auto l2_gas_cost = static_cast(GAS_COST_TABLE.at(opcode).gas_l2_gas_fixed_table); + auto da_gas_cost = static_cast(GAS_COST_TABLE.at(opcode).gas_da_gas_fixed_table); remaining_l2_gas -= l2_gas_cost; remaining_da_gas -= da_gas_cost; @@ -69,8 +75,9 @@ void AvmGasTraceBuilder::constrain_gas_for_external_call(uint32_t clk, // gas_opcode_lookup_counter[opcode]++; // Get the gas prices for this opcode - uint32_t opcode_l2_gas_cost = GAS_COST_TABLE.at(opcode).l2_fixed_gas_cost; - uint32_t opcode_da_gas_cost = GAS_COST_TABLE.at(opcode).da_fixed_gas_cost; + const auto& GAS_COST_TABLE = FixedGasTable::get(); + auto opcode_l2_gas_cost = static_cast(GAS_COST_TABLE.at(opcode).gas_l2_gas_fixed_table); + auto opcode_da_gas_cost = static_cast(GAS_COST_TABLE.at(opcode).gas_da_gas_fixed_table); remaining_l2_gas -= opcode_l2_gas_cost + nested_l2_gas_cost; remaining_da_gas -= opcode_da_gas_cost + nested_da_gas_cost; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp index 8085321586b5..1e5f226b55ac 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_gas_trace.hpp @@ -1,120 +1,17 @@ +#pragma once + +#include + #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_opcode.hpp" -#include namespace bb::avm_trace { -struct GasTableEntry { - uint32_t l2_fixed_gas_cost = 0; - uint32_t da_fixed_gas_cost = 0; -}; - -// Temporary values until the definitive gas cost values are settled. -// See TS counterpart constant TemporaryDefaultGasCost in avm_gas.ts -static const inline GasTableEntry temp_default_gas_entry{ .l2_fixed_gas_cost = 10, .da_fixed_gas_cost = 2 }; - -static const inline std::unordered_map GAS_COST_TABLE = { - // Compute - // Compute - Arithmetic - { OpCode::ADD, temp_default_gas_entry }, - { OpCode::SUB, temp_default_gas_entry }, - { OpCode::MUL, temp_default_gas_entry }, - { OpCode::DIV, temp_default_gas_entry }, - { OpCode::FDIV, temp_default_gas_entry }, - // Compute - Comparators - { OpCode::EQ, temp_default_gas_entry }, - { OpCode::LT, temp_default_gas_entry }, - { OpCode::LTE, temp_default_gas_entry }, - // Compute - Bitwise - { OpCode::AND, temp_default_gas_entry }, - { OpCode::OR, temp_default_gas_entry }, - { OpCode::XOR, temp_default_gas_entry }, - { OpCode::NOT, temp_default_gas_entry }, - { OpCode::SHL, temp_default_gas_entry }, - { OpCode::SHR, temp_default_gas_entry }, - // Compute - Type Conversions - { OpCode::CAST, temp_default_gas_entry }, - - // Execution Environment - { OpCode::ADDRESS, temp_default_gas_entry }, - { OpCode::STORAGEADDRESS, temp_default_gas_entry }, - { OpCode::SENDER, temp_default_gas_entry }, - { OpCode::FEEPERL2GAS, temp_default_gas_entry }, - { OpCode::FEEPERDAGAS, temp_default_gas_entry }, - { OpCode::TRANSACTIONFEE, temp_default_gas_entry }, - { OpCode::CONTRACTCALLDEPTH, temp_default_gas_entry }, - // Execution Environment - Globals - { OpCode::CHAINID, temp_default_gas_entry }, - { OpCode::VERSION, temp_default_gas_entry }, - { OpCode::BLOCKNUMBER, temp_default_gas_entry }, - { OpCode::TIMESTAMP, temp_default_gas_entry }, - { OpCode::COINBASE, temp_default_gas_entry }, - { OpCode::BLOCKL2GASLIMIT, temp_default_gas_entry }, - { OpCode::BLOCKDAGASLIMIT, temp_default_gas_entry }, - // Execution Environment - Calldata - { OpCode::CALLDATACOPY, temp_default_gas_entry }, - - // Machine State - // Machine State - Gas - { OpCode::L2GASLEFT, temp_default_gas_entry }, - { OpCode::DAGASLEFT, temp_default_gas_entry }, - // Machine State - Internal Control Flow - { OpCode::JUMP, temp_default_gas_entry }, - { OpCode::JUMPI, temp_default_gas_entry }, - { OpCode::INTERNALCALL, temp_default_gas_entry }, - { OpCode::INTERNALRETURN, temp_default_gas_entry }, - // Machine State - Memory - { OpCode::SET, temp_default_gas_entry }, - { OpCode::MOV, temp_default_gas_entry }, - { OpCode::CMOV, temp_default_gas_entry }, - - // World State - { OpCode::SLOAD, temp_default_gas_entry }, - { OpCode::SSTORE, temp_default_gas_entry }, - { OpCode::NOTEHASHEXISTS, temp_default_gas_entry }, - { OpCode::EMITNOTEHASH, temp_default_gas_entry }, - { OpCode::NULLIFIEREXISTS, temp_default_gas_entry }, - { OpCode::EMITNULLIFIER, temp_default_gas_entry }, - { OpCode::L1TOL2MSGEXISTS, temp_default_gas_entry }, - { OpCode::HEADERMEMBER, temp_default_gas_entry }, - { OpCode::GETCONTRACTINSTANCE, temp_default_gas_entry }, - - // Accrued Substate - { OpCode::EMITUNENCRYPTEDLOG, temp_default_gas_entry }, - { OpCode::SENDL2TOL1MSG, temp_default_gas_entry }, - - // Control Flow - Contract Calls - { OpCode::CALL, temp_default_gas_entry }, - { OpCode::STATICCALL, temp_default_gas_entry }, - { OpCode::DELEGATECALL, temp_default_gas_entry }, - { OpCode::RETURN, temp_default_gas_entry }, - { OpCode::REVERT, temp_default_gas_entry }, - - // Misc - { OpCode::DEBUGLOG, temp_default_gas_entry }, - - // Gadgets - { OpCode::KECCAK, temp_default_gas_entry }, - { OpCode::POSEIDON2, temp_default_gas_entry }, - { OpCode::SHA256, temp_default_gas_entry }, - { OpCode::PEDERSEN, temp_default_gas_entry }, - { OpCode::ECADD, temp_default_gas_entry }, - - // Conversions - { OpCode::TORADIXLE, temp_default_gas_entry }, - - // Future Gadgets -- pending changes in noir - { OpCode::SHA256COMPRESSION, temp_default_gas_entry }, - { OpCode::KECCAKF1600, temp_default_gas_entry }, // Here for when we eventually support this - // Sentinel - // LAST_OPCODE_SENTINEL, -}; - class AvmGasTraceBuilder { public: struct GasTraceEntry { uint32_t clk = 0; - OpCode opcode = OpCode::ADD; // 0 + OpCode opcode; uint32_t l2_gas_cost = 0; uint32_t da_gas_cost = 0; uint32_t remaining_l2_gas = 0; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp index 8ee4f02595f6..e46fb93d6706 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_mem_trace.cpp @@ -150,7 +150,7 @@ bool AvmMemTraceBuilder::load_from_mem_trace(uint8_t space_id, AvmMemoryTag m_tag = mem_space.contains(addr) ? mem_space.at(addr).tag : AvmMemoryTag::U0; if (m_tag == AvmMemoryTag::U0 || m_tag == r_in_tag) { - insert_in_mem_trace(space_id, clk, sub_clk, addr, val, r_in_tag, r_in_tag, w_in_tag, false); + insert_in_mem_trace(space_id, clk, sub_clk, addr, val, m_tag, r_in_tag, w_in_tag, false); return true; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index c97c71eccb23..ae472b6643d1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -21,6 +21,8 @@ #include "barretenberg/vm/avm_trace/avm_helper.hpp" #include "barretenberg/vm/avm_trace/avm_opcode.hpp" #include "barretenberg/vm/avm_trace/avm_trace.hpp" +#include "barretenberg/vm/avm_trace/fixed_gas.hpp" +#include "barretenberg/vm/avm_trace/fixed_powers.hpp" namespace bb::avm_trace { @@ -67,49 +69,103 @@ void AvmTraceBuilder::reset() external_call_counter = 0; } -AvmTraceBuilder::IndirectThreeResolution AvmTraceBuilder::resolve_ind_three( - uint8_t space_id, uint32_t clk, uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t c_offset) +/** + * @brief Returns an array of mem_offsets and tags them with their given Addressing Mode (direct/indirect) based on the + * given indirect byte. + * @tparam N The number of memory offsets to resolve. + */ +template +std::array unpack_indirects(uint8_t indirect, std::array mem_offsets) { - bool indirect_flag_a = is_operand_indirect(indirect, 0); - bool indirect_flag_b = is_operand_indirect(indirect, 1); - bool indirect_flag_c = is_operand_indirect(indirect, 2); - - uint32_t direct_a_offset = a_offset; - uint32_t direct_b_offset = b_offset; - uint32_t direct_c_offset = c_offset; - - bool tag_match = true; - - if (indirect_flag_a) { - auto read_ind_a = - mem_trace_builder.indirect_read_and_load_from_memory(space_id, clk, IndirectRegister::IND_A, a_offset); - direct_a_offset = uint32_t(read_ind_a.val); - tag_match = tag_match && read_ind_a.tag_match; + std::array addr_mode_arr; + + for (size_t i = 0; i < N; i++) { + // No need to type this as a bool as is implied by the (& 1). + uint8_t indirect_bit = (indirect >> i) & 1; + // Cast straight to AddressingMode, saves having to have a branching statement here. + auto addr_mode = static_cast(indirect_bit); + addr_mode_arr[i] = { addr_mode, mem_offsets[i] }; } + return addr_mode_arr; +} - if (indirect_flag_b) { - auto read_ind_b = - mem_trace_builder.indirect_read_and_load_from_memory(space_id, clk, IndirectRegister::IND_B, b_offset); - direct_b_offset = uint32_t(read_ind_b.val); - tag_match = tag_match && read_ind_b.tag_match; +/** + * @brief Loads a value from memory into a given intermediate register at a specified clock cycle. + * Handles both direct and indirect memory access. + * @tparam reg The intermediate register to load the value into. + */ +AvmTraceBuilder::MemOp AvmTraceBuilder::constrained_read_from_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + AvmMemoryTag read_tag, + AvmMemoryTag write_tag, + IntermRegister reg) +{ + // Get the same matching indirect register for the given intermediate register. + // This is a hack that we can replace with a mapping of IntermediateRegister to IndirectRegister. + auto indirect_reg = static_cast(reg); + // Set up direct and indirect offsets that may be overwritten + uint32_t direct_offset = addr.offset; + uint32_t indirect_offset = 0; + bool tag_match = true; + bool is_indirect = false; + if (addr.mode == AddressingMode::INDIRECT) { + is_indirect = true; + indirect_offset = direct_offset; + auto read_ind = + mem_trace_builder.indirect_read_and_load_from_memory(space_id, clk, indirect_reg, indirect_offset); + if (!read_ind.tag_match) { + tag_match = false; + } + direct_offset = uint32_t(read_ind.val); } + auto read_dir = mem_trace_builder.read_and_load_from_memory(space_id, clk, reg, direct_offset, read_tag, write_tag); + + return MemOp{ + .is_indirect = is_indirect, + .indirect_address = indirect_offset, + .direct_address = direct_offset, + .tag = read_tag, + .tag_match = tag_match && read_dir.tag_match, + .val = read_dir.val, + }; +} - if (indirect_flag_c) { - auto read_ind_c = - mem_trace_builder.indirect_read_and_load_from_memory(space_id, clk, IndirectRegister::IND_C, c_offset); - direct_c_offset = uint32_t(read_ind_c.val); - tag_match = tag_match && read_ind_c.tag_match; +/** + * @brief Writes a value to memory from a given intermediate register at a specified clock cycle. + * Handles both direct and indirect memory access. + * @tparam reg The intermediate register to write the value from. + */ +AvmTraceBuilder::MemOp AvmTraceBuilder::constrained_write_to_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + FF const& value, + AvmMemoryTag read_tag, + AvmMemoryTag write_tag, + IntermRegister reg) +{ + auto indirect_reg = static_cast(reg); + uint32_t direct_offset = addr.offset; + uint32_t indirect_offset = 0; + bool tag_match = true; + bool is_indirect = false; + if (addr.mode == AddressingMode::INDIRECT) { + is_indirect = true; + indirect_offset = direct_offset; + auto read_ind = + mem_trace_builder.indirect_read_and_load_from_memory(space_id, clk, indirect_reg, indirect_offset); + if (!read_ind.tag_match) { + tag_match = false; + } + direct_offset = uint32_t(read_ind.val); } - - return IndirectThreeResolution{ - .tag_match = tag_match, - .direct_a_offset = direct_a_offset, - .direct_b_offset = direct_b_offset, - .direct_c_offset = direct_c_offset, - .indirect_flag_a = indirect_flag_a, - .indirect_flag_b = indirect_flag_b, - .indirect_flag_c = indirect_flag_c, - }; + mem_trace_builder.write_into_memory(space_id, clk, reg, direct_offset, value, read_tag, write_tag); + return MemOp{ .is_indirect = is_indirect, + .indirect_address = indirect_offset, + .direct_address = direct_offset, + .tag = write_tag, + .tag_match = tag_match, + .val = value }; } /** @@ -126,15 +182,14 @@ void AvmTraceBuilder::op_add( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + // Resolve any potential indirects in the order they are encoded in the indirect byte. + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + + bool tag_match = read_a.tag_match && read_b.tag_match; // a + b = c FF a = read_a.val; @@ -146,7 +201,7 @@ void AvmTraceBuilder::op_add( FF c = tag_match ? alu_trace_builder.op_add(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::ADD); @@ -155,16 +210,16 @@ void AvmTraceBuilder::op_add( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -172,9 +227,9 @@ void AvmTraceBuilder::op_add( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_add = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -194,15 +249,14 @@ void AvmTraceBuilder::op_sub( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + // Resolve any potential indirects in the order they are encoded in the indirect byte. + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + + bool tag_match = read_a.tag_match && read_b.tag_match; // a - b = c FF a = read_a.val; @@ -214,7 +268,7 @@ void AvmTraceBuilder::op_sub( FF c = tag_match ? alu_trace_builder.op_sub(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SUB); @@ -223,16 +277,16 @@ void AvmTraceBuilder::op_sub( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -240,9 +294,9 @@ void AvmTraceBuilder::op_sub( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_sub = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -262,15 +316,14 @@ void AvmTraceBuilder::op_mul( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + // Resolve any potential indirects in the order they are encoded in the indirect byte. + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + + bool tag_match = read_a.tag_match && read_b.tag_match; // a * b = c FF a = read_a.val; @@ -282,7 +335,7 @@ void AvmTraceBuilder::op_mul( FF c = tag_match ? alu_trace_builder.op_mul(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::MUL); @@ -291,16 +344,16 @@ void AvmTraceBuilder::op_mul( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -308,9 +361,9 @@ void AvmTraceBuilder::op_mul( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_mul = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -329,15 +382,16 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + // Resolve any potential indirects in the order they are encoded in the indirect byte. + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = + constrained_read_from_memory(call_ptr, clk, resolved_a, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); + auto read_b = + constrained_read_from_memory(call_ptr, clk, resolved_b, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IB); + + bool tag_match = read_a.tag_match && read_b.tag_match; // a * b^(-1) = c FF a = read_a.val; @@ -358,8 +412,8 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of } // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto write_c = constrained_write_to_memory( + call_ptr, clk, resolved_c, c, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::FDIV); @@ -367,17 +421,17 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of main_trace.push_back(Row{ .main_clk = clk, .main_call_ptr = call_ptr, - .main_ia = tag_match ? a : FF(0), - .main_ib = tag_match ? b : FF(0), - .main_ic = tag_match ? c : FF(0), - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = tag_match ? read_a.val : FF(0), + .main_ib = tag_match ? read_b.val : FF(0), + .main_ic = tag_match ? write_c.val : FF(0), + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), .main_inv = tag_match ? inv : FF(1), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_op_err = tag_match ? error : FF(1), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), @@ -386,9 +440,9 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_fdiv = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); @@ -405,31 +459,14 @@ void AvmTraceBuilder::op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_of void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_a_offset = a_offset; - uint32_t direct_dst_offset = dst_offset; - bool indirect_a_flag = is_operand_indirect(indirect, 0); - bool indirect_c_flag = is_operand_indirect(indirect, 1); + // Resolve any potential indirects in the order they are encoded in the indirect byte. + auto [resolved_a, resolved_c] = unpack_indirects<2>(indirect, { a_offset, dst_offset }); - if (indirect_a_flag) { - auto read_ind_a = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, a_offset); - tag_match = read_ind_a.tag_match; - direct_a_offset = uint32_t(read_ind_a.val); - } - - if (indirect_c_flag) { - auto read_ind_c = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, dst_offset); - tag_match = tag_match && read_ind_c.tag_match; - direct_dst_offset = uint32_t(read_ind_c.val); - } + // Reading from memory and loading into ia + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); - // Reading from memory and loading into ia. - auto read_a = - mem_trace_builder.read_and_load_from_memory(call_ptr, clk, IntermRegister::IA, direct_a_offset, in_tag, in_tag); - tag_match = read_a.tag_match && tag_match; + bool tag_match = read_a.tag_match; // ~a = c FF a = read_a.val; @@ -439,7 +476,7 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o FF c = tag_match ? alu_trace_builder.op_not(a, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, direct_dst_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::NOT); @@ -448,21 +485,21 @@ void AvmTraceBuilder::op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_o .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ic = c, - .main_ind_addr_a = indirect_a_flag ? FF(a_offset) : FF(0), - .main_ind_addr_c = indirect_c_flag ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_a_offset), - .main_mem_addr_c = FF(direct_dst_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_not = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_a_flag)), - .main_sel_resolve_ind_addr_c = FF(static_cast(indirect_c_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!read_a.tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -482,15 +519,12 @@ void AvmTraceBuilder::op_eq( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, AvmMemoryTag::U8); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, AvmMemoryTag::U8); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, AvmMemoryTag::U8, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, AvmMemoryTag::U8, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = read_a.val; FF b = read_b.val; @@ -501,8 +535,8 @@ void AvmTraceBuilder::op_eq( FF c = tag_match ? alu_trace_builder.op_eq(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, AvmMemoryTag::U8); + auto write_c = + constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::EQ); @@ -511,16 +545,16 @@ void AvmTraceBuilder::op_eq( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -528,9 +562,9 @@ void AvmTraceBuilder::op_eq( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_eq = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), }); @@ -541,15 +575,12 @@ void AvmTraceBuilder::op_and( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -557,7 +588,7 @@ void AvmTraceBuilder::op_and( FF c = tag_match ? bin_trace_builder.op_and(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::AND); @@ -566,16 +597,16 @@ void AvmTraceBuilder::op_and( .main_clk = clk, .main_bin_op_id = FF(0), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -584,9 +615,9 @@ void AvmTraceBuilder::op_and( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_and = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -596,16 +627,12 @@ void AvmTraceBuilder::op_or( uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag) { auto clk = static_cast(main_trace.size()) + 1; - - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -613,7 +640,7 @@ void AvmTraceBuilder::op_or( FF c = tag_match ? bin_trace_builder.op_or(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::OR); @@ -622,16 +649,16 @@ void AvmTraceBuilder::op_or( .main_clk = clk, .main_bin_op_id = FF(1), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -640,9 +667,9 @@ void AvmTraceBuilder::op_or( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_or = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -653,15 +680,12 @@ void AvmTraceBuilder::op_xor( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -669,7 +693,7 @@ void AvmTraceBuilder::op_xor( FF c = tag_match ? bin_trace_builder.op_xor(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::XOR); @@ -678,16 +702,16 @@ void AvmTraceBuilder::op_xor( .main_clk = clk, .main_bin_op_id = FF(2), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -696,9 +720,9 @@ void AvmTraceBuilder::op_xor( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_xor = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -709,15 +733,11 @@ void AvmTraceBuilder::op_lt( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); - // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, AvmMemoryTag::U8); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, AvmMemoryTag::U8); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, AvmMemoryTag::U8, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, AvmMemoryTag::U8, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -725,8 +745,8 @@ void AvmTraceBuilder::op_lt( FF c = tag_match ? alu_trace_builder.op_lt(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, AvmMemoryTag::U8); + auto write_c = + constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::LT); @@ -735,16 +755,16 @@ void AvmTraceBuilder::op_lt( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -752,9 +772,9 @@ void AvmTraceBuilder::op_lt( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_lt = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), }); @@ -765,15 +785,12 @@ void AvmTraceBuilder::op_lte( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, AvmMemoryTag::U8); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, AvmMemoryTag::U8); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, AvmMemoryTag::U8, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, AvmMemoryTag::U8, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -781,8 +798,8 @@ void AvmTraceBuilder::op_lte( FF c = tag_match ? alu_trace_builder.op_lte(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, AvmMemoryTag::U8); + auto write_c = + constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, AvmMemoryTag::U8, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::LTE); @@ -791,16 +808,16 @@ void AvmTraceBuilder::op_lte( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -808,9 +825,9 @@ void AvmTraceBuilder::op_lte( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_lte = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), }); @@ -822,15 +839,12 @@ void AvmTraceBuilder::op_shr( auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -838,8 +852,7 @@ void AvmTraceBuilder::op_shr( FF c = tag_match ? alu_trace_builder.op_shr(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); - + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SHR); @@ -847,16 +860,16 @@ void AvmTraceBuilder::op_shr( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -864,9 +877,9 @@ void AvmTraceBuilder::op_shr( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_shr = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -877,15 +890,12 @@ void AvmTraceBuilder::op_shl( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_c] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; FF a = tag_match ? read_a.val : FF(0); FF b = tag_match ? read_b.val : FF(0); @@ -893,8 +903,7 @@ void AvmTraceBuilder::op_shl( FF c = tag_match ? alu_trace_builder.op_shl(a, b, in_tag, clk) : FF(0); // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); - + auto write_c = constrained_write_to_memory(call_ptr, clk, resolved_c, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SHL); @@ -902,16 +911,16 @@ void AvmTraceBuilder::op_shl( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, - .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ia = read_a.val, + .main_ib = read_b.val, + .main_ic = write_c.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), .main_rwc = FF(1), @@ -919,9 +928,9 @@ void AvmTraceBuilder::op_shl( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_shl = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -945,19 +954,10 @@ void AvmTraceBuilder::op_set(uint8_t indirect, uint128_t val, uint32_t dst_offse { auto const clk = static_cast(main_trace.size()) + 1; auto const val_ff = FF{ uint256_t::from_uint128(val) }; - uint32_t direct_dst_offset = dst_offset; // Overriden in indirect mode - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - bool tag_match = true; - - if (indirect_dst_flag) { - auto read_ind_c = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, dst_offset); - tag_match = read_ind_c.tag_match; - direct_dst_offset = uint32_t(read_ind_c.val); - } + auto [resolved_c] = unpack_indirects<1>(indirect, { dst_offset }); - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IC, direct_dst_offset, val_ff, AvmMemoryTag::U0, in_tag); + auto write_c = + constrained_write_to_memory(call_ptr, clk, resolved_c, val_ff, AvmMemoryTag::U0, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SET); @@ -965,16 +965,16 @@ void AvmTraceBuilder::op_set(uint8_t indirect, uint128_t val, uint32_t dst_offse main_trace.push_back(Row{ .main_clk = clk, .main_call_ptr = call_ptr, - .main_ic = val_ff, - .main_ind_addr_c = indirect_dst_flag ? dst_offset : 0, + .main_ic = write_c.val, + .main_ind_addr_c = FF(write_c.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_c = direct_dst_offset, + .main_mem_addr_c = FF(write_c.direct_address), .main_pc = pc++, .main_rwc = 1, .main_sel_mem_op_activate_gas = 1, // TODO: remove in the long term .main_sel_mem_op_c = 1, - .main_sel_resolve_ind_addr_c = static_cast(indirect_dst_flag), - .main_tag_err = static_cast(!tag_match), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_c.is_indirect)), + .main_tag_err = static_cast(!write_c.tag_match), .main_w_in_tag = static_cast(in_tag), }); } @@ -1160,35 +1160,28 @@ void AvmTraceBuilder::op_cmov( // Helper function to add kernel lookup operations into the main trace // TODO: add tag match to kernel_input_lookup opcodes to - it isnt written to - -ve test would catch Row AvmTraceBuilder::create_kernel_lookup_opcode( - bool indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag) + uint8_t indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag) { auto const clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_dst_offset = dst_offset; - if (indirect) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, dst_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - - AvmMemoryTag r_tag = AvmMemoryTag::U0; - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IA, direct_dst_offset, value, r_tag, w_tag); + auto [resolved_dst] = unpack_indirects<1>(indirect, { dst_offset }); + auto write_dst = + constrained_write_to_memory(call_ptr, clk, resolved_dst, value, AvmMemoryTag::U0, w_tag, IntermRegister::IA); return Row{ .main_clk = clk, .kernel_kernel_in_offset = selector, .main_call_ptr = call_ptr, .main_ia = value, - .main_ind_addr_a = indirect ? FF(dst_offset) : FF(0), + .main_ind_addr_a = FF(write_dst.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_dst_offset, + .main_mem_addr_a = FF(write_dst.direct_address), .main_pc = pc++, .main_rwa = 1, .main_sel_mem_op_a = 1, .main_sel_q_kernel_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect)), + .main_sel_resolve_ind_addr_a = FF(static_cast(write_dst.is_indirect)), + .main_tag_err = FF(static_cast(!write_dst.tag_match)), .main_w_in_tag = static_cast(w_tag), }; } @@ -1196,10 +1189,7 @@ Row AvmTraceBuilder::create_kernel_lookup_opcode( void AvmTraceBuilder::op_storage_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_storage_address(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode( - indirect_dst_flag, dst_offset, STORAGE_ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, STORAGE_ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_storage_address = FF(1); // Constrain gas cost @@ -1211,9 +1201,7 @@ void AvmTraceBuilder::op_storage_address(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_sender(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_sender(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, SENDER_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, SENDER_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_sender = FF(1); // Constrain gas cost @@ -1225,9 +1213,7 @@ void AvmTraceBuilder::op_sender(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_address(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_address = FF(1); // Constrain gas cost @@ -1239,10 +1225,7 @@ void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = - create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_fee_per_da_gas = FF(1); // Constrain gas cost @@ -1254,10 +1237,7 @@ void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = - create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_fee_per_l2_gas = FF(1); // Constrain gas cost @@ -1269,10 +1249,7 @@ void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_transaction_fee(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_transaction_fee(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode( - indirect_dst_flag, dst_offset, TRANSACTION_FEE_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, TRANSACTION_FEE_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_transaction_fee = FF(1); // Constrain gas cost @@ -1284,9 +1261,7 @@ void AvmTraceBuilder::op_transaction_fee(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_chain_id(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_chain_id(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, CHAIN_ID_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, CHAIN_ID_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_chain_id = FF(1); // Constrain gas cost @@ -1298,9 +1273,7 @@ void AvmTraceBuilder::op_chain_id(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_version(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_version(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, VERSION_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, VERSION_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_version = FF(1); // Constrain gas cost @@ -1312,10 +1285,7 @@ void AvmTraceBuilder::op_version(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_block_number(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_block_number(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = - create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, BLOCK_NUMBER_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, BLOCK_NUMBER_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_block_number = FF(1); // Constrain gas cost @@ -1327,9 +1297,7 @@ void AvmTraceBuilder::op_block_number(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_coinbase(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_coinbase(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, COINBASE_SELECTOR, ia_value, AvmMemoryTag::FF); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, COINBASE_SELECTOR, ia_value, AvmMemoryTag::FF); row.main_sel_op_coinbase = FF(1); // Constrain gas cost @@ -1341,10 +1309,7 @@ void AvmTraceBuilder::op_coinbase(uint8_t indirect, uint32_t dst_offset) void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_timestamp(); - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - Row row = - create_kernel_lookup_opcode(indirect_dst_flag, dst_offset, TIMESTAMP_SELECTOR, ia_value, AvmMemoryTag::U64); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, TIMESTAMP_SELECTOR, ia_value, AvmMemoryTag::U64); row.main_sel_op_timestamp = FF(1); // Constrain gas cost @@ -1356,32 +1321,24 @@ void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) // Helper function to add kernel lookup operations into the main trace Row AvmTraceBuilder::create_kernel_output_opcode(uint8_t indirect, uint32_t clk, uint32_t data_offset) { - bool indirect_data_flag = is_operand_indirect(indirect, 0); - - bool tag_match = true; - uint32_t direct_data_offset = data_offset; - if (indirect) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, data_offset); - direct_data_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - - AvmMemTraceBuilder::MemRead read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_data_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto [resolved_data] = unpack_indirects<1>(indirect, { data_offset }); + auto read_a = constrained_read_from_memory( + call_ptr, clk, resolved_data, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + bool tag_match = read_a.tag_match; return Row{ .main_clk = clk, .main_ia = read_a.val, - .main_ind_addr_a = indirect_data_flag ? FF(data_offset) : FF(0), + .main_ind_addr_a = FF(read_a.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_data_offset, + .main_mem_addr_a = FF(read_a.direct_address), .main_pc = pc++, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_rwa = 0, .main_sel_mem_op_a = 1, .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }; } @@ -1392,43 +1349,23 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_metadata(uint8_t indirect, uint32_t metadata_offset, AvmMemoryTag metadata_r_tag) { + auto [resolved_data, resolved_metadata] = unpack_indirects<2>(indirect, { data_offset, metadata_offset }); - bool indirect_a_flag = is_operand_indirect(indirect, 0); - bool indirect_b_flag = is_operand_indirect(indirect, 1); - - bool tag_match = true; - uint32_t direct_data_offset = data_offset; - uint32_t direct_metadata_offset = metadata_offset; - if (indirect_a_flag) { - auto read_a_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, data_offset); - direct_data_offset = static_cast(read_a_ind_dst.val); - - tag_match = tag_match && read_a_ind_dst.tag_match; - } - if (indirect_b_flag) { - auto read_b_ind_dst = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_B, metadata_offset); - direct_metadata_offset = static_cast(read_b_ind_dst.val); - - tag_match = tag_match && read_b_ind_dst.tag_match; - } - - AvmMemTraceBuilder::MemRead read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_data_offset, data_r_tag, AvmMemoryTag::U0); - - AvmMemTraceBuilder::MemRead read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_metadata_offset, metadata_r_tag, AvmMemoryTag::U0); + auto read_a = + constrained_read_from_memory(call_ptr, clk, resolved_data, data_r_tag, AvmMemoryTag::U0, IntermRegister::IA); + auto read_b = constrained_read_from_memory( + call_ptr, clk, resolved_metadata, metadata_r_tag, AvmMemoryTag::U0, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; return Row{ .main_clk = clk, .main_ia = read_a.val, .main_ib = read_b.val, - .main_ind_addr_a = indirect_a_flag ? data_offset : FF(0), - .main_ind_addr_b = indirect_b_flag ? metadata_offset : FF(0), + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_data_offset, - .main_mem_addr_b = direct_metadata_offset, + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), .main_pc = pc++, .main_r_in_tag = static_cast(data_r_tag), .main_rwa = 0, @@ -1436,8 +1373,9 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_metadata(uint8_t indirect, .main_sel_mem_op_a = 1, .main_sel_mem_op_b = 1, .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_a_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_b_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }; } @@ -1450,43 +1388,23 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_h FF exists = execution_hints.get_side_effect_hints().at(side_effect_counter); // TODO: throw error if incorrect - bool indirect_a_flag = is_operand_indirect(indirect, 0); - bool indirect_b_flag = is_operand_indirect(indirect, 1); - - bool tag_match = true; - uint32_t direct_data_offset = data_offset; - uint32_t direct_metadata_offset = metadata_offset; - if (indirect_a_flag) { - auto read_a_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, data_offset); - direct_data_offset = uint32_t(read_a_ind_dst.val); - - tag_match = tag_match && read_a_ind_dst.tag_match; - } - - if (indirect_b_flag) { - auto read_b_ind_dst = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_B, metadata_offset); - direct_metadata_offset = uint32_t(read_b_ind_dst.val); - - tag_match = tag_match && read_b_ind_dst.tag_match; - } - - AvmMemTraceBuilder::MemRead read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_data_offset, AvmMemoryTag::FF, AvmMemoryTag::U8); + auto [resolved_data, resolved_metadata] = unpack_indirects<2>(indirect, { data_offset, metadata_offset }); + auto read_a = constrained_read_from_memory( + call_ptr, clk, resolved_data, AvmMemoryTag::FF, AvmMemoryTag::U8, IntermRegister::IA); - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IB, direct_metadata_offset, exists, AvmMemoryTag::FF, AvmMemoryTag::U8); + auto write_b = constrained_write_to_memory( + call_ptr, clk, resolved_metadata, exists, AvmMemoryTag::FF, AvmMemoryTag::U8, IntermRegister::IB); + bool tag_match = read_a.tag_match && write_b.tag_match; return Row{ .main_clk = clk, .main_ia = read_a.val, - .main_ib = exists, - .main_ind_addr_a = indirect_a_flag ? data_offset : FF(0), - .main_ind_addr_b = indirect_b_flag ? metadata_offset : FF(0), + .main_ib = write_b.val, + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(write_b.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_data_offset, - .main_mem_addr_b = direct_metadata_offset, + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(write_b.direct_address), .main_pc = pc++, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_rwa = 0, @@ -1494,8 +1412,9 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_h .main_sel_mem_op_a = 1, .main_sel_mem_op_b = 1, .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_a_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_b_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(write_b.is_indirect)), + .main_tag_err = static_cast(!tag_match), .main_w_in_tag = static_cast(AvmMemoryTag::U8), }; } @@ -1508,39 +1427,22 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_value_from_hint(uint8_ FF value = execution_hints.get_side_effect_hints().at(side_effect_counter); // TODO: throw error if incorrect - bool indirect_a_flag = is_operand_indirect(indirect, 0); - bool indirect_b_flag = is_operand_indirect(indirect, 1); - - bool tag_match = true; - uint32_t direct_data_offset = data_offset; - uint32_t direct_metadata_offset = metadata_offset; - if (indirect) { - auto read_a_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, data_offset); - auto read_b_ind_dst = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_B, metadata_offset); - - direct_data_offset = uint32_t(read_a_ind_dst.val); - direct_metadata_offset = uint32_t(read_b_ind_dst.val); - - tag_match = tag_match && read_a_ind_dst.tag_match && read_b_ind_dst.tag_match; - } - - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IA, direct_data_offset, value, AvmMemoryTag::FF, AvmMemoryTag::FF); - - AvmMemTraceBuilder::MemRead read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_metadata_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto [resolved_data, resolved_metadata] = unpack_indirects<2>(indirect, { data_offset, metadata_offset }); + auto write_a = constrained_write_to_memory( + call_ptr, clk, resolved_data, value, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); + auto read_b = constrained_read_from_memory( + call_ptr, clk, resolved_metadata, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IB); + bool tag_match = write_a.tag_match && read_b.tag_match; return Row{ .main_clk = clk, - .main_ia = value, + .main_ia = write_a.val, .main_ib = read_b.val, - .main_ind_addr_a = indirect_a_flag ? data_offset : FF(0), - .main_ind_addr_b = indirect_b_flag ? metadata_offset : FF(0), + .main_ind_addr_a = FF(write_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_data_offset, - .main_mem_addr_b = direct_metadata_offset, + .main_mem_addr_a = FF(write_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), .main_pc = pc, // No PC increment here since we do it in the specific ops .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_rwa = 1, @@ -1548,8 +1450,9 @@ Row AvmTraceBuilder::create_kernel_output_opcode_with_set_value_from_hint(uint8_ .main_sel_mem_op_a = 1, .main_sel_mem_op_b = 1, .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_a_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_b_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(write_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_tag_err = static_cast(!tag_match), .main_w_in_tag = static_cast(AvmMemoryTag::FF), }; } @@ -1670,61 +1573,52 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t { auto clk = static_cast(main_trace.size()) + 1; - // TODO: align usage of indirect with simulator - // TODO: support indirect slot offset - bool dest_offset_is_indirect = is_operand_indirect(indirect, 1); - - auto direct_dest_offset = dest_offset; - if (dest_offset_is_indirect) { - auto read_ind_dest_offset = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, dest_offset); - direct_dest_offset = uint32_t(read_ind_dest_offset.val); - } - auto read_dest_value = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_dest_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); - - AvmMemTraceBuilder::MemRead read_slot = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, slot_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto [resolved_slot, resolved_dest] = unpack_indirects<2>(indirect, { slot_offset, dest_offset }); + auto read_slot = constrained_read_from_memory( + call_ptr, clk, resolved_slot, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + // Read the slot value that we will write hints to in a row main_trace.push_back(Row{ .main_clk = clk, - .main_ia = read_dest_value.val, - .main_ib = read_slot.val, - .main_ind_addr_a = dest_offset_is_indirect ? dest_offset : 0, + .main_ia = read_slot.val, + .main_ind_addr_a = FF(read_slot.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_dest_offset), - .main_mem_addr_b = FF(slot_offset), + .main_mem_addr_a = FF(read_slot.direct_address), .main_pc = pc, // No PC increment here since this is the same opcode as the rows created below .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_b = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(dest_offset_is_indirect)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_slot.is_indirect)), + .main_tag_err = FF(static_cast(!read_slot.tag_match)), }); clk++; + AddressWithMode write_dst = resolved_dest; + // Loop over the size and write the hints to memory for (uint32_t i = 0; i < size; i++) { FF value = execution_hints.get_side_effect_hints().at(side_effect_counter); - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IA, direct_dest_offset + i, value, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto write_a = constrained_write_to_memory( + call_ptr, clk, write_dst, value, AvmMemoryTag::U0, AvmMemoryTag::FF, IntermRegister::IA); auto row = Row{ .main_clk = clk, .main_ia = value, .main_ib = read_slot.val + i, // slot increments each time + .main_ind_addr_a = write_a.indirect_address, .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_dest_offset + i, + .main_mem_addr_a = write_a.direct_address, // direct address incremented at end of the loop .main_pc = pc, // No PC increment here since this is the same opcode for all loop iterations - .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_rwa = 1, .main_sel_mem_op_a = 1, .main_sel_op_sload = FF(1), .main_sel_q_kernel_output_lookup = 1, + .main_sel_resolve_ind_addr_a = FF(static_cast(write_a.is_indirect)), + .main_tag_err = FF(static_cast(!write_a.tag_match)), .main_w_in_tag = static_cast(AvmMemoryTag::FF), }; // Output storage read to kernel outputs (performs lookup) + // Tuples of (slot, value) in the kernel lookup kernel_trace_builder.op_sload(clk, side_effect_counter, row.main_ib, row.main_ia); // Constrain gas cost @@ -1733,6 +1627,9 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t main_trace.push_back(row); side_effect_counter++; clk++; + + // After the first loop, all future write destinations are direct, increment the direct address + write_dst = AddressWithMode{ AddressingMode::DIRECT, write_a.direct_address + 1 }; } pc++; } @@ -1741,54 +1638,47 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t { auto clk = static_cast(main_trace.size()) + 1; - // TODO: align usage of indirect with simulator - // TODO: support indirect slot offset - bool src_offset_is_indirect = is_operand_indirect(indirect, 0); + auto [resolved_src, resolved_slot] = unpack_indirects<2>(indirect, { src_offset, slot_offset }); - // Resolve loads and indirect - auto direct_src_offset = src_offset; - if (src_offset_is_indirect) { - auto read_ind_src_offset = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, src_offset); - direct_src_offset = uint32_t(read_ind_src_offset.val); - } - auto read_src_value = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); - - auto read_slot = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, slot_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto read_slot = constrained_read_from_memory( + call_ptr, clk, resolved_slot, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); main_trace.push_back(Row{ .main_clk = clk, - .main_ia = read_src_value.val, - .main_ib = read_slot.val, - .main_ind_addr_a = src_offset_is_indirect ? src_offset : 0, + .main_ia = read_slot.val, + .main_ind_addr_a = FF(read_slot.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), - .main_mem_addr_b = FF(slot_offset), + .main_mem_addr_a = FF(read_slot.direct_address), .main_pc = pc, // No PC increment here since this is the same opcode as the rows created below .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_b = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(src_offset_is_indirect)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_slot.is_indirect)), + .main_tag_err = FF(static_cast(!read_slot.tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); clk++; + AddressWithMode read_src = resolved_src; + + // This loop reads a _size_ number of elements from memory and places them into a tuple of (ele, slot) + // in the kernel lookup. for (uint32_t i = 0; i < size; i++) { - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset + i, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto read_a = constrained_read_from_memory( + call_ptr, clk, read_src, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); Row row = Row{ .main_clk = clk, .main_ia = read_a.val, .main_ib = read_slot.val + i, // slot increments each time + .main_ind_addr_a = read_a.indirect_address, .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = direct_src_offset + i, + .main_mem_addr_a = read_a.direct_address, // direct address incremented at end of the loop .main_pc = pc, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_sel_mem_op_a = 1, .main_sel_q_kernel_output_lookup = 1, + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_tag_err = FF(static_cast(!read_a.tag_match)), }; row.main_sel_op_sstore = FF(1); kernel_trace_builder.op_sstore(clk, side_effect_counter, row.main_ib, row.main_ia); @@ -1799,6 +1689,8 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t main_trace.push_back(row); side_effect_counter++; clk++; + // All future reads are direct, increment the direct address + read_src = AddressWithMode{ AddressingMode::DIRECT, read_a.direct_address + 1 }; } pc++; } @@ -1888,15 +1780,12 @@ void AvmTraceBuilder::op_div( { auto clk = static_cast(main_trace.size()) + 1; - auto const res = resolve_ind_three(call_ptr, clk, indirect, a_offset, b_offset, dst_offset); - bool tag_match = res.tag_match; + auto [resolved_a, resolved_b, resolved_dst] = unpack_indirects<3>(indirect, { a_offset, b_offset, dst_offset }); // Reading from memory and loading into ia resp. ib. - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, in_tag, in_tag); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, in_tag, in_tag); - tag_match = read_a.tag_match && read_b.tag_match; + auto read_a = constrained_read_from_memory(call_ptr, clk, resolved_a, in_tag, in_tag, IntermRegister::IA); + auto read_b = constrained_read_from_memory(call_ptr, clk, resolved_b, in_tag, in_tag, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; // a / b = c FF a = read_a.val; @@ -1921,7 +1810,7 @@ void AvmTraceBuilder::op_div( } // Write into memory value c from intermediate register ic. - mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IC, res.direct_c_offset, c, in_tag, in_tag); + auto write_dst = constrained_write_to_memory(call_ptr, clk, resolved_dst, c, in_tag, in_tag, IntermRegister::IC); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::DIV); @@ -1930,17 +1819,17 @@ void AvmTraceBuilder::op_div( .main_clk = clk, .main_alu_in_tag = FF(static_cast(in_tag)), .main_call_ptr = call_ptr, - .main_ia = a, - .main_ib = b, + .main_ia = read_a.val, + .main_ib = read_b.val, .main_ic = c, - .main_ind_addr_a = res.indirect_flag_a ? FF(a_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(b_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_c ? FF(dst_offset) : FF(0), + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), + .main_ind_addr_c = FF(write_dst.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), .main_inv = tag_match ? inv : FF(1), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), + .main_mem_addr_c = FF(write_dst.direct_address), .main_op_err = tag_match ? error : FF(1), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(in_tag)), @@ -1949,9 +1838,9 @@ void AvmTraceBuilder::op_div( .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_div = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(write_dst.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), .main_w_in_tag = FF(static_cast(in_tag)), }); @@ -2243,18 +2132,8 @@ void AvmTraceBuilder::execute_gasleft(OpCode opcode, uint8_t indirect, uint32_t assert(opcode == OpCode::L2GASLEFT || opcode == OpCode::DAGASLEFT); auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - - uint32_t direct_dst_offset = dst_offset; - - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, dst_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } + auto [resolved_dst] = unpack_indirects<1>(indirect, { dst_offset }); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, opcode); @@ -2268,29 +2147,25 @@ void AvmTraceBuilder::execute_gasleft(OpCode opcode, uint8_t indirect, uint32_t } // Write into memory from intermediate register ia. - mem_trace_builder.write_into_memory(call_ptr, - clk, - IntermRegister::IA, - direct_dst_offset, - gas_remaining, - AvmMemoryTag::U0, - AvmMemoryTag::FF); // TODO: probably will be U32 in final version + // TODO: probably will be U32 in final version + auto write_dst = constrained_write_to_memory( + call_ptr, clk, resolved_dst, gas_remaining, AvmMemoryTag::U0, AvmMemoryTag::FF, IntermRegister::IA); main_trace.push_back(Row{ .main_clk = clk, .main_call_ptr = call_ptr, .main_ia = gas_remaining, - .main_ind_addr_a = indirect_dst_flag ? FF(dst_offset) : FF(0), + .main_ind_addr_a = FF(write_dst.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_dst_offset), + .main_mem_addr_a = FF(write_dst.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U0)), .main_rwa = FF(1), .main_sel_mem_op_a = FF(1), .main_sel_op_dagasleft = (opcode == OpCode::DAGASLEFT) ? FF(1) : FF(0), .main_sel_op_l2gasleft = (opcode == OpCode::L2GASLEFT) ? FF(1) : FF(0), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_dst_flag)), - .main_tag_err = FF(static_cast(!tag_match)), + .main_sel_resolve_ind_addr_a = FF(static_cast(is_operand_indirect(indirect, 0))), + .main_tag_err = FF(static_cast(!write_dst.tag_match)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), // TODO: probably will be U32 in final version // Should the circuit (pil) constrain U32? }); @@ -2483,14 +2358,16 @@ void AvmTraceBuilder::internal_return() } // TODO(ilyas: #6383): Temporary way to bulk write slices -void AvmTraceBuilder::write_slice_to_memory(uint8_t space_id, - uint32_t clk, - uint32_t dst_offset, - AvmMemoryTag r_tag, - AvmMemoryTag w_tag, - FF internal_return_ptr, - std::vector const& slice) +uint32_t AvmTraceBuilder::write_slice_to_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + AvmMemoryTag r_tag, + AvmMemoryTag w_tag, + FF internal_return_ptr, + std::vector const& slice) { + bool is_indirect = addr.mode == AddressingMode::INDIRECT; + auto dst_offset = addr.offset; // We have 4 registers that we are able to use to write to memory within a single main trace row auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; // If the slice size isnt a multiple of 4, we still need an extra row to write the remainder @@ -2511,33 +2388,53 @@ void AvmTraceBuilder::write_slice_to_memory(uint8_t space_id, if (offset >= slice.size()) { break; } - mem_trace_builder.write_into_memory( - space_id, clk + i, register_order[j], dst_offset + offset, slice.at(offset), r_tag, w_tag); + MemOp mem_write; + if (is_indirect) { + mem_write = constrained_write_to_memory( + space_id, clk + i, addr, slice.at(offset), r_tag, w_tag, IntermRegister::IA); + // Ensure futures calls are direct + is_indirect = false; + dst_offset = mem_write.direct_address; + } else { + mem_trace_builder.write_into_memory( + space_id, clk + i, register_order[j], dst_offset + offset, slice.at(offset), r_tag, w_tag); + mem_write = MemOp{ + .is_indirect = false, + .indirect_address = 0, + .direct_address = dst_offset + offset, + .tag = w_tag, + .tag_match = true, + .val = slice.at(offset), + }; + } // This looks a bit gross, but it is fine for now. if (j == 0) { main_row.main_ia = slice.at(offset); - main_row.main_mem_addr_a = FF(dst_offset + offset); + main_row.main_ind_addr_a = FF(mem_write.indirect_address); + main_row.main_sel_resolve_ind_addr_a = FF(static_cast(mem_write.is_indirect)); + main_row.main_mem_addr_a = FF(mem_write.direct_address); main_row.main_sel_mem_op_a = FF(1); main_row.main_rwa = FF(1); } else if (j == 1) { main_row.main_ib = slice.at(offset); - main_row.main_mem_addr_b = FF(dst_offset + offset); + main_row.main_mem_addr_b = FF(mem_write.direct_address); main_row.main_sel_mem_op_b = FF(1); main_row.main_rwb = FF(1); } else if (j == 2) { main_row.main_ic = slice.at(offset); - main_row.main_mem_addr_c = FF(dst_offset + offset); + main_row.main_mem_addr_c = FF(mem_write.direct_address); main_row.main_sel_mem_op_c = FF(1); main_row.main_rwc = FF(1); } else { main_row.main_id = slice.at(offset); - main_row.main_mem_addr_d = FF(dst_offset + offset); + main_row.main_mem_addr_d = FF(mem_write.direct_address); main_row.main_sel_mem_op_d = FF(1); main_row.main_rwd = FF(1); } } main_trace.emplace_back(main_row); } + return num_main_rows; } template std::array vec_to_arr(std::vector const& vec) @@ -2553,13 +2450,16 @@ template std::array vec_to_arr(std::vector template uint32_t AvmTraceBuilder::read_slice_to_memory(uint8_t space_id, uint32_t clk, - uint32_t src_offset, + AddressWithMode addr, AvmMemoryTag r_tag, AvmMemoryTag w_tag, FF internal_return_ptr, size_t slice_len, std::vector& slice) { + // If the mem_op is indirect, it goes into register A + bool is_indirect = addr.mode == AddressingMode::INDIRECT; + auto src_offset = addr.offset; // We have 4 registers that we are able to use to read from memory within a single main trace row auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; // If the slice size isnt a multiple of 4, we still need an extra row to write the remainder @@ -2579,28 +2479,47 @@ uint32_t AvmTraceBuilder::read_slice_to_memory(uint8_t space_id, if (offset >= slice_len) { break; } - auto mem_read = mem_trace_builder.read_and_load_from_memory( - space_id, clk + i, register_order[j], src_offset + offset, r_tag, w_tag); + MemOp mem_read; + if (is_indirect) { + // If the first address is indirect we read it into register A, this can only happen once per slice read + mem_read = constrained_read_from_memory(space_id, clk + i, addr, r_tag, w_tag, IntermRegister::IA); + // Set this to false for the rest of the reads + is_indirect = false; + src_offset = mem_read.direct_address; + } else { + auto mem_load = mem_trace_builder.read_and_load_from_memory( + space_id, clk + i, register_order[j], src_offset + offset, r_tag, w_tag); + mem_read = MemOp{ + .is_indirect = false, + .indirect_address = 0, + .direct_address = src_offset + offset, + .tag = r_tag, + .tag_match = mem_load.tag_match, + .val = MEM(mem_load.val), + }; + } slice.emplace_back(MEM(mem_read.val)); // This looks a bit gross, but it is fine for now. if (j == 0) { main_row.main_ia = slice.at(offset); - main_row.main_mem_addr_a = FF(src_offset + offset); + main_row.main_ind_addr_a = FF(mem_read.indirect_address); + main_row.main_sel_resolve_ind_addr_a = FF(static_cast(mem_read.is_indirect)); + main_row.main_mem_addr_a = FF(mem_read.direct_address); main_row.main_sel_mem_op_a = FF(1); main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); } else if (j == 1) { main_row.main_ib = slice.at(offset); - main_row.main_mem_addr_b = FF(src_offset + offset); + main_row.main_mem_addr_b = FF(mem_read.direct_address); main_row.main_sel_mem_op_b = FF(1); main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); } else if (j == 2) { main_row.main_ic = slice.at(offset); - main_row.main_mem_addr_c = FF(src_offset + offset); + main_row.main_mem_addr_c = FF(mem_read.direct_address); main_row.main_sel_mem_op_c = FF(1); main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); } else { main_row.main_id = slice.at(offset); - main_row.main_mem_addr_d = FF(src_offset + offset); + main_row.main_mem_addr_d = FF(mem_read.direct_address); main_row.main_sel_mem_op_d = FF(1); main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); } @@ -2621,144 +2540,102 @@ uint32_t AvmTraceBuilder::read_slice_to_memory(uint8_t space_id, * @param addr_offset An index in memory pointing to the target contract address * @param args_offset An index in memory pointing to the first value of the input array for the external call * @param args_size The number of values in the input array for the external call - * @param ret_offset An index in memory pointing to where the first value of the external calls return value should be - * stored. + * @param ret_offset An index in memory pointing to where the first value of the external calls return value should + * be stored. * @param ret_size The number of values in the return array * @param success_offset An index in memory pointing to where the success flag (U8) of the external call should be * stored * @param function_selector_offset An index in memory pointing to the function selector of the external call (TEMP) */ -void AvmTraceBuilder::op_call([[maybe_unused]] uint8_t indirect, - [[maybe_unused]] uint32_t gas_offset, - [[maybe_unused]] uint32_t addr_offset, - [[maybe_unused]] uint32_t args_offset, - [[maybe_unused]] uint32_t args_size, - [[maybe_unused]] uint32_t ret_offset, - [[maybe_unused]] uint32_t ret_size, - [[maybe_unused]] uint32_t success_offset, +void AvmTraceBuilder::op_call(uint8_t indirect, + uint32_t gas_offset, + uint32_t addr_offset, + uint32_t args_offset, + uint32_t args_size, + uint32_t ret_offset, + uint32_t ret_size, + uint32_t success_offset, [[maybe_unused]] uint32_t function_selector_offset) { - // pc++; auto clk = static_cast(main_trace.size()) + 1; const ExternalCallHint& hint = execution_hints.externalcall_hints.at(external_call_counter); - // We can load up to 4 things per row - auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; - // Constrain gas cost + gas_trace_builder.constrain_gas_for_external_call( clk, static_cast(hint.l2_gas_used), static_cast(hint.da_gas_used)); - // Indirect is ZEROTH, SECOND and FOURTH bit COME BACK TO MAKING THIS ALL SUPPORTED - auto read_ind_gas_offset = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, gas_offset); - auto read_ind_args_offset = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, args_offset); - - std::vector first_row_load = { - uint32_t(read_ind_gas_offset.val), - addr_offset, - uint32_t(read_ind_args_offset.val), - }; - std::vector first_row_values = {}; - for (uint32_t j = 0; j < first_row_load.size(); j++) { - // We just read and load to set up the constraints, we dont actually use these values for now. - // info("Register order ", register_order[j]); - auto mem_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, register_order[j], first_row_load[j], AvmMemoryTag::FF, AvmMemoryTag::U0); - first_row_values.emplace_back(mem_read.val); - } + + auto [resolved_gas_offset, + resolved_addr_offset, + resolved_args_offset, + resolved_args_size, + resolved_ret_offset, + resolved_success_offset] = + unpack_indirects<6>(indirect, { gas_offset, addr_offset, args_offset, args_size, ret_offset, success_offset }); + + // Should read the address next to read_gas as well (tuple of gas values (l2Gas, daGas)) + auto read_gas_l2 = constrained_read_from_memory( + call_ptr, clk, resolved_gas_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + auto read_gas_da = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IB, read_gas_l2.direct_address + 1, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto read_addr = constrained_read_from_memory( + call_ptr, clk, resolved_addr_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IC); + auto read_args = constrained_read_from_memory( + call_ptr, clk, resolved_args_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::ID); + bool tag_match = read_gas_l2.tag_match && read_gas_da.tag_match && read_addr.tag_match && read_args.tag_match; // We read the input and output addresses in one row as they should contain FF elements main_trace.push_back(Row{ .main_clk = clk, - .main_ia = first_row_values[0], /* gas_offset */ - .main_ib = first_row_values[1], /* addr_offset */ - .main_ic = first_row_values[2], /* args_offset */ - .main_ind_addr_a = gas_offset, - .main_ind_addr_c = args_offset, + .main_ia = read_gas_l2.val, /* gas_offset_l2 */ + .main_ib = read_gas_da.val, /* gas_offset_da */ + .main_ic = read_addr.val, /* addr_offset */ + .main_id = read_args.val, /* args_offset */ + .main_ind_addr_a = FF(read_gas_l2.indirect_address), + .main_ind_addr_c = FF(read_addr.indirect_address), + .main_ind_addr_d = FF(read_args.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = read_ind_gas_offset.val, - .main_mem_addr_b = addr_offset, - .main_mem_addr_c = read_ind_args_offset.val, - .main_pc = FF(pc++), + .main_mem_addr_a = FF(read_gas_l2.direct_address), + .main_mem_addr_b = FF(read_gas_l2.direct_address + 1), + .main_mem_addr_c = FF(read_addr.direct_address), + .main_mem_addr_d = FF(read_args.direct_address), + .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), + .main_sel_mem_op_d = FF(1), .main_sel_op_external_call = FF(1), - .main_sel_resolve_ind_addr_a = FF(1), - .main_sel_resolve_ind_addr_c = FF(1), - }); - clk++; - // Read the rest on a separate line, remember that the 4th operand is indirect - auto read_ind_ret_offset = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, ret_offset); - // We just read and load to set up the constraints, we dont actually use these values for now. - auto mem_read_ret = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, uint32_t(read_ind_ret_offset.val), AvmMemoryTag::FF, AvmMemoryTag::U0); - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = mem_read_ret.val, /* ret_offset */ - .main_ind_addr_a = ret_offset, - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = read_ind_ret_offset.val, - .main_pc = FF(pc), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), - .main_sel_mem_op_a = FF(1), - .main_sel_resolve_ind_addr_a = FF(1), - }); - clk++; - auto mem_read_success = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, success_offset, AvmMemoryTag::U32, AvmMemoryTag::U0); - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = mem_read_success.val, /* success_offset */ - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(success_offset), - .main_pc = FF(pc), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), - .main_sel_mem_op_a = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_gas_l2.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(read_addr.is_indirect)), + .main_sel_resolve_ind_addr_d = FF(static_cast(read_args.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); clk++; + // The return data hint is used for now, we check it has the same length as the ret_size + ASSERT(hint.return_data.size() == ret_size); + // Write the return data to memory + uint32_t num_rows = write_slice_to_memory( + call_ptr, clk, resolved_ret_offset, AvmMemoryTag::U0, AvmMemoryTag::FF, internal_return_ptr, hint.return_data); + clk += num_rows; + // Write the success flag to memory write_slice_to_memory(call_ptr, clk, - uint32_t(read_ind_ret_offset.val), + resolved_success_offset, AvmMemoryTag::U0, - AvmMemoryTag::FF, + AvmMemoryTag::U8, internal_return_ptr, - hint.return_data); - clk++; - write_slice_to_memory( - call_ptr, clk, success_offset, AvmMemoryTag::U0, AvmMemoryTag::U8, internal_return_ptr, { hint.success }); + { hint.success }); external_call_counter++; + pc++; } void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_address_offset = address_offset; - uint32_t direct_dst_offset = dst_offset; - - bool indirect_address_flag = is_operand_indirect(indirect, 0); - bool indirect_dst_flag = is_operand_indirect(indirect, 1); - if (indirect_address_flag) { - auto read_ind_address = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_A, address_offset); - direct_address_offset = uint32_t(read_ind_address.val); - tag_match = tag_match && read_ind_address.tag_match; - } - - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_B, dst_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - - auto read_address = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_address_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); - auto read_dst = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto [resolved_address_offset, resolved_dst_offset] = unpack_indirects<2>(indirect, { address_offset, dst_offset }); + auto read_address = constrained_read_from_memory( + call_ptr, clk, resolved_address_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + bool tag_match = read_address.tag_match; // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::GETCONTRACTINSTANCE); @@ -2766,20 +2643,16 @@ void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t addres main_trace.push_back(Row{ .main_clk = clk, .main_ia = read_address.val, - .main_ib = read_dst.val, - .main_ind_addr_a = indirect_address_flag ? address_offset : 0, - .main_ind_addr_b = indirect_dst_flag ? dst_offset : 0, + .main_ind_addr_a = FF(read_address.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_address_offset), - .main_mem_addr_b = FF(direct_dst_offset), + .main_mem_addr_a = FF(read_address.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_activate_gas = FF(1), // TODO: remove in the long term - .main_sel_mem_op_b = FF(1), .main_sel_op_get_contract_instance = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_address_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_dst_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_address.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); clk++; // Read the contract instance @@ -2794,7 +2667,7 @@ void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t addres contract_instance.public_key_hash }; write_slice_to_memory(call_ptr, clk, - direct_dst_offset, + resolved_dst_offset, AvmMemoryTag::U0, AvmMemoryTag::FF, internal_return_ptr, @@ -2814,41 +2687,21 @@ void AvmTraceBuilder::op_to_radix_le( uint8_t indirect, uint32_t src_offset, uint32_t dst_offset, uint32_t radix, uint32_t num_limbs) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_src_offset = src_offset; - uint32_t direct_dst_offset = dst_offset; - - bool indirect_src_flag = is_operand_indirect(indirect, 0); - bool indirect_dst_flag = is_operand_indirect(indirect, 1); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, src_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } + auto [resolved_src_offset, resolved_dst_offset] = unpack_indirects<2>(indirect, { src_offset, dst_offset }); - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_B, dst_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } + auto read_src = constrained_read_from_memory( + call_ptr, clk, resolved_src_offset, AvmMemoryTag::FF, AvmMemoryTag::U8, IntermRegister::IA); - auto read_src = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::U8); - // Read in the memory address of where the first limb should be stored (the read_tag must be U32 and write tag - // U8) - auto read_dst = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U8); + auto read_dst = constrained_read_from_memory( + call_ptr, clk, resolved_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U8, IntermRegister::IB); FF input = read_src.val; - FF dst_addr = read_dst.val; // In case of a memory tag error, we do not perform the computation. // Therefore, we do not create any entry in gadget table and return a vector of 0 - std::vector res = tag_match ? conversion_trace_builder.op_to_radix_le(input, radix, num_limbs, clk) - : std::vector(num_limbs, 0); + std::vector res = read_src.tag_match + ? conversion_trace_builder.op_to_radix_le(input, radix, num_limbs, clk) + : std::vector(num_limbs, 0); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::TORADIXLE); @@ -2859,21 +2712,21 @@ void AvmTraceBuilder::op_to_radix_le( .main_clk = clk, .main_call_ptr = call_ptr, .main_ia = input, - .main_ib = dst_addr, + .main_ib = read_dst.val, .main_ic = radix, .main_id = num_limbs, - .main_ind_addr_a = indirect_src_flag ? src_offset : 0, - .main_ind_addr_b = indirect_dst_flag ? dst_offset : 0, + .main_ind_addr_a = read_src.indirect_address, + .main_ind_addr_b = read_dst.indirect_address, .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), - .main_mem_addr_b = FF(direct_dst_offset), + .main_mem_addr_a = read_src.direct_address, + .main_mem_addr_b = read_dst.direct_address, .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_op_radix_le = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_dst_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_src.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_dst.is_indirect)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), }); // Increment the clock so we dont write at the same clock cycle @@ -2887,7 +2740,7 @@ void AvmTraceBuilder::op_to_radix_le( ff_res.emplace_back(limb); } write_slice_to_memory( - call_ptr, clk, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U8, FF(internal_return_ptr), ff_res); + call_ptr, clk, resolved_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::U8, FF(internal_return_ptr), ff_res); } /** @@ -2898,7 +2751,8 @@ void AvmTraceBuilder::op_to_radix_le( * instance of sha256 compression. * @param input_offset An index in memory pointing to the first U32 value of the input array to be used in the next * instance of sha256 compression. - * @param output_offset An index in memory pointing to where the first U32 value of the output array should be stored. + * @param output_offset An index in memory pointing to where the first U32 value of the output array should be + * stored. */ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, uint32_t output_offset, @@ -2910,15 +2764,14 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, // Resolve the indirect flags, the results of this function are used to determine the memory offsets // that point to the starting memory addresses for the input and output values. - // Note::This function will add memory reads at clk in the mem_trace_builder - auto const res = resolve_ind_three(call_ptr, clk, indirect, h_init_offset, input_offset, output_offset); + auto [resolved_h_init_offset, resolved_input_offset, resolved_output_offset] = + unpack_indirects<3>(indirect, { h_init_offset, input_offset, output_offset }); - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, res.direct_a_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, res.direct_b_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); - auto read_c = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, res.direct_c_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); + auto read_a = constrained_read_from_memory( + call_ptr, clk, resolved_h_init_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IA); + auto read_b = constrained_read_from_memory( + call_ptr, clk, resolved_input_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SHA256COMPRESSION); @@ -2933,26 +2786,21 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, // did not lay down constraints), but this is a simplification main_trace.push_back(Row{ .main_clk = clk, - .main_ia = read_a.val, // First element of output (trivially 0) - .main_ib = read_b.val, // First element of state - .main_ic = read_c.val, // First element of input - .main_ind_addr_a = res.indirect_flag_a ? FF(h_init_offset) : FF(0), - .main_ind_addr_b = res.indirect_flag_b ? FF(input_offset) : FF(0), - .main_ind_addr_c = res.indirect_flag_a ? FF(output_offset) : FF(0), + .main_ia = read_a.val, // First element of state + .main_ib = read_b.val, // First element of input + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(res.direct_a_offset), - .main_mem_addr_b = FF(res.direct_b_offset), - .main_mem_addr_c = FF(res.direct_c_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), - .main_sel_mem_op_c = FF(1), .main_sel_op_sha256 = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(res.indirect_flag_a)), - .main_sel_resolve_ind_addr_b = FF(static_cast(res.indirect_flag_b)), - .main_sel_resolve_ind_addr_c = FF(static_cast(res.indirect_flag_c)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); // We store the current clk this main trace row occurred so that we can line up the sha256 gadget operation at // the same clk later. @@ -2966,7 +2814,7 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, // Read results are written to h_init array. read_slice_to_memory(call_ptr, clk, - res.direct_a_offset, + resolved_h_init_offset, AvmMemoryTag::U32, AvmMemoryTag::U32, FF(internal_return_ptr), @@ -2978,7 +2826,7 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, // Read results are written to input array read_slice_to_memory(call_ptr, clk, - res.direct_b_offset, + resolved_input_offset, AvmMemoryTag::U32, AvmMemoryTag::U32, FF(internal_return_ptr), @@ -3001,15 +2849,21 @@ void AvmTraceBuilder::op_sha256_compression(uint8_t indirect, } // Write the result to memory after - write_slice_to_memory( - call_ptr, clk, res.direct_c_offset, AvmMemoryTag::U32, AvmMemoryTag::U32, FF(internal_return_ptr), ff_result); + write_slice_to_memory(call_ptr, + clk, + resolved_output_offset, + AvmMemoryTag::U32, + AvmMemoryTag::U32, + FF(internal_return_ptr), + ff_result); } /** * @brief SHA256 Hash with direct or indirect memory access. * This function is temporary until we have transitioned to sha256Compression * @param indirect byte encoding information about indirect/direct memory access. - * @param output_offset An index in memory pointing to where the first U32 value of the output array should be stored. + * @param output_offset An index in memory pointing to where the first U32 value of the output array should be + * stored. * @param input_offset An index in memory pointing to the first U8 value of the state array to be used in the next * instance of sha256. * @param input_size_offset An index in memory pointing to the U32 value of the input size. @@ -3020,144 +2874,62 @@ void AvmTraceBuilder::op_sha256(uint8_t indirect, uint32_t input_size_offset) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_src_offset = input_offset; - uint32_t direct_dst_offset = output_offset; + auto [resolved_output_offset, resolved_input_offset, resolved_input_size_offset] = + unpack_indirects<3>(indirect, { output_offset, input_offset, input_size_offset }); - bool indirect_src_flag = is_operand_indirect(indirect, 1); - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } - - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, output_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - // Note we load the input and output onto one line in the main trace and the length on the next line - // We do this so we can load two different AvmMemoryTags (u8 for the I/O and u32 for the length) - auto input_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); - auto output_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); - - // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::SHA256); + auto input_length_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); + // Store the clock time that we will use to line up the gadget later auto sha256_op_clk = clk; - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = input_read.val, // First element of input - .main_ic = output_read.val, // First element of output - .main_ind_addr_a = indirect_src_flag ? FF(input_offset) : FF(0), - .main_ind_addr_c = indirect_dst_flag ? FF(output_offset) : FF(0), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), // input - .main_mem_addr_c = FF(direct_dst_offset), // output - .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), - .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_c = FF(1), - .main_sel_op_sha256 = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_sel_resolve_ind_addr_c = FF(static_cast(indirect_dst_flag)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), - }); - clk++; - auto input_length_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); main_trace.push_back(Row{ .main_clk = clk, .main_ib = input_length_read.val, // Message Length + .main_ind_addr_b = FF(input_length_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_b = FF(input_size_offset), // length - .main_pc = FF(pc), + .main_mem_addr_b = FF(input_length_read.direct_address), + .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_b = FF(1), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_sel_op_sha256 = FF(1), + .main_sel_resolve_ind_addr_b = FF(static_cast(input_length_read.is_indirect)), + .main_tag_err = FF(static_cast(!input_length_read.tag_match)), }); clk++; std::vector input; input.reserve(uint32_t(input_length_read.val)); - - // We unroll this loop because the function typically expects arrays and for this temporary sha256 function we - // have a dynamic amount of input so we will use a vector. - auto register_order = std::array{ IntermRegister::IA, IntermRegister::IB, IntermRegister::IC, IntermRegister::ID }; - // If the slice size isnt a multiple of 4, we still need an extra row to write the remainder - uint32_t const num_main_rows = static_cast(input_length_read.val) / 4 + - static_cast(uint32_t(input_length_read.val) % 4 != 0); - for (uint32_t i = 0; i < num_main_rows; i++) { - Row main_row{ - .main_clk = clk + i, - .main_internal_return_ptr = FF(internal_return_ptr), - .main_pc = FF(pc), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), - }; - // Write 4 values to memory in each_row - for (uint32_t j = 0; j < 4; j++) { - auto offset = i * 4 + j; - // If we exceed the slice size, we break - if (offset >= uint32_t(input_length_read.val)) { - break; - } - auto mem_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk + i, register_order[j], direct_src_offset + offset, AvmMemoryTag::U8, AvmMemoryTag::U8); - input.emplace_back(uint8_t(mem_read.val)); - // This looks a bit gross, but it is fine for now. - if (j == 0) { - main_row.main_ia = input.at(offset); - main_row.main_mem_addr_a = FF(direct_src_offset + offset); - main_row.main_sel_mem_op_a = FF(1); - main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); - } else if (j == 1) { - main_row.main_ib = input.at(offset); - main_row.main_mem_addr_b = FF(direct_src_offset + offset); - main_row.main_sel_mem_op_b = FF(1); - main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); - } else if (j == 2) { - main_row.main_ic = input.at(offset); - main_row.main_mem_addr_c = FF(direct_src_offset + offset); - main_row.main_sel_mem_op_c = FF(1); - main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); - } else { - main_row.main_id = input.at(offset); - main_row.main_mem_addr_d = FF(direct_src_offset + offset); - main_row.main_sel_mem_op_d = FF(1); - main_row.main_tag_err = FF(static_cast(!mem_read.tag_match)); - } - } - main_trace.emplace_back(main_row); - } - + uint32_t num_main_rows = read_slice_to_memory(call_ptr, + clk, + resolved_input_offset, + AvmMemoryTag::U8, + AvmMemoryTag::U0, + FF(internal_return_ptr), + uint32_t(input_length_read.val), + input); clk += num_main_rows; - + // std::array result = sha256_trace_builder.sha256(input, sha256_op_clk); - // We convert the results to field elements here + std::vector ff_result; for (uint32_t i = 0; i < 32; i++) { ff_result.emplace_back(result[i]); } // Write the result to memory after write_slice_to_memory( - call_ptr, clk, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8, FF(internal_return_ptr), ff_result); + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U0, AvmMemoryTag::U8, FF(internal_return_ptr), ff_result); } /** * @brief Poseidon2 Permutation with direct or indirect memory access. * * @param indirect byte encoding information about indirect/direct memory access. - * @param input_offset An index in memory pointing to the first Field value of the input array to be used in the next - * instance of poseidon2 permutation. - * @param output_offset An index in memory pointing to where the first Field value of the output array should be stored. + * @param input_offset An index in memory pointing to the first Field value of the input array to be used in the + * next instance of poseidon2 permutation. + * @param output_offset An index in memory pointing to where the first Field value of the output array should be + * stored. */ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_offset, uint32_t output_offset) { @@ -3166,32 +2938,14 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ // Resolve the indirect flags, the results of this function are used to determine the memory offsets // that point to the starting memory addresses for the input, output and h_init values // Note::This function will add memory reads at clk in the mem_trace_builder - bool tag_match = true; - uint32_t direct_src_offset = input_offset; - uint32_t direct_dst_offset = output_offset; - - bool indirect_src_flag = is_operand_indirect(indirect, 0); - bool indirect_dst_flag = is_operand_indirect(indirect, 1); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } - - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_B, output_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } + auto [resolved_input_offset, resolved_output_offset] = + unpack_indirects<2>(indirect, { input_offset, output_offset }); - auto read_a = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); - // Read in the memory address of where the first limb should be stored - auto read_b = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto read_a = constrained_read_from_memory( + call_ptr, clk, resolved_input_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + auto read_b = constrained_read_from_memory( + call_ptr, clk, resolved_output_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IB); + bool tag_match = read_a.tag_match && read_b.tag_match; // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::POSEIDON2); @@ -3200,19 +2954,19 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ .main_clk = clk, .main_ia = read_a.val, // First element of input .main_ib = read_b.val, // First element of output (trivially zero) - .main_ind_addr_a = indirect_src_flag ? FF(input_offset) : FF(0), - .main_ind_addr_b = indirect_dst_flag ? FF(output_offset) : FF(0), + .main_ind_addr_a = FF(read_a.indirect_address), + .main_ind_addr_b = FF(read_b.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), - .main_mem_addr_b = FF(direct_dst_offset), + .main_mem_addr_a = FF(read_a.direct_address), + .main_mem_addr_b = FF(read_b.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_op_poseidon2 = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_dst_flag)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); // We store the current clk this main trace row occurred so that we can line up the poseidon2 gadget operation // at the same clk later. @@ -3222,8 +2976,14 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ clk++; // Read results are written to input array. std::vector input_vec; - read_slice_to_memory( - call_ptr, clk, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), 4, input_vec); + read_slice_to_memory(call_ptr, + clk, + resolved_input_offset, + AvmMemoryTag::FF, + AvmMemoryTag::U0, + FF(internal_return_ptr), + 4, + input_vec); // Increment the clock by 1 since (4 reads / 4 reads per row = 1) clk += 1; @@ -3235,19 +2995,21 @@ void AvmTraceBuilder::op_poseidon2_permutation(uint8_t indirect, uint32_t input_ } // // Write the result to memory after write_slice_to_memory( - call_ptr, clk, direct_dst_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), ff_result); + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U0, AvmMemoryTag::FF, FF(internal_return_ptr), ff_result); } /** * @brief Keccakf1600 with direct or indirect memory access. - * This function temporarily has the same interface as the kecccak opcode for compatibility, when the keccak migration - * is complete (to keccakf1600) We will update this function call as we will not likely need input_size_offset + * This function temporarily has the same interface as the kecccak opcode for compatibility, when the keccak + * migration is complete (to keccakf1600) We will update this function call as we will not likely need + * input_size_offset * @param indirect byte encoding information about indirect/direct memory access. - * @param output_offset An index in memory pointing to where the first u64 value of the output array should be stored. + * @param output_offset An index in memory pointing to where the first u64 value of the output array should be + * stored. * @param input_offset An index in memory pointing to the first u64 value of the input array to be used in the next * instance of poseidon2 permutation. - * @param input_size offset An index in memory pointing to the size of the input array. Temporary while we maintain the - * same interface as keccak (this is fixed to 25) + * @param input_size offset An index in memory pointing to the size of the input array. Temporary while we maintain + * the same interface as keccak (this is fixed to 25) */ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, uint32_t output_offset, @@ -3256,32 +3018,13 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, { // What happens if the input_size_offset is > 25 when the state is more that that? auto clk = static_cast(main_trace.size()) + 1; - // bool tag_match = res.tag_match; - bool tag_match = true; - uint32_t direct_src_offset = input_offset; - uint32_t direct_dst_offset = output_offset; - - bool indirect_src_flag = is_operand_indirect(indirect, 1); - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } - - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, output_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - - auto input_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::U64, AvmMemoryTag::U64); - auto output_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, direct_dst_offset, AvmMemoryTag::U64, AvmMemoryTag::U64); + auto [resolved_output_offset, resolved_input_offset] = + unpack_indirects<2>(indirect, { output_offset, input_offset }); + auto input_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IA); + auto output_read = constrained_read_from_memory( + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U64, AvmMemoryTag::U0, IntermRegister::IC); + bool tag_match = input_read.tag_match && output_read.tag_match; // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::KECCAKF1600); @@ -3290,19 +3033,19 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, .main_clk = clk, .main_ia = input_read.val, // First element of input .main_ic = output_read.val, // First element of output - .main_ind_addr_a = indirect_src_flag ? FF(input_offset) : FF(0), - .main_ind_addr_c = indirect_dst_flag ? FF(output_offset) : FF(0), + .main_ind_addr_a = FF(input_read.indirect_address), + .main_ind_addr_c = FF(output_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), // input - .main_mem_addr_c = FF(direct_dst_offset), // output + .main_mem_addr_a = FF(input_read.direct_address), + .main_mem_addr_c = FF(output_read.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U64)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_op_keccak = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_sel_resolve_ind_addr_c = FF(static_cast(indirect_dst_flag)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U64)), + .main_sel_resolve_ind_addr_a = FF(static_cast(input_read.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(output_read.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); // We store the current clk this main trace row occurred so that we can line up the keccak gadget operation // at the same clk later. @@ -3310,7 +3053,7 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, // We need to increment the clk clk++; auto input_length_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); + call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0); main_trace.push_back(Row{ .main_clk = clk, .main_ib = input_length_read.val, // Message Length @@ -3319,18 +3062,24 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_b = FF(1), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_tag_err = FF(static_cast(!input_length_read.tag_match)), }); clk++; // Array input is fixed to 1600 bits std::vector input_vec; // Read results are written to input array - read_slice_to_memory( - call_ptr, clk, direct_src_offset, AvmMemoryTag::U64, AvmMemoryTag::U64, FF(internal_return_ptr), 25, input_vec); + uint32_t num_main_rows = read_slice_to_memory(call_ptr, + clk, + resolved_input_offset, + AvmMemoryTag::U64, + AvmMemoryTag::U0, + FF(internal_return_ptr), + 25, + input_vec); std::array input = vec_to_arr(input_vec); // Increment the clock by 7 since (25 reads / 4 reads per row = 7) - clk += 7; + clk += num_main_rows; // Now that we have read all the values, we can perform the operation to get the resulting witness. // Note: We use the keccak_op_clk to ensure that the keccakf1600 operation is performed at the same clock cycle @@ -3344,16 +3093,16 @@ void AvmTraceBuilder::op_keccakf1600(uint8_t indirect, // Write the result to memory after write_slice_to_memory( - call_ptr, clk, direct_dst_offset, AvmMemoryTag::U64, AvmMemoryTag::U64, FF(internal_return_ptr), ff_result); + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U0, AvmMemoryTag::U64, FF(internal_return_ptr), ff_result); } /** * @brief Keccak with direct or indirect memory access. * Keccak is TEMPORARY while we wait for the transition to keccakf1600, so we do the minimal to store the result * @param indirect byte encoding information about indirect/direct memory access. - * @param output_offset An index in memory pointing to where the first u8 value of the output array should be stored. - * @param input_offset An index in memory pointing to the first u8 value of the input array to be used in the next - * instance of poseidon2 permutation. + * @param output_offset An index in memory pointing to where the first u8 value of the output array should be + * stored. + * @param input_offset An index in memory pointing to the first u8 value of the input array to be used * @param input_size offset An index in memory pointing to the size of the input array. */ void AvmTraceBuilder::op_keccak(uint8_t indirect, @@ -3362,76 +3111,44 @@ void AvmTraceBuilder::op_keccak(uint8_t indirect, uint32_t input_size_offset) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_src_offset = input_offset; - uint32_t direct_dst_offset = output_offset; - - bool indirect_src_flag = is_operand_indirect(indirect, 1); - bool indirect_dst_flag = is_operand_indirect(indirect, 0); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } - - if (indirect_dst_flag) { - auto read_ind_dst = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_C, output_offset); - direct_dst_offset = uint32_t(read_ind_dst.val); - tag_match = tag_match && read_ind_dst.tag_match; - } - // Note we load the input and output onto one line in the main trace and the length on the next line - // We do this so we can load two different AvmMemoryTags (u8 for the I/O and u32 for the length) - auto input_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); - auto output_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8); + auto [resolved_output_offset, resolved_input_offset, resolved_input_size_offset] = + unpack_indirects<3>(indirect, { output_offset, input_offset, input_size_offset }); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::KECCAK); + // Read the input length first + auto input_length_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); + // Store the clock time that we will use to line up the gadget later auto keccak_op_clk = clk; - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = input_read.val, // First element of input - .main_ic = output_read.val, // First element of output - .main_ind_addr_a = indirect_src_flag ? FF(input_offset) : FF(0), - .main_ind_addr_c = indirect_dst_flag ? FF(output_offset) : FF(0), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), // input - .main_mem_addr_c = FF(direct_dst_offset), // output - .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), - .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_c = FF(1), - .main_sel_op_keccak = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_sel_resolve_ind_addr_c = FF(static_cast(indirect_dst_flag)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), - }); - clk++; - auto input_length_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); main_trace.push_back(Row{ .main_clk = clk, .main_ib = input_length_read.val, // Message Length + .main_ind_addr_b = FF(input_length_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_b = FF(input_size_offset), // length - .main_pc = FF(pc), + .main_mem_addr_b = FF(input_length_read.direct_address), // length + .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_b = FF(1), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_sel_op_keccak = FF(1), + .main_sel_resolve_ind_addr_b = FF(static_cast(input_length_read.is_indirect)), + .main_tag_err = FF(static_cast(!input_length_read.tag_match)), }); clk++; std::vector input; input.reserve(uint32_t(input_length_read.val)); - - uint32_t num_main_rows = read_slice_to_memory( - call_ptr, clk, direct_src_offset, AvmMemoryTag::U8, AvmMemoryTag::U8, FF(internal_return_ptr), 4, input); + // Read the slice length from memory + uint32_t num_main_rows = read_slice_to_memory(call_ptr, + clk, + resolved_input_offset, + AvmMemoryTag::U8, + AvmMemoryTag::U8, + FF(internal_return_ptr), + uint32_t(input_length_read.val), + input); clk += num_main_rows; @@ -3443,7 +3160,7 @@ void AvmTraceBuilder::op_keccak(uint8_t indirect, } // Write the result to memory after write_slice_to_memory( - call_ptr, clk, direct_dst_offset, AvmMemoryTag::U8, AvmMemoryTag::U8, FF(internal_return_ptr), ff_result); + call_ptr, clk, resolved_output_offset, AvmMemoryTag::U8, AvmMemoryTag::U8, FF(internal_return_ptr), ff_result); } /** @@ -3460,19 +3177,10 @@ void AvmTraceBuilder::op_pedersen_hash(uint8_t indirect, uint32_t input_size_offset) { auto clk = static_cast(main_trace.size()) + 1; - bool tag_match = true; - uint32_t direct_src_offset = input_offset; - bool indirect_src_flag = is_operand_indirect(indirect, 2); - - if (indirect_src_flag) { - auto read_ind_src = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, input_offset); - direct_src_offset = uint32_t(read_ind_src.val); - tag_match = tag_match && read_ind_src.tag_match; - } - - auto input_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_src_offset, AvmMemoryTag::FF, AvmMemoryTag::FF); + auto [resolved_gen_ctx_offset, resolved_output_offset, resolved_input_offset, resolved_input_size_offset] = + unpack_indirects<4>(indirect, { gen_ctx_offset, output_offset, input_offset, input_size_offset }); + auto input_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); // Constrain gas cost gas_trace_builder.constrain_gas_lookup(clk, OpCode::PEDERSEN); @@ -3482,41 +3190,44 @@ void AvmTraceBuilder::op_pedersen_hash(uint8_t indirect, main_trace.push_back(Row{ .main_clk = clk, .main_ia = input_read.val, // First element of input - .main_ind_addr_a = indirect_src_flag ? FF(input_offset) : FF(0), + .main_ind_addr_a = FF(input_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_src_offset), // input + .main_mem_addr_a = FF(input_read.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_op_pedersen = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_src_flag)), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), + .main_sel_resolve_ind_addr_a = FF(static_cast(input_read.is_indirect)), + .main_tag_err = FF(static_cast(!input_read.tag_match)), }); clk++; // We read the input size and gen_ctx addresses in one row as they should contain U32 elements - auto input_size_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); - auto gen_ctx_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, gen_ctx_offset, AvmMemoryTag::U32, AvmMemoryTag::U32); + auto input_size_read = constrained_read_from_memory( + call_ptr, clk, resolved_input_size_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IA); + auto gen_ctx_read = constrained_read_from_memory( + call_ptr, clk, resolved_gen_ctx_offset, AvmMemoryTag::U32, AvmMemoryTag::U0, IntermRegister::IB); main_trace.push_back(Row{ .main_clk = clk, .main_ia = input_size_read.val, .main_ib = gen_ctx_read.val, + .main_ind_addr_a = FF(input_size_read.indirect_address), + .main_ind_addr_b = FF(gen_ctx_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(input_size_offset), - .main_mem_addr_b = FF(gen_ctx_offset), + .main_mem_addr_a = FF(input_size_read.direct_address), + .main_mem_addr_b = FF(gen_ctx_read.direct_address), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U32)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), - .main_w_in_tag = FF(static_cast(AvmMemoryTag::U32)), + .main_sel_resolve_ind_addr_a = FF(static_cast(input_size_read.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(gen_ctx_read.is_indirect)), }); clk++; std::vector inputs; uint32_t num_main_rows = read_slice_to_memory(call_ptr, clk, - direct_src_offset, + resolved_input_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), @@ -3525,7 +3236,7 @@ void AvmTraceBuilder::op_pedersen_hash(uint8_t indirect, clk += num_main_rows; FF output = pedersen_trace_builder.pedersen_hash(inputs, uint32_t(gen_ctx_read.val), pedersen_clk); write_slice_to_memory( - call_ptr, clk, output_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), { output }); + call_ptr, clk, resolved_output_offset, AvmMemoryTag::FF, AvmMemoryTag::FF, FF(internal_return_ptr), { output }); } void AvmTraceBuilder::op_ec_add(uint8_t indirect, @@ -3538,16 +3249,31 @@ void AvmTraceBuilder::op_ec_add(uint8_t indirect, uint32_t output_offset) { auto clk = static_cast(main_trace.size()) + 1; + auto [resolved_lhs_x_offset, + resolved_lhs_y_offset, + resolved_lhs_is_inf_offset, + resolved_rhs_x_offset, + resolved_rhs_y_offset, + resolved_rhs_is_inf_offset, + resolved_output_offset] = unpack_indirects<7>(indirect, + { lhs_x_offset, + lhs_y_offset, + lhs_is_inf_offset, + rhs_x_offset, + rhs_y_offset, + rhs_is_inf_offset, + output_offset }); // Load lhs point - auto lhs_x_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, lhs_x_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); - auto lhs_y_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, lhs_y_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto lhs_x_read = constrained_read_from_memory( + call_ptr, clk, resolved_lhs_x_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); + auto lhs_y_read = constrained_read_from_memory( + call_ptr, clk, resolved_lhs_y_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IB); // Load rhs point - auto rhs_x_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, rhs_x_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); - auto rhs_y_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::ID, rhs_y_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto rhs_x_read = constrained_read_from_memory( + call_ptr, clk, resolved_rhs_x_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IC); + auto rhs_y_read = constrained_read_from_memory( + call_ptr, clk, resolved_rhs_y_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::ID); + bool tag_match = lhs_x_read.tag_match && lhs_y_read.tag_match && rhs_x_read.tag_match && rhs_y_read.tag_match; // Save this clk time to line up with the gadget op. auto ecc_clk = clk; @@ -3557,24 +3283,34 @@ void AvmTraceBuilder::op_ec_add(uint8_t indirect, .main_ib = lhs_y_read.val, .main_ic = rhs_x_read.val, .main_id = rhs_y_read.val, + .main_ind_addr_a = FF(lhs_x_read.indirect_address), + .main_ind_addr_b = FF(lhs_y_read.indirect_address), + .main_ind_addr_c = FF(rhs_x_read.indirect_address), + .main_ind_addr_d = FF(rhs_y_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(lhs_x_offset), - .main_mem_addr_b = FF(lhs_y_offset), - .main_mem_addr_c = FF(rhs_x_offset), - .main_mem_addr_d = FF(rhs_y_offset), + .main_mem_addr_a = FF(lhs_x_read.direct_address), + .main_mem_addr_b = FF(lhs_y_read.direct_address), + .main_mem_addr_c = FF(rhs_x_read.direct_address), + .main_mem_addr_d = FF(rhs_y_read.direct_address), .main_pc = FF(pc++), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), .main_sel_mem_op_c = FF(1), .main_sel_mem_op_d = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(lhs_x_read.is_indirect)), + .main_sel_resolve_ind_addr_b = FF(static_cast(lhs_y_read.is_indirect)), + .main_sel_resolve_ind_addr_c = FF(static_cast(rhs_x_read.is_indirect)), + .main_sel_resolve_ind_addr_d = FF(static_cast(rhs_y_read.is_indirect)), + .main_tag_err = FF(static_cast(!tag_match)), }); clk++; // Load the infinite bools separately since they have a different memory tag - auto lhs_is_inf_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, lhs_is_inf_offset, AvmMemoryTag::U8, AvmMemoryTag::U0); - auto rhs_is_inf_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, rhs_is_inf_offset, AvmMemoryTag::U8, AvmMemoryTag::U0); + auto lhs_is_inf_read = constrained_read_from_memory( + call_ptr, clk, resolved_lhs_is_inf_offset, AvmMemoryTag::U8, AvmMemoryTag::U0, IntermRegister::IA); + auto rhs_is_inf_read = constrained_read_from_memory( + call_ptr, clk, resolved_rhs_is_inf_offset, AvmMemoryTag::U8, AvmMemoryTag::U0, IntermRegister::IB); + bool tag_match_inf = lhs_is_inf_read.tag_match && rhs_is_inf_read.tag_match; main_trace.push_back(Row{ .main_clk = clk, @@ -3587,6 +3323,7 @@ void AvmTraceBuilder::op_ec_add(uint8_t indirect, .main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), + .main_tag_err = FF(static_cast(!tag_match_inf)), }); clk++; grumpkin::g1::affine_element lhs = uint8_t(lhs_is_inf_read.val) == 1 @@ -3596,47 +3333,49 @@ void AvmTraceBuilder::op_ec_add(uint8_t indirect, ? grumpkin::g1::affine_element::infinity() : grumpkin::g1::affine_element{ rhs_x_read.val, rhs_y_read.val }; auto result = ecc_trace_builder.embedded_curve_add(lhs, rhs, ecc_clk); - // Write across two lines since we have different mem_tags - uint32_t direct_output_offset = output_offset; - bool indirect_flag_output = is_operand_indirect(indirect, 6); - if (indirect_flag_output) { - auto read_ind_output = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, output_offset); - direct_output_offset = uint32_t(read_ind_output.val); - } + // Write point coordinates + auto write_x = constrained_write_to_memory( + call_ptr, clk, resolved_output_offset, result.x, AvmMemoryTag::U0, AvmMemoryTag::FF, IntermRegister::IA); + // Write y (directly) using the write_x.direct_address + 1 mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IA, direct_output_offset, result.x, AvmMemoryTag::U0, AvmMemoryTag::FF); - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IB, direct_output_offset + 1, result.y, AvmMemoryTag::U0, AvmMemoryTag::FF); + call_ptr, clk, IntermRegister::IB, write_x.direct_address + 1, result.y, AvmMemoryTag::U0, AvmMemoryTag::FF); main_trace.push_back(Row{ .main_clk = clk, .main_ia = result.x, .main_ib = result.y, - .main_ind_addr_a = indirect_flag_output ? FF(output_offset) : FF(0), + .main_ind_addr_a = FF(write_x.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_output_offset), - .main_mem_addr_b = FF(direct_output_offset + 1), + .main_mem_addr_a = FF(write_x.direct_address), + .main_mem_addr_b = FF(write_x.direct_address + 1), .main_pc = FF(pc), .main_rwa = FF(1), .main_rwb = FF(1), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_flag_output)), + .main_sel_resolve_ind_addr_a = FF(static_cast(write_x.is_indirect)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); clk++; - write_slice_to_memory(call_ptr, - clk, - direct_output_offset + 2, - AvmMemoryTag::U8, - AvmMemoryTag::U8, - FF(internal_return_ptr), - { result.is_point_at_infinity() }); -} + mem_trace_builder.write_into_memory(call_ptr, + clk, + IntermRegister::IA, + write_x.direct_address + 2, + result.is_point_at_infinity(), + AvmMemoryTag::U0, + AvmMemoryTag::U8); -// This function is a bit overloaded with logic around reconstructing points and scalars that could probably be moved to -// the gadget at some stage (although this is another temporary gadget..) + main_trace.push_back(Row{ + .main_clk = clk, + .main_ia = result.is_point_at_infinity(), + .main_internal_return_ptr = FF(internal_return_ptr), + .main_mem_addr_a = FF(write_x.direct_address + 2), + .main_pc = FF(pc), + .main_rwa = FF(1), + .main_sel_mem_op_a = FF(1), + .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), + }); +} void AvmTraceBuilder::op_variable_msm(uint8_t indirect, uint32_t points_offset, uint32_t scalars_offset, @@ -3644,60 +3383,12 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, uint32_t point_length_offset) { auto clk = static_cast(main_trace.size()) + 1; - // This will all get refactored as part of the indirection refactor - bool tag_match = true; - uint32_t direct_points_offset = points_offset; - uint32_t direct_scalars_offset = scalars_offset; - uint32_t direct_output_offset = output_offset; - // Resolve the indirects - bool indirect_points_flag = is_operand_indirect(indirect, 0); - bool indirect_scalars_flag = is_operand_indirect(indirect, 1); - bool indirect_output_flag = is_operand_indirect(indirect, 2); - - // Read in the points first - if (indirect_points_flag) { - auto read_ind_a = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, points_offset); - direct_points_offset = uint32_t(read_ind_a.val); - tag_match = tag_match && read_ind_a.tag_match; - } - - auto read_points = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_points_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); + auto [resolved_points_offset, resolved_scalars_offset, resolved_output_offset] = + unpack_indirects<3>(indirect, { points_offset, scalars_offset, output_offset }); - // Read in the scalars - if (indirect_scalars_flag) { - auto read_ind_b = mem_trace_builder.indirect_read_and_load_from_memory( - call_ptr, clk, IndirectRegister::IND_B, scalars_offset); - direct_scalars_offset = uint32_t(read_ind_b.val); - tag_match = tag_match && read_ind_b.tag_match; - } - auto read_scalars = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_scalars_offset, AvmMemoryTag::FF, AvmMemoryTag::U0); - - // In the refactor we will have the read_slice function handle indirects as well - main_trace.push_back(Row{ - .main_clk = clk, - .main_ia = read_points.val, - .main_ib = read_scalars.val, - .main_ind_addr_a = indirect_points_flag ? FF(points_offset) : FF(0), - .main_ind_addr_b = indirect_scalars_flag ? FF(scalars_offset) : FF(0), - .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_points_offset), - .main_mem_addr_b = FF(direct_scalars_offset), - .main_pc = FF(pc++), - .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), - .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_b = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_points_flag)), - .main_sel_resolve_ind_addr_b = FF(static_cast(indirect_scalars_flag)), - .main_tag_err = FF(static_cast(!tag_match)), - }); - clk++; - - // Read the points length (different row since it has a different memory tag) auto points_length_read = mem_trace_builder.read_and_load_from_memory( call_ptr, clk, IntermRegister::IA, point_length_offset, AvmMemoryTag::U32, AvmMemoryTag::U0); + main_trace.push_back(Row{ .main_clk = clk, .main_ia = points_length_read.val, @@ -3716,97 +3407,69 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, std::vector points_coords_vec; std::vector points_inf_vec; std::vector scalars_vec; - // Read the coordinates first, +2 since we read 2 points per row - for (uint32_t i = 0; i < num_points; i += 2) { - // We can read up to 4 coordinates per row (x1,y1,x2,y2) - // Each pair of coordinates are separated by 3 memory addressess - auto point_x1_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, direct_points_offset + i * 3, AvmMemoryTag::FF, AvmMemoryTag::U0); + AddressWithMode coords_offset = resolved_points_offset; + // Loading the points is a bit more complex since we need to read the coordinates and the infinity flags separately + // The current circuit constraints does not allow for multiple memory tags to be loaded from within the same row. + // If we could we would be able to replace the following loops with a single read_slice_to_memory call. + // For now we load the coordinates first and then the infinity flags, and finally splice them together when creating + // the points + + // Read the coordinates first, +2 since we read 2 points per row, the first load could be indirect + for (uint32_t i = 0; i < num_points; i++) { + auto point_x1_read = constrained_read_from_memory( + call_ptr, clk, coords_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, IntermRegister::IA); auto point_y1_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, direct_points_offset + i * 3 + 1, AvmMemoryTag::FF, AvmMemoryTag::U0); - auto point_x2_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, direct_points_offset + (i + 1) * 3, AvmMemoryTag::FF, AvmMemoryTag::U0); - auto point_y2_read = mem_trace_builder.read_and_load_from_memory(call_ptr, - clk, - IntermRegister::ID, - direct_points_offset + (i + 1) * 3 + 1, - AvmMemoryTag::FF, - AvmMemoryTag::U0); - bool tag_match = - point_x1_read.tag_match && point_y1_read.tag_match && point_x2_read.tag_match && point_y2_read.tag_match; - points_coords_vec.insert(points_coords_vec.end(), - { point_x1_read.val, point_y1_read.val, point_x2_read.val, point_y2_read.val }); + call_ptr, clk, IntermRegister::IB, point_x1_read.direct_address + 1, AvmMemoryTag::FF, AvmMemoryTag::U0); + + bool tag_match = point_x1_read.tag_match && point_y1_read.tag_match; + points_coords_vec.insert(points_coords_vec.end(), { point_x1_read.val, point_y1_read.val }); main_trace.push_back(Row{ .main_clk = clk, .main_ia = point_x1_read.val, .main_ib = point_y1_read.val, - .main_ic = point_x2_read.val, - .main_id = point_y2_read.val, + .main_ind_addr_a = FF(point_x1_read.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_points_offset + i * 3), - .main_mem_addr_b = FF(direct_points_offset + i * 3 + 1), - .main_mem_addr_c = FF(direct_points_offset + (i + 1) * 3), - .main_mem_addr_d = FF(direct_points_offset + (i + 1) * 3 + 1), + .main_mem_addr_a = FF(point_x1_read.direct_address), + .main_mem_addr_b = FF(point_x1_read.direct_address + 1), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::FF)), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), - .main_sel_mem_op_c = FF(1), - .main_sel_mem_op_d = FF(1), + .main_sel_resolve_ind_addr_a = FF(static_cast(point_x1_read.is_indirect)), .main_tag_err = FF(static_cast(!tag_match)), }); clk++; + // Update the coords offset to read the next point (subsequent points are always direct and separated by 3 + // addresses) + coords_offset = { AddressingMode::DIRECT, point_x1_read.direct_address + 3 }; } - // Read the Infinities flags, +4 since we read 4 points row - for (uint32_t i = 0; i < num_points; i += 4) { - // We can read up to 4 infinities per row - // Each infinity flag is separated by 3 memory addressess - uint32_t offset = direct_points_offset + i * 3 + 2; - auto point_inf1_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IA, offset, AvmMemoryTag::U8, AvmMemoryTag::U0); - offset += 3; - - auto point_inf2_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IB, offset, AvmMemoryTag::U8, AvmMemoryTag::U0); - offset += 3; - - auto point_inf3_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::IC, offset, AvmMemoryTag::U8, AvmMemoryTag::U0); - offset += 3; - - auto point_inf4_read = mem_trace_builder.read_and_load_from_memory( - call_ptr, clk, IntermRegister::ID, offset, AvmMemoryTag::U8, AvmMemoryTag::U0); - - points_inf_vec.insert(points_inf_vec.end(), - { point_inf1_read.val, point_inf2_read.val, point_inf3_read.val, point_inf4_read.val }); - bool tag_match = point_inf1_read.tag_match && point_inf2_read.tag_match && point_inf3_read.tag_match && - point_inf4_read.tag_match; + uint32_t inf_direct_address = resolved_points_offset.offset + 2; + // Read the Infinities flags + for (uint32_t i = 0; i < num_points; i++) { + auto point_inf_read = mem_trace_builder.read_and_load_from_memory( + call_ptr, clk, IntermRegister::IA, inf_direct_address, AvmMemoryTag::U8, AvmMemoryTag::U0); + points_inf_vec.emplace_back(point_inf_read.val); + main_trace.push_back(Row{ .main_clk = clk, - .main_ia = point_inf1_read.val, - .main_ib = point_inf2_read.val, - .main_ic = point_inf3_read.val, - .main_id = point_inf4_read.val, + .main_ia = point_inf_read.val, .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_points_offset + i * 3 + 2), - .main_mem_addr_b = FF(direct_points_offset + (i + 1) * 3 + 2), - .main_mem_addr_c = FF(direct_points_offset + (i + 2) * 3 + 2), - .main_mem_addr_d = FF(direct_points_offset + (i + 3) * 3 + 2), + .main_mem_addr_a = FF(inf_direct_address), .main_pc = FF(pc), .main_r_in_tag = FF(static_cast(AvmMemoryTag::U8)), .main_sel_mem_op_a = FF(1), - .main_sel_mem_op_b = FF(1), - .main_sel_mem_op_c = FF(1), - .main_sel_mem_op_d = FF(1), - .main_tag_err = FF(static_cast(!tag_match)), + .main_tag_err = FF(static_cast(!point_inf_read.tag_match)), }); clk++; + // Update the inf offset to read the next point (subsequent points are always direct and separated by 3 + inf_direct_address += 3; } // Scalar read length is num_points* 2 since scalars are stored as lo and hi limbs uint32_t scalar_read_length = num_points * 2; + // Scalars are easy to read since they are stored as [lo1, hi1, lo2, hi2, ...] with the types [FF, FF, FF,FF, ...] auto num_scalar_rows = read_slice_to_memory(call_ptr, clk, - direct_scalars_offset, + resolved_scalars_offset, AvmMemoryTag::FF, AvmMemoryTag::U0, FF(internal_return_ptr), @@ -3838,29 +3501,25 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, // Perform the variable MSM - could just put the logic in here since there are no constraints. auto result = ecc_trace_builder.variable_msm(points, scalars, clk); // Write the result back to memory [x, y, inf] with tags [FF, FF, U8] - if (indirect_output_flag) { - auto read_ind_a = - mem_trace_builder.indirect_read_and_load_from_memory(call_ptr, clk, IndirectRegister::IND_A, output_offset); - direct_output_offset = uint32_t(read_ind_a.val); - } - mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IA, direct_output_offset, result.x, AvmMemoryTag::U0, AvmMemoryTag::FF); + auto write_x = constrained_write_to_memory( + call_ptr, clk, resolved_output_offset, result.x, AvmMemoryTag::U0, AvmMemoryTag::FF, IntermRegister::IA); mem_trace_builder.write_into_memory( - call_ptr, clk, IntermRegister::IB, direct_output_offset + 1, result.y, AvmMemoryTag::U0, AvmMemoryTag::FF); + call_ptr, clk, IntermRegister::IB, write_x.direct_address + 1, result.y, AvmMemoryTag::U0, AvmMemoryTag::FF); + main_trace.push_back(Row{ .main_clk = clk, .main_ia = result.x, .main_ib = result.y, - .main_ind_addr_a = indirect_output_flag ? FF(output_offset) : FF(0), + .main_ind_addr_a = FF(write_x.indirect_address), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_output_offset), - .main_mem_addr_b = FF(direct_output_offset + 1), + .main_mem_addr_a = FF(write_x.direct_address), + .main_mem_addr_b = FF(write_x.direct_address + 1), .main_pc = FF(pc), .main_rwa = FF(1), .main_rwb = FF(1), .main_sel_mem_op_a = FF(1), .main_sel_mem_op_b = FF(1), - .main_sel_resolve_ind_addr_a = FF(static_cast(indirect_output_flag)), + .main_sel_resolve_ind_addr_a = FF(static_cast(write_x.is_indirect)), .main_w_in_tag = FF(static_cast(AvmMemoryTag::FF)), }); clk++; @@ -3868,7 +3527,7 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, mem_trace_builder.write_into_memory(call_ptr, clk, IntermRegister::IA, - direct_output_offset + 2, + write_x.direct_address + 2, result.is_point_at_infinity(), AvmMemoryTag::U0, AvmMemoryTag::U8); @@ -3876,12 +3535,14 @@ void AvmTraceBuilder::op_variable_msm(uint8_t indirect, .main_clk = clk, .main_ia = static_cast(result.is_point_at_infinity()), .main_internal_return_ptr = FF(internal_return_ptr), - .main_mem_addr_a = FF(direct_output_offset + 2), + .main_mem_addr_a = FF(write_x.direct_address + 2), .main_pc = FF(pc), .main_rwa = FF(1), .main_sel_mem_op_a = FF(1), .main_w_in_tag = FF(static_cast(AvmMemoryTag::U8)), }); + + pc++; } // Finalise Lookup Counts // @@ -4036,6 +3697,7 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c auto pedersen_trace = pedersen_trace_builder.finalize(); auto bin_trace = bin_trace_builder.finalize(); auto gas_trace = gas_trace_builder.finalize(); + const auto& fixed_gas_table = FixedGasTable::get(); size_t mem_trace_size = mem_trace.size(); size_t main_trace_size = main_trace.size(); size_t alu_trace_size = alu_trace.size(); @@ -4057,11 +3719,11 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c // 2**16 long) size_t const lookup_table_size = (bin_trace_size > 0 && range_check_required) ? 3 * (1 << 16) : 0; size_t const range_check_size = range_check_required ? UINT16_MAX + 1 : 0; - std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, - range_check_size, conv_trace_size, lookup_table_size, - sha256_trace_size, poseidon2_trace_size, pedersen_trace_size, - gas_trace_size + 1, KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, - min_trace_size, GAS_COST_TABLE.size() }; + std::vector trace_sizes = { mem_trace_size, main_trace_size, alu_trace_size, + range_check_size, conv_trace_size, lookup_table_size, + sha256_trace_size, poseidon2_trace_size, pedersen_trace_size, + gas_trace_size + 1, KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, + min_trace_size, fixed_gas_table.size() }; auto trace_size = std::max_element(trace_sizes.begin(), trace_sizes.end()); // We only need to pad with zeroes to the size to the largest trace here, pow_2 padding is handled in the @@ -4569,13 +4231,16 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c r.incl_main_tag_err_counts = mem_trace_builder.m_tag_err_lookup_counts[static_cast(counter)]; if (counter <= UINT8_MAX) { - r.lookup_u8_0_counts = alu_trace_builder.u8_range_chk_counters[0][static_cast(counter)]; - r.lookup_u8_1_counts = alu_trace_builder.u8_range_chk_counters[1][static_cast(counter)]; - r.lookup_pow_2_0_counts = alu_trace_builder.u8_pow_2_counters[0][static_cast(counter)]; - r.lookup_pow_2_1_counts = alu_trace_builder.u8_pow_2_counters[1][static_cast(counter)]; - r.lookup_mem_rng_chk_hi_counts = mem_rng_check_hi_counts[static_cast(counter)]; + auto counter_u8 = static_cast(counter); + r.lookup_u8_0_counts = alu_trace_builder.u8_range_chk_counters[0][counter_u8]; + r.lookup_u8_1_counts = alu_trace_builder.u8_range_chk_counters[1][counter_u8]; + r.lookup_pow_2_0_counts = alu_trace_builder.u8_pow_2_counters[0][counter_u8]; + r.lookup_pow_2_1_counts = alu_trace_builder.u8_pow_2_counters[1][counter_u8]; + r.lookup_mem_rng_chk_hi_counts = mem_rng_check_hi_counts[counter_u8]; r.main_sel_rng_8 = FF(1); - r.main_table_pow_2 = uint256_t(1) << uint256_t(counter); + + // Also merge the powers of 2 table. + merge_into(r, FixedPowersTable::get().at(counter)); } if (counter <= UINT16_MAX) { @@ -4624,12 +4289,12 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } // Write the kernel trace into the main trace - // 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values until - // we + // 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values + // until we // hit an operation that changes one of the write_offsets (a relevant opcode) // 2. Upon hitting the clk of each kernel operation we copy the values into the main trace - // 3. When an increment is required, we increment the value in the next row, then continue the process until the - // end + // 3. When an increment is required, we increment the value in the next row, then continue the process until + // the end // 4. Whenever we hit the last row, we zero all write_offsets such that the shift relation will succeed std::vector kernel_trace = kernel_trace_builder.finalize(); size_t kernel_padding_main_trace_bottom = 1; @@ -4645,9 +4310,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c // Check the clock and iterate through the main trace until we hit the clock auto clk = src.clk; - // Until the next kernel changing instruction is encountered we set all of the values of the offset arrays - // to be the same as the previous row This satisfies the `offset' - (offset + operation_selector) = 0` - // constraints + // Until the next kernel changing instruction is encountered we set all of the values of the offset + // arrays to be the same as the previous row This satisfies the `offset' - (offset + operation_selector) + // = 0` constraints for (size_t j = kernel_padding_main_trace_bottom; j < clk; j++) { auto const& prev = main_trace.at(j); auto& dest = main_trace.at(j + 1); @@ -4722,7 +4387,8 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c Row const& prev = main_trace.at(i - 1); Row& dest = main_trace.at(i); - // Setting all of the counters to 0 after the IS_LAST check so we can satisfy the constraints until the end + // Setting all of the counters to 0 after the IS_LAST check so we can satisfy the constraints until the + // end if (i == old_trace_size) { dest.kernel_note_hash_exist_write_offset = 0; dest.kernel_emit_note_hash_write_offset = 0; @@ -4797,12 +4463,8 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c // Add the gas costs table to the main trace // For each opcode we write its l2 gas cost and da gas cost - for (auto const& [opcode, gas_entry] : GAS_COST_TABLE) { - auto& dest = main_trace.at(static_cast(opcode)); - - dest.gas_sel_gas_cost = FF(1); - dest.gas_l2_gas_fixed_table = gas_entry.l2_fixed_gas_cost; - dest.gas_da_gas_fixed_table = gas_entry.da_fixed_gas_cost; + for (size_t i = 0; i < fixed_gas_table.size(); i++) { + merge_into(main_trace.at(i), fixed_gas_table.at(i)); } // Finalise gas left lookup counts diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index b0d86f4c5da1..3a6e13dbc06b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -21,6 +21,14 @@ namespace bb::avm_trace { using Row = bb::AvmFullRow; +enum class AddressingMode { + DIRECT, + INDIRECT, +}; +struct AddressWithMode { + AddressingMode mode; + uint32_t offset; +}; // This is the internal context that we keep along the lifecycle of bytecode execution // to iteratively build the whole trace. This is effectively performing witness generation. @@ -210,19 +218,16 @@ class AvmTraceBuilder { uint32_t output_offset, uint32_t point_length_offset); - private: - // Used for the standard indirect address resolution of three operands opcode. - struct IndirectThreeResolution { - bool tag_match = false; - uint32_t direct_a_offset; - uint32_t direct_b_offset; - uint32_t direct_c_offset; - - bool indirect_flag_a = false; - bool indirect_flag_b = false; - bool indirect_flag_c = false; + struct MemOp { + bool is_indirect; + uint32_t indirect_address; + uint32_t direct_address; + AvmMemoryTag tag; + bool tag_match; + FF val; }; + private: std::vector main_trace; AvmMemTraceBuilder mem_trace_builder; AvmAluTraceBuilder alu_trace_builder; @@ -249,7 +254,7 @@ class AvmTraceBuilder { * @return Row */ Row create_kernel_lookup_opcode( - bool indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); + uint8_t indirect, uint32_t dst_offset, uint32_t selector, FF value, AvmMemoryTag w_tag); /** * @brief Create a kernel output opcode object @@ -321,9 +326,6 @@ class AvmTraceBuilder { void finalise_mem_trace_lookup_counts(); - IndirectThreeResolution resolve_ind_three( - uint8_t space_id, uint32_t clk, uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t c_offset); - uint32_t pc = 0; uint32_t internal_return_ptr = 0; // After a nested call, it should be initialized with MAX_SIZE_INTERNAL_STACK * call_ptr @@ -339,23 +341,37 @@ class AvmTraceBuilder { // Mapping of side effect counter -> value ExecutionHints execution_hints; + MemOp constrained_read_from_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + AvmMemoryTag read_tag, + AvmMemoryTag write_tag, + IntermRegister reg); + MemOp constrained_write_to_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + FF const& value, + AvmMemoryTag read_tag, + AvmMemoryTag write_tag, + IntermRegister reg); + // TODO(ilyas: #6383): Temporary way to bulk read slices template uint32_t read_slice_to_memory(uint8_t space_id, uint32_t clk, - uint32_t src_offset, + AddressWithMode addr, AvmMemoryTag r_tag, AvmMemoryTag w_tag, FF internal_return_ptr, size_t slice_len, std::vector& slice); - void write_slice_to_memory(uint8_t space_id, - uint32_t clk, - uint32_t dst_offset, - AvmMemoryTag r_tag, - AvmMemoryTag w_tag, - FF internal_return_ptr, - std::vector const& slice); + uint32_t write_slice_to_memory(uint8_t space_id, + uint32_t clk, + AddressWithMode addr, + AvmMemoryTag r_tag, + AvmMemoryTag w_tag, + FF internal_return_ptr, + std::vector const& slice); }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.cpp new file mode 100644 index 000000000000..d27331a48118 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.cpp @@ -0,0 +1,23 @@ +#include "barretenberg/vm/avm_trace/fixed_gas.hpp" + +namespace bb::avm_trace { + +FixedGasTable::FixedGasTable() +{ + for (int i = 0; i < static_cast(OpCode::LAST_OPCODE_SENTINEL); i++) { + table_rows.push_back(GasRow{ + .gas_da_gas_fixed_table = FF(2), + .gas_l2_gas_fixed_table = FF(10), + .gas_sel_gas_cost = FF(1), + }); + } +} + +// Singleton. +const FixedGasTable& FixedGasTable::get() +{ + static FixedGasTable table; + return table; +} + +} // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.hpp new file mode 100644 index 000000000000..15e7687c385e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_gas.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/relations/generated/avm/gas.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" +#include "barretenberg/vm/avm_trace/avm_opcode.hpp" + +namespace bb::avm_trace { + +class FixedGasTable { + public: + using GasRow = bb::Avm_vm::GasRow; + + static const FixedGasTable& get(); + + size_t size() const { return table_rows.size(); } + const GasRow& at(size_t i) const { return table_rows.at(i); } + const GasRow& at(OpCode o) const { return at(static_cast(o)); } + + private: + FixedGasTable(); + + std::vector table_rows; +}; + +template void merge_into(DestRow& dest, FixedGasTable::GasRow const& src) +{ + dest.gas_sel_gas_cost = src.gas_sel_gas_cost; + dest.gas_l2_gas_fixed_table = src.gas_l2_gas_fixed_table; + dest.gas_da_gas_fixed_table = src.gas_da_gas_fixed_table; +} + +} // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.cpp new file mode 100644 index 000000000000..6ef8b8b4248e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.cpp @@ -0,0 +1,25 @@ +#include "barretenberg/vm/avm_trace/fixed_powers.hpp" + +#include + +#include "barretenberg/numeric/uint256/uint256.hpp" + +namespace bb::avm_trace { + +FixedPowersTable::FixedPowersTable() +{ + for (uint64_t i = 0; i < 256; i++) { + table_rows.push_back(PowersRow{ + .powers_power_of_2 = FF(uint256_t(1) << uint256_t(i)), + }); + } +} + +// Singleton. +const FixedPowersTable& FixedPowersTable::get() +{ + static FixedPowersTable table; + return table; +} + +} // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.hpp new file mode 100644 index 000000000000..d19a1d81ecc1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/fixed_powers.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/relations/generated/avm/powers.hpp" +#include "barretenberg/vm/avm_trace/avm_common.hpp" + +namespace bb::avm_trace { + +class FixedPowersTable { + public: + using PowersRow = bb::Avm_vm::PowersRow; + + static const FixedPowersTable& get(); + + size_t size() const { return table_rows.size(); } + const PowersRow& at(size_t i) const { return table_rows.at(i); } + + private: + FixedPowersTable(); + + std::vector table_rows; +}; + +template void merge_into(DestRow& dest, FixedPowersTable::PowersRow const& src) +{ + dest.powers_power_of_2 = src.powers_power_of_2; +} + +} // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp index 7d58df8071ae..448bf350a0e9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -261,7 +261,6 @@ template std::vector AvmFullRow::names() "main_sel_rng_16", "main_sel_rng_8", "main_space_id", - "main_table_pow_2", "main_tag_err", "main_w_in_tag", "mem_addr", @@ -303,6 +302,7 @@ template std::vector AvmFullRow::names() "poseidon2_input", "poseidon2_output", "poseidon2_sel_poseidon_perm", + "powers_power_of_2", "sha256_clk", "sha256_input", "sha256_output", @@ -541,38 +541,38 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << field_to_string(row.main_sel_resolve_ind_addr_c) << "," << field_to_string(row.main_sel_resolve_ind_addr_d) << "," << field_to_string(row.main_sel_rng_16) << "," << field_to_string(row.main_sel_rng_8) << "," << field_to_string(row.main_space_id) << "," - << field_to_string(row.main_table_pow_2) << "," << field_to_string(row.main_tag_err) << "," - << field_to_string(row.main_w_in_tag) << "," << field_to_string(row.mem_addr) << "," - << field_to_string(row.mem_clk) << "," << field_to_string(row.mem_diff_hi) << "," - << field_to_string(row.mem_diff_lo) << "," << field_to_string(row.mem_diff_mid) << "," - << field_to_string(row.mem_glob_addr) << "," << field_to_string(row.mem_last) << "," - << field_to_string(row.mem_lastAccess) << "," << field_to_string(row.mem_one_min_inv) << "," - << field_to_string(row.mem_r_in_tag) << "," << field_to_string(row.mem_rw) << "," - << field_to_string(row.mem_sel_mem) << "," << field_to_string(row.mem_sel_mov_ia_to_ic) << "," - << field_to_string(row.mem_sel_mov_ib_to_ic) << "," << field_to_string(row.mem_sel_op_a) << "," - << field_to_string(row.mem_sel_op_b) << "," << field_to_string(row.mem_sel_op_c) << "," - << field_to_string(row.mem_sel_op_cmov) << "," << field_to_string(row.mem_sel_op_d) << "," - << field_to_string(row.mem_sel_resolve_ind_addr_a) << "," << field_to_string(row.mem_sel_resolve_ind_addr_b) - << "," << field_to_string(row.mem_sel_resolve_ind_addr_c) << "," - << field_to_string(row.mem_sel_resolve_ind_addr_d) << "," << field_to_string(row.mem_sel_rng_chk) << "," - << field_to_string(row.mem_skip_check_tag) << "," << field_to_string(row.mem_space_id) << "," + << field_to_string(row.main_tag_err) << "," << field_to_string(row.main_w_in_tag) << "," + << field_to_string(row.mem_addr) << "," << field_to_string(row.mem_clk) << "," + << field_to_string(row.mem_diff_hi) << "," << field_to_string(row.mem_diff_lo) << "," + << field_to_string(row.mem_diff_mid) << "," << field_to_string(row.mem_glob_addr) << "," + << field_to_string(row.mem_last) << "," << field_to_string(row.mem_lastAccess) << "," + << field_to_string(row.mem_one_min_inv) << "," << field_to_string(row.mem_r_in_tag) << "," + << field_to_string(row.mem_rw) << "," << field_to_string(row.mem_sel_mem) << "," + << field_to_string(row.mem_sel_mov_ia_to_ic) << "," << field_to_string(row.mem_sel_mov_ib_to_ic) << "," + << field_to_string(row.mem_sel_op_a) << "," << field_to_string(row.mem_sel_op_b) << "," + << field_to_string(row.mem_sel_op_c) << "," << field_to_string(row.mem_sel_op_cmov) << "," + << field_to_string(row.mem_sel_op_d) << "," << field_to_string(row.mem_sel_resolve_ind_addr_a) << "," + << field_to_string(row.mem_sel_resolve_ind_addr_b) << "," << field_to_string(row.mem_sel_resolve_ind_addr_c) + << "," << field_to_string(row.mem_sel_resolve_ind_addr_d) << "," << field_to_string(row.mem_sel_rng_chk) + << "," << field_to_string(row.mem_skip_check_tag) << "," << field_to_string(row.mem_space_id) << "," << field_to_string(row.mem_tag) << "," << field_to_string(row.mem_tag_err) << "," << field_to_string(row.mem_tsp) << "," << field_to_string(row.mem_val) << "," << field_to_string(row.mem_w_in_tag) << "," << field_to_string(row.pedersen_clk) << "," << field_to_string(row.pedersen_input) << "," << field_to_string(row.pedersen_output) << "," << field_to_string(row.pedersen_sel_pedersen) << "," << field_to_string(row.poseidon2_clk) << "," << field_to_string(row.poseidon2_input) << "," << field_to_string(row.poseidon2_output) << "," - << field_to_string(row.poseidon2_sel_poseidon_perm) << "," << field_to_string(row.sha256_clk) << "," - << field_to_string(row.sha256_input) << "," << field_to_string(row.sha256_output) << "," - << field_to_string(row.sha256_sel_sha256_compression) << "," << field_to_string(row.sha256_state) << "," - << field_to_string(row.perm_main_alu) << "," << field_to_string(row.perm_main_bin) << "," - << field_to_string(row.perm_main_conv) << "," << field_to_string(row.perm_main_pos2_perm) << "," - << field_to_string(row.perm_main_pedersen) << "," << field_to_string(row.perm_main_mem_a) << "," - << field_to_string(row.perm_main_mem_b) << "," << field_to_string(row.perm_main_mem_c) << "," - << field_to_string(row.perm_main_mem_d) << "," << field_to_string(row.perm_main_mem_ind_addr_a) << "," - << field_to_string(row.perm_main_mem_ind_addr_b) << "," << field_to_string(row.perm_main_mem_ind_addr_c) - << "," << field_to_string(row.perm_main_mem_ind_addr_d) << "," << field_to_string(row.lookup_byte_lengths) - << "," << field_to_string(row.lookup_byte_operations) << "," << field_to_string(row.lookup_opcode_gas) << "," + << field_to_string(row.poseidon2_sel_poseidon_perm) << "," << field_to_string(row.powers_power_of_2) << "," + << field_to_string(row.sha256_clk) << "," << field_to_string(row.sha256_input) << "," + << field_to_string(row.sha256_output) << "," << field_to_string(row.sha256_sel_sha256_compression) << "," + << field_to_string(row.sha256_state) << "," << field_to_string(row.perm_main_alu) << "," + << field_to_string(row.perm_main_bin) << "," << field_to_string(row.perm_main_conv) << "," + << field_to_string(row.perm_main_pos2_perm) << "," << field_to_string(row.perm_main_pedersen) << "," + << field_to_string(row.perm_main_mem_a) << "," << field_to_string(row.perm_main_mem_b) << "," + << field_to_string(row.perm_main_mem_c) << "," << field_to_string(row.perm_main_mem_d) << "," + << field_to_string(row.perm_main_mem_ind_addr_a) << "," << field_to_string(row.perm_main_mem_ind_addr_b) + << "," << field_to_string(row.perm_main_mem_ind_addr_c) << "," + << field_to_string(row.perm_main_mem_ind_addr_d) << "," << field_to_string(row.lookup_byte_lengths) << "," + << field_to_string(row.lookup_byte_operations) << "," << field_to_string(row.lookup_opcode_gas) << "," << field_to_string(row.range_check_l2_gas_hi) << "," << field_to_string(row.range_check_l2_gas_lo) << "," << field_to_string(row.range_check_da_gas_hi) << "," << field_to_string(row.range_check_da_gas_lo) << "," << field_to_string(row.kernel_output_lookup) << "," << field_to_string(row.lookup_into_kernel) << "," diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index b8f8a1079010..9bbe9334c855 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -19,6 +19,7 @@ #include "barretenberg/relations/generated/avm/alu.hpp" #include "barretenberg/relations/generated/avm/binary.hpp" #include "barretenberg/relations/generated/avm/conversion.hpp" +#include "barretenberg/relations/generated/avm/gas.hpp" #include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" #include "barretenberg/relations/generated/avm/incl_mem_tag_err.hpp" #include "barretenberg/relations/generated/avm/keccakf1600.hpp" @@ -75,6 +76,7 @@ #include "barretenberg/relations/generated/avm/perm_main_pedersen.hpp" #include "barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp" #include "barretenberg/relations/generated/avm/poseidon2.hpp" +#include "barretenberg/relations/generated/avm/powers.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp" #include "barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp" @@ -328,7 +330,6 @@ template struct AvmFullRow { FF main_sel_rng_16{}; FF main_sel_rng_8{}; FF main_space_id{}; - FF main_table_pow_2{}; FF main_tag_err{}; FF main_w_in_tag{}; FF mem_addr{}; @@ -370,6 +371,7 @@ template struct AvmFullRow { FF poseidon2_input{}; FF poseidon2_output{}; FF poseidon2_sel_poseidon_perm{}; + FF powers_power_of_2{}; FF sha256_clk{}; FF sha256_input{}; FF sha256_output{}; @@ -812,7 +814,6 @@ class AvmCircuitBuilder { polys.main_sel_rng_16[i] = rows[i].main_sel_rng_16; polys.main_sel_rng_8[i] = rows[i].main_sel_rng_8; polys.main_space_id[i] = rows[i].main_space_id; - polys.main_table_pow_2[i] = rows[i].main_table_pow_2; polys.main_tag_err[i] = rows[i].main_tag_err; polys.main_w_in_tag[i] = rows[i].main_w_in_tag; polys.mem_addr[i] = rows[i].mem_addr; @@ -854,6 +855,7 @@ class AvmCircuitBuilder { polys.poseidon2_input[i] = rows[i].poseidon2_input; polys.poseidon2_output[i] = rows[i].poseidon2_output; polys.poseidon2_sel_poseidon_perm[i] = rows[i].poseidon2_sel_poseidon_perm; + polys.powers_power_of_2[i] = rows[i].powers_power_of_2; polys.sha256_clk[i] = rows[i].sha256_clk; polys.sha256_input[i] = rows[i].sha256_input; polys.sha256_output[i] = rows[i].sha256_output; @@ -1058,6 +1060,10 @@ class AvmCircuitBuilder { Avm_vm::get_relation_label_conversion); }; + auto gas = [=]() { + return evaluate_relation.template operator()>("gas", Avm_vm::get_relation_label_gas); + }; + auto keccakf1600 = [=]() { return evaluate_relation.template operator()>( "keccakf1600", Avm_vm::get_relation_label_keccakf1600); @@ -1086,6 +1092,11 @@ class AvmCircuitBuilder { Avm_vm::get_relation_label_poseidon2); }; + auto powers = [=]() { + return evaluate_relation.template operator()>("powers", + Avm_vm::get_relation_label_powers); + }; + auto sha256 = [=]() { return evaluate_relation.template operator()>("sha256", Avm_vm::get_relation_label_sha256); @@ -1331,6 +1342,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, conversion)); + relation_futures.emplace_back(std::async(std::launch::async, gas)); + relation_futures.emplace_back(std::async(std::launch::async, keccakf1600)); relation_futures.emplace_back(std::async(std::launch::async, kernel)); @@ -1343,6 +1356,8 @@ class AvmCircuitBuilder { relation_futures.emplace_back(std::async(std::launch::async, poseidon2)); + relation_futures.emplace_back(std::async(std::launch::async, powers)); + relation_futures.emplace_back(std::async(std::launch::async, sha256)); relation_futures.emplace_back(std::async(std::launch::async, perm_main_alu)); @@ -1468,6 +1483,8 @@ class AvmCircuitBuilder { conversion(); + gas(); + keccakf1600(); kernel(); @@ -1480,6 +1497,8 @@ class AvmCircuitBuilder { poseidon2(); + powers(); + sha256(); perm_main_alu(); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index 283812ece0f1..e5729066c00e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -16,6 +16,7 @@ #include "barretenberg/relations/generated/avm/alu.hpp" #include "barretenberg/relations/generated/avm/binary.hpp" #include "barretenberg/relations/generated/avm/conversion.hpp" +#include "barretenberg/relations/generated/avm/gas.hpp" #include "barretenberg/relations/generated/avm/incl_main_tag_err.hpp" #include "barretenberg/relations/generated/avm/incl_mem_tag_err.hpp" #include "barretenberg/relations/generated/avm/keccakf1600.hpp" @@ -72,6 +73,7 @@ #include "barretenberg/relations/generated/avm/perm_main_pedersen.hpp" #include "barretenberg/relations/generated/avm/perm_main_pos2_perm.hpp" #include "barretenberg/relations/generated/avm/poseidon2.hpp" +#include "barretenberg/relations/generated/avm/powers.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_hi.hpp" #include "barretenberg/relations/generated/avm/range_check_da_gas_lo.hpp" #include "barretenberg/relations/generated/avm/range_check_l2_gas_hi.hpp" @@ -162,12 +164,14 @@ class AvmFlavor { using Relations = std::tuple, Avm_vm::binary, Avm_vm::conversion, + Avm_vm::gas, Avm_vm::keccakf1600, Avm_vm::kernel, Avm_vm::main, Avm_vm::mem, Avm_vm::pedersen, Avm_vm::poseidon2, + Avm_vm::powers, Avm_vm::sha256, perm_main_alu_relation, perm_main_bin_relation, @@ -497,7 +501,6 @@ class AvmFlavor { main_sel_rng_16, main_sel_rng_8, main_space_id, - main_table_pow_2, main_tag_err, main_w_in_tag, mem_addr, @@ -539,6 +542,7 @@ class AvmFlavor { poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, + powers_power_of_2, sha256_clk, sha256_input, sha256_output, @@ -883,7 +887,6 @@ class AvmFlavor { main_sel_rng_16, main_sel_rng_8, main_space_id, - main_table_pow_2, main_tag_err, main_w_in_tag, mem_addr, @@ -925,6 +928,7 @@ class AvmFlavor { poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, + powers_power_of_2, sha256_clk, sha256_input, sha256_output, @@ -1274,7 +1278,6 @@ class AvmFlavor { main_sel_rng_16, main_sel_rng_8, main_space_id, - main_table_pow_2, main_tag_err, main_w_in_tag, mem_addr, @@ -1316,6 +1319,7 @@ class AvmFlavor { poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, + powers_power_of_2, sha256_clk, sha256_input, sha256_output, @@ -1727,7 +1731,6 @@ class AvmFlavor { main_sel_rng_16, main_sel_rng_8, main_space_id, - main_table_pow_2, main_tag_err, main_w_in_tag, mem_addr, @@ -1769,6 +1772,7 @@ class AvmFlavor { poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, + powers_power_of_2, sha256_clk, sha256_input, sha256_output, @@ -2180,7 +2184,6 @@ class AvmFlavor { main_sel_rng_16, main_sel_rng_8, main_space_id, - main_table_pow_2, main_tag_err, main_w_in_tag, mem_addr, @@ -2222,6 +2225,7 @@ class AvmFlavor { poseidon2_input, poseidon2_output, poseidon2_sel_poseidon_perm, + powers_power_of_2, sha256_clk, sha256_input, sha256_output, @@ -2989,7 +2993,6 @@ class AvmFlavor { Base::main_sel_rng_16 = "MAIN_SEL_RNG_16"; Base::main_sel_rng_8 = "MAIN_SEL_RNG_8"; Base::main_space_id = "MAIN_SPACE_ID"; - Base::main_table_pow_2 = "MAIN_TABLE_POW_2"; Base::main_tag_err = "MAIN_TAG_ERR"; Base::main_w_in_tag = "MAIN_W_IN_TAG"; Base::mem_addr = "MEM_ADDR"; @@ -3031,6 +3034,7 @@ class AvmFlavor { Base::poseidon2_input = "POSEIDON2_INPUT"; Base::poseidon2_output = "POSEIDON2_OUTPUT"; Base::poseidon2_sel_poseidon_perm = "POSEIDON2_SEL_POSEIDON_PERM"; + Base::powers_power_of_2 = "POWERS_POWER_OF_2"; Base::sha256_clk = "SHA256_CLK"; Base::sha256_input = "SHA256_INPUT"; Base::sha256_output = "SHA256_OUTPUT"; @@ -3391,7 +3395,6 @@ class AvmFlavor { Commitment main_sel_rng_16; Commitment main_sel_rng_8; Commitment main_space_id; - Commitment main_table_pow_2; Commitment main_tag_err; Commitment main_w_in_tag; Commitment mem_addr; @@ -3433,6 +3436,7 @@ class AvmFlavor { Commitment poseidon2_input; Commitment poseidon2_output; Commitment poseidon2_sel_poseidon_perm; + Commitment powers_power_of_2; Commitment sha256_clk; Commitment sha256_input; Commitment sha256_output; @@ -3805,7 +3809,6 @@ class AvmFlavor { main_sel_rng_16 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_rng_8 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_space_id = deserialize_from_buffer(Transcript::proof_data, num_frs_read); - main_table_pow_2 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_tag_err = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_w_in_tag = deserialize_from_buffer(Transcript::proof_data, num_frs_read); mem_addr = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3847,6 +3850,7 @@ class AvmFlavor { poseidon2_input = deserialize_from_buffer(Transcript::proof_data, num_frs_read); poseidon2_output = deserialize_from_buffer(Transcript::proof_data, num_frs_read); poseidon2_sel_poseidon_perm = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + powers_power_of_2 = deserialize_from_buffer(Transcript::proof_data, num_frs_read); sha256_clk = deserialize_from_buffer(Transcript::proof_data, num_frs_read); sha256_input = deserialize_from_buffer(Transcript::proof_data, num_frs_read); sha256_output = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -4211,7 +4215,6 @@ class AvmFlavor { serialize_to_buffer(main_sel_rng_16, Transcript::proof_data); serialize_to_buffer(main_sel_rng_8, Transcript::proof_data); serialize_to_buffer(main_space_id, Transcript::proof_data); - serialize_to_buffer(main_table_pow_2, Transcript::proof_data); serialize_to_buffer(main_tag_err, Transcript::proof_data); serialize_to_buffer(main_w_in_tag, Transcript::proof_data); serialize_to_buffer(mem_addr, Transcript::proof_data); @@ -4253,6 +4256,7 @@ class AvmFlavor { serialize_to_buffer(poseidon2_input, Transcript::proof_data); serialize_to_buffer(poseidon2_output, Transcript::proof_data); serialize_to_buffer(poseidon2_sel_poseidon_perm, Transcript::proof_data); + serialize_to_buffer(powers_power_of_2, Transcript::proof_data); serialize_to_buffer(sha256_clk, Transcript::proof_data); serialize_to_buffer(sha256_input, Transcript::proof_data); serialize_to_buffer(sha256_output, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index c6a7622629b5..a10bc668d027 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -7,7 +7,6 @@ #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/relations/lookup_relation.hpp" #include "barretenberg/relations/permutation_relation.hpp" #include "barretenberg/sumcheck/sumcheck.hpp" @@ -312,7 +311,6 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.main_sel_rng_16 = commitment_key->commit(key->main_sel_rng_16); witness_commitments.main_sel_rng_8 = commitment_key->commit(key->main_sel_rng_8); witness_commitments.main_space_id = commitment_key->commit(key->main_space_id); - witness_commitments.main_table_pow_2 = commitment_key->commit(key->main_table_pow_2); witness_commitments.main_tag_err = commitment_key->commit(key->main_tag_err); witness_commitments.main_w_in_tag = commitment_key->commit(key->main_w_in_tag); witness_commitments.mem_addr = commitment_key->commit(key->mem_addr); @@ -354,6 +352,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.poseidon2_input = commitment_key->commit(key->poseidon2_input); witness_commitments.poseidon2_output = commitment_key->commit(key->poseidon2_output); witness_commitments.poseidon2_sel_poseidon_perm = commitment_key->commit(key->poseidon2_sel_poseidon_perm); + witness_commitments.powers_power_of_2 = commitment_key->commit(key->powers_power_of_2); witness_commitments.sha256_clk = commitment_key->commit(key->sha256_clk); witness_commitments.sha256_input = commitment_key->commit(key->sha256_input); witness_commitments.sha256_output = commitment_key->commit(key->sha256_output); @@ -694,7 +693,6 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.main_sel_rng_16, witness_commitments.main_sel_rng_16); transcript->send_to_verifier(commitment_labels.main_sel_rng_8, witness_commitments.main_sel_rng_8); transcript->send_to_verifier(commitment_labels.main_space_id, witness_commitments.main_space_id); - transcript->send_to_verifier(commitment_labels.main_table_pow_2, witness_commitments.main_table_pow_2); transcript->send_to_verifier(commitment_labels.main_tag_err, witness_commitments.main_tag_err); transcript->send_to_verifier(commitment_labels.main_w_in_tag, witness_commitments.main_w_in_tag); transcript->send_to_verifier(commitment_labels.mem_addr, witness_commitments.mem_addr); @@ -741,6 +739,7 @@ void AvmProver::execute_wire_commitments_round() transcript->send_to_verifier(commitment_labels.poseidon2_output, witness_commitments.poseidon2_output); transcript->send_to_verifier(commitment_labels.poseidon2_sel_poseidon_perm, witness_commitments.poseidon2_sel_poseidon_perm); + transcript->send_to_verifier(commitment_labels.powers_power_of_2, witness_commitments.powers_power_of_2); transcript->send_to_verifier(commitment_labels.sha256_clk, witness_commitments.sha256_clk); transcript->send_to_verifier(commitment_labels.sha256_input, witness_commitments.sha256_input); transcript->send_to_verifier(commitment_labels.sha256_output, witness_commitments.sha256_output); @@ -962,15 +961,16 @@ void AvmProver::execute_relation_check_rounds() * @details See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. * * */ -void AvmProver::execute_zeromorph_rounds() +void AvmProver::execute_pcs_rounds() { - ZeroMorph::prove(prover_polynomials.get_unshifted(), - prover_polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations.get_unshifted(), - sumcheck_output.claimed_evaluations.get_shifted(), - sumcheck_output.challenge, - commitment_key, - transcript); + auto prover_opening_claim = ZeroMorph::prove(prover_polynomials.get_unshifted(), + prover_polynomials.get_to_be_shifted(), + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), + sumcheck_output.challenge, + commitment_key, + transcript); + PCS::compute_opening_proof(commitment_key, prover_opening_claim, transcript); } HonkProof AvmProver::export_proof() @@ -996,7 +996,7 @@ HonkProof AvmProver::construct_proof() // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - execute_zeromorph_rounds(); + execute_pcs_rounds(); return export_proof(); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp index 74d504446a30..3f95563ac066 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp @@ -16,6 +16,8 @@ class AvmProver { using Flavor = AvmFlavor; using FF = Flavor::FF; using PCS = Flavor::PCS; + using Curve = Flavor::Curve; + using ZeroMorph = ZeroMorphProver_; using PCSCommitmentKey = Flavor::CommitmentKey; using ProvingKey = Flavor::ProvingKey; using Polynomial = Flavor::Polynomial; @@ -30,7 +32,7 @@ class AvmProver { void execute_wire_commitments_round(); void execute_log_derivative_inverse_round(); void execute_relation_check_rounds(); - void execute_zeromorph_rounds(); + void execute_pcs_rounds(); HonkProof export_proof(); HonkProof construct_proof(); @@ -55,8 +57,6 @@ class AvmProver { std::shared_ptr commitment_key; - using ZeroMorph = ZeroMorphProver_; - private: HonkProof proof; }; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 24a8b6c6f0b2..0a863144aadb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -52,7 +52,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector; + // using Curve = Flavor::Curve; + // using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = Flavor::VerifierCommitments; using CommitmentLabels = Flavor::CommitmentLabels; @@ -452,8 +453,6 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.main_sel_rng_16); commitments.main_sel_rng_8 = transcript->template receive_from_prover(commitment_labels.main_sel_rng_8); commitments.main_space_id = transcript->template receive_from_prover(commitment_labels.main_space_id); - commitments.main_table_pow_2 = - transcript->template receive_from_prover(commitment_labels.main_table_pow_2); commitments.main_tag_err = transcript->template receive_from_prover(commitment_labels.main_tag_err); commitments.main_w_in_tag = transcript->template receive_from_prover(commitment_labels.main_w_in_tag); commitments.mem_addr = transcript->template receive_from_prover(commitment_labels.mem_addr); @@ -510,6 +509,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.poseidon2_output); commitments.poseidon2_sel_poseidon_perm = transcript->template receive_from_prover(commitment_labels.poseidon2_sel_poseidon_perm); + commitments.powers_power_of_2 = + transcript->template receive_from_prover(commitment_labels.powers_power_of_2); commitments.sha256_clk = transcript->template receive_from_prover(commitment_labels.sha256_clk); commitments.sha256_input = transcript->template receive_from_prover(commitment_labels.sha256_input); commitments.sha256_output = transcript->template receive_from_prover(commitment_labels.sha256_output); @@ -739,13 +740,15 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectorget_g1_identity(), // transcript); + // auto pairing_points = PCS::reduce_verify(opening_claim, transcript); // auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); // return sumcheck_verified.value() && verified; return sumcheck_verified.value(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index 0db934ed1ed8..fa7c78ab02f4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -205,20 +205,15 @@ size_t common_validate_div(std::vector const& trace, class AvmArithmeticTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmArithmeticTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; // Generate a trace with an EQ opcode operation. std::vector gen_trace_eq(uint128_t const& a, @@ -1877,7 +1872,7 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) // Test that error flag cannot be raised for a non-relevant operation such as // the addition, subtraction, multiplication. -TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag) +TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) { trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); @@ -1894,35 +1889,37 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag) row->main_op_err = FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_ERROR_RELEVANT_OP"); +} - trace_builder = AvmTraceBuilder(public_inputs); - +TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) +{ trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] trace_builder.return_op(0, 0, 3); - trace = trace_builder.finalize(); + auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector - row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == FF(1); }); + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == FF(1); }); // Activate the operator error row->main_op_err = FF(1); EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), "SUBOP_ERROR_RELEVANT_OP"); +} - trace_builder = AvmTraceBuilder(public_inputs); - +TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) +{ trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] trace_builder.return_op(0, 0, 3); - trace = trace_builder.finalize(); + auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector - row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); + auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); // Activate the operator error row->main_op_err = FF(1); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index ff1c41686160..482d397cbcc1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -346,20 +346,15 @@ std::vector gen_mutated_trace_bit(std::vector trace, class AvmBitwiseTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmBitwiseTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; std::vector gen_mutated_trace_not(FF const& a, FF const& c_mutated, avm_trace::AvmMemoryTag tag) { diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 040a19376886..446215b1ec00 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -13,25 +13,22 @@ using namespace bb::avm_trace; using namespace testing; class AvmCastTests : public ::testing::Test { - protected: - VmPublicInputs public_inputs{}; + public: + AvmCastTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) + { + srs::init_crs_factory("../srs_db/ignition"); + } + + VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + std::vector trace; size_t main_addr; size_t alu_addr; size_t mem_addr_c; - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override - { - srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; - void gen_trace( uint128_t const& a, uint32_t src_address, uint32_t dst_address, AvmMemoryTag src_tag, AvmMemoryTag dst_tag) { diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp index 38b028306f7d..0f0f4ebac527 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp @@ -80,23 +80,20 @@ std::vector positive_op_lte_test_values = { std::vector mem_tag_arr{ { AvmMemoryTag::U8, AvmMemoryTag::U16, AvmMemoryTag::U32, AvmMemoryTag::U64, AvmMemoryTag::U128 } }; + class AvmCmpTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmCmpTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; }; + class AvmCmpTestsLT : public AvmCmpTests, public testing::WithParamInterface {}; class AvmCmpTestsLTE : public AvmCmpTests, public testing::WithParamInterface {}; diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index eb2b13781d1a..616bdd5f1267 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -38,20 +38,15 @@ void validate_internal_return(Row const& row, uint32_t current_pc, uint32_t retu class AvmControlFlowTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmControlFlowTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; }; /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 696d0641ba39..10f971f1f701 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -1,4 +1,9 @@ #include "barretenberg/vm/avm_trace/avm_execution.hpp" + +#include +#include +#include + #include "avm_common.test.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/utils.hpp" @@ -7,11 +12,10 @@ #include "barretenberg/vm/avm_trace/avm_kernel_trace.hpp" #include "barretenberg/vm/avm_trace/avm_opcode.hpp" #include "barretenberg/vm/avm_trace/aztec_constants.hpp" -#include -#include -#include +#include "barretenberg/vm/avm_trace/fixed_gas.hpp" namespace tests_avm { + using namespace bb; using namespace bb::avm_trace; using namespace testing; @@ -27,6 +31,8 @@ class AvmExecutionTests : public ::testing::Test { : public_inputs_vec(PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH){}; protected: + const FixedGasTable& GAS_COST_TABLE = FixedGasTable::get(); + // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. void SetUp() override { @@ -784,34 +790,12 @@ TEST_F(AvmExecutionTests, toRadixLeOpcode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); - - // TORADIXLE - EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::TORADIXLE), - Field(&Instruction::operands, - ElementsAre(VariantWith(3), - VariantWith(17), - VariantWith(21), - VariantWith(2), - VariantWith(256))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector returndata = std::vector(); auto trace = Execution::gen_trace(instructions, returndata, std::vector{ FF::modulus - FF(1) }, public_inputs_vec); // Find the first row enabling the TORADIXLE selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_radix_le == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 17); - EXPECT_EQ(row->main_ind_addr_b, 21); - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(17) -> 1 - EXPECT_EQ(row->main_mem_addr_b, 5); // Indirect(21) -> 5 - EXPECT_EQ(row->main_ia, FF(FF::modulus - FF(1))); // Indirect(17) -> Direct(1) -> FF::modulus - FF(1) - EXPECT_EQ(row->main_ib, 0); // Indirect(21) -> 5 -> Unintialized memory - EXPECT_EQ(row->main_ic, 2); - EXPECT_EQ(row->main_id, 256); - // Expected output is bitwise decomposition of MODULUS - 1..could hardcode the result but it's a bit long std::vector expected_output; // Extract each bit. @@ -877,18 +861,6 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - // 8 SET for state + 16 SET for input + 3 SET for setting up indirects + 1 SHA256COMPRESSION + 1 RETURN - ASSERT_THAT(instructions, SizeIs(29)); - - // SHA256COMPRESSION - EXPECT_THAT(instructions.at(27), - AllOf(Field(&Instruction::op_code, OpCode::SHA256COMPRESSION), - Field(&Instruction::operands, - ElementsAre(VariantWith(7), - VariantWith(36), - VariantWith(34), - VariantWith(35))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector calldata = std::vector(); std::vector returndata = std::vector(); @@ -897,21 +869,8 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) // 4091010797,3974542186]), std::vector expected_output = { 1862536192, 526086805, 2067405084, 593147560, 726610467, 813867028, 4091010797ULL, 3974542186ULL }; - auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the Sha256Compression selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sha256 == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 34); - EXPECT_EQ(row->main_ind_addr_b, 35); - EXPECT_EQ(row->main_ind_addr_c, 36); - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(34) -> 9 - EXPECT_EQ(row->main_mem_addr_b, 9); // Indirect(35) -> 9 - EXPECT_EQ(row->main_mem_addr_c, 256); // Indirect(36) -> 256 - EXPECT_EQ(row->main_ia, 1); // Trivially contains 0. (See avm_trace for explanation why) - EXPECT_EQ(row->main_ib, 1); // Contains first element of the state - EXPECT_EQ(row->main_ic, 0); // Contains first element of the input - EXPECT_EQ(returndata, expected_output); validate_trace(std::move(trace), public_inputs); @@ -975,36 +934,11 @@ TEST_F(AvmExecutionTests, sha256Opcode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(8)); - // - // SHA256 - EXPECT_THAT(instructions.at(6), - AllOf(Field(&Instruction::op_code, OpCode::SHA256), - Field(&Instruction::operands, - ElementsAre(VariantWith(3), - VariantWith(35), - VariantWith(36), - VariantWith(37))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector returndata = std::vector(); std::vector calldata = std::vector(); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the sha256 selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sha256 == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 36); // Register A is indirect - EXPECT_EQ(row->main_ind_addr_c, 35); // Register C is indirect - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(36) -> 1 - EXPECT_EQ(row->main_mem_addr_c, 256); // Indirect(35) -> 256 - EXPECT_EQ(row->main_ia, 97); - EXPECT_EQ(row->main_ic, 0); - // Register b checks are done in the next row due to the difference in the memory tag - std::advance(row, 1); - EXPECT_EQ(row->main_ind_addr_b, 0); // Register B is not - EXPECT_EQ(row->main_mem_addr_b, 37); // Load(37) -> input length - EXPECT_EQ(row->main_ib, 3); // Input length - EXPECT_EQ(returndata, expected_output); validate_trace(std::move(trace), public_inputs); @@ -1046,16 +980,6 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - // 1 CALLDATACOPY for input + 2 SET for setting up indirects + 1 POSEIDON2 + 1 RETURN - ASSERT_THAT(instructions, SizeIs(5)); - - // POSEIDON2_PERM - EXPECT_THAT( - instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::POSEIDON2), - Field(&Instruction::operands, - ElementsAre(VariantWith(3), VariantWith(36), VariantWith(35))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector returndata = std::vector(); std::vector expected_output = { @@ -1064,18 +988,8 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) FF(std::string("0x018555a8eb50cf07f64b019ebaf3af3c925c93e631f3ecd455db07bbb52bbdd3")), FF(std::string("0x0cbea457c91c22c6c31fd89afd2541efc2edf31736b9f721e823b2165c90fd41")) }; - auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the poseidon2 selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_poseidon2 == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 36); - EXPECT_EQ(row->main_ind_addr_b, 35); - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(36) -> 1 - EXPECT_EQ(row->main_mem_addr_b, 9); // Indirect(34) -> 9 - EXPECT_EQ(row->main_ia, FF(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"))); - EXPECT_EQ(row->main_ib, 0); // Contains first element of the output (trivially 0) - EXPECT_EQ(returndata, expected_output); validate_trace(std::move(trace), public_inputs); @@ -1145,36 +1059,11 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - // 25 SET for input + 2 SET for setting up indirects + 1 KECCAK + 1 RETURN - ASSERT_THAT(instructions, SizeIs(30)); - // - // KECCAKF1600 - EXPECT_THAT(instructions.at(28), - AllOf(Field(&Instruction::op_code, OpCode::KECCAKF1600), - Field(&Instruction::operands, - ElementsAre(VariantWith(3), - VariantWith(35), - VariantWith(36), - VariantWith(37))))); - // // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector calldata = std::vector(); std::vector returndata = std::vector(); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the keccak selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_keccak == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 36); // Register A is indirect - EXPECT_EQ(row->main_ind_addr_c, 35); // Register C is indirect - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(36) -> 1 - EXPECT_EQ(row->main_mem_addr_c, 256); // Indirect(35) -> 256 - EXPECT_EQ(row->main_ia, (0xF1258F7940E1DDE7LLU)); - EXPECT_EQ(row->main_ic, 0); - - std::advance(row, 1); - EXPECT_EQ(row->main_ind_addr_b, 0); // Register B is not - EXPECT_EQ(row->main_mem_addr_b, 37); // Load(37) -> input length - EXPECT_EQ(row->main_ib, 25); // Input length EXPECT_EQ(returndata, expected_output); validate_trace(std::move(trace), public_inputs); @@ -1228,36 +1117,11 @@ TEST_F(AvmExecutionTests, keccakOpCode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); - // - // KECCAK - EXPECT_THAT(instructions.at(4), - AllOf(Field(&Instruction::op_code, OpCode::KECCAK), - Field(&Instruction::operands, - ElementsAre(VariantWith(3), - VariantWith(35), - VariantWith(36), - VariantWith(37))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector calldata = std::vector(); std::vector returndata = std::vector(); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the keccak selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_keccak == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 36); // Register A is indirect - EXPECT_EQ(row->main_ind_addr_c, 35); // Register C is indirect - EXPECT_EQ(row->main_mem_addr_a, 1); // Indirect(36) -> 1 - EXPECT_EQ(row->main_mem_addr_c, 256); // Indirect(35) -> 256 - EXPECT_EQ(row->main_ia, 189); - EXPECT_EQ(row->main_ic, 0); - // Register b checks are done in the next row due to the difference in the memory tag - std::advance(row, 1); - EXPECT_EQ(row->main_ind_addr_b, 0); // Register B is not - EXPECT_EQ(row->main_mem_addr_b, 37); // Load(37) -> input length - EXPECT_EQ(row->main_ib, 1); // Input length - EXPECT_EQ(returndata, expected_output); validate_trace(std::move(trace), public_inputs); @@ -1306,32 +1170,11 @@ TEST_F(AvmExecutionTests, pedersenHashOpCode) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); - // Pedersen - EXPECT_THAT(instructions.at(4), - AllOf(Field(&Instruction::op_code, OpCode::PEDERSEN), - Field(&Instruction::operands, - ElementsAre(VariantWith(4), - VariantWith(2), - VariantWith(3), - VariantWith(4), - VariantWith(5))))); - // Assign a vector that we will mutate internally in gen_trace to store the return values; std::vector returndata = std::vector(); std::vector calldata = { FF(1), FF(1) }; auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); - // Find the first row enabling the pedersen selector - auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_pedersen == 1; }); - EXPECT_EQ(row->main_ind_addr_a, 4); // Register A is indirect - EXPECT_EQ(row->main_mem_addr_a, 0); // Indirect(4) -> 1 - EXPECT_EQ(row->main_ia, 1); // The first input - // The second row loads the U32 values - std::advance(row, 1); - EXPECT_EQ(row->main_ia, 2); // Input length is 2 - EXPECT_EQ(row->main_ib, 5); // Hash offset is 5 - EXPECT_EQ(returndata[0], expected_output); validate_trace(std::move(trace), public_inputs); @@ -1714,8 +1557,9 @@ TEST_F(AvmExecutionTests, l2GasLeft) // Find the first row enabling the L2GASLEFT selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_l2gasleft == 1; }); - uint32_t expected_rem_gas = DEFAULT_INITIAL_L2_GAS - GAS_COST_TABLE.at(OpCode::SET).l2_fixed_gas_cost - - GAS_COST_TABLE.at(OpCode::L2GASLEFT).l2_fixed_gas_cost; + uint32_t expected_rem_gas = DEFAULT_INITIAL_L2_GAS - + static_cast(GAS_COST_TABLE.at(OpCode::SET).gas_l2_gas_fixed_table) - + static_cast(GAS_COST_TABLE.at(OpCode::L2GASLEFT).gas_l2_gas_fixed_table); EXPECT_EQ(row->main_ia, expected_rem_gas); EXPECT_EQ(row->main_mem_addr_a, 257); // Resolved direct address: 257 @@ -1755,8 +1599,9 @@ TEST_F(AvmExecutionTests, daGasLeft) // Find the first row enabling the DAGASLEFT selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_dagasleft == 1; }); - uint32_t expected_rem_gas = DEFAULT_INITIAL_DA_GAS - GAS_COST_TABLE.at(OpCode::ADD).da_fixed_gas_cost - - GAS_COST_TABLE.at(OpCode::DAGASLEFT).da_fixed_gas_cost; + uint32_t expected_rem_gas = DEFAULT_INITIAL_DA_GAS - + static_cast(GAS_COST_TABLE.at(OpCode::ADD).gas_da_gas_fixed_table) - + static_cast(GAS_COST_TABLE.at(OpCode::DAGASLEFT).gas_da_gas_fixed_table); EXPECT_EQ(row->main_ia, expected_rem_gas); EXPECT_EQ(row->main_mem_addr_a, 39); @@ -1886,13 +1731,12 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) { // Sload from a value that has not previously been written to will require a hint to process - std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET - "00" // Indirect flag - "03" // U32 - "00000009" // value 9 - "00000001" // dst_offset 1 - // Cast set to field - + to_hex(OpCode::CAST) + // opcode CAST + std::string bytecode_hex = to_hex(OpCode::SET) + // opcode SET + "00" // Indirect flag + "03" // U32 + "00000009" // value 9 + "00000001" // dst_offset 1 + + to_hex(OpCode::CAST) + // opcode CAST (Cast set to field) "00" // Indirect flag "06" // tag field "00000001" // dst 1 @@ -1900,7 +1744,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) + to_hex(OpCode::SLOAD) + // opcode SLOAD "00" // Indirect flag "00000001" // slot offset 1 - "00000001" // slot offset 1 + "00000001" // slot size 1 "00000002" // write storage value to offset 2 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag @@ -1957,7 +1801,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeComplex) + to_hex(OpCode::SLOAD) + // opcode SLOAD "00" // Indirect flag (second operand indirect - dest offset) "00000001" // slot offset 1 - "00000002" // slot offset 2 + "00000002" // slot size 2 "00000002" // write storage value to offset 2 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag @@ -2292,74 +2136,83 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) validate_trace(std::move(trace), public_inputs); } -// TEST_F(AvmExecutionTests, opCallOpcodes) -// { -// std::string bytecode_preamble; -// // Gas offset preamble -// bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for gas offset indirect -// "00" // Indirect flag -// "03" // U32 -// "00000010" // val 16 (address where gas offset is located) -// "00000011" + // dst_offset 17 -// to_hex(OpCode::SET) + // opcode SET for value stored in gas offset -// "00" // Indirect flag -// "03" // U32 -// "00000011" // val i -// "00000000"; -// // args offset preamble -// bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for args offset indirect -// "00" // Indirect flag -// "03" // U32 -// "00000100" // val i -// "00000012" + // dst_offset 0 -// to_hex(OpCode::SET) + // opcode SET for value stored in args offset -// "00" // Indirect flag -// "03" // U32 -// "00000012" // val i -// "00000001"; -// // ret offset preamble -// bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect -// "00" // Indirect flag -// "03" // U32 -// "00000008" // val i -// "00000004" + // dst_offset 0 -// to_hex(OpCode::SET) + // opcode SET for value stored in ret offset -// "00" // Indirect flag -// "03" // U32 -// "00000002" // val i -// "00000007"; -// std::string bytecode_hex = bytecode_preamble // SET gas, addr, args size, ret offset, success, function -// selector -// + to_hex(OpCode::CALL) + // opcode CALL -// "15" // Indirect flag -// "00000000" // gas offset -// "00000001" // addr offset -// "00000002" // args offset -// "00000003" // args size offset -// "00000004" // ret offset -// "00000007" // ret size -// "0000000a" // success offset -// "00000006" // function_selector_offset -// + to_hex(OpCode::RETURN) + // opcode RETURN -// "00" // Indirect flag -// "00000008" // ret offset 8 -// "00000003"; // ret size 3 - -// auto bytecode = hex_to_bytes(bytecode_hex); -// auto instructions = Deserialization::parse(bytecode); - -// std::vector calldata = {}; -// std::vector returndata = {}; - -// // Generate Hint for call operation -// auto execution_hints = ExecutionHints().with_externalcall_hints( -// { { .success = 1, .return_data = { 9, 8 }, .l2_gas_used = 0, .da_gas_used = 0 } }); - -// auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); -// EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success - -// validate_trace(std::move(trace), public_inputs); -// } +TEST_F(AvmExecutionTests, opCallOpcodes) +{ + // Calldata for l2_gas, da_gas, contract_address, nested_call_args (4 elements), + std::vector calldata = { 17, 10, 34802342, 1, 2, 3, 4 }; + std::string bytecode_preamble; + // Set up Gas offsets + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for gas offset indirect + "00" // Indirect flag + "03" // U32 + "00000000" // val 0 (address where gas tuple is located) + "00000011"; // dst_offset 17 + // Set up contract address offset + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for args offset indirect + "00" // Indirect flag + "03" // U32 + "00000002" // val 2 (where contract address is located) + "00000012"; // dst_offset 18 + // Set up args offset + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "00000003" // val 3 (the start of the args array) + "00000013"; // dst_offset 19 + // Set up args size offset + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "00000004" // val 4 (the length of the args array) + "00000014"; // dst_offset 20 + // Set up the ret offset + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "00000100" // val 256 (the start of where to write the return data) + "00000015"; // dst_offset 21 + // Set up the success offset + bytecode_preamble += to_hex(OpCode::SET) + // opcode SET for ret offset indirect + "00" // Indirect flag + "03" // U32 + "00000102" // val 258 (write the success flag at ret_offset + ret_size) + "00000016"; // dst_offset 22 + + std::string bytecode_hex = to_hex(OpCode::CALLDATACOPY) + // opcode CALLDATACOPY + "00" // Indirect flag + "00000000" // cd_offset + "00000007" // copy_size + "00000000" // dst_offset + + bytecode_preamble // Load up memory offsets + + to_hex(OpCode::CALL) + // opcode CALL + "3f" // Indirect flag + "00000011" // gas offset + "00000012" // addr offset + "00000013" // args offset + "00000014" // args size offset + "00000015" // ret offset + "00000002" // ret size + "00000016" // success offset + "00000017" // function_selector_offset + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000100" // ret offset 8 + "00000003"; // ret size 3 (extra read is for the success flag) + + auto bytecode = hex_to_bytes(bytecode_hex); + auto instructions = Deserialization::parse(bytecode); + + std::vector returndata = {}; + + // Generate Hint for call operation + auto execution_hints = ExecutionHints().with_externalcall_hints( + { { .success = 1, .return_data = { 9, 8 }, .l2_gas_used = 0, .da_gas_used = 0 } }); + + auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); + EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success + + validate_trace(std::move(trace), public_inputs); +} TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) { diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp index 75ebab122707..2666bb40e018 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp @@ -9,7 +9,6 @@ using namespace bb; using namespace bb::avm_trace; class AvmGasTests : public ::testing::Test { - protected: // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. void SetUp() override { srs::init_crs_factory("../srs_db/ignition"); }; @@ -34,7 +33,7 @@ void test_gas(StartGas startGas, OpcodesFunc apply_opcodes, CheckFunc check_trac kernel_inputs[L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = FF(startGas.l2_gas); kernel_inputs[DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET] = FF(startGas.da_gas); - VmPublicInputs public_inputs{}; + VmPublicInputs public_inputs; std::get<0>(public_inputs) = kernel_inputs; AvmTraceBuilder trace_builder(public_inputs); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp index d75c53f49eb0..f45924769244 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp @@ -7,20 +7,15 @@ using namespace bb::avm_trace; class AvmIndirectMemTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmIndirectMemTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; }; /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp index 9a4855892e50..098dbb0c181c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp @@ -14,20 +14,15 @@ using namespace bb::avm_trace; class AvmInterTableTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmInterTableTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; }; /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp index a985bb45a635..786902dc1105 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -12,7 +12,6 @@ using namespace bb; using namespace bb::avm_trace; class AvmKernelTests : public ::testing::Test { - protected: // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. void SetUp() override { srs::init_crs_factory("../srs_db/ignition"); }; @@ -1084,7 +1083,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) /*ib=*/slot, /*mem_addr_b=*/0, /*ind_b=*/false, - /*r_in_tag=*/AvmMemoryTag::FF, + /*r_in_tag=*/AvmMemoryTag::U0, // Kernel Sload is writing to memory /*side_effect_counter=*/0, /*rwa=*/1, /*no_b=*/true); @@ -1126,7 +1125,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) /*ib=*/slot, /*mem_addr_b=*/0, /*ind_b*/ false, - /*w_in_tag=*/AvmMemoryTag::FF, + /*r_in_tag=*/AvmMemoryTag::FF, /*side_effect_counter=*/0, /*rwa=*/0, /*no_b=*/true); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp index 3f0538411a2f..71bfcbbe39e7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp @@ -17,8 +17,15 @@ using namespace testing; class AvmMemOpcodeTests : public ::testing::Test { public: + AvmMemOpcodeTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) + { + srs::init_crs_factory("../srs_db/ignition"); + } + + VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; protected: std::vector trace; @@ -32,17 +39,6 @@ class AvmMemOpcodeTests : public ::testing::Test { size_t mem_ind_c_addr; size_t mem_ind_d_addr; - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override - { - srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; - void build_mov_trace(bool indirect, uint128_t const& val, uint32_t src_offset, @@ -173,7 +169,8 @@ class AvmMemOpcodeTests : public ::testing::Test { uint32_t dst_offset, AvmMemoryTag tag, uint32_t dir_src_offset = 0, - uint32_t dir_dst_offset = 0) + uint32_t dir_dst_offset = 0, + bool indirect_uninitialized = false) { compute_mov_indices(indirect); FF const val_ff = uint256_t::from_uint128(val); @@ -220,7 +217,9 @@ class AvmMemOpcodeTests : public ::testing::Test { EXPECT_THAT(mem_ind_a_row, AllOf(MEM_ROW_FIELD_EQ(tag_err, 0), MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), - MEM_ROW_FIELD_EQ(tag, static_cast(AvmMemoryTag::U32)), + MEM_ROW_FIELD_EQ(tag, + indirect_uninitialized ? static_cast(AvmMemoryTag::U0) + : static_cast(AvmMemoryTag::U32)), MEM_ROW_FIELD_EQ(addr, src_offset), MEM_ROW_FIELD_EQ(val, dir_src_offset), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_a, 1))); @@ -376,7 +375,7 @@ TEST_F(AvmMemOpcodeTests, indUninitializedValueMov) trace_builder.return_op(0, 0, 0); trace = trace_builder.finalize(); - validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::U0, 0, 1); + validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::U0, 0, 1, true); } TEST_F(AvmMemOpcodeTests, indirectMov) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 38428559194a..5dcfe52e0dfa 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -2,25 +2,21 @@ #include "barretenberg/vm/avm_trace/avm_common.hpp" namespace tests_avm { + using namespace bb; using namespace bb::avm_trace; class AvmMemoryTests : public ::testing::Test { public: - AvmTraceBuilder trace_builder; - VmPublicInputs public_inputs{}; - - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - void SetUp() override + AvmMemoryTests() + : public_inputs(generate_base_public_inputs()) + , trace_builder(AvmTraceBuilder(public_inputs)) { srs::init_crs_factory("../srs_db/ignition"); - std::array kernel_inputs{}; - kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; - kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; - std::get<0>(public_inputs) = kernel_inputs; - trace_builder = AvmTraceBuilder(public_inputs); - }; + } + + VmPublicInputs public_inputs; + AvmTraceBuilder trace_builder; }; /****************************************************************************** diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 8d31f30ce9a1..1657ba8ce0db 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -5,8 +5,8 @@ #include "barretenberg/vm/generated/avm_flavor.hpp" #include -using namespace bb; namespace tests_avm { + using namespace bb; std::vector gen_three_op_params(std::vector operands, @@ -241,4 +241,14 @@ void clear_range_check_counters(std::vector& trace, uint256_t previous_valu previous_value >>= 16; } +VmPublicInputs generate_base_public_inputs() +{ + VmPublicInputs public_inputs; + std::array kernel_inputs{}; + kernel_inputs.at(DA_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_DA_GAS; + kernel_inputs.at(L2_GAS_LEFT_CONTEXT_INPUTS_OFFSET) = DEFAULT_INITIAL_L2_GAS; + std::get<0>(public_inputs) = kernel_inputs; + return public_inputs; +} + } // namespace tests_avm diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index c3c665f34901..0dcf63815024 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -41,4 +41,6 @@ void update_slice_registers(Row& row, uint256_t a); std::vector gen_three_op_params(std::vector> operands, std::vector mem_tags); +VmPublicInputs generate_base_public_inputs(); + } // namespace tests_avm diff --git a/barretenberg/ts/src/types/fields.ts b/barretenberg/ts/src/types/fields.ts index 9305f0d6142d..ef9d9188cedb 100644 --- a/barretenberg/ts/src/types/fields.ts +++ b/barretenberg/ts/src/types/fields.ts @@ -15,7 +15,7 @@ export class Fr { const valueBigInt = typeof value === 'bigint' ? value : toBigIntBE(value); if (valueBigInt > Fr.MAX_VALUE) { - throw new Error(`Fr out of range: ${valueBigInt}`); + throw new Error(`Value 0x${valueBigInt.toString(16)} is greater or equal to field modulus.`); } this.value = typeof value === 'bigint' ? toBufferBE(value) : value; diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index 863d7cf3eac6..8e574163eb54 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -76,7 +76,6 @@ "ts-jest": "^29.1.0", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", - "tty-browserify": "^0.0.1", "typescript": "^5.0.4", "util": "^0.12.5", "webpack": "^5.88.2", diff --git a/boxes/boxes/react/src/contracts/src/main.nr b/boxes/boxes/react/src/contracts/src/main.nr index 944c66a75e95..6cbe8afbba82 100644 --- a/boxes/boxes/react/src/contracts/src/main.nr +++ b/boxes/boxes/react/src/contracts/src/main.nr @@ -1,7 +1,7 @@ contract BoxReact { use dep::aztec::prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; #[aztec(storage)] @@ -20,7 +20,7 @@ contract BoxReact { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); + numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } #[aztec(private)] @@ -33,7 +33,7 @@ contract BoxReact { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); + numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote { diff --git a/boxes/boxes/react/webpack.config.js b/boxes/boxes/react/webpack.config.js index d5e6fc11e015..4db17529911f 100644 --- a/boxes/boxes/react/webpack.config.js +++ b/boxes/boxes/react/webpack.config.js @@ -48,7 +48,6 @@ export default (_, argv) => ({ util: require.resolve('util/'), stream: require.resolve('stream-browserify'), string_decoder: require.resolve('string_decoder/'), - tty: require.resolve('tty-browserify'), }, }, devServer: { diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 0921135a760b..045d0e976fa6 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -28,7 +28,6 @@ "html-webpack-plugin": "^5.6.0", "stream-browserify": "^3.0.0", "ts-loader": "^9.5.1", - "tty-browserify": "^0.0.1", "typescript": "^5.0.4", "util": "^0.12.5", "webpack": "^5.90.1", diff --git a/boxes/boxes/vanilla/src/contracts/src/main.nr b/boxes/boxes/vanilla/src/contracts/src/main.nr index 424471e8bfd5..c8090a00f883 100644 --- a/boxes/boxes/vanilla/src/contracts/src/main.nr +++ b/boxes/boxes/vanilla/src/contracts/src/main.nr @@ -1,7 +1,7 @@ contract Vanilla { use dep::aztec::prelude::{AztecAddress, PrivateMutable, Map, NoteInterface, NoteHeader}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys; use dep::value_note::value_note::{ValueNote, VALUE_NOTE_LEN}; #[aztec(storage)] @@ -20,7 +20,7 @@ contract Vanilla { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); + numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } #[aztec(private)] @@ -33,7 +33,7 @@ contract Vanilla { ) { let numbers = storage.numbers; let mut new_number = ValueNote::new(number, owner_npk_m_hash); - numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); + numbers.at(owner).replace(&mut new_number).emit(encode_and_encrypt_note_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); } unconstrained fn getNumber(owner: AztecAddress) -> pub ValueNote { diff --git a/boxes/boxes/vanilla/webpack.config.js b/boxes/boxes/vanilla/webpack.config.js index aa9f974b3a2c..6fe89595fe09 100644 --- a/boxes/boxes/vanilla/webpack.config.js +++ b/boxes/boxes/vanilla/webpack.config.js @@ -44,7 +44,6 @@ export default (_, argv) => ({ util: require.resolve('util/'), stream: require.resolve('stream-browserify'), string_decoder: require.resolve('string_decoder/'), - tty: require.resolve('tty-browserify'), }, }, devServer: { diff --git a/boxes/contract-only/package.json b/boxes/contract-only/package.json index f262a39f6fce..f68de951d8e2 100644 --- a/boxes/contract-only/package.json +++ b/boxes/contract-only/package.json @@ -43,7 +43,6 @@ "jest": "^29.6.4", "stream-browserify": "^3.0.0", "ts-loader": "^9.5.1", - "tty-browserify": "^0.0.1", "typescript": "^5.0.4", "util": "^0.12.5", "webpack": "^5.90.1", diff --git a/boxes/yarn.lock b/boxes/yarn.lock index 47091d6cb8cc..526dda9a34fe 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -104,7 +104,6 @@ __metadata: ts-jest: "npm:^29.1.0" ts-loader: "npm:^9.4.4" ts-node: "npm:^10.9.1" - tty-browserify: "npm:^0.0.1" typescript: "npm:^5.0.4" util: "npm:^0.12.5" webpack: "npm:^5.88.2" @@ -133,7 +132,6 @@ __metadata: html-webpack-plugin: "npm:^5.6.0" stream-browserify: "npm:^3.0.0" ts-loader: "npm:^9.5.1" - tty-browserify: "npm:^0.0.1" typescript: "npm:^5.0.4" util: "npm:^0.12.5" webpack: "npm:^5.90.1" @@ -8957,13 +8955,6 @@ __metadata: languageName: node linkType: hard -"tty-browserify@npm:^0.0.1": - version: 0.0.1 - resolution: "tty-browserify@npm:0.0.1" - checksum: 5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d - languageName: node - linkType: hard - "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" diff --git a/build-images/Earthfile b/build-images/Earthfile index ca3fa661e1ba..bde054493209 100644 --- a/build-images/Earthfile +++ b/build-images/Earthfile @@ -71,7 +71,7 @@ osxcross: && apt-get -y autoremove \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - RUN git clone --depth=1 https://github.com/tpoechtrager/osxcross.git \ + RUN git clone https://github.com/tpoechtrager/osxcross.git \ && cd /osxcross \ && git reset --hard ff8d100f3f026b4ffbe4ce96d8aac4ce06f1278b \ && export OSX_SDK="MacOSX14.0.sdk" \ @@ -116,7 +116,6 @@ foundry: # It acts as the base image for all CI builds, and we build on it to produce a developer box. build: BUILD +wasi-sdk - BUILD +osxcross BUILD +foundry FROM +base-build RUN apt update && \ @@ -154,11 +153,6 @@ build: # Install wasi-sdk. COPY +wasi-sdk/opt/wasi-sdk /opt/wasi-sdk - # Install osxcross. Requires developer to mount SDK from their mac host. - COPY +osxcross/opt/osxcross /opt/osxcross - ENV PATH="/opt/osxcross/bin:$PATH" - ENV LD_LIBRARY_PATH="/opt/osxcross/lib:$LD_LIBRARY_PATH" - # Install foundry. COPY +foundry-build/opt/foundry /opt/foundry ENV PATH="/opt/foundry/bin:$PATH" @@ -204,6 +198,7 @@ build: # We want to produce downstream images: devbox and sysbox. This image is the base image for each. # It contains a suite of tools that developers might use to develop aztec. basebox: + BUILD +osxcross BUILD +build FROM +build RUN yes | unminimize @@ -237,6 +232,11 @@ basebox: RUN wget https://github.com/earthly/earthly/releases/latest/download/earthly-linux-$(dpkg --print-architecture) -O /usr/local/bin/earthly && \ chmod +x /usr/local/bin/earthly + # Install osxcross. Requires developer to mount SDK from their mac host. + COPY +osxcross/opt/osxcross /opt/osxcross + ENV PATH="/opt/osxcross/bin:$PATH" + ENV LD_LIBRARY_PATH="/opt/osxcross/lib:$LD_LIBRARY_PATH" + # Install gh (github cli). RUN mkdir -p -m 755 /etc/apt/keyrings && wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg > /etc/apt/keyrings/githubcli-archive-keyring.gpg \ && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \ diff --git a/cspell.json b/cspell.json index 78f4bd23c72d..9a41fb4eb43a 100644 --- a/cspell.json +++ b/cspell.json @@ -169,6 +169,9 @@ "nullifer", "offchain", "onchain", + "opentelemetry", + "otel", + "OTLP", "otterscan", "outdir", "overlayfs", @@ -219,6 +222,7 @@ "rushstack", "schnorr", "secp", + "SEMRESATTRS", "sigchld", "Signerless", "siloes", @@ -253,6 +257,7 @@ "typegen", "typeparam", "undeployed", + "undici", "unexclude", "unexcluded", "unprefixed", @@ -270,6 +275,7 @@ "viem", "wasms", "webassembly", + "WITGEN", "workdir", "yamux", "yarnrc", @@ -301,5 +307,7 @@ "lib", "*.cmake" ], - "flagWords": ["anonymous"] -} \ No newline at end of file + "flagWords": [ + "anonymous" + ] +} diff --git a/docker-compose.yml b/docker-compose.yml index 952fd382939e..b65e980c58d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,8 +5,8 @@ services: # need to run bb for proofs and bb is only built for x86 platform: linux/amd64 environment: - LOG_LEVEL: info - DEBUG: aztec:* + LOG_LEVEL: ${LOG_LEVEL:-info} + DEBUG: ${DEBUG:-aztec:*,-json-rpc:*,-aztec:circuits:artifact_hash,-aztec:randomness_singleton} DEBUG_COLORS: 1 CHAIN_ID: 31337 VERSION: 1 @@ -28,14 +28,16 @@ services: - aztec:/var/lib/aztec ports: - 8080:8080/tcp + profiles: + - pxe node: image: aztecprotocol/aztec${AZTEC_DOCKER_TAG:-@sha256:03feac60e91f1aabf678cecbcd13271dda229120ec6007f2c1bac718ff550c70} # need to run bb for proofs and bb is only built for x86 platform: linux/amd64 environment: - LOG_LEVEL: info - DEBUG: aztec:* + LOG_LEVEL: ${LOG_LEVEL:-info} + DEBUG: ${DEBUG:-aztec:*,-json-rpc:*,-aztec:circuits:artifact_hash,-aztec:randomness_singleton,-aztec:avm_simulator:*} DEBUG_COLORS: 1 CHAIN_ID: 31337 VERSION: 1 @@ -59,18 +61,34 @@ services: P2P_ENABLED: true PEER_ID_PRIVATE_KEY: AZTEC_PORT: 8999 + TEL_COLLECTOR_BASE_URL: ${TEL_COLLECTOR_BASE_URL:-http://otel-collector:4318} secrets: - ethereum-host - p2p-boot-node - entrypoint: [ - "/bin/sh", - "-c", - "export ETHEREUM_HOST=$$(cat /var/run/secrets/ethereum-host);\ - export BOOTSTRAP_NODES=$$(cat /var/run/secrets/p2p-boot-node);\ - test -z \"$$PEER_ID_PRIVATE_KEY\" -a ! -f /var/lib/aztec/p2p-private-key && node /usr/src/yarn-project/cli/dest/bin/index.js generate-p2p-private-key | head -1 | cut -d' ' -f 3 | tee /var/lib/aztec/p2p-private-key || echo 'Re-using existing P2P private key';\ - test -z \"$$PEER_ID_PRIVATE_KEY\" && export PEER_ID_PRIVATE_KEY=$$(cat /var/lib/aztec/p2p-private-key);\ - node /usr/src/yarn-project/aztec/dest/bin/index.js start --node --archiver", - ] + entrypoint: | + /bin/sh -c ' + export ETHEREUM_HOST=$$(cat /var/run/secrets/ethereum-host) + export BOOTSTRAP_NODES=$$(cat /var/run/secrets/p2p-boot-node) + + test -z "$$PEER_ID_PRIVATE_KEY" -a ! -f /var/lib/aztec/p2p-private-key && node /usr/src/yarn-project/cli/dest/bin/index.js generate-p2p-private-key | head -1 | cut -d" " -f 3 | tee /var/lib/aztec/p2p-private-key || echo "Re-using existing P2P private key" + test -z "$$PEER_ID_PRIVATE_KEY" && export PEER_ID_PRIVATE_KEY=$$(cat /var/lib/aztec/p2p-private-key) + + # if the stack is started with --profile metrics --profile node, give the collector a chance to start before the node + i=0 + max=3 + while ! curl --head --silent $$TEL_COLLECTOR_BASE_URL > /dev/null; do + echo "OpenTelemetry collector not up. Retrying after 1s"; + sleep 1; + i=$$((i+1)); + if [ $$i -eq $$max ]; then + echo "OpenTelemetry collector at $$TEL_COLLECTOR_BASE_URL not up after $${max}s. Running without metrics"; + unset TEL_COLLECTOR_BASE_URL; + break + fi; + done; + + node /usr/src/yarn-project/aztec/dest/bin/index.js start --node --archiver + ' volumes: - aztec:/var/lib/aztec profiles: @@ -94,8 +112,103 @@ services: profiles: - cli + otel-collector: + image: otel/opentelemetry-collector-contrib + configs: + - source: otel-collector-config + target: /etc/otelcol-contrib/config.yaml + profiles: + - metrics + ports: + - 4318:4318 + + prometheus: + image: prom/prometheus + profiles: + - metrics + configs: + - source: prometheus-config + target: /etc/prometheus/prometheus.yml + + grafana: + image: grafana/grafana + ports: + - 3000:3000 + profiles: + - metrics + volumes: + - ./grafana_dashboards:/etc/grafana/provisioning/dashboards + - grafana:/var/lib/grafana + configs: + - source: grafana-sources + target: /etc/grafana/provisioning/datasources/default.yml + + jaeger: + image: jaegertracing/all-in-one + ports: + - 16686:16686 + profiles: + - metrics + volumes: aztec: + grafana: + +configs: + grafana-sources: + content: | + apiVersion: 1 + datasources: + - name: Prometheus + uid: aztec-node-metrics + type: prometheus + url: http://prometheus:9090 + editable: false + isDefault: true + jsonData: + timeInterval: 10s + + prometheus-config: + content: | + global: + evaluation_interval: 30s + scrape_interval: 10s + scrape_configs: + - job_name: otel-collector + static_configs: + - targets: ['otel-collector:8888'] + - job_name: aztec + static_configs: + - targets: ['otel-collector:8889'] + otel-collector-config: + content: | + receivers: + otlp: + protocols: + http: + + processors: + batch: + + exporters: + prometheus: + endpoint: 0.0.0.0:8889 + metric_expiration: 5m + otlp/jaeger: + endpoint: "jaeger:4317" + tls: + insecure: true + + service: + pipelines: + traces: + receivers: [otlp] + processors: [batch] + exporters: [otlp/jaeger] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [prometheus] secrets: aztec-node-url: diff --git a/docs/.gitignore b/docs/.gitignore index 07d9321798d4..bfd44418b7d2 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -24,3 +24,4 @@ yarn-error.log* docs/reference/aztecjs docs/reference/smart_contract_reference/aztec-nr +test-results diff --git a/docs/docs/aztec/_category_.json b/docs/docs/aztec/_category_.json index 336394a563a1..22b47d59039f 100644 --- a/docs/docs/aztec/_category_.json +++ b/docs/docs/aztec/_category_.json @@ -1,6 +1,6 @@ { "label": "Aztec", - "position": 0, + "position": 1, "collapsible": true, "collapsed": true } diff --git a/docs/docs/getting_started.md b/docs/docs/getting_started.md index 163fa2588a5b..9b78a80b8e17 100644 --- a/docs/docs/getting_started.md +++ b/docs/docs/getting_started.md @@ -2,43 +2,45 @@ title: Quickstart --- -The easiest way to start developing on Aztec is simply to click on one of these buttons: +The easiest way to start developing on Aztec locally is through `npx aztec-app`. This is a convenient way of installing the development environment (A.K.A. Sandbox) and starting new projects from a boilerplate. -[![One-Click React Starter](/img/codespaces_badges/react_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Freact%2Fdevcontainer.json) [![One-Click HTML/TS Starter](/img/codespaces_badges/vanilla_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Fvanilla%2Fdevcontainer.json) [![One-Click Token Starter](/img/codespaces_badges/token_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Ftoken%2Fdevcontainer.json) +To locally install the Sandbox without other tools, see [here](./getting_started/manual_install.md). -That's it! +## Prerequisites -This creates a codespace with a prebuilt image containing one of the "Aztec Boxes" and a development network (sandbox). -- You can develop directly on the codespace, push it to a repo, make yourself at home. -- You can also just use the sandbox that comes with it. The URL will be logged, you just need to use it as your `PXE_URL`. +- Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) +- Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) -## Develop Locally +### Run the `npx` script -The above method uses Aztec boxes to install the sandbox and clone the repo. You can use it too to get started on your own machine and use your own IDE. +Thanks to Node, you can run the recommended `npx script`: + +```bash +npx aztec-app +``` -You can also [install the sandbox manually](/reference/sandbox_reference). +This script gives you some options to bootstrap a new project, start/stop the sandbox, or see the logs. Run `npx aztec-app -h` for a list of options. -### Prerequisites +## Install Noir LSP (recommended) -- Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) -- Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) +Install the [Noir Language Support extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir) to get syntax highlighting, syntax error detection and go-to definitions for your Aztec contracts. -### Run the `npx` script +Once the extension is installed, check your nargo binary by hovering over `Nargo` in the status bar on the bottom right of the application window. Click to choose the path to `aztec-nargo` (or regular `nargo`, if you have that installed). -With the node installation, you now should have `npm` and be able to run `npx` scripts. You can do that by running: +You can print the path of your `aztec-nargo` executable by running: ```bash -npx create-aztec-app +which aztec-nargo ``` -And follow the instructions. If all goes well, you should now have a development environment running locally on your machine. - -You can run `npx create-aztec-app sandbox -h` to start, stop, update and output logs from the sandbox. +To specify a custom nargo executable, go to the VSCode settings and search for "noir", or click extension settings on the `noir-lang` LSP plugin. +Update the `Noir: Nargo Path` field to point to your desired `aztec-nargo` executable. ## What's next? -To deploy a smart contract to your sandbox and interact with it using Aztec.js, go to the [next page](getting_started/aztecjs-getting-started.md). +Now you have a development network running, so you're ready to start coding your first app with Aztec.nr and Aztec.js! -To skip this and write your first smart contract, go to the [Aztec.nr getting started page](getting_started/aztecnr-getting-started.md). +To follow the series of tutorials, start with the private voting contract [here](./tutorials/contract_tutorials/private_voting_contract.md). +If you want to just keep learning, you can read about the high level architecture on the [Core Components page](./aztec/concepts/state_model/index.md) and [the lifecycle of a transaction](./aztec/concepts/transactions.md). diff --git a/docs/docs/getting_started/codespaces.md b/docs/docs/getting_started/codespaces.md new file mode 100644 index 000000000000..5d57ac291e29 --- /dev/null +++ b/docs/docs/getting_started/codespaces.md @@ -0,0 +1,25 @@ +--- +title: Codespaces +sidebar_position: 0 +draft: true +--- + +All machines are different, and you may not want to run the sandbox locally (for example when using Windows). We thought about you exactly ❤️ + +[Codespaces](https://github.com/features/codespaces) are a quick way to develop: they provision a remote machine with all tooling you need for Aztec in just a few minutes. We're big fans, so we prepared some prebuilt images to make it easier and faster. + +Just choose a boilerplate and click "create new codespace": + +[![One-Click React Starter](/img/codespaces_badges/react_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Freact%2Fdevcontainer.json) [![One-Click HTML/TS Starter](/img/codespaces_badges/vanilla_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Fvanilla%2Fdevcontainer.json) [![One-Click Token Starter](/img/codespaces_badges/token_cta_badge.svg)](https://codespaces.new/AztecProtocol/aztec-packages?devcontainer_path=.devcontainer%2Ftoken%2Fdevcontainer.json) + +This creates a codespace with a prebuilt image containing one of the "Aztec Boxes" and a development network (sandbox). +- You can develop directly on the codespace, push it to a repo, make yourself at home. +- You can also just use the sandbox that comes with it. The URL will be logged, you just need to use it as your `PXE_URL`. + +You can then start, stop, or see the logs of your sandbox just by calling `sandbox` or `npx aztec-app sandbox`. Run `sandbox -h` for a list of commands. + +## More about codespaces + +Codespaces are way more powerful than you may initially think. For example, you can connect your local `vscode` to a remote codespace, for a fully contained development environment that doesn't use any of your computer resources! + +Visit the [codespaces documentation](https://docs.github.com/en/codespaces/overview) for more specific documentation around codespaces. diff --git a/docs/docs/getting_started/manual_install.md b/docs/docs/getting_started/manual_install.md new file mode 100644 index 000000000000..a5e3f3ad93b2 --- /dev/null +++ b/docs/docs/getting_started/manual_install.md @@ -0,0 +1,77 @@ +--- +title: Manual install +sidebar_position: 1 +--- + +You can have some more control over the sandbox by installing it manually through the underlying script used by [`npx aztec-app`](../getting_started.md). + +This involves some knowledge on Docker if you want to stop, restart, or detach from logs. But it also gives you better control over things such as environment variables. + +### Prerequisites + +- Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) +- Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) + +### Install the sandbox + +To install the latest Sandbox version, run: + +```bash +bash -i <(curl -s install.aztec.network) +``` + +This will install the following tools: + +- **aztec** - launches various infrastructure subsystems (sequencer, prover, pxe, etc). +- **aztec-nargo** - aztec's build of nargo, the noir compiler toolchain. +- **aztec-sandbox** - a wrapper around docker-compose that launches services needed for sandbox testing. +- **aztec-up** - a tool to upgrade the aztec toolchain to the latest, or specific versions. +- **aztec-builder** - A useful tool for projects to generate ABIs and update their dependencies. + +Once these have been installed, to start the sandbox, run: + +```bash +aztec-sandbox +``` + +### Have fun + +**Congratulations, you have just installed and run the Aztec Sandbox!** + +```bash + /\ | | + / \ ___| |_ ___ ___ + / /\ \ |_ / __/ _ \/ __| + / ____ \ / /| || __/ (__ + /_/___ \_\/___|\__\___|\___| + +``` + +In the terminal, you will see some logs: + +1. Sandbox version +2. Contract addresses of rollup contracts +3. PXE (private execution environment) setup logs +4. Initial accounts that are shipped with the sandbox and can be used in tests + +## Running Aztec PXE / Node / P2P-Bootstrap node + +If you wish to run components of the Aztec network stack separately, you can use the `aztec start` command with various options for enabling components. + +```bash +aztec start --node [nodeOptions] --pxe [pxeOptions] --archiver [archiverOptions] --sequencer [sequencerOptions] --prover [proverOptions] ----p2p-bootstrap [p2pOptions] +``` + +Starting the aztec node alongside a PXE, sequencer or archiver, will attach the components to the node.Eg if you want to run a PXE separately to a node, you can [read this guide](../aztec/concepts/pxe/index.md)/ + +## Update the sandbox + +To update the sandbox, you can just run: + +```bash +aztec-up +``` + +## Next steps + +Visit the [sandbox reference](../reference/sandbox_reference/index.md) for more info on which environment variables you can set, which cheat codes you can use, and learn about what exactly is the Aztec Sandbox. diff --git a/docs/docs/guides/smart_contracts/how_to_compile_contract.md b/docs/docs/guides/smart_contracts/how_to_compile_contract.md index 39e91a84166b..605d80504211 100644 --- a/docs/docs/guides/smart_contracts/how_to_compile_contract.md +++ b/docs/docs/guides/smart_contracts/how_to_compile_contract.md @@ -222,7 +222,7 @@ export class TokenContract extends ContractBase { } ``` -Read more about interacting with contracts using `aztec.js` [here](../../getting_started/aztecjs-getting-started.md). +Read more about interacting with contracts using `aztec.js` [here](../../tutorials/aztecjs-getting-started.md). ### Aztec.nr interfaces diff --git a/docs/docs/guides/smart_contracts/writing_contracts/authwit.md b/docs/docs/guides/smart_contracts/writing_contracts/authwit.md index 18b21cd75b72..8f74c3bf3409 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/authwit.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/authwit.md @@ -74,7 +74,7 @@ As part of `AuthWit` we are assuming that the `on_behalf_of` implements the priv ```rust #[aztec(private)] -fn spend_private_authwit(inner_hash: Field) -> Field; +fn verify_private_authwit(inner_hash: Field) -> Field; ``` For public authwit, we have a shared registry that is used, there we are using a `consume` function. @@ -101,10 +101,8 @@ To make it convenient to compute the message hashes in TypeScript, the `aztec.js For private calls where we allow execution on behalf of others, we generally want to check if the current call is authenticated by `on_behalf_of`. To easily do so, we can use the `assert_current_call_valid_authwit` which fetches information from the current context without us needing to provide much beyond the `on_behalf_of`. -This function will then make a to `on_behalf_of` to execute the `spend_private_authwit` function which validates that the call is authenticated. -The `on_behalf_of` should assert that we are indeed authenticated and then emit a nullifier when we are spending the authwit to prevent replay attacks. -If the return value is not as expected, we throw an error. -This is to cover the case where the `on_behalf_of` might implemented some function with the same selector as the `spend_private_authwit` that could be used to authenticate unintentionally. +This function will then make a call to `on_behalf_of` to execute the `verify_private_authwit` function which validates that the call is authenticated. +The `on_behalf_of` should assert that we are indeed authenticated and then return the `IS_VALID` selector. If the return value is not as expected, we throw an error. This is to cover the case where the `on_behalf_of` might implemented some function with the same selector as the `verify_private_authwit` that could be used to authenticate unintentionally. #### Example diff --git a/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/index.md b/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/index.md index 5e0997a595e4..a44b376779a4 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/index.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/common_patterns/index.md @@ -31,7 +31,7 @@ E.g. you don't want a user to subscribe once they have subscribed already. Or yo Emit a nullifier in your function. By adding this nullifier into the tree, you prevent another nullifier from being added again. This is also why in authwit, we emit a nullifier, to prevent someone from reusing their approval. -#include_code spend_private_authwit /noir-projects/aztec-nr/authwit/src/account.nr rust +#include_code verify_private_authwit /noir-projects/aztec-nr/authwit/src/account.nr rust Note be careful to ensure that the nullifier is not deterministic and that no one could do a preimage analysis attack. More in [the anti pattern section on deterministic nullifiers](#deterministic-nullifiers) diff --git a/docs/docs/guides/smart_contracts/writing_contracts/initializers.md b/docs/docs/guides/smart_contracts/writing_contracts/initializers.md index 7428af87fbf3..80f7d3de38d1 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/initializers.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/initializers.md @@ -27,4 +27,4 @@ Initializers are commonly used to set an admin, such as this example: Here, the initializer is calling a public function. It can also call a private function. Learn more about calling functions from functions [here](./call_functions.md). -To see constructors in action, check out the [Aztec.nr getting started guide](../../../getting_started/aztecnr-getting-started.md). +To see an initializer in action, check out the [Counter Contract Tutorial](../../../tutorials/contract_tutorials/counter_contract.md). diff --git a/docs/docs/reference/sandbox_reference/index.md b/docs/docs/reference/sandbox_reference/index.md index 1697ca3d4151..ba339531a852 100644 --- a/docs/docs/reference/sandbox_reference/index.md +++ b/docs/docs/reference/sandbox_reference/index.md @@ -5,26 +5,6 @@ sidebar_position: 0 The Aztec Sandbox is an environment for local development on the Aztec Network. It's easy to get setup with just a single, simple command, and contains all the components needed to develop and test Aztec contracts and applications. -## Components of the Aztec network - -Aztec's Layer 2 network is a fully programmable combined private/public ZK rollup. To achieve this, the network contains the following primary components: - -- Aztec Node - Aggregates all of the 'backend' services necessary for the building and publishing of rollups. This package is currently in development and much of the functionality is mocked. -- [Private Execution Environment (PXE)](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/pxe) - Normally residing with the end client, this decrypts and stores a client's private state, executes simulations and submits transactions to the Aztec Node. -- [Aztec.js](https://github.com/AztecProtocol/aztec-packages/tree/master/yarn-project/aztec.js) - Aztec's client library for interacting with the PXE (think Ethers.js). See the getting started guide [here](../../getting_started/aztecjs-getting-started.md). - -All of this is included in the Sandbox, with the exception of Aztec.js which you can use to interact with it. - -With the help of Aztec.js you will be able to: - -- Create an account -- Deploy a contract -- Call view methods on contracts -- Simulate the calling of contract functions -- Send transactions to the network -- Be notified when transactions settle -- Query chain state such as chain id, block number etc. - ## What's in the Sandbox? The sandbox contains a local Ethereum instance running [Anvil](https://book.getfoundry.sh/anvil/), a local instance of the Aztec rollup and an aztec private execution client for handling user transactions and state. diff --git a/docs/docs/reference/sandbox_reference/sandbox-reference.md b/docs/docs/reference/sandbox_reference/sandbox-reference.md index b20ffd891755..5e9ef0fbfbd9 100644 --- a/docs/docs/reference/sandbox_reference/sandbox-reference.md +++ b/docs/docs/reference/sandbox_reference/sandbox-reference.md @@ -8,67 +8,6 @@ For a quick start, follow the [guide](../../getting_started.md) to install the s ::: -## Manual Install - -You can manually install the sandbox via the underlying script used in the [Aztec Boxes](getting_started.md#run-the-npx-script). - -### Prerequisites - -- Node.js >= v18 (recommend installing with [nvm](https://github.com/nvm-sh/nvm)) -- Docker (visit [this page of the Docker docs](https://docs.docker.com/get-docker/) on how to install it) - -### Install the sandbox - -To install the latest Sandbox version, run: - -```bash -bash -i <(curl -s install.aztec.network) -``` - -This will install the following tools: - -- **aztec** - launches various infrastructure subsystems (sequencer, prover, pxe, etc). -- **aztec-nargo** - aztec's build of nargo, the noir compiler toolchain. -- **aztec-sandbox** - a wrapper around docker-compose that launches services needed for sandbox testing. -- **aztec-up** - a tool to upgrade the aztec toolchain to the latest, or specific versions. -- **aztec-builder** - A useful tool for projects to generate ABIs and update their dependencies. - -Once these have been installed, to start the sandbox, run: - -```bash -aztec-sandbox -``` - -### Have fun! - -**Congratulations, you have just installed and run the Aztec Sandbox!** - -```bash - /\ | | - / \ ___| |_ ___ ___ - / /\ \ |_ / __/ _ \/ __| - / ____ \ / /| || __/ (__ - /_/___ \_\/___|\__\___|\___| - -``` - -In the terminal, you will see some logs: - -1. Sandbox version -2. Contract addresses of rollup contracts -3. PXE (private execution environment) setup logs -4. Initial accounts that are shipped with the sandbox and can be used in tests - -## Running Aztec PXE / Node / P2P-Bootstrap node - -If you wish to run components of the Aztec network stack separately, you can use the `aztec start` command with various options for enabling components. - -```bash -aztec start --node [nodeOptions] --pxe [pxeOptions] --archiver [archiverOptions] --sequencer [sequencerOptions] --prover [proverOptions] ----p2p-bootstrap [p2pOptions] -``` - -Starting the aztec node alongside a PXE, sequencer or archiver, will attach the components to the node.Eg if you want to run a PXE separately to a node, you can [read this guide](../../aztec/concepts/pxe/index.md)/ - ## Environment Variables There are various environment variables you can use when running the whole sandbox or when running on of the available modes. diff --git a/docs/docs/getting_started/aztecjs-getting-started.md b/docs/docs/tutorials/aztecjs-getting-started.md similarity index 99% rename from docs/docs/getting_started/aztecjs-getting-started.md rename to docs/docs/tutorials/aztecjs-getting-started.md index 7d435faae956..6f9d145da5e4 100644 --- a/docs/docs/getting_started/aztecjs-getting-started.md +++ b/docs/docs/tutorials/aztecjs-getting-started.md @@ -357,4 +357,4 @@ That's it! We have successfully deployed a token contract to an instance of the ## Next Steps -Write your first smart contract on the [next page](./aztecnr-getting-started.md). +Write your first account contract on the [next page](./write_accounts_contract.md). diff --git a/docs/docs/tutorials/contract_tutorials/advanced/_category_.json b/docs/docs/tutorials/contract_tutorials/advanced/_category_.json index b867f5fd3637..81a03772f7d1 100644 --- a/docs/docs/tutorials/contract_tutorials/advanced/_category_.json +++ b/docs/docs/tutorials/contract_tutorials/advanced/_category_.json @@ -1,6 +1,6 @@ { "label": "Advanced", - "position": 3, + "position": 5, "collapsible": true, "collapsed": true } diff --git a/docs/docs/getting_started/aztecnr-getting-started.md b/docs/docs/tutorials/contract_tutorials/counter_contract.md similarity index 78% rename from docs/docs/getting_started/aztecnr-getting-started.md rename to docs/docs/tutorials/contract_tutorials/counter_contract.md index 000e1c0d1d8d..8d140da25f35 100644 --- a/docs/docs/getting_started/aztecnr-getting-started.md +++ b/docs/docs/tutorials/contract_tutorials/counter_contract.md @@ -1,15 +1,15 @@ --- -title: Writing Your First Smart Contract -sidebar_position: 2 +title: Counter Contract +sidebar_position: 0 --- In this guide, we will create our first Aztec.nr smart contract. We will build a simple private counter. This contract will get you started with the basic setup and syntax of Aztec.nr, but doesn't showcase the awesome stuff Aztec is capable of. -If you already have some experience with Noir and want to build a cooler contract that utilizes both private and public state, you might want to check out the [token contract tutorial instead](../tutorials/contract_tutorials/token_contract.md). +If you already have some experience with Noir and want to build a cooler contract that utilizes both private and public state, you might want to check out the [token contract tutorial instead](../../tutorials/contract_tutorials/token_contract.md). ## Prerequisites -- You have followed the [quickstart](../getting_started.md) +- You have followed the [quickstart](../../getting_started.md) - Running Aztec Sandbox ## Set up a project @@ -116,7 +116,7 @@ Let’s create a constructor method to run on deployment that assigns an initial This function accesses the counts from storage. Then it assigns the passed initial counter to the `owner`'s counter privately using `at().add()`. -We have annotated this and other functions with `#[aztec(private)]` which are ABI macros so the compiler understands it will handle private inputs. Learn more about functions and annotations [here](../aztec/concepts/smart_contracts/functions/index.md). +We have annotated this and other functions with `#[aztec(private)]` which are ABI macros so the compiler understands it will handle private inputs. Learn more about functions and annotations [here](../../aztec/concepts/smart_contracts/functions/index.md). ## Incrementing our counter @@ -160,28 +160,4 @@ In the same directory, run this: aztec-builder codegen -o src/artifacts target ``` -You can now use the artifact and/or the TS class in your Aztec.js! If you skipped the Aztec.js getting-started guide, you can follow it [here](aztecjs-getting-started.md). This will teach you about deploying and calling contracts in Aztec.js. - -## Install Noir LSP (recommended) - -Install the [Noir Language Support extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir) to get syntax highlighting, syntax error detection and go-to definitions for your Aztec contracts. - -Once the extension is installed, check your nargo binary by hovering over `Nargo` in the status bar on the bottom right of the application window. Click to choose the path to `aztec-nargo` (or regular `nargo`, if you have that installed). - -You can print the path of your `aztec-nargo` executable by running: - -```bash -which aztec-nargo -``` - -To specify a custom nargo executable, go to the VSCode settings and search for "noir", or click extension settings on the `noir-lang` LSP plugin. -Update the `Noir: Nargo Path` field to point to your desired `aztec-nargo` executable. - -## What's next? - -The next recommmended steps are follow the tutorials in order. They will teach you more about contracts, Aztec.js, and how Aztec works in general. - -To follow the series of tutorials, start with the private voting contract [here](../tutorials/contract_tutorials/private_voting_contract.md). - -Alternatively, you can read about the high level architecture on the [Core Components page](../aztec/concepts/state_model/index.md) and [the lifecycle of a transaction](../aztec/concepts/transactions.md). - +You can now use the artifact and/or the TS class in your Aztec.js! diff --git a/docs/docs/tutorials/contract_tutorials/crowdfunding_contract.md b/docs/docs/tutorials/contract_tutorials/crowdfunding_contract.md index 11735715ce33..ce858d65ef1e 100644 --- a/docs/docs/tutorials/contract_tutorials/crowdfunding_contract.md +++ b/docs/docs/tutorials/contract_tutorials/crowdfunding_contract.md @@ -1,6 +1,6 @@ --- title: "Crowdfunding contract" -sidebar_position: 2 +sidebar_position: 3 tags: [developers, tutorial, example] --- diff --git a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md index fa6becef8313..16606e5c5082 100644 --- a/docs/docs/tutorials/contract_tutorials/private_voting_contract.md +++ b/docs/docs/tutorials/contract_tutorials/private_voting_contract.md @@ -1,6 +1,6 @@ --- title: "Private voting contract" -sidebar_position: 0 +sidebar_position: 1 --- import Image from '@theme/IdealImage'; @@ -164,12 +164,11 @@ Once it is compiled you can [deploy](../../reference/sandbox_reference/index.md) aztec-builder target -o src/artifacts ``` -Once it is compiled you can [deploy](../../guides/smart_contracts/how_to_deploy_contract.md) it to the sandbox. This is out of scope for this tutorial but you can learn how to do this in the [Aztec.js getting-started guide](../../getting_started/aztecjs-getting-started.md). +Once it is compiled you can [deploy](../../guides/smart_contracts/how_to_deploy_contract.md) it to the sandbox just like you did in the [counter contract tutorial](./counter_contract.md). ## Next steps Now you have learned the foundations of Aztec smart contracts, you can start to play around with some more advanced features. Some ideas: - Add some more features into this contract, like the admin can distribute votes, people can delegate their votes, or voteIds can have more data like names, descriptions, etc -- Create a frontend for this contract using [Aztec.js](../../getting_started/aztecjs-getting-started.md). - Go to the [next tutorial](token_contract.md) and learn how to write a token contract diff --git a/docs/docs/tutorials/contract_tutorials/token_contract.md b/docs/docs/tutorials/contract_tutorials/token_contract.md index 2a21152707fc..eb5618f3d520 100644 --- a/docs/docs/tutorials/contract_tutorials/token_contract.md +++ b/docs/docs/tutorials/contract_tutorials/token_contract.md @@ -1,6 +1,6 @@ --- title: "Private token contract" -sidebar_position: 1 +sidebar_position: 4 --- In this tutorial we will go through writing an L2 native token contract diff --git a/docs/docs/vision.mdx b/docs/docs/vision.mdx index 2e4ff8478979..a7e748579fa1 100644 --- a/docs/docs/vision.mdx +++ b/docs/docs/vision.mdx @@ -1,7 +1,7 @@ --- title: Aztec's Vision sidebar_label: Vision -sidebar_position: 1 +sidebar_position: 0 --- import Disclaimer from "@site/src/components/Disclaimers/_wip_disclaimer.mdx"; diff --git a/docs/sidebars.js b/docs/sidebars.js index 1b84e84f3033..9e9383590d82 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -59,10 +59,6 @@ export default { { label: "Proving System", type: "category", - link: { - type: "doc", - id: "protocol-specs/cryptography/proving-system/performance-targets", - }, items: [ "protocol-specs/cryptography/proving-system/performance-targets", "protocol-specs/cryptography/proving-system/overview", @@ -72,10 +68,6 @@ export default { { label: "Hashing", type: "category", - link: { - type: "doc", - id: "protocol-specs/cryptography/hashing/hashing", - }, items: [ "protocol-specs/cryptography/hashing/hashing", "protocol-specs/cryptography/hashing/poseidon2", @@ -217,7 +209,6 @@ export default { { label: "Decentralization", type: "category", - link: { type: "doc", id: "protocol-specs/decentralization/governance" }, items: [ "protocol-specs/decentralization/actors", "protocol-specs/decentralization/governance", diff --git a/grafana_dashboards/aztec/aztec-node-dashboard.json b/grafana_dashboards/aztec/aztec-node-dashboard.json new file mode 100644 index 000000000000..863e0079d491 --- /dev/null +++ b/grafana_dashboards/aztec/aztec-node-dashboard.json @@ -0,0 +1,576 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Stats from the Aztec Node", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 6, + "panels": [], + "title": "Node status", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "fieldMinMax": false, + "mappings": [], + "max": 1, + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 0, + "y": 1 + }, + "id": 7, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "center", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "valueSize": 64 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(process_cpu_utilization)", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "CPU utilization", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 15, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 1, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 5, + "y": 1 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "system_memory_usage{system_memory_state=\"used\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Memory use", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 12, + "y": 1 + }, + "id": 9, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "aztec_archiver_block_height", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Current block height", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 0, + "displayName": "txs/block", + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 17, + "y": 1 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "text": { + "titleSize": 12 + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(aztec_archiver_block_size_sum[$__rate_interval]) / rate(aztec_archiver_block_size_count[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Average block size", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 3, + "panels": [], + "title": "Mempool", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(aztec_mempool_tx_size_bytes_sum[$__rate_interval]) / rate(aztec_mempool_tx_size_bytes_count[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Tx size", + "range": true, + "refId": "Avg tx size", + "useBackend": false + } + ], + "title": "Average transaction size ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["last"], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.0.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "aztec_mempool_tx_count", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "tx", + "useBackend": false + } + ], + "title": "Transactions in mempool", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Aztec Node", + "uid": "edp4qxqgjoav4e", + "version": 1, + "weekStart": "" +} diff --git a/grafana_dashboards/aztec/protocol-circuits-dashboard.json b/grafana_dashboards/aztec/protocol-circuits-dashboard.json new file mode 100644 index 000000000000..1849485d30c1 --- /dev/null +++ b/grafana_dashboards/aztec/protocol-circuits-dashboard.json @@ -0,0 +1,747 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Metrics relating to protocol circuits", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 3, + "panels": [], + "title": "Circuit proving", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"base-parity\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Base parity", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"root-parity\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Root parity", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"base-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Base rollup", + "range": true, + "refId": "C", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"merge-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Merge rollup", + "range": true, + "refId": "D", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"root-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Root rollup", + "range": true, + "refId": "E", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-setup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Setup", + "range": true, + "refId": "F", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-app-logic\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - App logic", + "range": true, + "refId": "G", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-teardown\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Teardown", + "range": true, + "refId": "H", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_proving_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-tail\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Tail", + "range": true, + "refId": "I", + "useBackend": false + } + ], + "title": "Circuit proving", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"base-parity\"}", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Base parity", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"root-parity\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Root parity", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"base-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Base rollup", + "range": true, + "refId": "C", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"merge-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Merge rollup", + "range": true, + "refId": "D", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"root-rollup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Root rollup", + "range": true, + "refId": "E", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-setup\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Setup", + "range": true, + "refId": "F", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-app-logic\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - App logic", + "range": true, + "refId": "G", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-teardown\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Teardown", + "range": true, + "refId": "H", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "aztec_circuit_witness_generation_duration_seconds{aztec_circuit_protocol_circuit_name=\"public-kernel-tail\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Public Kernel - Tail", + "range": true, + "refId": "I", + "useBackend": false + } + ], + "title": "Circuit witness generation", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 2, + "panels": [], + "title": "Circuit simulation", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "noValue": "0", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "maxHeight": 600, + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"base-parity\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"base-parity\"}[$__rate_interval])", + "instant": false, + "legendFormat": "Base paritiy", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"root-parity\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"root-parity\"}[$__rate_interval])", + "hide": true, + "instant": false, + "legendFormat": "Root paritiy", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"base-rollup\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"base-rollup\"}[$__rate_interval])", + "hide": true, + "instant": false, + "legendFormat": "Base rollup", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"merge-rollup\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"merge-rollup\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Merge rollup", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"root-rollup\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"root-rollup\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Root rollup", + "range": true, + "refId": "E" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"public-kernel-setup\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"public-kernel-setup\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Public kernel - Setup", + "range": true, + "refId": "F" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"public-kernel-app-logic\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"public-kernel-app-logic\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Public kernel - App logic", + "range": true, + "refId": "H" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"public-kernel-teardown\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"public-kernel-teardown\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Public kernel - Teardown", + "range": true, + "refId": "I" + }, + { + "datasource": { + "type": "prometheus", + "uid": "aztec-node-metrics" + }, + "editorMode": "code", + "expr": "rate(aztec_circuit_simulation_duration_seconds_sum{aztec_circuit_protocol_circuit_name=\"public-kernel-tail\"}[$__rate_interval]) / rate(aztec_circuit_simulation_duration_seconds_count{aztec_circuit_protocol_circuit_name=\"public-kernel-tail\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Public kernel - Tail", + "range": true, + "refId": "G" + } + ], + "title": "Circuit simulation (only when faking proofs)", + "type": "timeseries" + } + ], + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timeRangeUpdatedDuringEditOrView": false, + "timepicker": {}, + "timezone": "browser", + "title": "Protocol circuits", + "uid": "ddp5sfpkscb9cf", + "version": 3, + "weekStart": "" +} diff --git a/grafana_dashboards/default.yml b/grafana_dashboards/default.yml new file mode 100644 index 000000000000..d83924c0ffb6 --- /dev/null +++ b/grafana_dashboards/default.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: "Aztec" + orgId: 1 + folder: "Aztec" + type: file + disableDeletion: false + editable: true + options: + path: /etc/grafana/provisioning/dashboards/aztec diff --git a/noir-projects/Dockerfile.test b/noir-projects/Dockerfile.test index 40edcbaaf35e..91adc723c6a5 100644 --- a/noir-projects/Dockerfile.test +++ b/noir-projects/Dockerfile.test @@ -28,7 +28,9 @@ RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ # Wait for TXE to initialize sleep 5 && \ cd ./noir-contracts && \ - ./bootstrap.sh && nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ + # We need to increase the timeout since all tests running in parallel hammer TXE at the same time, and processing slows down leading to timeouts + # The only way we currently have to batch tests is via RAYON_NUM_THREADS, which is not ideal + ./bootstrap.sh && NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ kill $(cat /tmp/txe.pid) RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ diff --git a/noir-projects/Earthfile b/noir-projects/Earthfile index df8db2aa0469..a828544fea27 100644 --- a/noir-projects/Earthfile +++ b/noir-projects/Earthfile @@ -58,7 +58,10 @@ test: RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ # Wait for TXE to initialize sleep 5 && \ - cd /usr/src/noir-projects/noir-contracts && nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ + cd /usr/src/noir-projects/noir-contracts && \ + # We need to increase the timeout since all tests running in parallel hammer TXE at the same time and processing slows down, leading to timeouts + # The only way we currently have to batch tests is via RAYON_NUM_THREADS, which is not ideal + NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ kill $(cat /tmp/txe.pid) format: diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index a9b40658cc8a..3f39ac213c50 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 = 2e5113eff6fa3209baf95f4053cda88f821a664f + commit = 65a04245e871878b76ba738dc13d2a8cc1cda2e3 method = merge cmdver = 0.4.6 - parent = 4913192d0539a407399ad77e31ab1346930c1361 + parent = f6b4d721f92ed87d3f865254c240e80f26a36c30 diff --git a/noir-projects/aztec-nr/authwit/src/account.nr b/noir-projects/aztec-nr/authwit/src/account.nr index c00592520a3d..3f63137f08cc 100644 --- a/noir-projects/aztec-nr/authwit/src/account.nr +++ b/noir-projects/aztec-nr/authwit/src/account.nr @@ -31,8 +31,8 @@ impl AccountActions<&mut PrivateContext> { } // docs:end:entrypoint - // docs:start:spend_private_authwit - pub fn spend_private_authwit(self, inner_hash: Field) -> Field { + // docs:start:verify_private_authwit + pub fn verify_private_authwit(self, inner_hash: Field) -> Field { // The `inner_hash` is "siloed" with the `msg_sender` to ensure that only it can // consume the message. // This ensures that contracts cannot consume messages that are not intended for them. @@ -44,8 +44,7 @@ impl AccountActions<&mut PrivateContext> { ); let valid_fn = self.is_valid_impl; assert(valid_fn(self.context, message_hash) == true, "Message not authorized by account"); - self.context.push_new_nullifier(message_hash, 0); IS_VALID_SELECTOR } - // docs:end:spend_private_authwit + // docs:end:verify_private_authwit } diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index b24bad76c171..18342ce4f7b6 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -1,6 +1,9 @@ use dep::aztec::protocol_types::{ abis::function_selector::FunctionSelector, address::AztecAddress, - constants::{GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, CANONICAL_AUTH_REGISTRY_ADDRESS}, + constants::{ + GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER, + CANONICAL_AUTH_REGISTRY_ADDRESS +}, hash::pedersen_hash }; use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array}; @@ -10,20 +13,36 @@ global IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256("IS_VALID() // docs:start:assert_current_call_valid_authwit // Assert that `on_behalf_of` have authorized the current call with a valid authentication witness pub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) { - let function_selector = FunctionSelector::from_signature("spend_private_authwit(Field)"); let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]); - let result: Field = context.call_private_function(on_behalf_of, function_selector, [inner_hash]).unpack_into(); - assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); + assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash); } // docs:end:assert_current_call_valid_authwit +pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) { + // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter. + let result: Field = context.static_call_private_function( + on_behalf_of, + FunctionSelector::from_signature("verify_private_authwit(Field)"), + [inner_hash] + ).unpack_into(); + assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); + // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version. + // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors. + let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); + context.push_new_nullifier(nullifier, 0); +} + // docs:start:assert_current_call_valid_authwit_public // Assert that `on_behalf_of` have authorized the current call in a public context pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) { let inner_hash = compute_inner_authwit_hash( [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()] ); + assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash); +} +// docs:end:assert_current_call_valid_authwit_public +pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) { let result: Field = context.call_public_function( AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS), FunctionSelector::from_signature("consume((Field),Field)"), @@ -32,7 +51,6 @@ pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_ ).deserialize_into(); assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); } -// docs:end:assert_current_call_valid_authwit_public // docs:start:compute_call_authwit_hash // Compute the message hash to be used by an authentication witness @@ -54,6 +72,13 @@ pub fn compute_inner_authwit_hash(args: [Field; N]) -> Field { pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER) } +pub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field { + pedersen_hash( + [on_behalf_of.to_field(), inner_hash], + GENERATOR_INDEX__AUTHWIT_NULLIFIER + ) +} + pub fn compute_outer_authwit_hash( consumer: AztecAddress, chain_id: Field, diff --git a/noir-projects/aztec-nr/authwit/src/cheatcodes.nr b/noir-projects/aztec-nr/authwit/src/cheatcodes.nr new file mode 100644 index 000000000000..f673a2032772 --- /dev/null +++ b/noir-projects/aztec-nr/authwit/src/cheatcodes.nr @@ -0,0 +1,44 @@ +use dep::aztec::{ + protocol_types::address::AztecAddress, + context::{public_context::PublicContext, call_interfaces::CallInterface}, test::helpers::cheatcodes, + hash::hash_args +}; + +use crate::auth::{compute_inner_authwit_hash, compute_outer_authwit_hash, set_authorized}; + +pub fn add_private_authwit_from_call_interface( + on_behalf_of: AztecAddress, + caller: AztecAddress, + call_interface: C +) where C: CallInterface { + let target = call_interface.get_contract_address(); + let inputs = cheatcodes::get_private_context_inputs(cheatcodes::get_block_number()); + let chain_id = inputs.tx_context.chain_id; + let version = inputs.tx_context.version; + let args_hash = hash_args(call_interface.get_args()); + let selector = call_interface.get_selector(); + let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); + let message_hash = compute_outer_authwit_hash(target, chain_id, version, inner_hash); + cheatcodes::add_authwit(on_behalf_of, message_hash); +} + +pub fn add_public_authwit_from_call_interface( + on_behalf_of: AztecAddress, + caller: AztecAddress, + call_interface: C +) where C: CallInterface { + let current_contract = cheatcodes::get_contract_address(); + cheatcodes::set_contract_address(on_behalf_of); + let target = call_interface.get_contract_address(); + let inputs = cheatcodes::get_private_context_inputs(cheatcodes::get_block_number()); + let chain_id = inputs.tx_context.chain_id; + let version = inputs.tx_context.version; + let args_hash = hash_args(call_interface.get_args()); + let selector = call_interface.get_selector(); + let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); + let message_hash = compute_outer_authwit_hash(target, chain_id, version, inner_hash); + let mut inputs = cheatcodes::get_public_context_inputs(); + let mut context = PublicContext::new(inputs); + set_authorized(&mut context, message_hash, true); + cheatcodes::set_contract_address(current_contract); +} diff --git a/noir-projects/aztec-nr/authwit/src/lib.nr b/noir-projects/aztec-nr/authwit/src/lib.nr index e56460fd7019..c4d792a4a26c 100644 --- a/noir-projects/aztec-nr/authwit/src/lib.nr +++ b/noir-projects/aztec-nr/authwit/src/lib.nr @@ -2,3 +2,4 @@ mod account; mod auth_witness; mod auth; mod entrypoint; +mod cheatcodes; diff --git a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr index dd1374f9eb01..35151d1427d0 100644 --- a/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr +++ b/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr @@ -16,6 +16,7 @@ trait CallInterface { fn get_selector(self) -> FunctionSelector; fn get_name(self) -> str; fn get_contract_address(self) -> AztecAddress; + fn get_is_static(self) -> bool; } impl CallInterface for PrivateCallInterface { @@ -38,6 +39,10 @@ impl CallInterface AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PrivateCallInterface { @@ -46,7 +51,8 @@ struct PrivateCallInterface { name: str, args_hash: Field, args: [Field], - original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs + original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs, + is_static: bool } impl PrivateCallInterface { @@ -93,6 +99,10 @@ impl CallInterface AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PrivateVoidCallInterface { @@ -101,7 +111,8 @@ struct PrivateVoidCallInterface { name: str, args_hash: Field, args: [Field], - original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs + original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs, + is_static: bool } impl PrivateVoidCallInterface { @@ -144,6 +155,10 @@ impl CallInterface AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PrivateStaticCallInterface { @@ -152,7 +167,8 @@ struct PrivateStaticCallInterface { name: str, args_hash: Field, args: [Field], - original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs + original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs, + is_static: bool } impl PrivateStaticCallInterface { @@ -182,6 +198,10 @@ impl CallInterface AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PrivateStaticVoidCallInterface { @@ -190,7 +210,8 @@ struct PrivateStaticVoidCallInterface { name: str, args_hash: Field, args: [Field], - original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs + original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs, + is_static: bool } impl PrivateStaticVoidCallInterface { @@ -219,6 +240,10 @@ impl CallInterface for PublicCallI fn get_contract_address(self) -> AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PublicCallInterface { @@ -227,7 +252,8 @@ struct PublicCallInterface { name: str, args: [Field], gas_opts: GasOpts, - original: fn[Env](PublicContextInputs) -> T + original: fn[Env](PublicContextInputs) -> T, + is_static: bool } impl PublicCallInterface { @@ -308,6 +334,10 @@ impl CallInterface for PublicVoid fn get_contract_address(self) -> AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PublicVoidCallInterface { @@ -316,7 +346,8 @@ struct PublicVoidCallInterface { name: str, args: [Field], gas_opts: GasOpts, - original: fn[Env](PublicContextInputs) -> () + original: fn[Env](PublicContextInputs) -> (), + is_static: bool } impl PublicVoidCallInterface { @@ -378,7 +409,7 @@ impl PublicVoidCallInterface { } impl CallInterface for PublicStaticCallInterface { - fn get_args(self) -> [Field] { + fn get_args(self) -> [Field] { self.args } @@ -397,6 +428,10 @@ impl CallInterface for PublicStati fn get_contract_address(self) -> AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PublicStaticCallInterface { @@ -405,7 +440,8 @@ struct PublicStaticCallInterface { name: str, args: [Field], gas_opts: GasOpts, - original: fn[Env](PublicContextInputs) -> T + original: fn[Env](PublicContextInputs) -> T, + is_static: bool } impl PublicStaticCallInterface { @@ -453,6 +489,10 @@ impl CallInterface for PublicStat fn get_contract_address(self) -> AztecAddress { self.target_contract } + + fn get_is_static(self) -> bool { + self.is_static + } } struct PublicStaticVoidCallInterface { @@ -461,7 +501,8 @@ struct PublicStaticVoidCallInterface { name: str, args: [Field], gas_opts: GasOpts, - original: fn[Env](PublicContextInputs) -> () + original: fn[Env](PublicContextInputs) -> (), + is_static: bool } impl PublicStaticVoidCallInterface { 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 71d69f484a6c..25bb33ba6633 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,5 +1,3 @@ -use crate::encrypted_logs::{payload::compute_encrypted_note_log}; - use crate::{ context::{inputs::PrivateContextInputs, packed_returns::PackedReturns}, messaging::process_l1_to_l2_message, @@ -10,7 +8,7 @@ use crate::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, logs::{ - emit_encrypted_note_log, emit_encrypted_event_log, compute_encrypted_event_log, + emit_encrypted_note_log, emit_encrypted_event_log, emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal }, logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, @@ -276,10 +274,7 @@ impl PrivateContext { // --> might be a better approach to force devs to make a public function call that emits the log if needed then // it would be less easy to accidentally leak information. // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log. - pub fn emit_unencrypted_log( - &mut self, - log: T - ) where T: ToBytesForUnencryptedLog { + pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog { let event_selector = 5; // TODO: compute actual event selector. let contract_address = self.this_address(); let counter = self.next_counter(); @@ -313,36 +308,7 @@ impl PrivateContext { // NB: A randomness value of 0 signals that the kernels should not mask the contract address // used in siloing later on e.g. 'handshaking' contract w/ known address. - pub fn encrypt_and_emit_event( - &mut self, - randomness: Field, // Secret random value used later for masked_contract_address - event_type_id: Field, - ovpk_m: GrumpkinPoint, - ivpk_m: GrumpkinPoint, - preimage: [Field; N] - ) where [Field; N]: LensForEncryptedLog { - let ovsk_app = self.request_ovsk_app(ovpk_m.hash()); - let contract_address = self.this_address(); - - // We are currently just encrypting it unconstrained, but otherwise the same way as if it was a note. - let encrypted_log: [u8; M] = compute_encrypted_event_log( - contract_address, - randomness, - event_type_id, - ovsk_app, - ovpk_m, - ivpk_m, - preimage - ); - - self.emit_raw_event_log_with_masked_address(randomness, encrypted_log); - } - - pub fn emit_raw_event_log_with_masked_address( - &mut self, - randomness: Field, - encrypted_log: [u8; M] - ) { + pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) { let counter = self.next_counter(); let contract_address = self.this_address(); let len = encrypted_log.len() as Field + 4; diff --git a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr index 514995eedd8a..8811a048c0db 100644 --- a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr @@ -2,7 +2,9 @@ use dep::protocol_types::address::AztecAddress; struct UnconstrainedContext { block_number: u32, - contract_address: AztecAddress, + contract_address: AztecAddress, + version: Field, + chain_id: Field, } impl UnconstrainedContext { @@ -13,7 +15,9 @@ impl UnconstrainedContext { // available. let block_number = block_number_oracle(); let contract_address = contract_address_oracle(); - Self { block_number, contract_address } + let chain_id = chain_id_oracle(); + let version = version_oracle(); + Self { block_number, contract_address, version, chain_id } } fn block_number(self) -> u32 { @@ -23,6 +27,14 @@ impl UnconstrainedContext { fn this_address(self) -> AztecAddress { self.contract_address } + + fn version(self) -> Field { + self.version + } + + fn chain_id(self) -> Field { + self.chain_id + } } #[oracle(getContractAddress)] @@ -30,3 +42,9 @@ unconstrained fn contract_address_oracle() -> AztecAddress {} #[oracle(getBlockNumber)] unconstrained fn block_number_oracle() -> u32 {} + +#[oracle(getChainId)] +unconstrained fn chain_id_oracle() -> Field {} + +#[oracle(getVersion)] +unconstrained fn version_oracle() -> Field {} diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr index 2f1b93d9aad1..dfc49fc0a86e 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr @@ -3,3 +3,4 @@ mod incoming_body; mod outgoing_body; mod payload; mod encrypted_note_emission; +mod encrypted_event_emission; diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr new file mode 100644 index 000000000000..a027c1685150 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr @@ -0,0 +1,45 @@ +use crate::{ + context::PrivateContext, event::event_interface::EventInterface, + encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent +}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; + +fn emit_with_keys( + context: &mut PrivateContext, + randomness: Field, + event: Event, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + let contract_address: AztecAddress = context.this_address(); + let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); + + let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event); + + context.emit_raw_event_log_with_masked_address(randomness, encrypted_log); +} + +pub fn encode_and_encrypt_event( + context: &mut PrivateContext, + randomness: Field, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + emit_with_keys(context, randomness, e, ovpk, ivpk); + } +} + +pub fn encode_and_encrypt_event_with_keys( + context: &mut PrivateContext, + randomness: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + emit_with_keys(context, randomness, e, ovpk, ivpk); + } +} diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 12994a4b4fae..5b66e2e80270 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -33,7 +33,7 @@ fn emit_with_keys( context.emit_raw_note_log(note_hash_counter, encrypted_log); } -pub fn encode_and_encrypt( +pub fn encode_and_encrypt_note( context: &mut PrivateContext, ov: AztecAddress, iv: AztecAddress @@ -46,7 +46,7 @@ pub fn encode_and_encrypt( } } -pub fn encode_and_encrypt_with_keys( +pub fn encode_and_encrypt_note_with_keys( context: &mut PrivateContext, ovpk: GrumpkinPoint, ivpk: GrumpkinPoint diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr index 98c2d42d5b9c..8819906d2b02 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr @@ -44,7 +44,7 @@ fn test_encrypted_log_header() { let ciphertext = header.compute_ciphertext(secret, point); let expected_header_ciphertext = [ - 131, 119, 105, 129, 244, 32, 151, 205, 12, 99, 93, 62, 10, 180, 72, 21, 179, 36, 250, 95, 56, 167, 171, 16, 195, 164, 223, 57, 75, 5, 24, 119, 198, 34, 99, 189, 193, 183, 227, 43, 79, 204, 214, 89, 221, 153, 246, 64 + 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 23, 131, 32, 226, 26, 176, 43, 39, 239, 177, 177, 192, 85, 216, 17, 15, 18, 187, 35, 225, 135, 192, 63, 88, 29, 173, 232, 46, 72, 82, 187, 139 ]; assert_eq(ciphertext, expected_header_ciphertext); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 871f5fd7771e..07e0cb74b123 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -15,8 +15,8 @@ impl EncryptedLogIncomingBody { EncryptedLogIncomingBody { plaintext } } - pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface { - let mut plaintext = event.to_be_bytes(randomness); + pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface { + let mut plaintext = event.private_to_be_bytes(randomness); EncryptedLogIncomingBody { plaintext } } @@ -38,7 +38,7 @@ mod test { use dep::protocol_types::{ address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, traits::Serialize, - abis::function_selector::FunctionSelector + abis::event_selector::EventSelector }; use crate::{ @@ -60,7 +60,9 @@ mod test { impl NoteInterface for AddressNote { fn compute_note_content_hash(self) -> Field {1} - fn get_note_type_id() -> Field {1} + fn get_note_type_id() -> Field { + 1 + } fn get_header(self) -> NoteHeader { self.header} @@ -131,7 +133,7 @@ mod test { let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app); let expected_note_body_ciphertext = [ - 131, 119, 105, 129, 244, 32, 151, 205, 12, 99, 93, 62, 10, 180, 72, 21, 47, 232, 95, 17, 240, 230, 80, 129, 174, 158, 23, 76, 114, 185, 43, 18, 254, 148, 147, 230, 66, 216, 167, 62, 180, 213, 238, 33, 108, 29, 84, 139, 99, 206, 212, 253, 92, 116, 137, 31, 0, 104, 45, 91, 250, 109, 141, 114, 189, 53, 35, 60, 108, 156, 170, 206, 150, 114, 150, 187, 198, 13, 62, 153, 133, 13, 169, 167, 242, 221, 40, 168, 186, 203, 104, 82, 47, 238, 142, 179, 90, 37, 9, 70, 245, 176, 122, 247, 42, 87, 75, 7, 20, 89, 166, 123, 14, 26, 230, 156, 49, 94, 0, 94, 72, 58, 171, 239, 115, 174, 155, 7, 151, 17, 60, 206, 193, 134, 70, 87, 215, 88, 21, 194, 63, 26, 106, 105, 124, 213, 252, 152, 192, 71, 115, 13, 181, 5, 169, 15, 170, 196, 174, 228, 170, 192, 91, 76, 110, 220, 89, 47, 248, 144, 189, 251, 167, 149, 248, 226 + 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100 ]; assert_eq(expected_note_body_ciphertext.len(), ciphertext.len()); @@ -155,17 +157,18 @@ mod test { global TEST_EVENT_LEN: Field = 3; global TEST_EVENT_BYTES_LEN = 32 * 3 + 64; + global TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS = 32 * 3 + 32; - impl EventInterface for TestEvent { - fn _selector(self) -> FunctionSelector { - FunctionSelector::from_signature("TestEvent(Field,Field,Field)") + impl EventInterface for TestEvent { + fn get_event_type_id() -> EventSelector { + EventSelector::from_signature("TestEvent(Field,Field,Field)") } - fn to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] { + fn private_to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] { let mut buffer: [u8; TEST_EVENT_BYTES_LEN] = [0; TEST_EVENT_BYTES_LEN]; let randomness_bytes = randomness.to_be_bytes(32); - let event_type_id_bytes = self._selector().to_field().to_be_bytes(32); + let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32); for i in 0..32 { buffer[i] = randomness_bytes[i]; @@ -183,6 +186,31 @@ mod test { buffer } + + fn to_be_bytes(self) -> [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] { + let mut buffer: [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] = [0; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS]; + + let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32); + + for i in 0..32 { + buffer[i] = event_type_id_bytes[i]; + } + + let serialized_event = self.serialize(); + + for i in 0..serialized_event.len() { + let bytes = serialized_event[i].to_be_bytes(32); + for j in 0..32 { + buffer[32 + i * 32 + j] = bytes[j]; + } + } + + buffer + } + + fn emit(self, _emit: fn[Env](Self) -> ()) { + _emit(self); + } } #[test] @@ -206,7 +234,7 @@ mod test { let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app); let expected_event_body_ciphertext = [ - 131, 119, 105, 129, 244, 32, 151, 205, 12, 99, 93, 62, 10, 180, 72, 21, 47, 232, 95, 17, 240, 230, 80, 129, 174, 158, 23, 76, 114, 185, 43, 18, 254, 148, 147, 230, 66, 216, 167, 62, 180, 213, 238, 33, 108, 29, 84, 139, 157, 165, 187, 138, 35, 3, 236, 75, 197, 105, 102, 247, 224, 253, 13, 217, 145, 62, 96, 167, 93, 23, 18, 198, 187, 91, 8, 3, 197, 195, 127, 9, 218, 111, 125, 97, 141, 129, 142, 1, 230, 108, 35, 211, 170, 170, 170, 249, 249, 104, 68, 191, 245, 207, 182, 245, 248, 82, 175, 83, 155, 138, 208, 65, 31, 129, 251, 242, 219, 76, 17, 61, 178, 187, 108, 114, 177, 215, 175, 189, 166, 221, 94, 9, 22, 57, 151, 204, 57, 220, 129, 243, 217, 18, 101, 128, 229, 40, 254, 175, 2, 21, 31, 198, 18, 152, 169, 32, 113, 92, 37, 65, 169, 119, 95, 149, 239, 8, 23, 182, 22, 209, 207, 120, 133, 90, 252, 106 + 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160 ]; assert_eq(expected_event_body_ciphertext.len(), ciphertext.len()); diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr index 4aa90d6d282d..460cc73bb852 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr @@ -99,7 +99,7 @@ mod test { let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk); let expected_outgoing_body_ciphertext = [ - 126, 10, 214, 39, 130, 143, 96, 143, 79, 143, 22, 36, 55, 41, 234, 255, 226, 26, 138, 236, 91, 188, 204, 216, 172, 133, 134, 69, 161, 237, 134, 5, 75, 192, 10, 6, 229, 54, 194, 56, 103, 243, 57, 248, 147, 237, 4, 3, 39, 28, 226, 30, 237, 228, 212, 115, 246, 244, 105, 39, 129, 119, 126, 207, 176, 14, 75, 134, 241, 23, 2, 187, 239, 86, 47, 56, 239, 20, 92, 176, 70, 12, 219, 226, 150, 70, 192, 43, 125, 53, 230, 153, 135, 228, 210, 197, 76, 123, 185, 190, 61, 172, 29, 168, 241, 191, 205, 71, 136, 72, 52, 115, 232, 246, 87, 42, 50, 150, 134, 108, 225, 90, 191, 191, 182, 150, 124, 147, 78, 249, 144, 111, 122, 187, 187, 5, 249, 167, 186, 14, 228, 128, 158, 138, 55, 99, 228, 46, 219, 187, 248, 122, 70, 31, 39, 209, 127, 23, 244, 84, 14, 93, 86, 208, 155, 151, 238, 70, 63, 3, 137, 59, 206, 230, 4, 20 + 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 122, 191, 158, 69, 35, 255, 215, 171, 196, 45, 91, 184, 83, 80, 238, 201, 1, 233, 235, 159, 171, 130, 158, 64, 176, 165, 132, 30, 84, 81, 71, 195, 145, 47, 82, 247, 210, 192, 23, 4, 220, 90, 56, 109, 46, 105, 79, 251, 165, 141, 185, 233, 191, 118, 219, 153, 191, 162, 99, 238, 241, 249, 9, 74, 210, 241, 54, 28, 126, 226, 85, 235, 174, 75, 239, 207, 100, 184, 248, 194 ]; for i in 0..expected_outgoing_body_ciphertext.len() { diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 273142bca9d7..16454145ec4c 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -7,6 +7,7 @@ use dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, fie use crate::oracle::unsafe_rand::unsafe_rand; +use crate::event::event_interface::EventInterface; use crate::note::note_interface::NoteInterface; use crate::encrypted_logs::{ @@ -14,6 +15,63 @@ use crate::encrypted_logs::{ outgoing_body::EncryptedLogOutgoingBody }; +pub fn compute_encrypted_event_log( + contract_address: AztecAddress, + randomness: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + event: Event +) -> [u8; OB] where Event: EventInterface { + // @todo Need to draw randomness from the full domain of Fq not only Fr + let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand()); + let eph_pk = eph_sk.derive_public_key(); + + // TODO: (#7177) This value needs to be populated! + let recipient = AztecAddress::from_field(0); + + let ivpk_app = compute_ivpk_app(ivpk, contract_address); + + let header = EncryptedLogHeader::new(contract_address); + + let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk); + let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk); + let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app); + let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk); + + let mut encrypted_bytes: [u8; OB] = [0; OB]; + // @todo We ignore the tags for now + + let eph_pk_bytes = eph_pk.to_be_bytes(); + for i in 0..64 { + encrypted_bytes[64 + i] = eph_pk_bytes[i]; + } + for i in 0..48 { + encrypted_bytes[128 + i] = incoming_header_ciphertext[i]; + encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i]; + } + for i in 0..176 { + encrypted_bytes[224 + i] = outgoing_body_ciphertext[i]; + } + // Then we fill in the rest as the incoming body ciphertext + let size = OB - 400; + assert_eq(size, incoming_body_ciphertext.len(), "ciphertext length mismatch"); + for i in 0..size { + encrypted_bytes[400 + i] = incoming_body_ciphertext[i]; + } + + // Current unoptimized size of the encrypted log + // incoming_tag (32 bytes) + // outgoing_tag (32 bytes) + // eph_pk (64 bytes) + // incoming_header (48 bytes) + // outgoing_header (48 bytes) + // outgoing_body (176 bytes) + // incoming_body_fixed (64 bytes) + // incoming_body_variable (N * 32 bytes + 16 bytes padding) + encrypted_bytes +} + pub fn compute_encrypted_note_log( contract_address: AztecAddress, storage_slot: Field, @@ -26,7 +84,7 @@ pub fn compute_encrypted_note_log( let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand()); let eph_pk = eph_sk.derive_public_key(); - // @todo This value needs to be populated! + // TODO: (#7177) This value needs to be populated! let recipient = AztecAddress::from_field(0); let ivpk_app = compute_ivpk_app(ivpk, contract_address); diff --git a/noir-projects/aztec-nr/aztec/src/event/event_interface.nr b/noir-projects/aztec-nr/aztec/src/event/event_interface.nr index fe4b63fedd7f..4505dedd1ab3 100644 --- a/noir-projects/aztec-nr/aztec/src/event/event_interface.nr +++ b/noir-projects/aztec-nr/aztec/src/event/event_interface.nr @@ -1,9 +1,10 @@ use crate::context::PrivateContext; use crate::note::note_header::NoteHeader; -use dep::protocol_types::{grumpkin_point::GrumpkinPoint, abis::function_selector::FunctionSelector}; +use dep::protocol_types::{grumpkin_point::GrumpkinPoint, abis::event_selector::EventSelector}; -trait EventInterface { - // Should be autogenerated by the #[aztec(event)] macro unless it is overridden by a custom implementation - fn _selector(self) -> FunctionSelector; - fn to_be_bytes(self, randomness: Field) -> [u8; N]; +trait EventInterface { + fn private_to_be_bytes(self, randomness: Field) -> [u8; NB]; + fn to_be_bytes(self) -> [u8; MB]; + fn get_event_type_id() -> EventSelector; + fn emit(self, _emit: fn[Env](Self) -> ()); } diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index 934306e32ab9..4fa31d5813ec 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -34,7 +34,7 @@ fn check_point_to_symmetric_key() { let key = point_to_symmetric_key(secret, point); // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1 let expected_key = [ - 198, 74, 242, 51, 177, 36, 183, 8, 2, 246, 197, 138, 59, 166, 86, 96, 155, 50, 186, 34, 242, 3, 208, 144, 161, 64, 69, 165, 70, 57, 226, 139 + 49, 167, 146, 222, 151, 129, 138, 184, 87, 210, 245, 249, 99, 100, 1, 59, 223, 180, 5, 99, 14, 7, 177, 236, 159, 203, 231, 72, 220, 180, 241, 23 ]; assert_eq(key, expected_key); } diff --git a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr index e6c82b833d05..fe65ff9e37ed 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr @@ -82,7 +82,8 @@ fn compute_public_keys_hash() { }; let actual = keys.hash(); - let expected_public_keys_hash = 0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3; + let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717; + assert(actual.to_field() == expected_public_keys_hash); } diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 4a7a3a95e945..7fe6021326a6 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -15,12 +15,10 @@ pub fn create_note( let note_hash_counter = context.side_effect_counter; let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; - // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed - Note::set_header(note, header); + note.set_header(header); let inner_note_hash = compute_inner_note_hash(*note); - // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088 - let serialized_note: [Field; N] = Note::serialize_content(*note); + let serialized_note = Note::serialize_content(*note); assert( notify_created_note( storage_slot, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index 4bb26359cab0..d512a3bf0708 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -79,6 +79,7 @@ pub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_F // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields! + // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash() let item = PublicCallStackItem { contract_address: AztecAddress::from_field(reader.read()), function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false }, diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr index c6632f5a4d3d..899f7f0d0d10 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr @@ -31,7 +31,6 @@ impl LensForEncryptedLog<3, 576> for [Field; 3] { impl LensForEncryptedLog<4, 608> for [Field; 4] { fn output_fields(self) -> [Field; 4] {[self[0]; 4]} fn output_bytes(self) -> [u8; 608] {[self[0] as u8; 608]} - } impl LensForEncryptedLog<5, 640> for [Field; 5] { fn output_fields(self) -> [Field; 5] {[self[0]; 5]} @@ -40,7 +39,31 @@ impl LensForEncryptedLog<5, 640> for [Field; 5] { impl LensForEncryptedLog<6, 672> for [Field; 6] { fn output_fields(self) -> [Field; 6] {[self[0]; 6]} fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]} +} +trait LensForEncryptedEvent { + // N = event preimage input in bytes + // M = encryption output len in bytes (= 480 + M) + fn output(self: [u8; N]) -> [u8; M]; +} + +impl LensForEncryptedEvent<96, 512> for [u8; 96] { + fn output(self) -> [u8; 512] {[self[0] as u8; 512]} +} +impl LensForEncryptedEvent<128, 544> for [u8; 128] { + fn output(self) -> [u8; 544] {[self[0] as u8; 544]} +} +impl LensForEncryptedEvent<160, 576> for [u8; 160] { + fn output(self) -> [u8; 576] {[self[0] as u8; 576]} +} +impl LensForEncryptedEvent<192, 608> for [u8; 192] { + fn output(self) -> [u8; 608] {[self[0] as u8; 608]} +} +impl LensForEncryptedEvent<224, 640> for [u8; 224] { + fn output(self) -> [u8; 640] {[self[0] as u8; 640]} +} +impl LensForEncryptedEvent<256, 672> for [u8; 256] { + fn output(self) -> [u8; 672] {[self[0] as u8; 672]} } // This trait defines the length of the inputs in bytes to diff --git a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr index 42c6bcdb7ee3..4d7aad6f6e26 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/notes.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/notes.nr @@ -145,8 +145,7 @@ unconstrained pub fn get_notes( let header = NoteHeader { contract_address, nonce, storage_slot, note_hash_counter }; let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2); let mut note = Note::deserialize_content(serialized_note); - // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed - Note::set_header(&mut note, header); + note.set_header(header); placeholder_opt_notes[i] = Option::some(note); }; } diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers.nr b/noir-projects/aztec-nr/aztec/src/test/helpers.nr index b28a85add1cb..b7164a823595 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers.nr @@ -1,4 +1,4 @@ mod test_environment; mod cheatcodes; -mod types; +mod utils; mod keys; diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr index 014757cf9b00..db5e13ed4240 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr @@ -1,6 +1,9 @@ -use dep::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, PartialAddress}}; +use dep::protocol_types::{ + abis::function_selector::FunctionSelector, address::{AztecAddress, PartialAddress}, + constants::CONTRACT_INSTANCE_LENGTH, contract_instance::ContractInstance +}; use crate::context::inputs::{PublicContextInputs, PrivateContextInputs}; -use crate::test::helpers::types::{Deployer, TestAccount}; +use crate::test::helpers::utils::{Deployer, TestAccount}; use crate::keys::public_keys::PublicKeys; unconstrained pub fn reset() { @@ -19,8 +22,8 @@ unconstrained pub fn get_block_number() -> u32 { oracle_get_block_number() } -unconstrained pub fn advance_blocks(blocks: u32) { - oracle_time_travel(blocks); +unconstrained pub fn advance_blocks_by(blocks: u32) { + oracle_advance_blocks_by(blocks); } unconstrained pub fn get_private_context_inputs(historical_block_number: u32) -> PrivateContextInputs { @@ -31,20 +34,12 @@ unconstrained pub fn get_public_context_inputs() -> PublicContextInputs { oracle_get_public_context_inputs() } -unconstrained pub fn deploy( - path: str, - initializer: str, - args: [Field], - public_keys_hash: Field -) -> AztecAddress { - oracle_deploy(path, initializer, args, public_keys_hash) +unconstrained pub fn deploy(path: str, initializer: str, args: [Field], public_keys_hash: Field) -> ContractInstance { + let instance_fields = oracle_deploy(path, initializer, args, public_keys_hash); + ContractInstance::deserialize(instance_fields) } -unconstrained pub fn direct_storage_write( - contract_address: AztecAddress, - storage_slot: Field, - fields: [Field; N] -) { +unconstrained pub fn direct_storage_write(contract_address: AztecAddress, storage_slot: Field, fields: [Field; N]) { let _hash = direct_storage_write_oracle(contract_address, storage_slot, fields); } @@ -72,6 +67,40 @@ unconstrained pub fn get_side_effects_counter() -> u32 { oracle_get_side_effects_counter() } +unconstrained pub fn add_authwit(address: AztecAddress, message_hash: Field) { + orable_add_authwit(address, message_hash) +} + +unconstrained pub fn assert_public_call_fails(target_address: AztecAddress, function_selector: FunctionSelector, args: [Field]) { + oracle_assert_public_call_fails(target_address, function_selector, args) +} + +unconstrained pub fn assert_private_call_fails( + target_address: AztecAddress, + function_selector: FunctionSelector, + argsHash: Field, + sideEffectsCounter: Field, + isStaticCall: bool, + isDelegateCall: bool +) { + oracle_assert_private_call_fails( + target_address, + function_selector, + argsHash, + sideEffectsCounter, + isStaticCall, + isDelegateCall + ) +} + +unconstrained pub fn add_nullifiers(contractAddress: AztecAddress, nullifiers: [Field]) { + oracle_add_nullifiers(contractAddress, nullifiers) +} + +unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, inner_note_hashes: [Field]) { + oracle_add_note_hashes(contractAddress, inner_note_hashes) +} + #[oracle(reset)] fn oracle_reset() {} @@ -84,8 +113,8 @@ fn oracle_set_contract_address(address: AztecAddress) {} #[oracle(getBlockNumber)] fn oracle_get_block_number() -> u32 {} -#[oracle(timeTravel)] -fn oracle_time_travel(blocks: u32) {} +#[oracle(advanceBlocksBy)] +fn oracle_advance_blocks_by(blocks: u32) {} #[oracle(getPrivateContextInputs)] fn oracle_get_private_context_inputs(historical_block_number: u32) -> PrivateContextInputs {} @@ -99,7 +128,7 @@ fn oracle_deploy( initializer: str, args: [Field], public_keys_hash: Field -) -> AztecAddress {} +) -> [Field; CONTRACT_INSTANCE_LENGTH] {} #[oracle(directStorageWrite)] fn direct_storage_write_oracle( @@ -125,3 +154,30 @@ fn oracle_set_msg_sender(msg_sender: AztecAddress) {} #[oracle(getSideEffectsCounter)] fn oracle_get_side_effects_counter() -> u32 {} + +#[oracle(addAuthWitness)] +fn orable_add_authwit(address: AztecAddress, message_hash: Field) {} + +#[oracle(assertPublicCallFails)] +fn oracle_assert_public_call_fails( + target_address: AztecAddress, + function_selector: FunctionSelector, + args: [Field] +) {} + +#[oracle(assertPrivateCallFails)] +fn oracle_assert_private_call_fails( + target_address: AztecAddress, + function_selector: FunctionSelector, + argsHash: Field, + sideEffectsCounter: Field, + isStaticCall: bool, + isDelegateCall: bool +) {} + +#[oracle(addNullifiers)] +fn oracle_add_nullifiers(contractAddress: AztecAddress, nullifiers: [Field]) {} + +#[oracle(addNoteHashes)] +fn oracle_add_note_hashes(contractAddress: AztecAddress, inner_note_hashes: [Field]) {} + diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 4f2800b19fc9..9b66e64264b3 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -8,9 +8,9 @@ use crate::context::inputs::{PublicContextInputs, PrivateContextInputs}; use crate::context::{packed_returns::PackedReturns, call_interfaces::CallInterface}; use crate::context::{PrivateContext, PublicContext, PrivateVoidCallInterface}; -use crate::test::helpers::{cheatcodes, types::{Deployer, TestAccount}, keys}; +use crate::test::helpers::{cheatcodes, utils::{apply_side_effects_private, Deployer, TestAccount}, keys}; use crate::keys::constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}; -use crate::hash::hash_args; +use crate::hash::{hash_args, hash_args_array}; use crate::note::{ note_header::NoteHeader, note_interface::NoteInterface, @@ -18,16 +18,12 @@ use crate::note::{ }; use crate::oracle::notes::notify_created_note; -struct TestEnvironment { - contract_address: Option, - args_hash: Option, - function_selector: Option -} +struct TestEnvironment {} impl TestEnvironment { fn new() -> Self { cheatcodes::reset(); - Self { contract_address: Option::none(), args_hash: Option::none(), function_selector: Option::none() } + Self {} } fn block_number(self) -> u32 { @@ -40,7 +36,7 @@ impl TestEnvironment { } fn advance_block_by(&mut self, blocks: u32) { - cheatcodes::advance_blocks(blocks); + cheatcodes::advance_blocks_by(blocks); } fn public(self) -> PublicContext { @@ -74,26 +70,41 @@ impl TestEnvironment { test_account.address } - fn create_account_contract(self, secret: Field) -> AztecAddress { + fn create_account_contract(&mut self, secret: Field) -> AztecAddress { let public_keys = cheatcodes::derive_keys(secret); - let args = &[public_keys.ivpk_m.x, public_keys.ivpk_m.y]; - let address = cheatcodes::deploy( + let args = [public_keys.ivpk_m.x, public_keys.ivpk_m.y]; + let instance = cheatcodes::deploy( "@aztec/noir-contracts.js/SchnorrAccount", "constructor", - args, + args.as_slice(), public_keys.hash().to_field() ); - cheatcodes::advance_blocks(1); - let test_account = cheatcodes::add_account(secret, PartialAddress::from_field(address.to_field())); - let address = test_account.address; + cheatcodes::advance_blocks_by(1); + let test_account = cheatcodes::add_account( + secret, + PartialAddress::compute( + instance.contract_class_id, + instance.salt, + instance.initialization_hash, + instance.deployer + ) + ); let keys = test_account.keys; + let address = instance.to_address(); + keys::store_master_key(NULLIFIER_INDEX, address, keys.npk_m); keys::store_master_key(INCOMING_INDEX, address, keys.ivpk_m); keys::store_master_key(OUTGOING_INDEX, address, keys.ovpk_m); keys::store_master_key(TAGGING_INDEX, address, keys.tpk_m); - test_account.address + let selector = FunctionSelector::from_signature("constructor(Field,Field)"); + + let mut context = self.private_at(cheatcodes::get_block_number()); + + let _ = context.call_private_function(address, selector, args); + + address } fn deploy(self, path: str) -> Deployer { @@ -113,7 +124,9 @@ impl TestEnvironment { cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_private_context_inputs(cheatcodes::get_block_number() - 1); inputs.call_context.function_selector = call_interface.get_selector(); + inputs.call_context.is_static_call = call_interface.get_is_static(); let public_inputs = original_fn(inputs); + apply_side_effects_private(target_address, public_inputs); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); @@ -133,7 +146,9 @@ impl TestEnvironment { cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_private_context_inputs(cheatcodes::get_block_number() - 1); inputs.call_context.function_selector = call_interface.get_selector(); + inputs.call_context.is_static_call = call_interface.get_is_static(); let public_inputs = original_fn(inputs); + apply_side_effects_private(target_address, public_inputs); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); @@ -151,6 +166,7 @@ impl TestEnvironment { let mut inputs = cheatcodes::get_public_context_inputs(); inputs.selector = call_interface.get_selector().to_field(); inputs.args_hash = hash_args(call_interface.get_args()); + inputs.is_static_call = call_interface.get_is_static(); let result = original_fn(inputs); cheatcodes::set_contract_address(original_contract_address); @@ -158,21 +174,23 @@ impl TestEnvironment { result } - fn call_public_void(self, call_interface: C) where C: CallInterface { - let original_fn = call_interface.get_original(); - let original_msg_sender = cheatcodes::get_msg_sender(); - let original_contract_address = cheatcodes::get_contract_address(); - let target_address = call_interface.get_contract_address(); - - cheatcodes::set_contract_address(target_address); - cheatcodes::set_msg_sender(original_contract_address); - let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.selector = call_interface.get_selector().to_field(); - inputs.args_hash = hash_args(call_interface.get_args()); - original_fn(inputs); + fn assert_public_call_fails(self, call_interface: C) where C: CallInterface { + cheatcodes::assert_public_call_fails( + call_interface.get_contract_address(), + call_interface.get_selector(), + call_interface.get_args() + ); + } - cheatcodes::set_contract_address(original_contract_address); - cheatcodes::set_msg_sender(original_msg_sender); + fn assert_private_call_fails(self, call_interface: C) where C: CallInterface { + cheatcodes::assert_private_call_fails( + call_interface.get_contract_address(), + call_interface.get_selector(), + hash_args(call_interface.get_args()), + cheatcodes::get_side_effects_counter() as Field, + call_interface.get_is_static(), + false + ); } pub fn store_note_in_cache( @@ -186,12 +204,9 @@ impl TestEnvironment { let note_hash_counter = cheatcodes::get_side_effects_counter(); let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter }; - // TODO: change this to note.set_header(header) once https://github.com/noir-lang/noir/issues/4095 is fixed - Note::set_header(note, header); + note.set_header(header); let inner_note_hash = compute_inner_note_hash(*note); - - // TODO: Strong typing required because of https://github.com/noir-lang/noir/issues/4088 - let serialized_note: [Field; N] = Note::serialize_content(*note); + let serialized_note = Note::serialize_content(*note); assert( notify_created_note( storage_slot, diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/types.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr similarity index 67% rename from noir-projects/aztec-nr/aztec/src/test/helpers/types.nr rename to noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index 7baec3523d8b..808b5ad37f5f 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/types.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -1,6 +1,7 @@ use dep::protocol_types::{ traits::{Deserialize, Serialize}, address::AztecAddress, - abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs} + abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs}, + contract_instance::ContractInstance }; use crate::context::inputs::{PublicContextInputs, PrivateContextInputs}; @@ -9,6 +10,25 @@ use crate::test::helpers::cheatcodes; use crate::keys::public_keys::{PUBLIC_KEYS_LENGTH, PublicKeys}; use crate::hash::hash_args; +use crate::oracle::notes::notify_nullified_note; + +pub fn apply_side_effects_private(contract_address: AztecAddress, public_inputs: PrivateCircuitPublicInputs) { + let mut nullifiers = &[]; + for nullifier in public_inputs.new_nullifiers { + if nullifier.value != 0 { + nullifiers = nullifiers.push_back(nullifier.value); + } + } + cheatcodes::add_nullifiers(contract_address, nullifiers); + let mut note_hashes = &[]; + for note_hash in public_inputs.new_note_hashes { + if note_hash.value != 0 { + note_hashes = note_hashes.push_back(note_hash.value); + } + } + cheatcodes::add_note_hashes(contract_address, note_hashes); +} + struct Deployer { path: str, public_keys_hash: Field @@ -18,14 +38,15 @@ impl Deployer { pub fn with_private_initializer( self, call_interface: C - ) -> AztecAddress where C: CallInterface { - let address = cheatcodes::deploy( + ) -> ContractInstance where C: CallInterface { + let instance = cheatcodes::deploy( self.path, call_interface.get_name(), call_interface.get_args(), self.public_keys_hash ); - cheatcodes::advance_blocks(1); + let address = instance.to_address(); + cheatcodes::advance_blocks_by(1); let block_number = cheatcodes::get_block_number(); let original_fn = call_interface.get_original(); let original_msg_sender = cheatcodes::get_msg_sender(); @@ -35,29 +56,30 @@ impl Deployer { cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_private_context_inputs(block_number - 1); inputs.call_context.function_selector = call_interface.get_selector(); - let _result = original_fn(inputs); - + let public_inputs = original_fn(inputs); + apply_side_effects_private(address, public_inputs); + cheatcodes::advance_blocks_by(1); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); - address + instance } pub fn with_public_initializer( self, call_interface: C - ) -> AztecAddress where C: CallInterface { - let address = cheatcodes::deploy( + ) -> ContractInstance where C: CallInterface { + let instance = cheatcodes::deploy( self.path, call_interface.get_name(), call_interface.get_args(), self.public_keys_hash ); - cheatcodes::advance_blocks(1); + cheatcodes::advance_blocks_by(1); let original_fn = call_interface.get_original(); let original_msg_sender = cheatcodes::get_msg_sender(); let original_contract_address = cheatcodes::get_contract_address(); - cheatcodes::set_contract_address(address); + cheatcodes::set_contract_address(instance.to_address()); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); inputs.selector = call_interface.get_selector().to_field(); @@ -66,12 +88,11 @@ impl Deployer { cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); - address + instance } - pub fn without_initializer(self) -> AztecAddress { - let address = cheatcodes::deploy(self.path, "", &[], self.public_keys_hash); - address + pub fn without_initializer(self) -> ContractInstance { + cheatcodes::deploy(self.path, "", &[], self.public_keys_hash) } } diff --git a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr index ff23dd0e159e..1a84b86acba9 100644 --- a/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr +++ b/noir-projects/aztec-nr/easy-private-state/src/easy_private_uint.nr @@ -1,7 +1,7 @@ use dep::aztec::{ context::PrivateContext, protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}, note::note_getter_options::NoteGetterOptions, state_vars::PrivateSet, - encrypted_logs::encrypted_note_emission::encode_and_encrypt + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note }; use dep::value_note::{filter::filter_notes_min_sum, value_note::ValueNote}; @@ -30,7 +30,7 @@ impl EasyPrivateUint<&mut PrivateContext> { // Insert the new note to the owner's set of notes. // docs:start:insert - self.set.insert(&mut addend_note).emit(encode_and_encrypt(self.context, outgoing_viewer, owner)); + self.set.insert(&mut addend_note).emit(encode_and_encrypt_note(self.context, outgoing_viewer, owner)); // docs:end:insert } @@ -63,6 +63,6 @@ impl EasyPrivateUint<&mut PrivateContext> { // Creates change note for the owner. let result_value = minuend - subtrahend; let mut result_note = ValueNote::new(result_value as Field, owner_npk_m_hash); - self.set.insert(&mut result_note).emit(encode_and_encrypt(self.context, outgoing_viewer, owner)); + self.set.insert(&mut result_note).emit(encode_and_encrypt_note(self.context, outgoing_viewer, owner)); } } diff --git a/noir-projects/aztec-nr/value-note/src/utils.nr b/noir-projects/aztec-nr/value-note/src/utils.nr index 927f83252818..44094999c760 100644 --- a/noir-projects/aztec-nr/value-note/src/utils.nr +++ b/noir-projects/aztec-nr/value-note/src/utils.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::{AztecAddress, PrivateContext, PrivateSet, NoteGetterOptions}; use dep::aztec::note::note_getter_options::SortOrder; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; -use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; +use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use crate::{filter::filter_notes_min_sum, value_note::{ValueNote, VALUE_NOTE_LEN, VALUE_NOTE_BYTES_LEN}}; // Sort the note values (0th field) in descending order. @@ -23,7 +23,7 @@ pub fn increment( let mut note = ValueNote::new(amount, recipient_npk_m_hash); // Insert the new note to the owner's set of notes and emit the log if value is non-zero. - balance.insert(&mut note).emit(encode_and_encrypt(balance.context, outgoing_viewer, recipient)); + balance.insert(&mut note).emit(encode_and_encrypt_note(balance.context, outgoing_viewer, recipient)); } // Find some of the `owner`'s notes whose values add up to the `amount`. diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 53dd5747074e..4e0dae683c95 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -3,6 +3,7 @@ members = [ "contracts/app_subscription_contract", "contracts/auth_contract", "contracts/auth_registry_contract", + "contracts/auth_wit_test_contract", "contracts/avm_initializer_test_contract", "contracts/avm_test_contract", "contracts/fpc_contract", 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 df46548453e0..d9c5e6e6b1d9 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 @@ -9,7 +9,7 @@ contract AppSubscription { AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, - encrypted_logs::encrypted_note_emission::encode_and_encrypt, + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note, protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint} }, authwit::{auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, @@ -45,7 +45,7 @@ contract AppSubscription { // We are emitting both the outgoing and the incoming logs to the subscriber here because passing a separate // outgoing_viewer arg to entrypoint function is impractical and the outgoing are not so valuable here. - storage.subscriptions.at(user_address).replace(&mut note).emit(encode_and_encrypt(&mut context, user_address, user_address)); + storage.subscriptions.at(user_address).replace(&mut note).emit(encode_and_encrypt_note(&mut context, user_address, user_address)); context.set_as_fee_payer(); @@ -116,7 +116,7 @@ contract AppSubscription { let subscriber_npk_m_hash = header.get_npk_m_hash(&mut context, subscriber_address); let mut subscription_note = SubscriptionNote::new(subscriber_npk_m_hash, expiry_block_number, tx_count); - storage.subscriptions.at(subscriber_address).initialize_or_replace(&mut subscription_note).emit(encode_and_encrypt(&mut context, context.msg_sender(), subscriber_address)); + storage.subscriptions.at(subscriber_address).initialize_or_replace(&mut subscription_note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), subscriber_address)); } unconstrained fn is_initialized(subscriber_address: AztecAddress) -> pub bool { diff --git a/noir-projects/noir-contracts/contracts/auth_wit_test_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/auth_wit_test_contract/Nargo.toml new file mode 100644 index 000000000000..dc0fb24920ce --- /dev/null +++ b/noir-projects/noir-contracts/contracts/auth_wit_test_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "auth_wit_test_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/auth_wit_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/auth_wit_test_contract/src/main.nr new file mode 100644 index 000000000000..997d53439a61 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/auth_wit_test_contract/src/main.nr @@ -0,0 +1,14 @@ +contract AuthWitTest { + use dep::aztec::protocol_types::address::AztecAddress; + use dep::authwit::auth::{assert_inner_hash_valid_authwit, assert_inner_hash_valid_authwit_public}; + + #[aztec(private)] + fn consume(on_behalf_of: AztecAddress, inner_hash: Field) { + assert_inner_hash_valid_authwit(&mut context, on_behalf_of, inner_hash); + } + + #[aztec(public)] + fn consume_public(on_behalf_of: AztecAddress, inner_hash: Field) { + assert_inner_hash_valid_authwit_public(&mut context, on_behalf_of, inner_hash); + } +} 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 d870e8564f88..a9dd932bdace 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 @@ -363,19 +363,19 @@ contract AvmTest { // Use the standard context interface to check for a nullifier #[aztec(public)] fn nullifier_exists(nullifier: Field) -> bool { - context.nullifier_exists(nullifier, context.this_address()) + context.nullifier_exists(nullifier, context.storage_address()) } #[aztec(public)] fn assert_nullifier_exists(nullifier: Field) { - assert(context.nullifier_exists(nullifier, context.this_address()), "Nullifier doesn't exist!"); + assert(context.nullifier_exists(nullifier, context.storage_address()), "Nullifier doesn't exist!"); } // Use the standard context interface to emit a new nullifier #[aztec(public)] fn emit_nullifier_and_check(nullifier: Field) { context.push_new_nullifier(nullifier, 0); - let exists = context.nullifier_exists(nullifier, context.this_address()); + let exists = context.nullifier_exists(nullifier, context.storage_address()); assert(exists, "Nullifier was just created, but its existence wasn't detected!"); } diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index e8ae03dd9531..7065267bc2e4 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -6,7 +6,7 @@ use dep::aztec::{ traits::{ToField, Serialize, FromField}, grumpkin_point::GrumpkinPoint, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL }, - encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys, + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys, note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; use dep::std; @@ -114,7 +114,7 @@ impl Deck<&mut PrivateContext> { let mut inserted_cards = &[]; for card in cards { let mut card_note = CardNote::from_card(card, owner_npk_m_hash); - self.set.insert(&mut card_note.note).emit(encode_and_encrypt_with_keys(self.set.context, msg_sender_ovpk_m, owner_ivpk_m)); + self.set.insert(&mut card_note.note).emit(encode_and_encrypt_note_with_keys(self.set.context, msg_sender_ovpk_m, owner_ivpk_m)); inserted_cards = inserted_cards.push_back(card_note); } 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 ab9483cce2ac..bd7220461a15 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -6,7 +6,7 @@ contract Child { context::gas::GasOpts, protocol_types::{abis::call_context::CallContext, grumpkin_point::GrumpkinPoint}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - encrypted_logs::encrypted_note_emission::encode_and_encrypt + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note }; use dep::value_note::value_note::ValueNote; @@ -56,7 +56,7 @@ contract Child { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(new_value, owner_npk_m_hash); - storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt(&mut context, owner, owner)); + storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note(&mut context, owner, owner)); new_value } diff --git a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr index b843313be4be..27631ddbe726 100644 --- a/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/counter_contract/src/main.nr @@ -44,15 +44,19 @@ contract Counter { use dep::aztec::note::note_viewer_options::NoteViewerOptions; #[test] - fn test_initialize() { + fn test_increment() { // Setup env, generate keys let mut env = TestEnvironment::new(); let owner = env.create_account(); let outgoing_viewer = env.create_account(); + let initial_value: Field = 5; + cheatcodes::set_contract_address(owner); // Deploy contract and initialize - let initializer = Counter::interface().initialize(5, owner, outgoing_viewer); - let contract_address = env.deploy("@aztec/noir-contracts.js/Counter").with_private_initializer(initializer); + let initializer = Counter::interface().initialize(initial_value as u64, owner, outgoing_viewer); + let counter_contract = env.deploy("@aztec/noir-contracts.js/Counter").with_private_initializer(initializer); + let contract_address = counter_contract.to_address(); + // Read the stored value in the note cheatcodes::set_contract_address(contract_address); @@ -60,6 +64,18 @@ contract Counter { let owner_slot = derive_storage_slot_in_map(counter_slot, owner); let mut options = NoteViewerOptions::new(); let notes: BoundedVec = view_notes(owner_slot, options); - assert(notes.get(0).value == 5); + let initial_note_value = notes.get(0).value; + assert( + initial_note_value == initial_value, f"Expected {initial_value} but got {initial_note_value}" + ); + + // Increment the counter + let increment_call_interface = Counter::at(contract_address).increment(owner, outgoing_viewer); + env.call_private_void(increment_call_interface); + let current_value_for_owner = get_counter(owner); + let expected_current_value = initial_value + 1; + assert( + expected_current_value == current_value_for_owner, f"Expected {expected_current_value} but got {current_value_for_owner}" + ); } } 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 d5f932c4a757..9e43661a329b 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -8,7 +8,7 @@ contract Crowdfunding { abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, grumpkin_point::GrumpkinPoint }, - encrypted_logs::encrypted_note_emission::encode_and_encrypt, + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; @@ -17,14 +17,8 @@ contract Crowdfunding { #[aztec(event)] struct WithdrawalProcessed { - who: AztecAddress, - amount: u64, - } - - impl Serialize<2> for WithdrawalProcessed { - fn serialize(self: Self) -> [Field; 2] { - [self.who.to_field(), self.amount as Field] - } + who: Field, + amount: Field, } // docs:start:storage @@ -87,7 +81,7 @@ contract Crowdfunding { // contract by proving that the hash of this note exists in the note hash tree. let donor_npk_m_hash = header.get_npk_m_hash(&mut context, donor); let mut note = ValueNote::new(amount as Field, donor_npk_m_hash); - storage.donation_receipts.insert(&mut note).emit(encode_and_encrypt(&mut context, donor, donor)); + storage.donation_receipts.insert(&mut note).emit(encode_and_encrypt_note(&mut context, donor, donor)); } // docs:end:donate @@ -103,7 +97,7 @@ contract Crowdfunding { Token::at(storage.donation_token.read_private()).transfer(operator_address, amount as Field).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 }; + let event = WithdrawalProcessed { amount: amount as Field, who: operator_address.to_field() }; context.emit_unencrypted_log(event.serialize()); } // docs:end:operator-withdrawals diff --git a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr index da7a24ce09b8..7a8484460555 100644 --- a/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegated_on_contract/src/main.nr @@ -4,7 +4,7 @@ contract DelegatedOn { AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PublicMutable, PrivateSet, PrivateContext, Map }; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::aztec::{protocol_types::grumpkin_point::GrumpkinPoint}; use dep::value_note::value_note::ValueNote; @@ -20,7 +20,7 @@ contract DelegatedOn { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(new_value, owner_npk_m_hash); - storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + storage.a_map_with_private_values.at(owner).insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); new_value } 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 9653946054c6..22242e9404a6 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 @@ -18,7 +18,7 @@ contract DocsExample { PrivateContext, Map, PublicMutable, PublicImmutable, PrivateMutable, PrivateImmutable, PrivateSet, SharedImmutable, Deserialize }; - use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys}; + use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys}; use dep::aztec::note::note_getter_options::Comparator; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; // how to import methods from other files/folders within your workspace @@ -173,7 +173,7 @@ contract DocsExample { let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); - storage.private_immutable.initialize(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); + storage.private_immutable.initialize(&mut new_card).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), context.msg_sender())); } // docs:end:initialize-private-mutable @@ -185,7 +185,7 @@ contract DocsExample { let mut legendary_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); // create and broadcast note - storage.legendary_card.initialize(&mut legendary_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); + storage.legendary_card.initialize(&mut legendary_card).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), context.msg_sender())); } #[aztec(private)] @@ -197,7 +197,7 @@ contract DocsExample { for i in 0..amounts.len() { let mut note = CardNote::new(amounts[i], 1, msg_sender_npk_m_hash); - storage.set.insert(&mut note).emit(encode_and_encrypt_with_keys(&mut context, msg_sender_ovpk_m, msg_sender_ivpk_m)); + storage.set.insert(&mut note).emit(encode_and_encrypt_note_with_keys(&mut context, msg_sender_ovpk_m, msg_sender_ivpk_m)); } } @@ -207,7 +207,7 @@ contract DocsExample { let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); let mut note = CardNote::new(amount, randomness, msg_sender_npk_m_hash); - storage.set.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); + storage.set.insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), context.msg_sender())); } // docs:start:state_vars-NoteGetterOptionsComparatorExampleNoir @@ -229,7 +229,7 @@ contract DocsExample { let msg_sender_npk_m_hash = header.get_npk_m_hash(&mut context, context.msg_sender()); let mut new_card = CardNote::new(points, randomness, msg_sender_npk_m_hash); - storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); + storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), context.msg_sender())); DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } @@ -250,14 +250,15 @@ contract DocsExample { let mut new_card = CardNote::new(points, card.randomness, msg_sender_npk_m_hash); // docs:start:state_vars-PrivateMutableReplace - storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt(&mut context, context.msg_sender(), context.msg_sender())); + storage.legendary_card.replace(&mut new_card).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), context.msg_sender())); // docs:end:state_vars-PrivateMutableReplace DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } #[aztec(private)] - fn spend_private_authwit(inner_hash: Field) -> Field { + #[aztec(view)] + fn verify_private_authwit(inner_hash: Field) -> Field { 1 } diff --git a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr index 0bb6c9c00764..f4495e48217d 100644 --- a/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr @@ -4,7 +4,7 @@ mod ecdsa_public_key_note; // The signing key is stored in an immutable private note and should be different from the signing key. contract EcdsaAccount { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, PrivateImmutable}; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::aztec::protocol_types::abis::call_context::CallContext; use dep::std; @@ -33,7 +33,7 @@ contract EcdsaAccount { // important. let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); - storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt(&mut context, this, this)); + storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this)); } // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts @@ -45,15 +45,10 @@ contract EcdsaAccount { #[aztec(private)] #[aztec(noinitcheck)] - fn spend_private_authwit(inner_hash: Field) -> Field { + #[aztec(view)] + fn verify_private_authwit(inner_hash: Field) -> Field { let actions = AccountActions::init(&mut context, is_valid_impl); - actions.spend_private_authwit(inner_hash) - } - - #[aztec(private)] - #[aztec(internal)] - fn cancel_authwit(outer_hash: Field) { - context.push_new_nullifier(outer_hash, 0); + actions.verify_private_authwit(inner_hash) } #[contract_library_method] 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 661283b1f856..27159437c1b3 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -1,7 +1,7 @@ // Sample escrow contract that stores a balance of a private token on behalf of an owner. contract Escrow { use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable}; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::address_note::address_note::AddressNote; @@ -20,7 +20,7 @@ contract Escrow { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = AddressNote::new(owner, owner_npk_m_hash); - storage.owner.initialize(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + storage.owner.initialize(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); } // Withdraws balance. Requires that msg.sender is the owner. diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 372b11fbd5b2..71cc8d803f7a 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -4,7 +4,7 @@ contract InclusionProofs { AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, Map, PrivateSet, PublicMutable }; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::aztec::protocol_types::{grumpkin_point::GrumpkinPoint, contract_class_id::ContractClassId, header::Header}; use dep::aztec::{note::note_getter_options::NoteStatus}; @@ -36,7 +36,7 @@ contract InclusionProofs { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(value, owner_npk_m_hash); - owner_private_values.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + owner_private_values.insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); } // docs:end:create_note 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 b8789b55e6fc..efeae7bcda8f 100644 --- a/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr @@ -257,8 +257,9 @@ contract Parent { let owner = env.create_account(); // Deploy child contract - let child_contract_address = env.deploy("@aztec/noir-contracts.js/Child").without_initializer(); - cheatcodes::advance_blocks(1); + let child_contract = env.deploy("@aztec/noir-contracts.js/Child").without_initializer(); + let child_contract_address = child_contract.to_address(); + cheatcodes::advance_blocks_by(1); // Set value in child through parent let value_to_set = 7; diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index 6f5076d4ddfe..c35c36d6eb52 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -8,7 +8,7 @@ contract PendingNoteHashes { use dep::value_note::{balance_utils, filter::filter_notes_min_sum, value_note::{VALUE_NOTE_LEN, ValueNote}}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; use dep::aztec::protocol_types::constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL}; - use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys}; + use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys}; use dep::aztec::note::note_emission::NoteEmission; #[aztec(storage)] @@ -36,7 +36,7 @@ contract PendingNoteHashes { let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + owner_balance.insert(&mut note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); let options = NoteGetterOptions::with_filter(filter_notes_min_sum, amount); // get note inserted above @@ -71,7 +71,7 @@ contract PendingNoteHashes { // Insert note let mut note = ValueNote::new(amount, owner_npk_m_hash); - owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + owner_balance.insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); 0 } @@ -91,7 +91,7 @@ contract PendingNoteHashes { let mut note = ValueNote::new(amount, owner_npk_m_hash); // Insert note - owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + owner_balance.insert(&mut note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); } // Nested/inner function to create and insert a note @@ -112,7 +112,7 @@ contract PendingNoteHashes { note.randomness = 2; // Insert note - owner_balance.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + owner_balance.insert(&mut note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); } // Nested/inner function to create and insert a note @@ -129,10 +129,10 @@ contract PendingNoteHashes { // Insert note let emission = owner_balance.insert(&mut note); - emission.emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); // Emit note again - emission.emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + emission.emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); } // Nested/inner function to get a note and confirm it matches the expected value @@ -351,7 +351,7 @@ contract PendingNoteHashes { let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); let mut good_note = ValueNote::new(10, owner_npk_m_hash); // Insert good note with real log - owner_balance.insert(&mut good_note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + owner_balance.insert(&mut good_note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); // We will emit a note log with an incorrect preimage to ensure the pxe throws // This note has not been inserted... @@ -360,7 +360,7 @@ contract PendingNoteHashes { let existing_note_header = good_note.get_header(); bad_note.set_header(existing_note_header); - NoteEmission::new(bad_note).emit(encode_and_encrypt_with_keys(&mut context, outgoing_viewer_ovpk_m, owner_ivpk_m)); + NoteEmission::new(bad_note).emit(encode_and_encrypt_note_with_keys(&mut context, outgoing_viewer_ovpk_m, owner_ivpk_m)); } #[contract_library_method] @@ -378,7 +378,7 @@ contract PendingNoteHashes { for i in 0..max_notes_per_call() { let mut note = ValueNote::new(i as Field, owner_npk_m_hash); - owner_balance.insert(&mut note).emit(encode_and_encrypt_with_keys(context, outgoing_viewer_ovpk_m, owner_ivpk_m)); + owner_balance.insert(&mut note).emit(encode_and_encrypt_note_with_keys(context, outgoing_viewer_ovpk_m, owner_ivpk_m)); } } diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 9334077bf57e..8632a64bc62b 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -6,10 +6,10 @@ contract SchnorrAccount { use dep::std; use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable}; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, - auth_witness::get_auth_witness + auth_witness::get_auth_witness, auth::{compute_authwit_nullifier, compute_outer_authwit_hash} }; use dep::aztec::hash::compute_siloed_nullifier; use dep::aztec::oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness; @@ -36,7 +36,7 @@ contract SchnorrAccount { // docs:start:initialize let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash); - storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt(&mut context, this, this)); + storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this)); // docs:end:initialize } @@ -50,15 +50,10 @@ contract SchnorrAccount { #[aztec(private)] #[aztec(noinitcheck)] - fn spend_private_authwit(inner_hash: Field) -> Field { + #[aztec(view)] + fn verify_private_authwit(inner_hash: Field) -> Field { let actions = AccountActions::init(&mut context, is_valid_impl); - actions.spend_private_authwit(inner_hash) - } - - #[aztec(private)] - #[aztec(internal)] - fn cancel_authwit(outer_hash: Field) { - context.push_new_nullifier(outer_hash, 0); + actions.verify_private_authwit(inner_hash) } #[contract_library_method] @@ -90,11 +85,15 @@ contract SchnorrAccount { /** * @notice Helper function to check validity of private authwitnesses + * @param consumer The address of the consumer of the message * @param message_hash The message hash of the message to check the validity * @return True if the message_hash can be consumed, false otherwise */ - unconstrained fn lookup_validity(message_hash: Field) -> pub bool { + unconstrained fn lookup_validity(consumer: AztecAddress, inner_hash: Field) -> pub bool { let public_key = storage.signing_public_key.view_note(); + + let message_hash = compute_outer_authwit_hash(consumer, context.chain_id(), context.version(), inner_hash); + let witness: [Field; 64] = get_auth_witness(message_hash); let mut signature: [u8; 64] = [0; 64]; for i in 0..64 { @@ -107,14 +106,12 @@ contract SchnorrAccount { message_hash.to_be_bytes(32) ); - let block_number = context.block_number(); - let myself = context.this_address(); - // Compute the nullifier and check if it is spent // This will BLINDLY TRUST the oracle, but the oracle is us, and // it is not as part of execution of the contract, so we are good. - let siloed_nullifier = compute_siloed_nullifier(myself, message_hash); - let lower_wit = get_low_nullifier_membership_witness(block_number, siloed_nullifier); + let nullifier = compute_authwit_nullifier(context.this_address(), inner_hash); + let siloed_nullifier = compute_siloed_nullifier(consumer, nullifier); + let lower_wit = get_low_nullifier_membership_witness(context.block_number(), siloed_nullifier); let is_spent = lower_wit.leaf_preimage.nullifier == siloed_nullifier; !is_spent & valid_in_private diff --git a/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr index 3441779536bd..8d776eab233c 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_hardcoded_account_contract/src/main.nr @@ -20,15 +20,10 @@ contract SchnorrHardcodedAccount { } #[aztec(private)] - fn spend_private_authwit(inner_hash: Field) -> Field { + #[aztec(view)] + fn verify_private_authwit(inner_hash: Field) -> Field { let actions = AccountActions::init(&mut context, is_valid_impl); - actions.spend_private_authwit(inner_hash) - } - - #[aztec(private)] - #[aztec(internal)] - fn cancel_authwit(outer_hash: Field) { - context.push_new_nullifier(outer_hash, 0); + actions.verify_private_authwit(inner_hash) } // docs:start:is-valid diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr index ca795fca2526..fbf81afb5fcc 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr @@ -16,15 +16,10 @@ contract SchnorrSingleKeyAccount { } #[aztec(private)] - fn spend_private_authwit(inner_hash: Field) -> Field { + #[aztec(view)] + fn verify_private_authwit(inner_hash: Field) -> Field { let actions = AccountActions::init(&mut context, is_valid_impl); - actions.spend_private_authwit(inner_hash) - } - - #[aztec(private)] - #[aztec(internal)] - fn cancel_authwit(outer_hash: Field) { - context.push_new_nullifier(outer_hash, 0); + actions.verify_private_authwit(inner_hash) } #[contract_library_method] diff --git a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr index 9ed71ce290e9..e0d113569fed 100644 --- a/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/static_child_contract/src/main.nr @@ -5,7 +5,7 @@ contract StaticChild { use dep::aztec::{ context::{PublicContext, gas::GasOpts}, protocol_types::{abis::{call_context::CallContext}}, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, - encrypted_logs::encrypted_note_emission::encode_and_encrypt + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note }; use dep::value_note::value_note::ValueNote; @@ -43,7 +43,7 @@ contract StaticChild { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(new_value, owner_npk_m_hash); - storage.a_private_value.insert(&mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + storage.a_private_value.insert(&mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); new_value } @@ -57,7 +57,7 @@ contract StaticChild { let header = context.get_header(); let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(new_value, owner_npk_m_hash); - storage.a_private_value.insert(&mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + storage.a_private_value.insert(&mut note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); new_value } 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 0ec38297670a..eb34674b095c 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,7 +7,8 @@ contract Test { AztecAddress, EthAddress, FunctionSelector, NoteHeader, NoteGetterOptions, NoteViewerOptions, PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable }; - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt; + use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; + use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys; use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, @@ -41,7 +42,11 @@ contract Test { #[aztec(event)] struct ExampleEvent { - value: Field, + value0: Field, + value1: Field, + value2: Field, + value3: Field, + value4: Field, } #[aztec(storage)] @@ -97,7 +102,7 @@ contract Test { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(value, owner_npk_m_hash); - create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt(&mut context, outgoing_viewer, owner)); + create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt_note(&mut context, outgoing_viewer, owner)); } #[aztec(private)] @@ -262,23 +267,34 @@ contract Test { let header = context.get_header(); let outgoing_viewer_ovpk_m = header.get_ovpk_m(&mut context, outgoing_viewer); let owner_ivpk_m = header.get_ivpk_m(&mut context, owner); - context.encrypt_and_emit_event( - 5, // testing only - this should be a secret random value to salt the addr - 1, - outgoing_viewer_ovpk_m, - owner_ivpk_m, - fields + + let event = ExampleEvent { value0: fields[0], value1: fields[1], value2: fields[2], value3: fields[3], value4: fields[4] }; + + event.emit( + encode_and_encrypt_event_with_keys( + &mut context, + // testing only - a secret random value is passed in here to salt / mask the address + 5, + outgoing_viewer_ovpk_m, + owner_ivpk_m + ) ); + // this contract has reached max number of functions, so using this one fn // to test nested and non nested encrypted logs if nest { Test::at(context.this_address()).emit_array_as_encrypted_log([0, 0, 0, 0, 0], owner, outgoing_viewer, false).call(&mut context); - context.encrypt_and_emit_event( - 0, // testing only - this signals to the kerels to not mask the address - 1, - outgoing_viewer_ovpk_m, - owner_ivpk_m, - [1, 2, 3, 4, 5] + + let otherEvent = ExampleEvent { value0: 1, value1: 2, value2: 3, value3: 4, value4: 5 }; + + otherEvent.emit( + encode_and_encrypt_event_with_keys( + &mut context, + // testing only - a randomness of 0 signals the kerels to not mask the address + 0, + outgoing_viewer_ovpk_m, + owner_ivpk_m + ) ); } } @@ -312,7 +328,7 @@ contract Test { let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); let mut note = ValueNote::new(value + 1, owner_npk_m_hash); - create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt(&mut context, context.msg_sender(), owner)); + create_note(&mut context, storage_slot, &mut note).emit(encode_and_encrypt_note(&mut context, context.msg_sender(), owner)); storage_slot += 1; Test::at(context.this_address()).call_create_note(value + 2, owner, outgoing_viewer, storage_slot).call(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr index 9412f8e19eb5..f42cb2ffd7a7 100644 --- a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr @@ -1,12 +1,10 @@ contract TestLog { use dep::aztec::prelude::PrivateSet; - use dep::aztec::protocol_types::{ - traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, - abis::function_selector::FunctionSelector - }; + use dep::aztec::protocol_types::{traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; use dep::value_note::value_note::ValueNote; use dep::aztec::encrypted_logs::incoming_body::EncryptedLogIncomingBody; use dep::aztec::event::event_interface::EventInterface; + use dep::aztec::encrypted_logs::encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys}; #[aztec(event)] struct ExampleEvent0 { @@ -14,56 +12,12 @@ contract TestLog { value1: Field, } - // This should be autogenerated by the macros - global EXAMPLE_EVENT_0_BYTES_LEN = 32 * 2 + 32 + 32; - - impl EventInterface for ExampleEvent0 { - fn _selector(self) -> FunctionSelector { - FunctionSelector::from_signature("TestEvent(Field,Field,Field)") - } - - fn to_be_bytes(self, randomness: Field) -> [u8; EXAMPLE_EVENT_0_BYTES_LEN] { - let mut buffer: [u8; EXAMPLE_EVENT_0_BYTES_LEN] = [0; EXAMPLE_EVENT_0_BYTES_LEN]; - - let randomness_bytes = randomness.to_be_bytes(32); - let event_type_id_bytes = self._selector().to_field().to_be_bytes(32); - - for i in 0..32 { - buffer[i] = randomness_bytes[i]; - buffer[32 + i] = event_type_id_bytes[i]; - } - - let serialized_event = self.serialize(); - - for i in 0..serialized_event.len() { - let bytes = serialized_event[i].to_be_bytes(32); - for j in 0..32 { - buffer[64 + i * 32 + j] = bytes[j]; - } - } - - buffer - } - } - #[aztec(event)] struct ExampleEvent1 { value2: Field, value3: Field, } - impl Serialize<2> for ExampleEvent0 { - fn serialize(self) -> [Field; 2] { - [self.value0, self.value1] - } - } - - impl Serialize<2> for ExampleEvent1 { - fn serialize(self) -> [Field; 2] { - [self.value2, self.value3] - } - } - #[aztec(storage)] struct Storage { example_set: PrivateSet, @@ -86,41 +40,28 @@ contract TestLog { ).compute_ciphertext(secret, point).as_array() } - #[aztec(private)] - fn emit_encrypted_log(randomness: Field, event_type_id: Field, preimage: [Field; 6]) { - let header = context.get_header(); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - - context.encrypt_and_emit_event( - randomness, - event_type_id, - msg_sender_ovpk_m, - msg_sender_ivpk_m, - preimage - ); - } - #[aztec(private)] fn emit_encrypted_events(randomness: [Field; 2], preimages: [Field; 4]) { - let header = context.get_header(); - let msg_sender_ivpk_m = header.get_ivpk_m(&mut context, context.msg_sender()); - let msg_sender_ovpk_m = header.get_ovpk_m(&mut context, context.msg_sender()); - - context.encrypt_and_emit_event( - randomness[0], - ExampleEvent0::selector().to_field(), - msg_sender_ovpk_m, - msg_sender_ivpk_m, - ExampleEvent0 { value0: preimages[0], value1: preimages[1] }.serialize() + let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; + + event0.emit( + encode_and_encrypt_event( + &mut context, + randomness[0], + context.msg_sender(), + context.msg_sender() + ) ); - context.encrypt_and_emit_event( - randomness[1], - ExampleEvent1::selector().to_field(), - msg_sender_ovpk_m, - msg_sender_ivpk_m, - ExampleEvent1 { value2: preimages[2], value3: preimages[3] }.serialize() + let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] }; + + event1.emit( + encode_and_encrypt_event( + &mut context, + randomness[1], + context.msg_sender(), + context.msg_sender() + ) ); } } 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 defab65772e6..114fa7645151 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 @@ -13,7 +13,7 @@ contract TokenBlacklist { use dep::aztec::{ hash::compute_secret_hash, prelude::{AztecAddress, FunctionSelector, Map, NoteGetterOptions, PrivateSet, PublicMutable, SharedMutable}, - encrypted_logs::encrypted_note_emission::encode_and_encrypt + encrypted_logs::encrypted_note_emission::encode_and_encrypt_note }; use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; @@ -179,7 +179,7 @@ contract TokenBlacklist { // Add the token note to user's balances set let caller = context.msg_sender(); - storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, caller, to)); + storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, to)); } #[aztec(private)] @@ -195,7 +195,7 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); TokenBlacklist::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } @@ -215,8 +215,8 @@ contract TokenBlacklist { } let amount = U128::from_integer(amount); - storage.balances.sub(from, amount).emit(encode_and_encrypt(&mut context, from, from)); - storage.balances.add(to, amount).emit(encode_and_encrypt(&mut context, from, to)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note(&mut context, from, from)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note(&mut context, from, to)); } #[aztec(private)] @@ -230,7 +230,7 @@ contract TokenBlacklist { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); TokenBlacklist::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } 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 b263abeff013..d13145c89e2e 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -1,6 +1,7 @@ // docs:start:token_all // docs:start:imports mod types; +mod test; // Minimal token implementation that supports `AuthWit` accounts. // The auth message follows a similar pattern to the cross-chain message and includes a designated caller. @@ -17,11 +18,11 @@ contract Token { use dep::aztec::{ hash::compute_secret_hash, prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, - encrypted_logs::encrypted_note_emission::{encode_and_encrypt, encode_and_encrypt_with_keys} + encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys} }; // docs:start:import_authwit - use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; + use dep::authwit::auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public, compute_authwit_nullifier}; // docs:end:import_authwit use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; @@ -195,7 +196,7 @@ contract Token { #[aztec(private)] fn privately_mint_private_note(amount: Field) { let caller = context.msg_sender(); - storage.balances.add(caller, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, caller, caller)); + storage.balances.add(caller, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, caller)); Token::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); } @@ -289,7 +290,7 @@ contract Token { // Note: Using context.msg_sender() as a sender below makes this incompatible with escrows because we send // outgoing logs to that address and to send outgoing logs you need to get a hold of ovsk_m. let from = context.msg_sender(); - storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, to)); + storage.balances.add(to, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, to)); } // docs:end:redeem_shield @@ -302,7 +303,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); Token::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } @@ -321,11 +322,22 @@ contract Token { let to_ivpk = header.get_ivpk_m(&mut context, to); let amount = U128::from_integer(amount); - storage.balances.sub(from, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, from_ivpk)); - storage.balances.add(to, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, to_ivpk)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); } // docs:end:transfer + /** + * Cancel a private authentication witness. + * @param inner_hash The inner hash of the authwit to cancel. + */ + #[aztec(private)] + fn cancel_authwit(inner_hash: Field) { + let on_behalf_of = context.msg_sender(); + let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); + context.push_new_nullifier(nullifier, 0); + } + #[aztec(private)] fn transfer_from(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { // docs:start:assert_current_call_valid_authwit @@ -346,10 +358,10 @@ contract Token { let amount = U128::from_integer(amount); // docs:start:increase_private_balance // docs:start:encrypted - storage.balances.sub(from, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, from_ivpk)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); // docs:end:encrypted // docs:end:increase_private_balance - storage.balances.add(to, amount).emit(encode_and_encrypt_with_keys(&mut context, from_ovpk, to_ivpk)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); } // docs:start:burn @@ -361,7 +373,7 @@ contract Token { assert(nonce == 0, "invalid nonce"); } - storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt(&mut context, from, from)); + storage.balances.sub(from, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, from, from)); Token::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } @@ -395,75 +407,5 @@ contract Token { storage.balances.balance_of(owner).to_field() } // docs:end:balance_of_private - - use dep::aztec::test::{helpers::{cheatcodes, test_environment::TestEnvironment}}; - use dep::aztec::protocol_types::storage::map::derive_storage_slot_in_map; - use dep::aztec::note::note_getter::{MAX_NOTES_PER_PAGE, view_notes}; - use dep::aztec::note::note_viewer_options::NoteViewerOptions; - - #[test] - fn test_private_transfer() { - // Setup env, generate keys - let mut env = TestEnvironment::new(); - let owner = env.create_account(); - let recipient = env.create_account(); - let mint_amount = 10000; - - // Start the test in the account contract address - cheatcodes::set_contract_address(owner); - - // Deploy token contract - let initializer_call_interface = Token::interface().constructor( - owner, - "TestToken0000000000000000000000", - "TT00000000000000000000000000000", - 18 - ); - let token_contract_address = env.deploy("@aztec/noir-contracts.js/Token").with_public_initializer(initializer_call_interface); - env.advance_block_by(1); - - // Mint some tokens - let secret = 1; - let secret_hash = compute_secret_hash(secret); - let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); - env.call_public(mint_private_call_interface); - - // Time travel so we can read keys from the registry - env.advance_block_by(6); - - // Store a note in the cache so we can redeem it - env.store_note_in_cache( - &mut TransparentNote::new(mint_amount, secret_hash), - Token::storage().pending_shields.slot, - token_contract_address - ); - - // Redeem our shielded tokens - let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret); - env.call_private_void(redeem_shield_call_interface); - - // Not really sure why this is needed? Nullifier inclusion in contract initializer fails otherwise. - // If it were to fail, it should do it at line 443, investigation required - env.advance_block_by(1); - - // Transfer tokens - let transfer_amount = 1000; - let private_token_transfer_call_interface = Token::at(token_contract_address).transfer(recipient, transfer_amount); - env.call_private_void(private_token_transfer_call_interface); - - // Check balances - cheatcodes::set_contract_address(token_contract_address); - - let balances_slot = Token::storage().balances.slot; - let recipient_slot = derive_storage_slot_in_map(balances_slot, recipient); - let mut options = NoteViewerOptions::new(); - let notes: BoundedVec = view_notes(recipient_slot, options); - assert(notes.get(0).amount.to_field() == transfer_amount); - - let owner_slot = derive_storage_slot_in_map(balances_slot, owner); - let mut options = NoteViewerOptions::new(); - let notes: BoundedVec = view_notes(owner_slot, options); - assert(notes.get(0).amount.to_field() == mint_amount - transfer_amount); - } } // docs:end:token_all \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test.nr new file mode 100644 index 000000000000..cf797ce3bcce --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test.nr @@ -0,0 +1,9 @@ +mod access_control; +mod burn; +mod utils; +mod transfer_public; +mod transfer_private; +mod unshielding; +mod minting; +mod reading_constants; +mod shielding; diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/access_control.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/access_control.nr new file mode 100644 index 000000000000..37a84e09a7b6 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/access_control.nr @@ -0,0 +1,52 @@ +use crate::test::utils; +use dep::aztec::test::helpers::cheatcodes; +use crate::Token; + +#[test] +unconstrained fn access_control() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient) = utils::setup(/* with_account_contracts */ false); + + // Set a new admin + let set_admin_call_interface = Token::at(token_contract_address).set_admin(recipient); + env.call_public(set_admin_call_interface); + + // Check it worked + let get_admin_call_interface = Token::at(token_contract_address).admin(); + let admin = env.call_public(get_admin_call_interface); + assert(admin == recipient.to_field()); + + // Impersonate new admin + cheatcodes::set_contract_address(recipient); + + // Check new admin is not a minter + let is_minter_call_interface = Token::at(token_contract_address).is_minter(recipient); + let is_minter = env.call_public(is_minter_call_interface); + assert(is_minter == false); + // Set admin as minter + let set_minter_call_interface = Token::at(token_contract_address).set_minter(recipient, true); + env.call_public(set_minter_call_interface); + + // Check it worked + let is_minter = env.call_public(is_minter_call_interface); + assert(is_minter == true); + + // Revoke minter as admin + let set_minter_call_interface = Token::at(token_contract_address).set_minter(recipient, false); + env.call_public(set_minter_call_interface); + + // Check it worked + let is_minter = env.call_public(is_minter_call_interface); + assert(is_minter == false); + + // Impersonate original admin + cheatcodes::set_contract_address(owner); + + // Try to set ourselves as admin, fail miserably + let set_admin_call_interface = Token::at(token_contract_address).set_admin(recipient); + env.assert_public_call_fails(set_admin_call_interface); + + // Try to revoke minter status to recipient, fail miserably + let set_minter_call_interface = Token::at(token_contract_address).set_minter(recipient, false); + env.assert_public_call_fails(set_minter_call_interface); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr new file mode 100644 index 000000000000..af0e6cb3c31b --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/burn.nr @@ -0,0 +1,179 @@ +use crate::test::utils; +use dep::aztec::{test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand}; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use crate::Token; + +#[test] +unconstrained fn burn_public_success() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + let burn_amount = mint_amount / 10; + + // Burn less than balance + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, 0); + env.call_public(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test] +unconstrained fn burn_public_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let burn_amount = mint_amount / 10; + + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, recipient, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Burn tokens + env.call_public(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test] +unconstrained fn burn_public_failure_more_than_balance() { + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount * 10; + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, 0); + env.assert_public_call_fails(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn burn_public_failure_on_behalf_of_self_non_zero_nonce() { + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + // Burn on behalf of self with non-zero nonce + let burn_amount = mint_amount / 10; + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, unsafe_rand()); + env.assert_public_call_fails(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn burn_public_failure_on_behalf_of_other_without_approval() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + // Burn on behalf of other without approval + let burn_amount = mint_amount / 10; + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, unsafe_rand()); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.assert_public_call_fails(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount); + + // Burn on behalf of other, wrong designated caller + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.assert_public_call_fails(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn burn_public_failure_on_behalf_of_other_wrong_caller() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + // Burn on behalf of other, wrong designated caller + let burn_amount = mint_amount / 10; + let burn_call_interface = Token::at(token_contract_address).burn_public(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.assert_public_call_fails(burn_call_interface); + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn burn_private_on_behalf_of_self() { + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + let burn_amount = mint_amount / 10; + + // Burn less than balance + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, 0); + env.call_private_void(burn_call_interface); + utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test] +unconstrained fn burn_private_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let burn_amount = mint_amount / 10; + + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Burn tokens + env.call_private_void(burn_call_interface); + utils::check_private_balance(token_contract_address, owner, mint_amount - burn_amount); +} + +#[test(should_fail_with="Balance too low")] +unconstrained fn burn_private_failure_more_than_balance() { + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount * 10; + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, 0); + env.call_private_void(burn_call_interface); + // Private doesnt revert, so we cannot check balances here since notes have already been nullified. Test is done. +} + +#[test(should_fail_with="invalid nonce")] +unconstrained fn burn_private_failure_on_behalf_of_self_non_zero_nonce() { + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + // Burn more than balance + let burn_amount = mint_amount / 10; + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, unsafe_rand()); + env.call_private_void(burn_call_interface); + // Private doesnt revert, so we cannot check balances here since notes have already been nullified. Test is done. +} + +#[test(should_fail)] +unconstrained fn burn_private_failure_on_behalf_of_other_more_than_balance() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount * 10; + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.call_private_void(burn_call_interface); + // Private doesnt revert, so we cannot check balances here since notes have already been nullified. Test is done. +} + +#[test(should_fail)] +unconstrained fn burn_private_failure_on_behalf_of_other_without_approval() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount / 10; + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, unsafe_rand()); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.call_private_void(burn_call_interface); + // Private doesnt revert, so we cannot check balances here since notes have already been nullified. Test is done. +} + +#[test(should_fail)] +unconstrained fn burn_private_failure_on_behalf_of_other_wrong_designated_caller() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + // Burn more than balance + let burn_amount = mint_amount / 10; + // Burn on behalf of other + let burn_call_interface = Token::at(token_contract_address).burn(owner, burn_amount, unsafe_rand()); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, owner, burn_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + env.call_private_void(burn_call_interface); + // Private doesnt revert, so we cannot check balances here since notes have already been nullified. Test is done. +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr new file mode 100644 index 000000000000..4e92489a59ad --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/minting.nr @@ -0,0 +1,239 @@ +use crate::test::utils; +use dep::aztec::{test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, hash::compute_secret_hash}; +use crate::{types::transparent_note::TransparentNote, Token}; + +#[test] +unconstrained fn mint_public_success() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _) = utils::setup(/* with_account_contracts */ false); + + let mint_amount = 10000; + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.call_public(mint_public_call_interface); + + utils::check_public_balance(token_contract_address, owner, mint_amount); + + let total_supply_call_interface = Token::at(token_contract_address).total_supply(); + let total_supply = env.call_public(total_supply_call_interface); + + assert(total_supply == mint_amount); +} + +#[test] +unconstrained fn mint_public_failures() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient) = utils::setup(/* with_account_contracts */ false); + + // As non-minter + let mint_amount = 10000; + cheatcodes::set_contract_address(recipient); + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.assert_public_call_fails(mint_public_call_interface); + + utils::check_public_balance(token_contract_address, owner, 0); + + cheatcodes::set_contract_address(owner); + + // Overflow recipient + + let mint_amount = 2.pow_32(128); + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.assert_public_call_fails(mint_public_call_interface); + + utils::check_public_balance(token_contract_address, owner, 0); + + // Overflow total supply + + let mint_for_recipient_amount = 1000; + + let mint_public_call_interface = Token::at(token_contract_address).mint_public(recipient, mint_for_recipient_amount); + env.call_public(mint_public_call_interface); + + let mint_amount = 2.pow_32(128) - mint_for_recipient_amount; + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.assert_public_call_fails(mint_public_call_interface); + + utils::check_public_balance(token_contract_address, recipient, mint_for_recipient_amount); + utils::check_public_balance(token_contract_address, owner, 0); +} + +#[test] +unconstrained fn mint_private_success() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _) = utils::setup(/* with_account_contracts */ false); + let mint_amount = 10000; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); + + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.call_public(mint_public_call_interface); + + // Time travel so we can read keys from the registry + env.advance_block_by(6); + + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test(should_fail_with="Cannot return zero notes")] +unconstrained fn mint_private_failure_double_spend() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient) = utils::setup(/* with_account_contracts */ false); + let mint_amount = 10000; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); + + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.call_public(mint_public_call_interface); + + // Time travel so we can read keys from the registry + env.advance_block_by(6); + + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + utils::check_private_balance(token_contract_address, owner, mint_amount); + + // Attempt to double spend + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(recipient, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); +} + +#[test(should_fail_with="caller is not minter")] +unconstrained fn mint_private_failure_non_minter() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, recipient) = utils::setup(/* with_account_contracts */ false); + let mint_amount = 10000; + // Try to mint some tokens impersonating recipient + cheatcodes::set_contract_address(recipient); + + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); +} + +#[test(should_fail_with="call to assert_max_bit_size")] +unconstrained fn mint_private_failure_overflow() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, _) = utils::setup(/* with_account_contracts */ false); + + // Overflow recipient + let mint_amount = 2.pow_32(128); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); +} + +#[test(should_fail_with="attempt to add with overflow")] +unconstrained fn mint_private_failure_overflow_recipient() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _) = utils::setup(/* with_account_contracts */ false); + let mint_amount = 10000; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); + + // Time travel so we can read keys from the registry + env.advance_block_by(6); + + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + utils::check_private_balance(token_contract_address, owner, mint_amount); + + let mint_amount = 2.pow_32(128) - mint_amount; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); +} + +#[test(should_fail_with="attempt to add with overflow")] +unconstrained fn mint_private_failure_overflow_total_supply() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient) = utils::setup(/* with_account_contracts */ false); + let mint_amount = 10000; + // Mint some tokens + let secret_owner = unsafe_rand(); + let secret_recipient = unsafe_rand(); + let secret_hash_owner = compute_secret_hash(secret_owner); + let secret_hash_recipient = compute_secret_hash(secret_recipient); + + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash_owner); + env.call_public(mint_private_call_interface); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash_recipient); + env.call_public(mint_private_call_interface); + + // Time travel so we can read keys from the registry + env.advance_block_by(6); + + // Store 2 notes in the cache so we can redeem it for owner and recipient + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash_owner), + Token::storage().pending_shields.slot, + token_contract_address + ); + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash_recipient), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem owner's shielded tokens + cheatcodes::set_contract_address(owner); + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret_owner); + env.call_private_void(redeem_shield_call_interface); + + // Redeem recipient's shielded tokens + cheatcodes::set_contract_address(recipient); + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(recipient, mint_amount, secret_recipient); + env.call_private_void(redeem_shield_call_interface); + + utils::check_private_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, recipient, mint_amount); + + cheatcodes::set_contract_address(owner); + let mint_amount = 2.pow_32(128) - 2 * mint_amount; + // Try to mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/reading_constants.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/reading_constants.nr new file mode 100644 index 000000000000..469ff747590d --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/reading_constants.nr @@ -0,0 +1,29 @@ +use crate::test::utils; +use dep::aztec::test::helpers::cheatcodes; +use crate::Token; + +// It is not possible to deserialize strings in Noir ATM, so name and symbol cannot be checked yet. + +#[test] +unconstrained fn check_decimals_private() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, _) = utils::setup(/* with_account_contracts */ false); + + // Check decimals + let private_get_decimals_call_interface = Token::at(token_contract_address).private_get_decimals(); + let result = env.call_private(private_get_decimals_call_interface); + + assert(result == 18); +} + +#[test] +unconstrained fn check_decimals_public() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, _) = utils::setup(/* with_account_contracts */ false); + + // Check decimals + let public_get_decimals_call_interface = Token::at(token_contract_address).public_get_decimals(); + let result = env.call_public(public_get_decimals_call_interface); + + assert(result == 18 as u8); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr new file mode 100644 index 000000000000..66280304481a --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/shielding.nr @@ -0,0 +1,156 @@ +use crate::test::utils; +use dep::aztec::{test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, hash::compute_secret_hash}; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use crate::{types::transparent_note::TransparentNote, Token}; + +#[test] +unconstrained fn shielding_on_behalf_of_self() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens + let shield_amount = mint_amount / 10; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + env.call_public(shield_call_interface); + + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(shield_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, shield_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount + shield_amount); +} + +#[test] +unconstrained fn shielding_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + + // Shield tokens on behalf of owner + let shield_amount = 1000; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, recipient, shield_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Shield tokens + env.call_public(shield_call_interface); + + // Become owner again + cheatcodes::set_contract_address(owner); + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(shield_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, shield_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount - shield_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount + shield_amount); +} + +#[test] +unconstrained fn shielding_failure_on_behalf_of_self_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens + let shield_amount = mint_amount + 1; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + env.assert_public_call_fails(shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn shielding_failure_on_behalf_of_self_invalid_nonce() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens + let shield_amount = mint_amount / 10; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, unsafe_rand()); + env.assert_public_call_fails(shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn shielding_failure_on_behalf_of_other_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens on behalf of owner + let shield_amount = mint_amount + 1; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, recipient, shield_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Shield tokens + env.assert_public_call_fails(shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn shielding_failure_on_behalf_of_other_wrong_caller() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens on behalf of owner + let shield_amount = mint_amount + 1; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, shield_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Shield tokens + env.assert_public_call_fails(shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn shielding_failure_on_behalf_of_other_without_approval() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + // Shield tokens on behalf of owner + let shield_amount = mint_amount + 1; + let shield_call_interface = Token::at(token_contract_address).shield(owner, shield_amount, secret_hash, 0); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Shield tokens + env.assert_public_call_fails(shield_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr new file mode 100644 index 000000000000..47e048091144 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_private.nr @@ -0,0 +1,131 @@ +use crate::test::utils; +use dep::aztec::{test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, protocol_types::address::AztecAddress}; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use crate::Token; + +#[test] +unconstrained fn transfer_private() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = 1000; + let transfer_private_call_interface = Token::at(token_contract_address).transfer(recipient, transfer_amount); + env.call_private_void(transfer_private_call_interface); + + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, recipient, transfer_amount); +} + +#[test] +unconstrained fn transfer_private_to_self() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = 1000; + let transfer_private_call_interface = Token::at(token_contract_address).transfer(owner, transfer_amount); + env.call_private_void(transfer_private_call_interface); + + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn transfer_private_to_non_deployed_account() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + let not_deployed = cheatcodes::create_account(); + // Transfer tokens + let transfer_amount = 1000; + let transfer_private_call_interface = Token::at(token_contract_address).transfer(not_deployed.address, transfer_amount); + env.call_private_void(transfer_private_call_interface); + + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, not_deployed.address, transfer_amount); +} + +#[test] +unconstrained fn transfer_private_on_behalf_of_other() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + // Add authwit + let transfer_amount = 1000; + let transfer_private_from_call_interface = Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, transfer_private_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, recipient, transfer_amount); +} + +#[test(should_fail_with="Balance too low")] +unconstrained fn transfer_private_failure_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, _, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = mint_amount + 1; + let transfer_private_call_interface = Token::at(token_contract_address).transfer(recipient, transfer_amount); + env.call_private_void(transfer_private_call_interface); +} + +#[test(should_fail_with="invalid nonce")] +unconstrained fn transfer_private_failure_on_behalf_of_self_non_zero_nonce() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, _) = utils::setup_and_mint(/* with_account_contracts */ true); + // Add authwit + let transfer_amount = 1000; + let transfer_private_from_call_interface = Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); +} + +#[test(should_fail_with="Balance too low")] +unconstrained fn transfer_private_failure_on_behalf_of_more_than_balance() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + // Add authwit + let transfer_amount = mint_amount + 1; + let transfer_private_from_call_interface = Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, transfer_private_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); +} + +#[test(should_fail)] +unconstrained fn transfer_private_failure_on_behalf_of_other_without_approval() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + // Add authwit + let transfer_amount = 1000; + let transfer_private_from_call_interface = Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, recipient, transfer_amount); +} + +#[test(should_fail)] +unconstrained fn transfer_private_failure_on_behalf_of_other_wrong_caller() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + // Add authwit + let transfer_amount = 1000; + let transfer_private_from_call_interface = Token::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, owner, transfer_private_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); + // Check balances + utils::check_private_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_private_balance(token_contract_address, recipient, transfer_amount); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr new file mode 100644 index 000000000000..ae0b631ce374 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/transfer_public.nr @@ -0,0 +1,122 @@ +use crate::test::utils; +use dep::aztec::{test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand}; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use crate::Token; + +#[test] +unconstrained fn public_transfer() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = mint_amount / 10; + let public_transfer_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 0); + env.call_public(public_transfer_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_public_balance(token_contract_address, recipient, transfer_amount); +} + +#[test] +unconstrained fn public_transfer_to_self() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = mint_amount / 10; + let public_transfer_call_interface = Token::at(token_contract_address).transfer_public(owner, owner, transfer_amount, 0); + env.call_public(public_transfer_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn public_transfer_on_behalf_of_other() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let transfer_amount = mint_amount / 10; + let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, recipient, public_transfer_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_public(public_transfer_from_call_interface); + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount - transfer_amount); + utils::check_public_balance(token_contract_address, recipient, transfer_amount); +} + +#[test] +unconstrained fn public_transfer_failure_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + // Transfer tokens + let transfer_amount = mint_amount + 1; + let public_transfer_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 0); + // Try to transfer tokens + env.assert_public_call_fails(public_transfer_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn public_transfer_failure_on_behalf_of_self_non_zero_nonce() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + // Transfer tokens + let transfer_amount = mint_amount / 10; + let public_transfer_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, unsafe_rand()); + // Try to transfer tokens + env.assert_public_call_fails(public_transfer_call_interface); + + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); +} + +#[test] +unconstrained fn public_transfer_failure_on_behalf_of_other_without_approval() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let transfer_amount = mint_amount / 10; + let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Try to transfer tokens + env.assert_public_call_fails(public_transfer_from_call_interface); + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_public_balance(token_contract_address, recipient, 0); +} + +#[test] +unconstrained fn public_transfer_failure_on_behalf_of_other_more_than_balance() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let transfer_amount = mint_amount + 1; + let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, recipient, public_transfer_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Try to transfer tokens + env.assert_public_call_fails(public_transfer_from_call_interface); + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_public_balance(token_contract_address, recipient, 0); +} + +#[test] +unconstrained fn public_transfer_failure_on_behalf_of_other_wrong_caller() { + // Setup with account contracts. Slower since we actually deploy them, but needed for authwits. + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + let transfer_amount = mint_amount / 10; + let public_transfer_from_call_interface = Token::at(token_contract_address).transfer_public(owner, recipient, transfer_amount, 1); + authwit_cheatcodes::add_public_authwit_from_call_interface(owner, owner, public_transfer_from_call_interface); + // Impersonate recipient to perform the call + cheatcodes::set_contract_address(recipient); + // Try to transfer tokens + env.assert_public_call_fails(public_transfer_from_call_interface); + // Check balances + utils::check_public_balance(token_contract_address, owner, mint_amount); + utils::check_public_balance(token_contract_address, recipient, 0); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr new file mode 100644 index 000000000000..52987cb17367 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/unshielding.nr @@ -0,0 +1,89 @@ +use crate::test::utils; +use dep::aztec::{oracle::unsafe_rand::unsafe_rand, test::helpers::cheatcodes}; +use dep::authwit::cheatcodes as authwit_cheatcodes; +use crate::Token; + +#[test] +unconstrained fn unshield_on_behalf_of_self() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + let unshield_amount = mint_amount / 10; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, owner, unshield_amount, 0); + env.call_private_void(unshield_call_interface); + utils::check_private_balance(token_contract_address, owner, mint_amount - unshield_amount); + utils::check_public_balance(token_contract_address, owner, mint_amount + unshield_amount); +} + +#[test] +unconstrained fn unshield_on_behalf_of_other() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + let unshield_amount = mint_amount / 10; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, recipient, unshield_amount, 0); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, unshield_call_interface); + // Impersonate recipient + cheatcodes::set_contract_address(recipient); + // Unshield tokens + env.call_private_void(unshield_call_interface); + utils::check_private_balance(token_contract_address, owner, mint_amount - unshield_amount); + utils::check_public_balance(token_contract_address, recipient, unshield_amount); +} + +#[test(should_fail_with="Balance too low")] +unconstrained fn unshield_failure_more_than_balance() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + let unshield_amount = mint_amount + 1; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, owner, unshield_amount, 0); + env.call_private_void(unshield_call_interface); +} + +#[test(should_fail_with="invalid nonce")] +unconstrained fn unshield_failure_on_behalf_of_self_non_zero_nonce() { + // Setup without account contracts. We are not using authwits here, so dummy accounts are enough + let (env, token_contract_address, owner, _, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ false); + + let unshield_amount = mint_amount + 1; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, owner, unshield_amount, unsafe_rand()); + env.call_private_void(unshield_call_interface); +} + +#[test(should_fail_with="Balance too low")] +unconstrained fn unshield_failure_on_behalf_of_other_more_than_balance() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + let unshield_amount = mint_amount + 1; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, recipient, unshield_amount, 0); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, unshield_call_interface); + // Impersonate recipient + cheatcodes::set_contract_address(recipient); + // Unshield tokens + env.call_private_void(unshield_call_interface); +} + +#[test(should_fail)] +unconstrained fn unshield_failure_on_behalf_of_other_invalid_designated_caller() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + let unshield_amount = mint_amount + 1; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, recipient, unshield_amount, 0); + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, owner, unshield_call_interface); + // Impersonate recipient + cheatcodes::set_contract_address(recipient); + // Unshield tokens + env.call_private_void(unshield_call_interface); +} + +#[test(should_fail)] +unconstrained fn unshield_failure_on_behalf_of_other_no_approval() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(/* with_account_contracts */ true); + + let unshield_amount = mint_amount + 1; + let unshield_call_interface = Token::at(token_contract_address).unshield(owner, recipient, unshield_amount, 0); + // Impersonate recipient + cheatcodes::set_contract_address(recipient); + // Unshield tokens + env.call_private_void(unshield_call_interface); +} diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr new file mode 100644 index 000000000000..1801ddd72130 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr @@ -0,0 +1,89 @@ +use dep::aztec::{ + hash::compute_secret_hash, prelude::AztecAddress, + test::helpers::{cheatcodes, test_environment::TestEnvironment}, + protocol_types::storage::map::derive_storage_slot_in_map, + note::{note_getter::{MAX_NOTES_PER_PAGE, view_notes}, note_viewer_options::NoteViewerOptions}, + oracle::{unsafe_rand::unsafe_rand, storage::storage_read} +}; + +use crate::{types::{token_note::TokenNote, transparent_note::TransparentNote}, Token}; + +pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress) { + // Setup env, generate keys + let mut env = TestEnvironment::new(); + let (owner, recipient) = if with_account_contracts { + let owner = env.create_account_contract(1); + let recipient = env.create_account_contract(2); + // Deploy canonical auth registry + let _auth_registry = env.deploy("@aztec/noir-contracts.js/AuthRegistry").without_initializer(); + (owner, recipient) + } else { + let owner = env.create_account(); + let recipient = env.create_account(); + (owner, recipient) + }; + + // Start the test in the account contract address + cheatcodes::set_contract_address(owner); + + // Deploy token contract + let initializer_call_interface = Token::interface().constructor( + owner, + "TestToken0000000000000000000000", + "TT00000000000000000000000000000", + 18 + ); + let token_contract = env.deploy("@aztec/noir-contracts.js/Token").with_public_initializer(initializer_call_interface); + let token_contract_address = token_contract.to_address(); + env.advance_block_by(1); + (&mut env, token_contract_address, owner, recipient) +} + +pub fn setup_and_mint(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { + // Setup + let (env, token_contract_address, owner, recipient) = setup(with_account_contracts); + let mint_amount = 10000; + // Mint some tokens + let secret = unsafe_rand(); + let secret_hash = compute_secret_hash(secret); + let mint_private_call_interface = Token::at(token_contract_address).mint_private(mint_amount, secret_hash); + env.call_public(mint_private_call_interface); + + let mint_public_call_interface = Token::at(token_contract_address).mint_public(owner, mint_amount); + env.call_public(mint_public_call_interface); + + // Time travel so we can read keys from the registry + env.advance_block_by(6); + + // Store a note in the cache so we can redeem it + env.store_note_in_cache( + &mut TransparentNote::new(mint_amount, secret_hash), + Token::storage().pending_shields.slot, + token_contract_address + ); + + // Redeem our shielded tokens + let redeem_shield_call_interface = Token::at(token_contract_address).redeem_shield(owner, mint_amount, secret); + env.call_private_void(redeem_shield_call_interface); + + (env, token_contract_address, owner, recipient, mint_amount) +} + +pub fn check_public_balance(token_contract_address: AztecAddress, address: AztecAddress, address_amount: Field) { + let current_contract_address = cheatcodes::get_contract_address(); + cheatcodes::set_contract_address(token_contract_address); + + let balances_slot = Token::storage().public_balances.slot; + let address_slot = derive_storage_slot_in_map(balances_slot, address); + let fields = storage_read(address_slot); + assert(U128::deserialize(fields).to_field() == address_amount, "Public balance is not correct"); + cheatcodes::set_contract_address(current_contract_address); +} + +pub fn check_private_balance(token_contract_address: AztecAddress, address: AztecAddress, address_amount: Field) { + let current_contract_address = cheatcodes::get_contract_address(); + cheatcodes::set_contract_address(token_contract_address); + let balance_of_private = Token::balance_of_private(address); + assert(balance_of_private == address_amount, "Private balance is not correct"); + cheatcodes::set_contract_address(current_contract_address); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr index 22746ed644de..2434f8ffdeb4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr @@ -2,6 +2,7 @@ mod append_only_tree_snapshot; mod contract_class_function_leaf_preimage; +mod event_selector; mod function_selector; mod function_data; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr new file mode 100644 index 000000000000..b03a9dfba1c1 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr @@ -0,0 +1,70 @@ +use crate::utils::field::field_from_bytes; +use dep::std::cmp::Eq; +use crate::traits::{Serialize, Deserialize, FromField, ToField, Empty}; + +global SELECTOR_SIZE = 4; + +struct EventSelector { + // 1st 4-bytes (big-endian leftmost) of abi-encoding of an event. + inner: u32, +} + +impl Eq for EventSelector { + fn eq(self, other: EventSelector) -> bool { + other.inner == self.inner + } +} + +impl Serialize<1> for EventSelector { + fn serialize(self: Self) -> [Field; 1] { + [self.inner as Field] + } +} + +impl Deserialize<1> for EventSelector { + fn deserialize(fields: [Field; 1]) -> Self { + Self { + inner: fields[0] as u32 + } + } +} + +impl FromField for EventSelector { + fn from_field(field: Field) -> Self { + Self { inner: field as u32 } + } +} + +impl ToField for EventSelector { + fn to_field(self) -> Field { + self.inner as Field + } +} + +impl Empty for EventSelector { + fn empty() -> Self { + Self { inner: 0 as u32 } + } +} + +impl EventSelector { + pub fn from_u32(value: u32) -> Self { + Self { inner: value } + } + + pub fn from_signature(signature: str) -> Self { + let bytes = signature.as_bytes(); + let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32); + + let mut selector_be_bytes = [0; SELECTOR_SIZE]; + for i in 0..SELECTOR_SIZE { + selector_be_bytes[i] = hash[i]; + } + + EventSelector::from_field(field_from_bytes(selector_be_bytes, true)) + } + + pub fn zero() -> Self { + Self { inner: 0 } + } +} 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 5c98a5854419..9572f179dd1b 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 @@ -30,6 +30,7 @@ impl Hash for PublicCallStackItem { impl PublicCallStackItem { fn as_execution_request(self) -> Self { + // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()` let public_inputs = self.public_inputs; let mut request_public_inputs = PublicCircuitPublicInputs::empty(); request_public_inputs.call_context = public_inputs.call_context; 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 2d48394e3aff..8d450bce84d7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -299,13 +299,14 @@ global GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS = 43; global GENERATOR_INDEX__FUNCTION_ARGS = 44; global GENERATOR_INDEX__AUTHWIT_INNER = 45; global GENERATOR_INDEX__AUTHWIT_OUTER = 46; +global GENERATOR_INDEX__AUTHWIT_NULLIFIER = 47; // Key related generators follow -global GENERATOR_INDEX__NSK_M = 47; -global GENERATOR_INDEX__IVSK_M = 48; -global GENERATOR_INDEX__OVSK_M = 49; -global GENERATOR_INDEX__TSK_M = 50; -global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 51; -global GENERATOR_INDEX__NOTE_NULLIFIER = 52; -global GENERATOR_INDEX__INNER_NOTE_HASH = 53; -global GENERATOR_INDEX__NOTE_CONTENT_HASH = 54; -global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 55; +global GENERATOR_INDEX__NSK_M = 48; +global GENERATOR_INDEX__IVSK_M = 49; +global GENERATOR_INDEX__OVSK_M = 50; +global GENERATOR_INDEX__TSK_M = 51; +global GENERATOR_INDEX__PUBLIC_KEYS_HASH = 52; +global GENERATOR_INDEX__NOTE_NULLIFIER = 53; +global GENERATOR_INDEX__INNER_NOTE_HASH = 54; +global GENERATOR_INDEX__NOTE_CONTENT_HASH = 55; +global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 56; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr index 95561df1094e..88624e254760 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr @@ -13,7 +13,8 @@ pub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field { } pub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] { - for i in 0..dst.len() { + let iterator_len = if N > M { M } else { N }; + for i in 0..iterator_len { dst[i] = src[i + offset]; } dst diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index a427e7cc2985..50b65919f1e9 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -451,6 +451,7 @@ dependencies = [ "noirc_errors", "noirc_frontend", "regex", + "tiny-keccak", ] [[package]] diff --git a/noir/noir-repo/aztec_macros/Cargo.toml b/noir/noir-repo/aztec_macros/Cargo.toml index ed70066af22e..a99a654aeed9 100644 --- a/noir/noir-repo/aztec_macros/Cargo.toml +++ b/noir/noir-repo/aztec_macros/Cargo.toml @@ -16,4 +16,4 @@ noirc_errors.workspace = true iter-extended.workspace = true convert_case = "0.6.0" regex = "1.10" - +tiny-keccak = { version = "2.0.0", features = ["keccak"] } diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index d79c7b190ed0..580a132aa5a4 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -7,7 +7,7 @@ use transforms::{ contract_interface::{ generate_contract_interface, stub_function, update_fn_signatures_in_contract_interface, }, - events::{generate_selector_impl, transform_events}, + events::{generate_event_impls, transform_event_abi}, functions::{ check_for_public_args, export_fn_abi, transform_function, transform_unconstrained, }, @@ -72,6 +72,7 @@ fn transform( } } + generate_event_impls(&mut ast).map_err(|err| (err.into(), file_id))?; generate_note_interface_impl(&mut ast).map_err(|err| (err.into(), file_id))?; Ok(ast) @@ -101,13 +102,6 @@ fn transform_module( generate_storage_layout(module, storage_struct_name.clone(), module_name)?; } - for structure in module.types.iter_mut() { - if structure.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) { - module.impls.push(generate_selector_impl(structure)); - has_transformed_module = true; - } - } - let has_initializer = module.functions.iter().any(|func| { func.def .attributes @@ -222,7 +216,7 @@ fn transform_hir( context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { if has_aztec_dependency(crate_id, context) { - transform_events(crate_id, context)?; + transform_event_abi(crate_id, context)?; inject_compute_note_hash_and_optionally_a_nullifier(crate_id, context)?; assign_storage_slots(crate_id, context)?; inject_note_exports(crate_id, context)?; diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs index 1875ab0b2521..8b763dfcc574 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -155,9 +155,17 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call name: \"{}\", args_hash, args: args_acc, - original: {} + original: {}, + is_static: {} }}", - args_hash, fn_selector, aztec_visibility, is_static, is_void, fn_name, original + args_hash, + fn_selector, + aztec_visibility, + is_static, + is_void, + fn_name, + original, + is_static_call ) } else { let args = format!( @@ -175,9 +183,17 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call name: \"{}\", args: args_acc, gas_opts: dep::aztec::context::gas::GasOpts::default(), - original: {} + original: {}, + is_static: {} }}", - args, fn_selector, aztec_visibility, is_static, is_void, fn_name, original + args, + fn_selector, + aztec_visibility, + is_static, + is_void, + fn_name, + original, + is_static_call ) }; diff --git a/noir/noir-repo/aztec_macros/src/transforms/events.rs b/noir/noir-repo/aztec_macros/src/transforms/events.rs index 69cb6ddafc3e..05861b96eb40 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/events.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/events.rs @@ -1,178 +1,333 @@ -use iter_extended::vecmap; -use noirc_errors::Span; -use noirc_frontend::ast::{ - ExpressionKind, FunctionDefinition, FunctionReturnType, ItemVisibility, Literal, NoirFunction, - Visibility, -}; +use noirc_frontend::ast::{ItemVisibility, NoirFunction, NoirTraitImpl, TraitImplItem}; +use noirc_frontend::macros_api::{NodeInterner, StructId}; +use noirc_frontend::token::SecondaryAttribute; use noirc_frontend::{ graph::CrateId, - macros_api::{ - BlockExpression, FileId, HirContext, HirExpression, HirLiteral, HirStatement, NodeInterner, - NoirStruct, PathKind, StatementKind, StructId, StructType, Type, TypeImpl, - UnresolvedTypeData, - }, - token::SecondaryAttribute, + macros_api::{FileId, HirContext}, + parse_program, + parser::SortedModule, }; -use crate::{ - chained_dep, - utils::{ - ast_utils::{ - call, expression, ident, ident_path, is_custom_attribute, make_statement, make_type, - path, variable_path, - }, - constants::SIGNATURE_PLACEHOLDER, - errors::AztecMacroError, - hir_utils::{collect_crate_structs, signature_of_type}, - }, -}; +use crate::utils::hir_utils::collect_crate_structs; +use crate::utils::{ast_utils::is_custom_attribute, errors::AztecMacroError}; + +// Automatic implementation of most of the methods in the EventInterface trait, guiding the user with meaningful error messages in case some +// methods must be implemented manually. +pub fn generate_event_impls(module: &mut SortedModule) -> Result<(), AztecMacroError> { + // Find structs annotated with #[aztec(event)] + // Why doesn't this work ? Events are not tagged and do not appear, it seems only going through the submodule works + // let annotated_event_structs = module + // .types + // .iter_mut() + // .filter(|typ| typ.attributes.iter().any(|attr: &SecondaryAttribute| is_custom_attribute(attr, "aztec(event)"))); + // This did not work because I needed the submodule itself to add the trait impl back in to, but it would be nice if it was tagged on the module level + // let mut annotated_event_structs = module.submodules.iter_mut() + // .flat_map(|submodule| submodule.contents.types.iter_mut()) + // .filter(|typ| typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)"))); + + // To diagnose + // let test = module.types.iter_mut(); + // for event_struct in test { + // print!("\ngenerate_event_interface_impl COUNT: {}\n", event_struct.name.0.contents); + // } + + for submodule in module.submodules.iter_mut() { + let annotated_event_structs = submodule.contents.types.iter_mut().filter(|typ| { + typ.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) + }); + + for event_struct in annotated_event_structs { + // event_struct.attributes.push(SecondaryAttribute::Abi("events".to_string())); + // If one impl is pushed, this doesn't throw the "#[abi(tag)] attributes can only be used in contracts" error + // But if more than one impl is pushed, we get an increasing amount of "#[abi(tag)] attributes can only be used in contracts" errors + // We work around this by doing this addition in the HIR pass via transform_event_abi below. + + let event_type = event_struct.name.0.contents.to_string(); + let event_len = event_struct.fields.len() as u32; + // event_byte_len = event fields * 32 + randomness (32) + event_type_id (32) + let event_byte_len = event_len * 32 + 64; + + let mut event_fields = vec![]; + + for (field_ident, field_type) in event_struct.fields.iter() { + event_fields.push(( + field_ident.0.contents.to_string(), + field_type.typ.to_string().replace("plain::", ""), + )); + } -/// Generates the impl for an event selector -/// -/// Inserts the following code: -/// ```noir -/// impl SomeStruct { -/// fn selector() -> FunctionSelector { -/// aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature("SIGNATURE_PLACEHOLDER") -/// } -/// } -/// ``` -/// -/// This allows developers to emit events without having to write the signature of the event every time they emit it. -/// The signature cannot be known at this point since types are not resolved yet, so we use a signature placeholder. -/// It'll get resolved after by transforming the HIR. -pub fn generate_selector_impl(structure: &mut NoirStruct) -> TypeImpl { - structure.attributes.push(SecondaryAttribute::Abi("events".to_string())); - let struct_type = - make_type(UnresolvedTypeData::Named(path(structure.name.clone()), vec![], true)); - - let selector_path = - chained_dep!("aztec", "protocol_types", "abis", "function_selector", "FunctionSelector"); - let mut from_signature_path = selector_path.clone(); - from_signature_path.segments.push(ident("from_signature")); - - let selector_fun_body = BlockExpression { - statements: vec![make_statement(StatementKind::Expression(call( - variable_path(from_signature_path), - vec![expression(ExpressionKind::Literal(Literal::Str( - SIGNATURE_PLACEHOLDER.to_string(), - )))], - )))], - }; - - // Define `FunctionSelector` return type - let return_type = - FunctionReturnType::Ty(make_type(UnresolvedTypeData::Named(selector_path, vec![], true))); - - let mut selector_fn_def = FunctionDefinition::normal( - &ident("selector"), - &vec![], - &[], - &selector_fun_body, - &[], - &return_type, - ); - - selector_fn_def.visibility = ItemVisibility::Public; - - // Seems to be necessary on contract modules - selector_fn_def.return_visibility = Visibility::Public; - - TypeImpl { - object_type: struct_type, - type_span: structure.span, - generics: vec![], - methods: vec![(NoirFunction::normal(selector_fn_def), Span::default())], + let mut event_interface_trait_impl = + generate_trait_impl_stub_event_interface(event_type.as_str(), event_byte_len)?; + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_get_event_type_id(event_type.as_str(), event_len)?, + )); + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_private_to_be_bytes(event_type.as_str(), event_byte_len)?, + )); + event_interface_trait_impl.items.push(TraitImplItem::Function( + generate_fn_to_be_bytes(event_type.as_str(), event_byte_len)?, + )); + event_interface_trait_impl + .items + .push(TraitImplItem::Function(generate_fn_emit(event_type.as_str())?)); + submodule.contents.trait_impls.push(event_interface_trait_impl); + + let serialize_trait_impl = + generate_trait_impl_serialize(event_type.as_str(), event_len, &event_fields)?; + submodule.contents.trait_impls.push(serialize_trait_impl); + + let deserialize_trait_impl = + generate_trait_impl_deserialize(event_type.as_str(), event_len, &event_fields)?; + submodule.contents.trait_impls.push(deserialize_trait_impl); + } } + + Ok(()) } -/// Computes the signature for a resolved event type. -/// It has the form 'EventName(Field,(Field),[u8;2])' -fn event_signature(event: &StructType) -> String { - let fields = vecmap(event.get_fields(&[]), |(_, typ)| signature_of_type(&typ)); - format!("{}({})", event.name.0.contents, fields.join(",")) +fn generate_trait_impl_stub_event_interface( + event_type: &str, + byte_length: u32, +) -> Result { + let byte_length_without_randomness = byte_length - 32; + let trait_impl_source = format!( + " +impl dep::aztec::event::event_interface::EventInterface<{byte_length}, {byte_length_without_randomness}> for {event_type} {{ + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of {event_type} for EventInterface). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut sorted_ast = parsed_ast.into_sorted(); + let event_interface_impl = sorted_ast.trait_impls.remove(0); + + Ok(event_interface_impl) } -/// Substitutes the signature literal that was introduced in the selector method previously with the actual signature. -fn transform_event( - struct_id: StructId, - interner: &mut NodeInterner, -) -> Result<(), (AztecMacroError, FileId)> { - let struct_type = interner.get_struct(struct_id); - let selector_id = interner - .lookup_method(&Type::Struct(struct_type.clone(), vec![]), struct_id, "selector", false) - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Selector method not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - let selector_function = interner.function(&selector_id); - - let compute_selector_statement = interner.statement( - selector_function.block(interner).statements().first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement not found".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?, - ); - - let compute_selector_expression = match compute_selector_statement { - HirStatement::Expression(expression_id) => match interner.expression(&expression_id) { - HirExpression::Call(hir_call_expression) => Some(hir_call_expression), - _ => None, - }, - _ => None, +fn generate_trait_impl_serialize( + event_type: &str, + event_len: u32, + event_fields: &[(String, String)], +) -> Result { + let field_names = + event_fields.iter().map(|field| format!("self.{}", field.0)).collect::>(); + let field_input = field_names.join(","); + + let trait_impl_source = format!( + " + impl dep::aztec::protocol_types::traits::Serialize<{event_len}> for {event_type} {{ + fn serialize(self: {event_type}) -> [Field; {event_len}] {{ + [{field_input}] + }} + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of Serialize for {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); } - .ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - let first_arg_id = compute_selector_expression.arguments.first().ok_or_else(|| { - let error = AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Compute selector statement is not a call expression".to_owned(), - }; - (error, struct_type.borrow().location.file) - })?; - - match interner.expression(first_arg_id) { - HirExpression::Literal(HirLiteral::Str(signature)) - if signature == SIGNATURE_PLACEHOLDER => - { - let selector_literal_id = *first_arg_id; - - let structure = interner.get_struct(struct_id); - let signature = event_signature(&structure.borrow()); - interner.update_expression(selector_literal_id, |expr| { - *expr = HirExpression::Literal(HirLiteral::Str(signature.clone())); - }); - - // Also update the type! It might have a different length now than the placeholder. - interner.push_expr_type( - selector_literal_id, - Type::String(Box::new(Type::Constant(signature.len() as u32))), - ); - Ok(()) - } - _ => Err(( - AztecMacroError::EventError { - span: struct_type.borrow().location.span, - message: "Signature placeholder literal does not match".to_owned(), - }, - struct_type.borrow().location.file, - )), + + let mut sorted_ast = parsed_ast.into_sorted(); + let serialize_impl = sorted_ast.trait_impls.remove(0); + + Ok(serialize_impl) +} + +fn generate_trait_impl_deserialize( + event_type: &str, + event_len: u32, + event_fields: &[(String, String)], +) -> Result { + let field_names: Vec = event_fields + .iter() + .enumerate() + .map(|(index, field)| format!("{}: fields[{}]", field.0, index)) + .collect::>(); + let field_input = field_names.join(","); + + let trait_impl_source = format!( + " + impl dep::aztec::protocol_types::traits::Deserialize<{event_len}> for {event_type} {{ + fn deserialize(fields: [Field; {event_len}]) -> {event_type} {{ + {event_type} {{ {field_input} }} + }} + }} + " + ) + .to_string(); + + let (parsed_ast, errors) = parse_program(&trait_impl_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (trait impl of Deserialize for {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); } + + let mut sorted_ast = parsed_ast.into_sorted(); + let deserialize_impl = sorted_ast.trait_impls.remove(0); + + Ok(deserialize_impl) } -pub fn transform_events( +fn generate_fn_get_event_type_id( + event_type: &str, + field_length: u32, +) -> Result { + let from_signature_input = + std::iter::repeat("Field").take(field_length as usize).collect::>().join(","); + let function_source = format!( + " + fn get_event_type_id() -> dep::aztec::protocol_types::abis::event_selector::EventSelector {{ + dep::aztec::protocol_types::abis::event_selector::EventSelector::from_signature(\"{event_type}({from_signature_input})\") + }} + ", + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn get_event_type_id, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_private_to_be_bytes( + event_type: &str, + byte_length: u32, +) -> Result { + let function_source = format!( + " + fn private_to_be_bytes(self: {event_type}, randomness: Field) -> [u8; {byte_length}] {{ + let mut buffer: [u8; {byte_length}] = [0; {byte_length}]; + + let randomness_bytes = randomness.to_be_bytes(32); + let event_type_id_bytes = {event_type}::get_event_type_id().to_field().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = randomness_bytes[i]; + buffer[32 + i] = event_type_id_bytes[i]; + }} + + let serialized_event = self.serialize(); + + for i in 0..serialized_event.len() {{ + let bytes = serialized_event[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[64 + i * 32 + j] = bytes[j]; + }} + }} + + buffer + }} + " + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn private_to_be_bytes, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_to_be_bytes( + event_type: &str, + byte_length: u32, +) -> Result { + let byte_length_without_randomness = byte_length - 32; + let function_source = format!( + " + fn to_be_bytes(self: {event_type}) -> [u8; {byte_length_without_randomness}] {{ + let mut buffer: [u8; {byte_length_without_randomness}] = [0; {byte_length_without_randomness}]; + + let event_type_id_bytes = {event_type}::get_event_type_id().to_field().to_be_bytes(32); + + for i in 0..32 {{ + buffer[i] = event_type_id_bytes[i]; + }} + + let serialized_event = self.serialize(); + + for i in 0..serialized_event.len() {{ + let bytes = serialized_event[i].to_be_bytes(32); + for j in 0..32 {{ + buffer[32 + i * 32 + j] = bytes[j]; + }} + }} + + buffer + }} + ") + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn to_be_bytes, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +fn generate_fn_emit(event_type: &str) -> Result { + let function_source = format!( + " + fn emit(self: {event_type}, _emit: fn[Env](Self) -> ()) {{ + _emit(self); + }} + " + ) + .to_string(); + + let (function_ast, errors) = parse_program(&function_source); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotImplementEventInterface { + secondary_message: Some(format!("Failed to parse Noir macro code (fn emit, implemented for EventInterface of {event_type}). This is either a bug in the compiler or the Noir macro code")), + }); + } + + let mut function_ast = function_ast.into_sorted(); + let mut noir_fn = function_ast.functions.remove(0); + noir_fn.def.visibility = ItemVisibility::Public; + Ok(noir_fn) +} + +// We do this pass in the HIR to work around the "#[abi(tag)] attributes can only be used in contracts" error +pub fn transform_event_abi( crate_id: &CrateId, context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { @@ -184,3 +339,14 @@ pub fn transform_events( } Ok(()) } + +fn transform_event( + struct_id: StructId, + interner: &mut NodeInterner, +) -> Result<(), (AztecMacroError, FileId)> { + interner.update_struct_attributes(struct_id, |struct_attributes| { + struct_attributes.push(SecondaryAttribute::Abi("events".to_string())); + }); + + Ok(()) +} 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 fdce8b81db29..3ace22a89c30 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -11,7 +11,10 @@ use noirc_frontend::{ Type, }; +use acvm::AcirField; use regex::Regex; +// TODO(#7165): nuke the following dependency from here and Cargo.toml +use tiny_keccak::{Hasher, Keccak}; use crate::{ chained_dep, @@ -97,7 +100,6 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt .collect::, _>>()?; let [note_serialized_len, note_bytes_len]: [_; 2] = note_interface_generics.try_into().unwrap(); - let note_type_id = note_type_id(¬e_type); // Automatically inject the header field if it's not present let (header_field_name, _) = if let Some(existing_header) = @@ -184,25 +186,26 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt } if !check_trait_method_implemented(trait_impl, "get_note_type_id") { + let note_type_id = compute_note_type_id(¬e_type); let get_note_type_id_fn = - generate_note_get_type_id(¬e_type_id, note_interface_impl_span)?; + generate_get_note_type_id(note_type_id, note_interface_impl_span)?; trait_impl.items.push(TraitImplItem::Function(get_note_type_id_fn)); } if !check_trait_method_implemented(trait_impl, "compute_note_content_hash") { - let get_header_fn = + let compute_note_content_hash_fn = generate_compute_note_content_hash(¬e_type, note_interface_impl_span)?; - trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + trait_impl.items.push(TraitImplItem::Function(compute_note_content_hash_fn)); } if !check_trait_method_implemented(trait_impl, "to_be_bytes") { - let get_header_fn = generate_note_to_be_bytes( + let to_be_bytes_fn = generate_note_to_be_bytes( ¬e_type, note_bytes_len.as_str(), note_serialized_len.as_str(), note_interface_impl_span, )?; - trait_impl.items.push(TraitImplItem::Function(get_header_fn)); + trait_impl.items.push(TraitImplItem::Function(to_be_bytes_fn)); } } @@ -324,16 +327,17 @@ fn generate_note_set_header( // Automatically generate the note type id getter method. The id itself its calculated as the concatenation // of the conversion of the characters in the note's struct name to unsigned integers. -fn generate_note_get_type_id( - note_type_id: &str, +fn generate_get_note_type_id( + note_type_id: u32, impl_span: Option, ) -> Result { + // TODO(#7165): replace {} with dep::aztec::protocol_types::abis::note_selector::compute_note_selector(\"{}\") in the function source below let function_source = format!( " - fn get_note_type_id() -> Field {{ - {} - }} - ", + fn get_note_type_id() -> Field {{ + {} + }} + ", note_type_id ) .to_string(); @@ -387,7 +391,7 @@ fn generate_note_properties_struct( // Generate the deserialize_content method as // -// fn deserialize_content(serialized_note: [Field; NOTE_SERILIZED_LEN]) -> Self { +// fn deserialize_content(serialized_note: [Field; NOTE_SERIALIZED_LEN]) -> Self { // NoteType { // note_field1: serialized_note[0] as Field, // note_field2: NoteFieldType2::from_field(serialized_note[1])... @@ -525,10 +529,10 @@ fn generate_note_exports_global( let struct_source = format!( " #[abi(notes)] - global {0}_EXPORTS: (Field, str<{1}>) = ({2},\"{0}\"); + global {0}_EXPORTS: (Field, str<{1}>) = (0x{2},\"{0}\"); ", note_type, - note_type_id.len(), + note_type.len(), note_type_id ) .to_string(); @@ -685,10 +689,18 @@ fn generate_note_deserialize_content_source( .to_string() } +// TODO(#7165): nuke this function // Utility function to generate the note type id as a Field -fn note_type_id(note_type: &str) -> String { +fn compute_note_type_id(note_type: &str) -> u32 { // TODO(#4519) Improve automatic note id generation and assignment - note_type.chars().map(|c| (c as u32).to_string()).collect::>().join("") + let mut keccak = Keccak::v256(); + let mut result = [0u8; 32]; + keccak.update(note_type.as_bytes()); + keccak.finalize(&mut result); + // Take the first 4 bytes of the hash and convert them to an integer + // If you change the following value you have to change NUM_BYTES_PER_NOTE_TYPE_ID in l1_note_payload.ts as well + let num_bytes_per_note_type_id = 4; + u32::from_be_bytes(result[0..num_bytes_per_note_type_id].try_into().unwrap()) } pub fn inject_note_exports( @@ -717,29 +729,42 @@ pub fn inject_note_exports( }, file_id, ))?; - let init_function = + let get_note_type_id_function = context.def_interner.function(&func_id).block(&context.def_interner); - let init_function_statement_id = init_function.statements().first().ok_or(( - AztecMacroError::CouldNotExportStorageLayout { - span: None, - secondary_message: Some(format!( - "Could not retrieve note id statement from function for note {}", - note.borrow().name.0.contents - )), - }, - file_id, - ))?; - let note_id_statement = context.def_interner.statement(init_function_statement_id); + let get_note_type_id_statement_id = + get_note_type_id_function.statements().first().ok_or(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some(format!( + "Could not retrieve note id statement from function for note {}", + note.borrow().name.0.contents + )), + }, + file_id, + ))?; + let note_type_id_statement = + context.def_interner.statement(get_note_type_id_statement_id); - let note_id_value = match note_id_statement { + let note_type_id = match note_type_id_statement { HirStatement::Expression(expression_id) => { match context.def_interner.expression(&expression_id) { HirExpression::Literal(HirLiteral::Integer(value, _)) => Ok(value), + HirExpression::Literal(_) => Err(( + AztecMacroError::CouldNotExportStorageLayout { + span: None, + secondary_message: Some( + "note_type_id statement must be a literal integer expression" + .to_string(), + ), + }, + file_id, + )), _ => Err(( AztecMacroError::CouldNotExportStorageLayout { span: None, secondary_message: Some( - "note_id statement must be a literal expression".to_string(), + "note_type_id statement must be a literal expression" + .to_string(), ), }, file_id, @@ -747,9 +772,10 @@ pub fn inject_note_exports( } } _ => Err(( - AztecMacroError::CouldNotAssignStorageSlots { + AztecMacroError::CouldNotExportStorageLayout { + span: None, secondary_message: Some( - "note_id statement must be an expression".to_string(), + "note_type_id statement must be an expression".to_string(), ), }, file_id, @@ -757,7 +783,7 @@ pub fn inject_note_exports( }?; let global = generate_note_exports_global( ¬e.borrow().name.0.contents, - ¬e_id_value.to_string(), + ¬e_type_id.to_hex(), ) .map_err(|err| (err, file_id))?; diff --git a/noir/noir-repo/aztec_macros/src/utils/constants.rs b/noir/noir-repo/aztec_macros/src/utils/constants.rs index 848cca0477d8..2178f7a25264 100644 --- a/noir/noir-repo/aztec_macros/src/utils/constants.rs +++ b/noir/noir-repo/aztec_macros/src/utils/constants.rs @@ -1,4 +1,3 @@ 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 852b5f1e57ac..557d065cb25b 100644 --- a/noir/noir-repo/aztec_macros/src/utils/errors.rs +++ b/noir/noir-repo/aztec_macros/src/utils/errors.rs @@ -14,6 +14,7 @@ pub enum AztecMacroError { CouldNotAssignStorageSlots { secondary_message: Option }, CouldNotImplementComputeNoteHashAndOptionallyANullifier { secondary_message: Option }, CouldNotImplementNoteInterface { span: Option, secondary_message: Option }, + CouldNotImplementEventInterface { secondary_message: Option }, MultipleStorageDefinitions { span: Option }, CouldNotExportStorageLayout { span: Option, secondary_message: Option }, CouldNotInjectContextGenericInStorage { secondary_message: Option }, @@ -67,6 +68,11 @@ impl From for MacroError { secondary_message, span }, + AztecMacroError::CouldNotImplementEventInterface { secondary_message } => MacroError { + primary_message: "Could not implement automatic methods for event, please provide an implementation of the EventInterface trait".to_string(), + secondary_message, + span: None, + }, AztecMacroError::MultipleStorageDefinitions { span } => MacroError { primary_message: "Only one struct can be tagged as #[aztec(storage)]".to_string(), secondary_message: None, diff --git a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs index 71dd1b187610..e959c61732a2 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -1,6 +1,7 @@ use std::collections::BTreeMap; use acvm::acir::circuit::ErrorSelector; +use acvm::AcirField; use iter_extended::vecmap; use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue}; use noirc_frontend::ast::Visibility; @@ -107,9 +108,7 @@ pub(super) fn value_from_hir_expression(context: &Context, expression: HirExpres }, HirLiteral::Bool(value) => AbiValue::Boolean { value }, HirLiteral::Str(value) => AbiValue::String { value }, - HirLiteral::Integer(field, sign) => { - AbiValue::Integer { value: field.to_string(), sign } - } + HirLiteral::Integer(field, sign) => AbiValue::Integer { value: field.to_hex(), sign }, _ => unreachable!("Literal cannot be used in the abi"), }, _ => unreachable!("Type cannot be used in the abi {:?}", expression), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index 343113836ed4..9a0be775c307 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -88,15 +88,12 @@ pub fn resolve_import( import_directive: &ImportDirective, def_maps: &BTreeMap, ) -> Result { - let allow_contracts = - allow_referencing_contracts(def_maps, crate_id, import_directive.module_id); - let module_scope = import_directive.module_id; let NamespaceResolution { module_id: resolved_module, namespace: resolved_namespace, mut error, - } = resolve_path_to_ns(import_directive, crate_id, crate_id, def_maps, allow_contracts)?; + } = resolve_path_to_ns(import_directive, crate_id, crate_id, def_maps)?; let name = resolve_path_name(import_directive); @@ -129,20 +126,11 @@ pub fn resolve_import( }) } -fn allow_referencing_contracts( - def_maps: &BTreeMap, - krate: CrateId, - local_id: LocalModuleId, -) -> bool { - ModuleId { krate, local_id }.module(def_maps).is_contract -} - fn resolve_path_to_ns( import_directive: &ImportDirective, crate_id: CrateId, importing_crate: CrateId, def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { let import_path = &import_directive.path.segments; let def_map = &def_maps[&crate_id]; @@ -150,21 +138,11 @@ fn resolve_path_to_ns( match import_directive.path.kind { crate::ast::PathKind::Crate => { // Resolve from the root of the crate - resolve_path_from_crate_root( - crate_id, - importing_crate, - import_path, - def_maps, - allow_contracts, - ) + resolve_path_from_crate_root(crate_id, importing_crate, import_path, def_maps) + } + crate::ast::PathKind::Dep => { + resolve_external_dep(def_map, import_directive, def_maps, importing_crate) } - crate::ast::PathKind::Dep => resolve_external_dep( - def_map, - import_directive, - def_maps, - allow_contracts, - importing_crate, - ), crate::ast::PathKind::Plain => { // Plain paths are only used to import children modules. It's possible to allow import of external deps, but maybe this distinction is better? // In Rust they can also point to external Dependencies, if no children can be found with the specified name @@ -174,7 +152,6 @@ fn resolve_path_to_ns( import_path, import_directive.module_id, def_maps, - allow_contracts, ) } } @@ -186,7 +163,6 @@ fn resolve_path_from_crate_root( import_path: &[Ident], def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { resolve_name_in_module( crate_id, @@ -194,7 +170,6 @@ fn resolve_path_from_crate_root( import_path, def_maps[&crate_id].root, def_maps, - allow_contracts, ) } @@ -204,7 +179,6 @@ fn resolve_name_in_module( import_path: &[Ident], starting_mod: LocalModuleId, def_maps: &BTreeMap, - allow_contracts: bool, ) -> NamespaceResolutionResult { let def_map = &def_maps[&krate]; let mut current_mod_id = ModuleId { krate, local_id: starting_mod }; @@ -267,10 +241,6 @@ fn resolve_name_in_module( return Err(PathResolutionError::Unresolved(current_segment.clone())); } - // Check if it is a contract and we're calling from a non-contract context - if current_mod.is_contract && !allow_contracts { - return Err(PathResolutionError::ExternalContractUsed(current_segment.clone())); - } current_ns = found_ns; } @@ -288,7 +258,6 @@ fn resolve_external_dep( current_def_map: &CrateDefMap, directive: &ImportDirective, def_maps: &BTreeMap, - allow_contracts: bool, importing_crate: CrateId, ) -> NamespaceResolutionResult { // Use extern_prelude to get the dep @@ -316,7 +285,7 @@ fn resolve_external_dep( is_prelude: false, }; - resolve_path_to_ns(&dep_directive, dep_module.krate, importing_crate, def_maps, allow_contracts) + resolve_path_to_ns(&dep_directive, dep_module.krate, importing_crate, def_maps) } // Issue an error if the given private function is being called from a non-child module, or 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 cef49332b001..cd82685c31e5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -623,6 +623,15 @@ impl NodeInterner { f(&mut value); } + pub fn update_struct_attributes( + &mut self, + type_id: StructId, + f: impl FnOnce(&mut StructAttributes), + ) { + let value = self.struct_attributes.get_mut(&type_id).unwrap(); + f(value); + } + pub fn update_trait(&mut self, trait_id: TraitId, f: impl FnOnce(&mut Trait)) { let value = self.traits.get_mut(&trait_id).unwrap(); f(value); diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 1ebc77c5a5fd..4619fd298dd3 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x00000000000000000000000000000044d7ca77b464f03aa44f6f8d49a0d3ada5","0x00000000000000000000000000000000002a36959f550517d82d0af666bcd7dc","0x0000000000000000000000000000000566b28c19f0b1732b95e0381bc5d6dbdd","0x00000000000000000000000000000000002511360b7a8c6a823559f0ac9eb02b","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x00000000000000000000000000000058035b1ed115023f42bf4ee93d2dc29dcb","0x00000000000000000000000000000000002de4b004225be4e68938b0db546287","0x0000000000000000000000000000003d18d72585ef033ab3663d1944abb2054a","0x0000000000000000000000000000000000149a1974c0c2b5f0639970cda1af83","0x000000000000000000000000000000bb1eb2b1fc10b55295ed6c1ae54e8a40da","0x000000000000000000000000000000000026da80059472ac8c64e437d6fe6134","0x000000000000000000000000000000d1f101b72ee710423ca44548910676a4fe","0x00000000000000000000000000000000000323378ad6b5aec67af99e522095a0","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x2622384e4b4688a3ad115007c1c09de1a141aeca06c31925898cf746038a5897","0x2f743e893a3880004db1ff3492279d89c025b9815f16e129d15f7a3687b6f833","0x03e05487307f18e3afb90cc524e56809e478039d317a3757433bfc8e06a32b73","0x099ba7011747dd2d8b5ac03ed02b93c9803d51899677409931d5b1571c3041b5","0x189ef108e334c5173619eac1067b99526a5cc6e47cbffaa3c117f0c3eb8bebd4","0x0b5f77b69ac2955ecc44a73e18b2ea8403224cf769657d53acc9a5d302d0b86e","0x1b81353a160e985e8a1fb09d3a3827fe68d03585757530dcec1b8038ac829a21","0x175e75cef1b974011de38e6e631f42bffd4dcb6fad6680930388cffaa60d940e","0x1631945a2aa39032cfa8cf379d18a983d4b5a487adab67252c6514b35bc88095","0x181b639e465a6f9842c5d75f6f5b855a065f498595146df3bd2b9c0ef66042a1","0x0c6e5af7add3e12f610c13d8066896d08882a7c50cfe33676fda8a75e250e9b9","0x28f94cd060c45a2e6b423831302deb456d0964879db5008a2be0957a2c749e2a","0x1c81fb20cea508580aa962e5b4736a43382816e7abac7e478e6c080cf896798d","0x23dea53784aa14dcf7e1cce5ee480796e67b2dd69a8e20c5c09558001640edfa","0x149c2548f8b0d96fefecab53e31aa3902341c903fa0ef863ef64610315de993b","0x16ad81b3129ccebe1682d14b726bc9b86acd0f0be8c304594ce5a87e756add27","0x2c1ef938516edccc0cd1d4d812644d72b6ead3c85e1c8500fc54e77e5652b23f","0x0eecb7fba3395b21197cb24bb9b733b1985d81f35a1ee944714ffd781a7bd136","0x06e2a96ecf1e8419198eca10133954f3560102467f40a234cf071d23c6cf411a","0x1e6bfa2adcbdc50313408ef28a77b76dd915fa372c093c4484ba662695a3eadc","0x28ccaf4d4759c1f4bb49429b961a59cdefbc445017ffa807e90c54b27e1ee657","0x22803d537311e757a146ae7a2fc396d42d67f27e73efca82e3e324dc493da4de","0x196255f687cede05f326204bfaead7a54f8d48b67ce8522cb8af6a7fffaffcb6","0x147ea42988386b944f006be242ccc6b099fadd7f450955d252768667bbaee4f9","0x1f9ccb05e508b1d08c79c11acbc0677fdc18d5d40827e2e1eaae60fee51b940f","0x28ea76870d22eea72821da25f9b7a89341347afcd6c077387986a82dc8afa833","0x0e6ef82d3e5a318a9c6233dffbb00d130599f4ac979a89b034ce9d930b11165a","0x2e97fa9299a218c982504199ada3278270b9cb566bf46fe1ecc1d151e06b8745","0x1a41ac9b1032ac24c11720407c253a866e9c75a4ec233f15f968b206ea1e5d0e","0x0b31b541bb044c1bc2428c2a57ba29438f620050d1628389ff1fa90c494d7c58","0x050fec8d69f182768a9b34eca8c3f4695dad8bc20a10904090cfe18777d44d25","0x069283ac40daaafff76c3679f54a0aa773c8d71152fbb9c3219906113fc4f683","0x25c3ec4e8b90214aafe3b5416abf11a98bd34b8acb449df8424f159ddf858bc1","0x1a3884f3a922d0da758cb7ed9a5ddc3c3c2132dde8d913753fa3e6b766be5697","0x222d05a0fce0565bf9cc490f97bd4eff53858f2ca6afe9d91c5c8d7de8076f39","0x054698b045b439467a3067a8dc2b4d020b2bb44df3d98a19f9cfb04c9ee5ffd1","0x0e39d66cded0f3df40e04124e36c827bcaf15fbe9fb6e9bbc3af889f8bd1ebf0","0x145aea47dc97ec35ac67f135aac37f8bc6eaf149551a2f48901529d10e25c860","0x1894877b2769ae2c288738f8aa33acfc7ca9a7d1e26a76908ca2909bf25aa59a","0x27e8c702be67be467f052abd180464a468b7d5d5d8a4961e56e8561f7863c91a","0x0326d3e4607d54a30c7fa99d1609f386aeb8c8094cabd7397246074f634dcec8","0x17eb8f62b5ba2dad391e3f81d3a6b9d03ff723a7d6a4d77b98b18ddd0debf4fd","0x1a5d3e8a27c1f69d6e4558b3c89cd9347c62182ce90fb6e34392bc4e7b7c178c","0x2293034bed3d33d5ad0d150f64d493c9be554f640103621f9ae56034a7323d84","0x13d75ffbb9d2ceb2daa6d42f3618d4ea9775befa1cf5f9df141dfebf794abc35","0x2ec339c42fbb2d50221ec907779e72be3eab2960d110a90d36cc6c0afcf5857e","0x15e9c913fa84a2657571831d5d7a90f6534ca67a1617b4063fa5bf09f46cd7a2","0x10f56fbe9fefd59d2acd49fa641fedcfb65d96d54cf47207e2c8ab34f22bbabe","0x117fa3859a400040ebe8dee4a60ddcb04484ff5cfb5294c6530354c3c8cb35f3","0x123260b824df2f8bbe6a351ba2fa94c61aa754741eb198b768a699b2d1cc2b6f","0x1e51d9a653adc6b67287d35bb60584261f57363177c6b54a56dbd39834d851ba","0x18a9b2e2fce77bdb5e41215e2caeb7e77e946dbb2f381c8e7974709e03a6c216","0x2b2640870195a40e374cfa834e37ad9a5e17cb687bd2119a63ac02c3769b0f1e","0x2da73263fef362dfc79dd1066fd7ec294b765e2533f3ac4320e8d1540f2639a8","0x0cc9f299e5291bb1bc0951ce510a634c418af9f9802a291fe6d951768c0a1b2d","0x02a940acb788df42cc9219531776d45465be19087fc3f523fe92df771e5efc10","0x2d5976cc5540e761824bdacf69a2dddabe104fdbb235985ae9080b488f642fa9","0x284c18d1574d2cb7b4ee45b3ff30176eff2ab9c7b7f60cd8a87cef599379244d","0x12a38d659bf38da09af8f445505baa16bcb036d83173f6f45a7e46cac511e5a1","0x0852ef710b2396ba5b7fd69a95b336908d3a368262ec41e0d972564f784201a4","0x240c467a31ed3bb7c4cef09407750d2d89b3750e6cebb4aaa9d0f1f92be77249","0x04edf7595087745abc11fe7780afd4754c5013725653a4cec31f039b77e7b3c7","0x080d04b50ae3acd787f33f8f4a639a58677b5c04ef8a352fd4dd9236883f0e81","0x0cd745e7540fe230038f024ab1269177599ad94e8d8099a010eb7eebd3e41ec8","0x25e2394f90f5b3e3046b8876a6b3ef19a03ef9e9aeae4813fcb14907decc0393","0x03df12a6e39c606d70d3d470aff710d9daa86dece773a6f6f057725b57d6d115","0x0f744082aecf54f55db19dfbe56a81c17b3eb48417305c129beb6c97a22c705b","0x244a80d6d82e82fc416e8e4694deb4e08b81c32bb90cb2f96ff3f687298322d1","0x251eb4d8692f49523e3972096264ee770b295fb62a970fbfdd8aa1fff661ef50","0x0c4d9200120430618493a9151d632faa95c9ae842b7d97103a4afb3330cafbed","0x09e970a55dd7335db16a3823b6489c77cb7785f674cb7c924994ee121122e514","0x19e5bd1113959463be673ee72103bfe7559f423c632fbf9701ff099e165c429b","0x071eb2916ba30652a328c98353f69f239c41a4913c34931f18e91e5414b3270a","0x2a0cd2ebac904b7ebd82b6509dfcaf9ecf32175758c691d01f4fb32dad6371c4","0x1aa43a3009417d95904ebecd4189545e52ca7e9c7dfa3bde5f255ddefed5c754","0x29fd7a93212d60af81b810dad13a240bbbe16966a4977408b1d64c5d692b50b4","0x000000000000000000000000000000bef7cad70fa62891e6329cb7c17d0c5459","0x0000000000000000000000000000000000209177f2a04609421c1f23c04b454e","0x00000000000000000000000000000060dec389686170618e2490100f3fcf39e2","0x0000000000000000000000000000000000213368873145aad5f93798c31730af","0x000000000000000000000000000000c0f21a470488d9cbe53650d941c25cd569","0x000000000000000000000000000000000016d6f88e6b319553f5948886a6bd5e","0x000000000000000000000000000000d6dbb8a54a071e01c46d648c8c555ec352","0x0000000000000000000000000000000000130a7ce06ad74eb6c83f5565e2f821","0x00000000000000000000000000000058ca3aa788bd6ff37a5da3ecefdc896601","0x00000000000000000000000000000000001381bddcf8fb976cc52fee0d920598","0x00000000000000000000000000000082bdd94acd10edf22e09b1a42be500f8f8","0x00000000000000000000000000000000002f27815e28b2bc0699336893abdc0f","0x000000000000000000000000000000eb1d6973a54f8848f4c0630370d6181e49","0x000000000000000000000000000000000000129c1889d64ab66303bf17bfc864","0x000000000000000000000000000000155918aa9f6d352b847bf860a261266282","0x0000000000000000000000000000000000216e687d2f85a811f67573cbf311ba","0x0000000000000000000000000000002d2662f79a7ba21a95f44e67ed0b5abf3b","0x00000000000000000000000000000000001351870a81dc6edff235df110fe798","0x000000000000000000000000000000b113a55b86f59b21fe419ed8518dfddfc6","0x00000000000000000000000000000000002f26cd920f79b0d72a49897acc521c","0x0000000000000000000000000000002a4e1689c65dcae73ed1a33b03c611a7fe","0x00000000000000000000000000000000001c5093a8ae791c00fdd763c95800c5","0x0000000000000000000000000000006231d049ec3683c06ec6b00348e0669c61","0x0000000000000000000000000000000000237bfd7ec06c28f22ce84db9bb17ed","0x0000000000000000000000000000008afa7fa0842467bded20491950c3c1cde0","0x00000000000000000000000000000000000194ab5c71154605b8483cb40d00b8","0x00000000000000000000000000000066709af193591e93e8be3b833f63cb8597","0x000000000000000000000000000000000008ab9091bb9225b00ca0c011dff12f"] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x0000000000000000000000000000007f36e0b4f59927ebbb2302e76cbe8bd44e","0x00000000000000000000000000000000001b95777c6c98640c80638c195909ca","0x0000000000000000000000000000006d4b1ad71244248cb2070fbbbb0ac9df88","0x00000000000000000000000000000000001abada4d5d816a67b6fc75746cb723","0x000000000000000000000000000000465811089df032ceb5269254547a101e57","0x000000000000000000000000000000000011a4a909c59776a6df9c7615e8e87d","0x000000000000000000000000000000311f6f724e7199351c9774225f15c25f20","0x00000000000000000000000000000000001ddba8eb0ab208ad3d96c70941fcbc","0x0000000000000000000000000000000dfa80bdf5be151b21ad89466b7201b63d","0x000000000000000000000000000000000015ca7dc258adab8ea406d94e00c56d","0x000000000000000000000000000000507ea3454165f92295b6e435c7d30d14f0","0x00000000000000000000000000000000002f522608db7b7d389d1df67eab104d","0x000000000000000000000000000000950102cce743fadb23965fc72e31efd36c","0x000000000000000000000000000000000018b4a7ec90df68dfe97d3c5367d1bf","0x000000000000000000000000000000118d90258b25dba8bc0f99d9f7547c6a62","0x000000000000000000000000000000000012d78638701da6322abbf325693b0f","0x000000000000000000000000000000144743e0d082f35295b51561af65f94c6b","0x00000000000000000000000000000000002322a615615e5405836374bb3c5336","0x000000000000000000000000000000e6f08dd5904ee42f826cde680919b41a96","0x00000000000000000000000000000000002d3f823ea255b68465e4b5360bf864","0x00000000000000000000000000000076d4db93683b6363ae92a5a20d8bb9922e","0x00000000000000000000000000000000002f8a7009cac72c9599b81cb9054308","0x00000000000000000000000000000085c12dd2be9f2b29e54c1a4bc3cbf9b6ce","0x000000000000000000000000000000000024e3688a1f4f50b0c6bd6c068f32b2","0x00000000000000000000000000000023a2015e7ea351e444c9405adfbd81e84d","0x00000000000000000000000000000000001fb3e4228c15dc4380db796925ec49","0x000000000000000000000000000000834ad9406b8ded7208b872373be7445e47","0x0000000000000000000000000000000000267544d6a9f5cc46d10555f2617c65"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr index d25fd804ce4c..c534b07fc77f 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -6,7 +6,7 @@ fn main( // This is the proof without public inputs attached. // // This means: the size of this does not change with the number of public inputs. - proof: [Field; 153], + proof: [Field; 156], public_inputs: pub [Field; 1], // This is currently not public. It is fine given that the vk is a part of the circuit definition. // I believe we want to eventually make it public too though. diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 82f52d6e6ebc..1f4e2fdc7906 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -202,7 +202,7 @@ anvil: FROM ../build-images+build SAVE ARTIFACT /opt/foundry/bin/anvil -end-to-end: +end-to-end-base: FROM ubuntu:noble # add repository for chromium RUN apt-get update && apt-get install -y software-properties-common \ @@ -221,10 +221,15 @@ end-to-end: ENV ACVM_BINARY_PATH=/usr/src/noir/noir-repo/target/release/acvm ENV PROVER_AGENT_CONCURRENCY=8 RUN mkdir -p $BB_WORKING_DIRECTORY $ACVM_WORKING_DIRECTORY + + RUN ln -s /usr/src/yarn-project/.yarn/releases/yarn-3.6.3.cjs /usr/local/bin/yarn + +end-to-end: + FROM +end-to-end-base + COPY +anvil/anvil /opt/foundry/bin/anvil COPY +end-to-end-prod/usr/src /usr/src WORKDIR /usr/src/yarn-project/end-to-end - RUN ln -s /usr/src/yarn-project/.yarn/releases/yarn-3.6.3.cjs /usr/local/bin/yarn ENTRYPOINT ["yarn", "test"] scripts-prod: diff --git a/yarn-project/accounts/package.json b/yarn-project/accounts/package.json index 2b3cde6cec1d..90d2d36ab832 100644 --- a/yarn-project/accounts/package.json +++ b/yarn-project/accounts/package.json @@ -45,7 +45,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 40f0a1799378..9514bf2b7e45 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -34,7 +34,15 @@ "workerThreads": true, "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -57,6 +65,7 @@ "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", "@aztec/protocol-contracts": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", "debug": "^4.3.4", "lodash.groupby": "^4.6.0", diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 9c83e57981d1..1040f308faea 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -10,6 +10,7 @@ import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { sleep } from '@aztec/foundation/sleep'; import { AvailabilityOracleAbi, type InboxAbi, RollupAbi } from '@aztec/l1-artifacts'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MockProxy, mock } from 'jest-mock-extended'; import { @@ -49,6 +50,7 @@ describe('Archiver', () => { registryAddress, archiverStore, 1000, + new NoopTelemetryClient(), ); let latestBlockNum = await archiver.getBlockNumber(); @@ -152,6 +154,7 @@ describe('Archiver', () => { registryAddress, archiverStore, 1000, + new NoopTelemetryClient(), ); let latestBlockNum = await archiver.getBlockNumber(); diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 9face3a26aeb..b03ce4d21153 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -29,6 +29,7 @@ import { Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; import { ClassRegistererAddress } from '@aztec/protocol-contracts/class-registerer'; +import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ContractClassPublic, type ContractDataSource, @@ -49,6 +50,7 @@ import { retrieveBlockMetadataFromRollup, retrieveL1ToL2Messages, } from './data_retrieval.js'; +import { ArchiverInstrumentation } from './instrumentation.js'; /** * Helper interface to combine all sources this archiver implementation provides. @@ -66,6 +68,9 @@ export class Archiver implements ArchiveSource { */ private runningPromise?: RunningPromise; + /** Capture runtime metrics */ + private instrumentation: ArchiverInstrumentation; + /** * Creates a new instance of the Archiver. * @param publicClient - A client for interacting with the Ethereum node. @@ -84,8 +89,11 @@ export class Archiver implements ArchiveSource { private readonly registryAddress: EthAddress, private readonly store: ArchiverDataStore, private readonly pollingIntervalMs = 10_000, + telemetry: TelemetryClient, private readonly log: DebugLogger = createDebugLogger('aztec:archiver'), - ) {} + ) { + this.instrumentation = new ArchiverInstrumentation(telemetry); + } /** * Creates a new instance of the Archiver and blocks until it syncs from chain. @@ -97,6 +105,7 @@ export class Archiver implements ArchiveSource { public static async createAndSync( config: ArchiverConfig, archiverStore: ArchiverDataStore, + telemetry: TelemetryClient, blockUntilSynced = true, ): Promise { const chain = createEthereumChain(config.rpcUrl, config.apiKey); @@ -114,6 +123,7 @@ export class Archiver implements ArchiveSource { config.l1Contracts.registryAddress, archiverStore, config.archiverPollingIntervalMS, + telemetry, ); await archiver.start(blockUntilSynced); return archiver; @@ -286,6 +296,7 @@ export class Archiver implements ArchiveSource { ); await this.store.addBlocks(retrievedBlocks); + this.instrumentation.processNewBlocks(retrievedBlocks.retrievedData); } /** diff --git a/yarn-project/archiver/src/archiver/instrumentation.ts b/yarn-project/archiver/src/archiver/instrumentation.ts new file mode 100644 index 000000000000..837b00af7f2d --- /dev/null +++ b/yarn-project/archiver/src/archiver/instrumentation.ts @@ -0,0 +1,30 @@ +import { type L2Block } from '@aztec/circuit-types'; +import { type Gauge, type Histogram, Metrics, type TelemetryClient, ValueType } from '@aztec/telemetry-client'; + +export class ArchiverInstrumentation { + private blockHeight: Gauge; + private blockSize: Histogram; + + constructor(telemetry: TelemetryClient) { + const meter = telemetry.getMeter('Archiver'); + this.blockHeight = meter.createGauge(Metrics.ARCHIVER_BLOCK_HEIGHT, { + description: 'The height of the latest block processed by the archiver', + valueType: ValueType.INT, + }); + + this.blockSize = meter.createHistogram(Metrics.ARCHIVER_BLOCK_SIZE, { + description: 'The number of transactions processed per block', + valueType: ValueType.INT, + advice: { + explicitBucketBoundaries: [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192], + }, + }); + } + + public processNewBlocks(blocks: L2Block[]) { + this.blockHeight.record(Math.max(...blocks.map(b => b.number))); + for (const block of blocks) { + this.blockSize.record(block.body.txEffects.length); + } + } +} diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts index 693b1e9c60cc..d22537ae824f 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/block_store.ts @@ -187,7 +187,6 @@ export class BlockStore { } if (start < INITIAL_L2_BLOCK_NUM) { - this.#log.verbose(`Clamping start block ${start} to ${INITIAL_L2_BLOCK_NUM}`); start = INITIAL_L2_BLOCK_NUM; } diff --git a/yarn-project/archiver/src/index.ts b/yarn-project/archiver/src/index.ts index fb3f8da310af..cf4549e81a0a 100644 --- a/yarn-project/archiver/src/index.ts +++ b/yarn-project/archiver/src/index.ts @@ -1,5 +1,6 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { createPublicClient, http } from 'viem'; import { localhost } from 'viem/chains'; @@ -34,6 +35,8 @@ async function main() { l1Contracts.inboxAddress, l1Contracts.registryAddress, archiverStore, + 1000, + new NoopTelemetryClient(), ); const shutdown = async () => { diff --git a/yarn-project/archiver/tsconfig.json b/yarn-project/archiver/tsconfig.json index ea0bb3a5469c..dbe9915c0107 100644 --- a/yarn-project/archiver/tsconfig.json +++ b/yarn-project/archiver/tsconfig.json @@ -27,6 +27,9 @@ { "path": "../protocol-contracts" }, + { + "path": "../telemetry-client" + }, { "path": "../types" }, diff --git a/yarn-project/aztec-faucet/package.json b/yarn-project/aztec-faucet/package.json index 957b2203b87e..567a3afb5dce 100644 --- a/yarn-project/aztec-faucet/package.json +++ b/yarn-project/aztec-faucet/package.json @@ -31,7 +31,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/aztec-node/package.json b/yarn-project/aztec-node/package.json index 6689da130017..6189671d5290 100644 --- a/yarn-project/aztec-node/package.json +++ b/yarn-project/aztec-node/package.json @@ -32,7 +32,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -62,6 +70,7 @@ "@aztec/prover-client": "workspace:^", "@aztec/sequencer-client": "workspace:^", "@aztec/simulator": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", "@aztec/world-state": "workspace:^", "koa": "^2.14.2", diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts index 309a9ef3bccc..a1d559bf498a 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.test.ts @@ -1,4 +1,5 @@ import { createEthereumChain } from '@aztec/ethereum'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type AztecNodeConfig, AztecNodeService } from '../index.js'; @@ -10,7 +11,9 @@ describe('aztec node service', () => { chainId: 12345, // not the testnet chain id }; const ethereumChain = createEthereumChain(config.rpcUrl!, config.apiKey); - await expect(() => AztecNodeService.createAndSync(config as AztecNodeConfig)).rejects.toThrow( + await expect(() => + AztecNodeService.createAndSync(config as AztecNodeConfig, new NoopTelemetryClient()), + ).rejects.toThrow( `RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`, ); }); diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index da82aa420e79..4e1eb36c75d7 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -63,6 +63,8 @@ import { getCanonicalMultiCallEntrypointAddress } from '@aztec/protocol-contract import { TxProver } from '@aztec/prover-client'; import { type GlobalVariableBuilder, SequencerClient, getGlobalVariableBuilder } from '@aztec/sequencer-client'; import { PublicProcessorFactory, WASMSimulator } from '@aztec/simulator'; +import { type TelemetryClient } from '@aztec/telemetry-client'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type ContractClassPublic, type ContractDataSource, @@ -104,6 +106,7 @@ export class AztecNodeService implements AztecNode { protected readonly merkleTreesDb: AztecKVStore, private readonly prover: ProverClient | undefined, private txValidator: TxValidator, + private telemetry: TelemetryClient, private log = createDebugLogger('aztec:node'), ) { this.packageVersion = getPackageInfo().version; @@ -124,9 +127,11 @@ export class AztecNodeService implements AztecNode { */ public static async createAndSync( config: AztecNodeConfig, + telemetry?: TelemetryClient, log = createDebugLogger('aztec:node'), storeLog = createDebugLogger('aztec:node:lmdb'), - ) { + ): Promise { + telemetry ??= new NoopTelemetryClient(); const ethereumChain = createEthereumChain(config.rpcUrl, config.apiKey); //validate that the actual chain id matches that specified in configuration if (config.chainId !== ethereumChain.chainInfo.id) { @@ -145,7 +150,7 @@ export class AztecNodeService implements AztecNode { if (!config.archiverUrl) { // first create and sync the archiver const archiverStore = new KVArchiverDataStore(store, config.maxLogs); - archiver = await Archiver.createAndSync(config, archiverStore, true); + archiver = await Archiver.createAndSync(config, archiverStore, telemetry, true); } else { archiver = createArchiverClient(config.archiverUrl); } @@ -155,7 +160,7 @@ export class AztecNodeService implements AztecNode { config.transactionProtocol = `/aztec/tx/${config.l1Contracts.rollupAddress.toString()}`; // create the tx pool and the p2p client, which will need the l2 block source - const p2pClient = await createP2PClient(store, config, new AztecKVTxPool(store), archiver); + const p2pClient = await createP2PClient(store, config, new AztecKVTxPool(store, telemetry), archiver); // now create the merkle trees and the world state synchronizer const merkleTrees = await MerkleTrees.new(store); @@ -179,6 +184,7 @@ export class AztecNodeService implements AztecNode { config, await proofVerifier.getVerificationKeys(), worldStateSynchronizer, + telemetry, await archiver .getBlock(-1) .then(b => b?.header ?? worldStateSynchronizer.getCommitted().buildInitialHeader()), @@ -200,6 +206,7 @@ export class AztecNodeService implements AztecNode { archiver, prover!, simulationProvider, + telemetry, ); return new AztecNodeService( @@ -218,6 +225,7 @@ export class AztecNodeService implements AztecNode { store, prover, txValidator, + telemetry, log, ); } @@ -756,6 +764,7 @@ export class AztecNodeService implements AztecNode { merkleTrees.asLatest(), this.contractDataSource, new WASMSimulator(), + this.telemetry, ); const processor = await publicProcessorFactory.create(prevHeader, newGlobalVariables); // REFACTOR: Consider merging ProcessReturnValues into ProcessedTx diff --git a/yarn-project/aztec-node/src/bin/index.ts b/yarn-project/aztec-node/src/bin/index.ts index e1688b791985..41aba729aebe 100644 --- a/yarn-project/aztec-node/src/bin/index.ts +++ b/yarn-project/aztec-node/src/bin/index.ts @@ -1,5 +1,6 @@ #!/usr/bin/env -S node --no-warnings import { createDebugLogger } from '@aztec/foundation/log'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import http from 'http'; @@ -15,7 +16,7 @@ const logger = createDebugLogger('aztec:node'); async function createAndDeployAztecNode() { const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars() }; - return await AztecNodeService.createAndSync(aztecNodeConfig); + return await AztecNodeService.createAndSync(aztecNodeConfig, new NoopTelemetryClient()); } /** diff --git a/yarn-project/aztec-node/tsconfig.json b/yarn-project/aztec-node/tsconfig.json index f023c003bff8..5a6637a7baca 100644 --- a/yarn-project/aztec-node/tsconfig.json +++ b/yarn-project/aztec-node/tsconfig.json @@ -48,6 +48,9 @@ { "path": "../simulator" }, + { + "path": "../telemetry-client" + }, { "path": "../types" }, diff --git a/yarn-project/aztec.js/package.json b/yarn-project/aztec.js/package.json index 96748862412c..367a1216ab2f 100644 --- a/yarn-project/aztec.js/package.json +++ b/yarn-project/aztec.js/package.json @@ -49,7 +49,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -86,7 +94,6 @@ "stream-browserify": "^3.0.0", "ts-loader": "^9.4.4", "ts-node": "^10.9.1", - "tty-browserify": "^0.0.1", "typescript": "^5.0.4", "util": "^0.12.5", "webpack": "^5.88.2", diff --git a/yarn-project/aztec.js/src/account/interface.ts b/yarn-project/aztec.js/src/account/interface.ts index 8919c3aa4031..cafef217f9e1 100644 --- a/yarn-project/aztec.js/src/account/interface.ts +++ b/yarn-project/aztec.js/src/account/interface.ts @@ -1,44 +1,25 @@ -import { type AuthWitness, type CompleteAddress, type FunctionCall } from '@aztec/circuit-types'; +import { type AuthWitness, type CompleteAddress } from '@aztec/circuit-types'; import { type AztecAddress } from '@aztec/circuits.js'; import { type Fq, type Fr } from '@aztec/foundation/fields'; -import { type ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; import { type EntrypointInterface } from '../entrypoint/entrypoint.js'; // docs:start:account-interface /** Creates authorization witnesses. */ export interface AuthWitnessProvider { /** - * Computes an authentication witness from either a message hash or an intent (caller and an action). - * If a message hash is provided, it will create a witness for that directly. - * Otherwise, it will compute the message hash using the caller and the action of the intent. - * @param messageHashOrIntent - The message hash or the intent (caller and action) to approve - * @param chainId - The chain id for the message, will default to the current chain id - * @param version - The version for the message, will default to the current protocol version + * Computes an authentication witness from either a message hash + * @param messageHash - The message hash to approve * @returns The authentication witness */ - createAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): Promise; + createAuthWit(messageHash: Fr | Buffer): Promise; } /** * Handler for interfacing with an account. Knows how to create transaction execution * requests and authorize actions for its corresponding account. */ -export interface AccountInterface extends AuthWitnessProvider, EntrypointInterface { +export interface AccountInterface extends EntrypointInterface, AuthWitnessProvider { /** Returns the complete address for this account. */ getCompleteAddress(): CompleteAddress; diff --git a/yarn-project/aztec.js/src/account/wallet.ts b/yarn-project/aztec.js/src/account/wallet.ts index d9d78aea434f..5dc257bca01e 100644 --- a/yarn-project/aztec.js/src/account/wallet.ts +++ b/yarn-project/aztec.js/src/account/wallet.ts @@ -1,8 +1,13 @@ -import { type PXE } from '@aztec/circuit-types'; +import { type AuthWitness, type PXE } from '@aztec/circuit-types'; +import { type IntentAction, type IntentInnerHash } from '../utils/authwit.js'; import { type AccountInterface, type AccountKeyRotationInterface } from './interface.js'; /** * The wallet interface. */ -export type Wallet = AccountInterface & PXE & AccountKeyRotationInterface; +export type Wallet = AccountInterface & + PXE & + AccountKeyRotationInterface & { + createAuthWit(intent: IntentInnerHash | IntentAction): Promise; + }; diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index 10e1b36de4c5..93618e261361 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -6,7 +6,6 @@ import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type Wallet } from '../account/wallet.js'; -import { computeAuthWitMessageHash } from '../utils/authwit.js'; import { type FeePaymentMethod } from './fee_payment_method.js'; /** @@ -55,11 +54,9 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { async getFunctionCalls(gasSettings: GasSettings): Promise { const nonce = Fr.random(); const maxFee = gasSettings.getFeeLimit(); - const messageHash = computeAuthWitMessageHash( - this.paymentContract, - this.wallet.getChainId(), - this.wallet.getVersion(), - { + await this.wallet.createAuthWit({ + caller: this.paymentContract, + action: { name: 'unshield', args: [this.wallet.getCompleteAddress().address, this.paymentContract, maxFee, nonce], selector: FunctionSelector.fromSignature('unshield((Field),(Field),Field,Field)'), @@ -68,8 +65,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { to: this.asset, returnTypes: [], }, - ); - await this.wallet.createAuthWit(messageHash); + }); const secretHashForRebate = computeSecretHash(this.rebateSecret); diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index 32e10f31be79..dae20d5fe8a1 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -4,7 +4,6 @@ import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; -import { computeAuthWitMessageHash } from '../utils/authwit.js'; import { type AccountWallet } from '../wallet/account_wallet.js'; import { type FeePaymentMethod } from './fee_payment_method.js'; @@ -47,23 +46,25 @@ export class PublicFeePaymentMethod implements FeePaymentMethod { getFunctionCalls(gasSettings: GasSettings): Promise { const nonce = Fr.random(); const maxFee = gasSettings.getFeeLimit(); - const messageHash = computeAuthWitMessageHash( - this.paymentContract, - this.wallet.getChainId(), - this.wallet.getVersion(), - { - name: 'transfer_public', - args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - type: FunctionType.PUBLIC, - isStatic: false, - to: this.asset, - returnTypes: [], - }, - ); return Promise.resolve([ - this.wallet.setPublicAuthWit(messageHash, true).request(), + this.wallet + .setPublicAuthWit( + { + caller: this.paymentContract, + action: { + name: 'transfer_public', + args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, + isStatic: false, + to: this.asset, + returnTypes: [], + }, + }, + true, + ) + .request(), { name: 'fee_entrypoint_public', to: this.paymentContract, diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 8fabb0e8f91e..4e3d71e4d8f2 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -46,12 +46,13 @@ export { FunctionSelectorLike, WrappedFieldLike, computeAuthWitMessageHash, + computeInnerAuthWitHashFromAction, computeInnerAuthWitHash, - computeOuterAuthWitHash, generatePublicKey, waitForAccountSynch, waitForPXE, } from './utils/index.js'; +export { NoteSelector } from '@aztec/foundation/abi'; export { createPXEClient } from './rpc_clients/index.js'; diff --git a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts index c54a9674c4d2..2b6871e885e3 100644 --- a/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts +++ b/yarn-project/aztec.js/src/rpc_clients/pxe_client.ts @@ -25,6 +25,7 @@ import { GrumpkinScalar, Point, } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { createJsonRpcClient, makeFetch } from '@aztec/foundation/json-rpc/client'; /** @@ -53,6 +54,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], false) Point, TxExecutionRequest, TxHash, + NoteSelector, }, { Tx, SimulatedTx, TxReceipt, EncryptedNoteL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness }, false, diff --git a/yarn-project/aztec.js/src/utils/authwit.ts b/yarn-project/aztec.js/src/utils/authwit.ts index 41655da79fb9..e3df2b9a5271 100644 --- a/yarn-project/aztec.js/src/utils/authwit.ts +++ b/yarn-project/aztec.js/src/utils/authwit.ts @@ -1,32 +1,77 @@ import { type FunctionCall, PackedValues } from '@aztec/circuit-types'; -import { type AztecAddress, type Fr, GeneratorIndex } from '@aztec/circuits.js'; +import { type AztecAddress, Fr, GeneratorIndex } from '@aztec/circuits.js'; import { pedersenHash } from '@aztec/foundation/crypto'; +import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; + +/** Metadata for the intent */ +export type IntentMetadata = { + /** The chain id to approve */ + chainId: Fr; + /** The version to approve */ + version: Fr; +}; + +/** Intent with an inner hash */ +export type IntentInnerHash = { + /** The consumer */ + consumer: AztecAddress; + /** The action to approve */ + innerHash: Buffer | Fr; +}; + +/** Intent with an action */ +export type IntentAction = { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; +}; + // docs:start:authwit_computeAuthWitMessageHash /** - * Compute an authentication witness message hash from a caller and a request - * H(target: AztecAddress, chainId: Field, version: Field, H(caller: AztecAddress, selector: Field, args_hash: Field)) - * Example usage would be `bob` authenticating `alice` to perform a transfer of `10` - * tokens from his account to herself: - * H(token, 1, 1, H(alice, transfer_selector, H(bob, alice, 10, nonce))) - * `bob` then signs the message hash and gives it to `alice` who can then perform the - * action. - * @param caller - The caller approved to make the call - * @param chainId - The chain id for the message - * @param version - The version for the message - * @param action - The request to be made (function call) - * @returns The message hash for the witness + * Compute an authentication witness message hash from an intent and metadata + * + * If using the `IntentInnerHash`, the consumer is the address that can "consume" the authwit, for token approvals it is the token contract itself. + * The `innerHash` itself will be the message that a contract is allowed to execute. + * At the point of "approval checking", the validating contract (account for private and registry for public) will be computing the message hash + * (`H(consumer, chainid, version, inner_hash)`) where the all but the `inner_hash` is injected from the context (consumer = msg_sender), + * and use it for the authentication check. + * Therefore, any allowed `innerHash` will therefore also have information around where it can be spent (version, chainId) and who can spend it (consumer). + * + * If using the `IntentAction`, the caller is the address that is making the call, for a token approval from Alice to Bob, this would be Bob. + * The action is then used along with the `caller` to compute the `innerHash` and the consumer. + * + * + * @param intent - The intent to approve (consumer and innerHash or caller and action) + * The consumer is the address that can "consume" the authwit, for token approvals it is the token contract itself. + * The caller is the address that is making the call, for a token approval from Alice to Bob, this would be Bob. + * The caller becomes part of the `inner_hash` and is dealt with entirely in application logic. + * @param metadata - The metadata for the intent (chainId, version) + * @returns The message hash for the action */ -export const computeAuthWitMessageHash = (caller: AztecAddress, chainId: Fr, version: Fr, action: FunctionCall) => { - return computeOuterAuthWitHash( - action.to.toField(), - chainId, - version, - computeInnerAuthWitHash([caller.toField(), action.selector.toField(), PackedValues.fromValues(action.args).hash]), - ); +export const computeAuthWitMessageHash = (intent: IntentInnerHash | IntentAction, metadata: IntentMetadata) => { + const chainId = metadata.chainId; + const version = metadata.version; + + if ('caller' in intent) { + const action = intent.action instanceof ContractFunctionInteraction ? intent.action.request() : intent.action; + return computeOuterAuthWitHash( + action.to.toField(), + chainId, + version, + computeInnerAuthWitHashFromAction(intent.caller, action), + ); + } else { + const inner = Buffer.isBuffer(intent.innerHash) ? Fr.fromBuffer(intent.innerHash) : intent.innerHash; + return computeOuterAuthWitHash(intent.consumer, chainId, version, inner); + } }; // docs:end:authwit_computeAuthWitMessageHash +export const computeInnerAuthWitHashFromAction = (caller: AztecAddress, action: FunctionCall) => + computeInnerAuthWitHash([caller.toField(), action.selector.toField(), PackedValues.fromValues(action.args).hash]); + /** * Compute the inner hash for an authentication witness. * This is the "intent" of the message, before siloed with the consumer. @@ -53,6 +98,6 @@ export const computeInnerAuthWitHash = (args: Fr[]) => { * @param innerHash - The inner hash for the witness * @returns The outer hash for the witness */ -export const computeOuterAuthWitHash = (consumer: AztecAddress, chainId: Fr, version: Fr, innerHash: Fr) => { +const computeOuterAuthWitHash = (consumer: AztecAddress, chainId: Fr, version: Fr, innerHash: Fr) => { return pedersenHash([consumer.toField(), chainId, version, innerHash], GeneratorIndex.AUTHWIT_OUTER); }; diff --git a/yarn-project/aztec.js/src/wallet/account_wallet.ts b/yarn-project/aztec.js/src/wallet/account_wallet.ts index 4452b15f953c..bf1098e48968 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet.ts @@ -1,4 +1,4 @@ -import { type AuthWitness, type FunctionCall, type PXE, type TxExecutionRequest } from '@aztec/circuit-types'; +import { type AuthWitness, type PXE, type TxExecutionRequest } from '@aztec/circuit-types'; import { AztecAddress, CANONICAL_KEY_REGISTRY_ADDRESS, Fq, Fr, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; import { type ABIParameterVisibility, type FunctionAbi, FunctionType } from '@aztec/foundation/abi'; import { AuthRegistryAddress } from '@aztec/protocol-contracts/auth-registry'; @@ -6,7 +6,12 @@ import { AuthRegistryAddress } from '@aztec/protocol-contracts/auth-registry'; import { type AccountInterface } from '../account/interface.js'; import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; import { type ExecutionRequestInit } from '../entrypoint/entrypoint.js'; -import { computeAuthWitMessageHash } from '../utils/authwit.js'; +import { + type IntentAction, + type IntentInnerHash, + computeAuthWitMessageHash, + computeInnerAuthWitHashFromAction, +} from '../utils/authwit.js'; import { BaseWallet } from './base_wallet.js'; /** @@ -30,28 +35,25 @@ export class AccountWallet extends BaseWallet { } /** - * Computes an authentication witness from either a message or a caller and an action. - * If a message is provided, it will create a witness for the message directly. - * Otherwise, it will compute the message using the caller and the action. - * @param messageHashOrIntent - The message or the caller and action to approve + * Computes an authentication witness from either a message hash or an intent. + * + * If a message hash is provided, it will create a witness for the hash directly. + * Otherwise, it will compute the message hash using the intent, along with the + * chain id and the version values provided by the wallet. + * + * @param messageHashOrIntent - The message hash of the intent to approve * @returns The authentication witness */ - async createAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): Promise { - const messageHash = this.getMessageHash(messageHashOrIntent); + async createAuthWit(messageHashOrIntent: Fr | Buffer | IntentAction | IntentInnerHash): Promise { + let messageHash: Fr; + if (Buffer.isBuffer(messageHashOrIntent)) { + messageHash = Fr.fromBuffer(messageHashOrIntent); + } else if (messageHashOrIntent instanceof Fr) { + messageHash = messageHashOrIntent; + } else { + messageHash = this.getMessageHash(messageHashOrIntent); + } + const witness = await this.account.createAuthWit(messageHash); await this.pxe.addAuthWitness(witness); return witness; @@ -59,129 +61,92 @@ export class AccountWallet extends BaseWallet { /** * Returns a function interaction to set a message hash as authorized or revoked in this account. + * * Public calls can then consume this authorization. - * @param messageHashOrIntent - The message or the caller and action to authorize/revoke + * + * @param messageHashOrIntent - The message hash or intent to authorize/revoke * @param authorized - True to authorize, false to revoke authorization. * @returns - A function interaction. */ public setPublicAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, + messageHashOrIntent: Fr | Buffer | IntentInnerHash | IntentAction, authorized: boolean, ): ContractFunctionInteraction { - const message = this.getMessageHash(messageHashOrIntent); + let messageHash: Fr; + if (Buffer.isBuffer(messageHashOrIntent)) { + messageHash = Fr.fromBuffer(messageHashOrIntent); + } else if (messageHashOrIntent instanceof Fr) { + messageHash = messageHashOrIntent; + } else { + messageHash = this.getMessageHash(messageHashOrIntent); + } + return new ContractFunctionInteraction(this, AuthRegistryAddress, this.getSetAuthorizedAbi(), [ - message, + messageHash, authorized, ]); } - /** - * Returns a function interaction to cancel a message hash as authorized or revoked. - * @param messageHashOrIntent - The message or the caller and action to revoke - * @returns - A function interaction. - */ - public cancelPublicAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): ContractFunctionInteraction { - return this.setPublicAuthWit(messageHashOrIntent, false); + private getInnerHashAndConsumer(intent: IntentInnerHash | IntentAction): { + /** The inner hash */ + innerHash: Fr; + /** The consumer of the authwit */ + consumer: AztecAddress; + } { + if ('caller' in intent && 'action' in intent) { + const action = intent.action instanceof ContractFunctionInteraction ? intent.action.request() : intent.action; + return { + innerHash: computeInnerAuthWitHashFromAction(intent.caller, action), + consumer: action.to, + }; + } else if (Buffer.isBuffer(intent.innerHash)) { + return { innerHash: Fr.fromBuffer(intent.innerHash), consumer: intent.consumer }; + } + return { innerHash: intent.innerHash, consumer: intent.consumer }; } /** - * Returns the message hash for the given message or authwit input. - * @param messageHashOrIntent - The message hash or the caller and action to authorize + * Returns the message hash for the given intent + * + * @param intent - A tuple of (consumer and inner hash) or (caller and action) * @returns The message hash */ - private getMessageHash( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): Fr { - if (Buffer.isBuffer(messageHashOrIntent)) { - return Fr.fromBuffer(messageHashOrIntent); - } else if (messageHashOrIntent instanceof Fr) { - return messageHashOrIntent; - } else { - return computeAuthWitMessageHash( - messageHashOrIntent.caller, - messageHashOrIntent.chainId || this.getChainId(), - messageHashOrIntent.version || this.getVersion(), - messageHashOrIntent.action instanceof ContractFunctionInteraction - ? messageHashOrIntent.action.request() - : messageHashOrIntent.action, - ); - } + private getMessageHash(intent: IntentInnerHash | IntentAction): Fr { + const chainId = this.getChainId(); + const version = this.getVersion(); + return computeAuthWitMessageHash(intent, { chainId, version }); } /** * Lookup the validity of an authwit in private and public contexts. - * If the authwit have been consumed already (nullifier spent), will return false in both contexts. - * @param target - The target contract address - * @param messageHashOrIntent - The message hash or the caller and action to authorize/revoke + * + * Uses the chain id and version of the wallet. + * + * @param onBehalfOf - The address of the "approver" + * @param intent - The consumer and inner hash or the caller and action to lookup + * * @returns - A struct containing the validity of the authwit in private and public contexts. */ async lookupValidity( - target: AztecAddress, - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, + onBehalfOf: AztecAddress, + intent: IntentInnerHash | IntentAction, ): Promise<{ /** boolean flag indicating if the authwit is valid in private context */ isValidInPrivate: boolean; /** boolean flag indicating if the authwit is valid in public context */ isValidInPublic: boolean; }> { - const messageHash = this.getMessageHash(messageHashOrIntent); + const { innerHash, consumer } = this.getInnerHashAndConsumer(intent); + + const messageHash = this.getMessageHash(intent); const results = { isValidInPrivate: false, isValidInPublic: false }; // Check private const witness = await this.getAuthWitness(messageHash); if (witness !== undefined) { - results.isValidInPrivate = (await new ContractFunctionInteraction(this, target, this.getLookupValidityAbi(), [ - messageHash, + results.isValidInPrivate = (await new ContractFunctionInteraction(this, onBehalfOf, this.getLookupValidityAbi(), [ + consumer, + innerHash, ]).simulate()) as boolean; } @@ -190,7 +155,7 @@ export class AccountWallet extends BaseWallet { this, AuthRegistryAddress, this.getIsConsumableAbi(), - [target, messageHash], + [onBehalfOf, messageHash], ).simulate()) as boolean; return results; @@ -220,31 +185,6 @@ export class AccountWallet extends BaseWallet { await interaction.send().wait(); } - /** - * Returns a function interaction to cancel a message hash as authorized in this account. - * @param messageHashOrIntent - The message or the caller and action to authorize/revoke - * @returns - A function interaction. - */ - public cancelAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): ContractFunctionInteraction { - const message = this.getMessageHash(messageHashOrIntent); - const args = [message]; - return new ContractFunctionInteraction(this, this.getAddress(), this.getCancelAuthwitAbi(), args); - } - /** Returns the complete address of the account that implements this wallet. */ public getCompleteAddress() { return this.account.getCompleteAddress(); @@ -278,24 +218,6 @@ export class AccountWallet extends BaseWallet { }; } - private getCancelAuthwitAbi(): FunctionAbi { - return { - name: 'cancel_authwit', - isInitializer: false, - functionType: FunctionType.PRIVATE, - isInternal: true, - isStatic: false, - parameters: [ - { - name: 'message_hash', - type: { kind: 'field' }, - visibility: 'private' as ABIParameterVisibility, - }, - ], - returnTypes: [], - }; - } - private getLookupValidityAbi(): FunctionAbi { return { name: 'lookup_validity', diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 974895fa96ea..247b509fbafb 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -2,7 +2,6 @@ import { type AuthWitness, type EventMetadata, type ExtendedNote, - type FunctionCall, type GetUnencryptedLogsResponse, type IncomingNotesFilter, type L2Block, @@ -32,8 +31,8 @@ import { type ContractClassWithId, type ContractInstanceWithAddress } from '@azt import { type NodeInfo } from '@aztec/types/interfaces'; import { type Wallet } from '../account/wallet.js'; -import { type ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; import { type ExecutionRequestInit } from '../entrypoint/entrypoint.js'; +import { type IntentAction, type IntentInnerHash } from '../utils/authwit.js'; /** * A base class for Wallet implementations @@ -49,21 +48,7 @@ export abstract class BaseWallet implements Wallet { abstract createTxExecutionRequest(exec: ExecutionRequestInit): Promise; - abstract createAuthWit( - messageHashOrIntent: - | Fr - | Buffer - | { - /** The caller to approve */ - caller: AztecAddress; - /** The action to approve */ - action: ContractFunctionInteraction | FunctionCall; - /** The chain id to approve */ - chainId?: Fr; - /** The version to approve */ - version?: Fr; - }, - ): Promise; + abstract createAuthWit(intent: Fr | Buffer | IntentInnerHash | IntentAction): Promise; abstract rotateNullifierKeys(newNskM: Fq): Promise; diff --git a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts index bba8c3ec66eb..f69c78d5f335 100644 --- a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts @@ -3,6 +3,7 @@ import { type CompleteAddress, type Fq, type Fr } from '@aztec/circuits.js'; import { DefaultEntrypoint } from '../entrypoint/default_entrypoint.js'; import { type EntrypointInterface, type ExecutionRequestInit } from '../entrypoint/entrypoint.js'; +import { type IntentAction, type IntentInnerHash } from '../utils/authwit.js'; import { BaseWallet } from './base_wallet.js'; /** @@ -12,7 +13,6 @@ export class SignerlessWallet extends BaseWallet { constructor(pxe: PXE, private entrypoint?: EntrypointInterface) { super(pxe); } - async createTxExecutionRequest(execution: ExecutionRequestInit): Promise { let entrypoint = this.entrypoint; if (!entrypoint) { @@ -39,7 +39,7 @@ export class SignerlessWallet extends BaseWallet { throw new Error('SignerlessWallet: Method getCompleteAddress not implemented.'); } - createAuthWit(_messageHash: Fr): Promise { + createAuthWit(_intent: Fr | Buffer | IntentInnerHash | IntentAction): Promise { throw new Error('SignerlessWallet: Method createAuthWit not implemented.'); } diff --git a/yarn-project/aztec.js/webpack.config.js b/yarn-project/aztec.js/webpack.config.js index 5e56741b6883..1b60153b54ba 100644 --- a/yarn-project/aztec.js/webpack.config.js +++ b/yarn-project/aztec.js/webpack.config.js @@ -66,7 +66,6 @@ export default { buffer: require.resolve('buffer/'), util: require.resolve('util/'), stream: require.resolve('stream-browserify'), - tty: require.resolve('tty-browserify'), }, }, }; diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 6caffb8c0cec..989cf37a0391 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -46,6 +46,7 @@ "@aztec/protocol-contracts": "workspace:^", "@aztec/prover-client": "workspace:^", "@aztec/pxe": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "abitype": "^0.8.11", "commander": "^11.1.0", "koa": "^2.14.2", @@ -76,7 +77,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/aztec/src/cli/cmds/start_archiver.ts b/yarn-project/aztec/src/cli/cmds/start_archiver.ts index 567f2b160b04..ad2f296d9585 100644 --- a/yarn-project/aztec/src/cli/cmds/start_archiver.ts +++ b/yarn-project/aztec/src/cli/cmds/start_archiver.ts @@ -9,6 +9,10 @@ import { createDebugLogger } from '@aztec/aztec.js'; import { type ServerList } from '@aztec/foundation/json-rpc/server'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; import { initStoreForRollup } from '@aztec/kv-store/utils'; +import { + createAndStartTelemetryClient, + getConfigEnvVars as getTelemetryClientConfig, +} from '@aztec/telemetry-client/start'; import { mergeEnvVarsAndCliOptions, parseModuleOptions } from '../util.js'; @@ -30,7 +34,8 @@ export const startArchiver = async (options: any, signalHandlers: (() => Promise ); const archiverStore = new KVArchiverDataStore(store, archiverConfig.maxLogs); - const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, true); + const telemetry = createAndStartTelemetryClient(getTelemetryClientConfig()); + const archiver = await Archiver.createAndSync(archiverConfig, archiverStore, telemetry, true); const archiverServer = createArchiverRpcServer(archiver); services.push({ archiver: archiverServer }); signalHandlers.push(archiver.stop); diff --git a/yarn-project/aztec/src/cli/cmds/start_node.ts b/yarn-project/aztec/src/cli/cmds/start_node.ts index 9245bd327083..6ef8e67fe4b5 100644 --- a/yarn-project/aztec/src/cli/cmds/start_node.ts +++ b/yarn-project/aztec/src/cli/cmds/start_node.ts @@ -8,6 +8,10 @@ import { type ServerList } from '@aztec/foundation/json-rpc/server'; import { type LogFn } from '@aztec/foundation/log'; import { createProvingJobSourceServer } from '@aztec/prover-client/prover-agent'; import { type PXEServiceConfig, createPXERpcServer, getPXEServiceConfig } from '@aztec/pxe'; +import { + createAndStartTelemetryClient, + getConfigEnvVars as getTelemetryClientConfig, +} from '@aztec/telemetry-client/start'; import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts'; @@ -81,7 +85,8 @@ export const startNode = async ( } // Create and start Aztec Node. - const node = await createAztecNode(nodeConfig); + const telemetryClient = createAndStartTelemetryClient(getTelemetryClientConfig()); + const node = await createAztecNode(telemetryClient, nodeConfig); const nodeServer = createAztecNodeRpcServer(node); // Add node to services list diff --git a/yarn-project/aztec/src/cli/cmds/start_prover.ts b/yarn-project/aztec/src/cli/cmds/start_prover.ts index 4b299ab56619..64fd693f9eda 100644 --- a/yarn-project/aztec/src/cli/cmds/start_prover.ts +++ b/yarn-project/aztec/src/cli/cmds/start_prover.ts @@ -2,6 +2,10 @@ import { BBNativeRollupProver, TestCircuitProver } from '@aztec/bb-prover'; import { type ServerCircuitProver } from '@aztec/circuit-types'; import { getProverEnvVars } from '@aztec/prover-client'; import { ProverAgent, createProvingJobSourceClient } from '@aztec/prover-client/prover-agent'; +import { + createAndStartTelemetryClient, + getConfigEnvVars as getTelemetryClientConfig, +} from '@aztec/telemetry-client/start'; import { type ServiceStarter, parseModuleOptions } from '../util.js'; @@ -30,20 +34,24 @@ export const startProver: ServiceStarter = async (options, signalHandlers, logge ? parseInt(proverOptions.proverAgentPollInterval, 10) : proverOptions.proverAgentPollInterval; + const telemetry = createAndStartTelemetryClient(getTelemetryClientConfig()); let circuitProver: ServerCircuitProver; if (proverOptions.realProofs) { if (!proverOptions.acvmBinaryPath || !proverOptions.bbBinaryPath) { throw new Error('Cannot start prover without simulation or native prover options'); } - circuitProver = await BBNativeRollupProver.new({ - acvmBinaryPath: proverOptions.acvmBinaryPath, - bbBinaryPath: proverOptions.bbBinaryPath, - acvmWorkingDirectory: proverOptions.acvmWorkingDirectory, - bbWorkingDirectory: proverOptions.bbWorkingDirectory, - }); + circuitProver = await BBNativeRollupProver.new( + { + acvmBinaryPath: proverOptions.acvmBinaryPath, + bbBinaryPath: proverOptions.bbBinaryPath, + acvmWorkingDirectory: proverOptions.acvmWorkingDirectory, + bbWorkingDirectory: proverOptions.bbWorkingDirectory, + }, + telemetry, + ); } else { - circuitProver = new TestCircuitProver(); + circuitProver = new TestCircuitProver(telemetry); } const agent = new ProverAgent(circuitProver, agentConcurrency, pollInterval); diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index d9c7f0d113d0..79d6e6e3218f 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -36,6 +36,8 @@ import { getCanonicalAuthRegistry } from '@aztec/protocol-contracts/auth-registr import { GasTokenAddress, getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; import { getCanonicalKeyRegistry } from '@aztec/protocol-contracts/key-registry'; import { type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; +import { type TelemetryClient } from '@aztec/telemetry-client'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type HDAccount, type PrivateKeyAccount, createPublicClient, http as httpViemTransport } from 'viem'; import { mnemonicToAccount } from 'viem/accounts'; @@ -252,7 +254,7 @@ export async function createSandbox(config: Partial = {}) { await deployContractsToL1(aztecNodeConfig, hdAccount); } - const node = await createAztecNode(aztecNodeConfig); + const node = await createAztecNode(new NoopTelemetryClient(), aztecNodeConfig); const pxe = await createAztecPXE(node); await deployCanonicalKeyRegistry( @@ -281,9 +283,9 @@ export async function createSandbox(config: Partial = {}) { * Create and start a new Aztec RPC HTTP Server * @param config - Optional Aztec node settings. */ -export async function createAztecNode(config: Partial = {}) { +export async function createAztecNode(telemetryClient: TelemetryClient, config: Partial = {}) { const aztecNodeConfig: AztecNodeConfig = { ...getConfigEnvVars(), ...config }; - const node = await AztecNodeService.createAndSync(aztecNodeConfig); + const node = await AztecNodeService.createAndSync(aztecNodeConfig, telemetryClient); return node; } diff --git a/yarn-project/aztec/tsconfig.json b/yarn-project/aztec/tsconfig.json index ef88fd561474..557c0080199f 100644 --- a/yarn-project/aztec/tsconfig.json +++ b/yarn-project/aztec/tsconfig.json @@ -62,6 +62,9 @@ }, { "path": "../pxe" + }, + { + "path": "../telemetry-client" } ], "include": ["src"] diff --git a/yarn-project/bb-prover/package.json b/yarn-project/bb-prover/package.json index 0d46748757b4..89ad0498089c 100644 --- a/yarn-project/bb-prover/package.json +++ b/yarn-project/bb-prover/package.json @@ -35,7 +35,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -56,6 +64,7 @@ "@aztec/foundation": "workspace:^", "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/simulator": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi", "@noir-lang/types": "portal:../../noir/packages/types", "commander": "^9.0.0", diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 917850189ffc..53987df2e8cb 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -35,6 +35,7 @@ import { initContext, initExecutionEnvironment, initHostStorage, + initPersistableStateManager, } from '@aztec/simulator/avm/fixtures'; import { jest } from '@jest/globals'; @@ -43,11 +44,7 @@ import fs from 'node:fs/promises'; import { tmpdir } from 'node:os'; import path from 'path'; -import { AvmPersistableStateManager } from '../../simulator/src/avm/journal/journal.js'; -import { - convertAvmResultsToPxResult, - createPublicExecution, -} from '../../simulator/src/public/transitional_adaptors.js'; +import { PublicSideEffectTrace } from '../../simulator/src/public/side_effect_trace.js'; import { SerializableContractInstance } from '../../types/src/contracts/contract_instance.js'; import { type BBSuccess, BB_RESULT, generateAvmProof, verifyAvmProof } from './bb/execute.js'; import { extractVkData } from './verification_key/verification_key_data.js'; @@ -224,15 +221,13 @@ const proveAndVerifyAvmTestContract = async ( storageDb.storageRead.mockResolvedValue(Promise.resolve(storageValue)); const hostStorage = initHostStorage({ contractsDb }); - const persistableState = new AvmPersistableStateManager(hostStorage); + const trace = new PublicSideEffectTrace(startSideEffectCounter); + const persistableState = initPersistableStateManager({ hostStorage, trace }); const context = initContext({ env: environment, persistableState }); const nestedCallBytecode = getAvmTestContractBytecode('add_args_return'); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(nestedCallBytecode)); + jest.spyOn(hostStorage.contractsDb, 'getBytecode').mockResolvedValue(nestedCallBytecode); const startGas = new Gas(context.machineState.gasLeft.daGas, context.machineState.gasLeft.l2Gas); - const oldPublicExecution = createPublicExecution(startSideEffectCounter, environment, calldata); const internalLogger = createDebugLogger('aztec:avm-proving-test'); const logger = (msg: string, _data?: any) => internalLogger.verbose(msg); @@ -255,25 +250,21 @@ const proveAndVerifyAvmTestContract = async ( expect(avmResult.revertReason?.message).toContain(assertionErrString); } - const pxResult = convertAvmResultsToPxResult( - avmResult, - startSideEffectCounter, - oldPublicExecution, + const pxResult = trace.toPublicExecutionResult( + environment, startGas, - context, - simulator.getBytecode(), + /*endGasLeft=*/ Gas.from(context.machineState.gasLeft), + /*bytecode=*/ simulator.getBytecode()!, + avmResult, functionName, ); - // TODO(dbanks12): public inputs should not be empty.... Need to construct them from AvmContext? - const uncompressedBytecode = simulator.getBytecode()!; - const publicInputs = getPublicInputs(pxResult); const avmCircuitInputs = new AvmCircuitInputs( functionName, - uncompressedBytecode, - context.environment.calldata, - publicInputs, - pxResult.avmHints, + /*bytecode=*/ simulator.getBytecode()!, // uncompressed bytecode + /*calldata=*/ context.environment.calldata, + /*publicInputs=*/ getPublicInputs(pxResult), + /*avmHints=*/ pxResult.avmCircuitHints, ); // Then we prove. diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 60113d1142bc..c3b28317377c 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -21,7 +21,7 @@ export enum BB_RESULT { export type BBSuccess = { status: BB_RESULT.SUCCESS | BB_RESULT.ALREADY_PRESENT; - duration: number; + durationMs: number; /** Full path of the public key. */ pkPath?: string; /** Base directory for the VKs (raw, fields). */ @@ -155,7 +155,7 @@ export async function generateKeyForNoirCircuit( if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, - duration, + durationMs: duration, pkPath: key === 'pk' ? outputPath : undefined, vkPath: key === 'vk' ? outputPath : undefined, proofPath: undefined, @@ -174,7 +174,7 @@ export async function generateKeyForNoirCircuit( if (!res) { return { status: BB_RESULT.ALREADY_PRESENT, - duration: 0, + durationMs: 0, pkPath: key === 'pk' ? outputPath : undefined, vkPath: key === 'vk' ? outputPath : undefined, }; @@ -237,7 +237,7 @@ export async function generateProof( if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, - duration, + durationMs: duration, proofPath: `${outputPath}`, pkPath: undefined, vkPath: `${outputPath}`, @@ -346,7 +346,7 @@ export async function generateAvmProof( if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, - duration, + durationMs: duration, proofPath: join(outputPath, PROOF_FILENAME), pkPath: undefined, vkPath: outputPath, @@ -426,7 +426,7 @@ async function verifyProofInternal( const result = await executeBB(pathToBB, command, args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { - return { status: BB_RESULT.SUCCESS, duration }; + return { status: BB_RESULT.SUCCESS, durationMs: duration }; } // Not a great error message here but it is difficult to decipher what comes from bb return { @@ -466,7 +466,7 @@ export async function writeVkAsFields( const result = await executeBB(pathToBB, 'vk_as_fields', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { - return { status: BB_RESULT.SUCCESS, duration, vkPath: verificationKeyPath }; + return { status: BB_RESULT.SUCCESS, durationMs: duration, vkPath: verificationKeyPath }; } // Not a great error message here but it is difficult to decipher what comes from bb return { @@ -508,7 +508,7 @@ export async function writeProofAsFields( const result = await executeBB(pathToBB, 'proof_as_fields', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { - return { status: BB_RESULT.SUCCESS, duration, proofPath: proofPath }; + return { status: BB_RESULT.SUCCESS, durationMs: duration, proofPath: proofPath }; } // Not a great error message here but it is difficult to decipher what comes from bb return { @@ -549,7 +549,7 @@ export async function generateContractForVerificationKey( const result = await executeBB(pathToBB, 'contract', args, log); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { - return { status: BB_RESULT.SUCCESS, duration, contractPath }; + return { status: BB_RESULT.SUCCESS, durationMs: duration, contractPath }; } // Not a great error message here but it is difficult to decipher what comes from bb return { @@ -564,7 +564,7 @@ export async function generateContractForVerificationKey( if (!res) { return { status: BB_RESULT.ALREADY_PRESENT, - duration: 0, + durationMs: 0, contractPath, }; } diff --git a/yarn-project/bb-prover/src/instrumentation.ts b/yarn-project/bb-prover/src/instrumentation.ts new file mode 100644 index 000000000000..a510388a428f --- /dev/null +++ b/yarn-project/bb-prover/src/instrumentation.ts @@ -0,0 +1,149 @@ +import { type CircuitName } from '@aztec/circuit-types/stats'; +import { type Timer } from '@aztec/foundation/timer'; +import { + Attributes, + type Gauge, + type Histogram, + Metrics, + type TelemetryClient, + type Tracer, + ValueType, +} from '@aztec/telemetry-client'; + +/** + * Instrumentation class for Prover implementations. + */ +export class ProverInstrumentation { + private simulationDuration: Histogram; + private witGenDuration: Gauge; + private provingDuration: Gauge; + + private witGenInputSize: Gauge; + private witGenOutputSize: Gauge; + + private proofSize: Gauge; + private circuitSize: Gauge; + private circuitPublicInputCount: Gauge; + + public readonly tracer: Tracer; + + constructor(telemetry: TelemetryClient, name: string) { + this.tracer = telemetry.getTracer(name); + const meter = telemetry.getMeter(name); + + this.simulationDuration = meter.createHistogram(Metrics.CIRCUIT_SIMULATION_DURATION, { + description: 'Records how long it takes to simulate a circuit', + unit: 's', + valueType: ValueType.DOUBLE, + advice: { + explicitBucketBoundaries: [0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60], + }, + }); + + this.witGenDuration = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_DURATION, { + description: 'Records how long it takes to generate the partial witness for a circuit', + unit: 's', + valueType: ValueType.DOUBLE, + }); + + // ideally this would be a histogram, but proving takes a long time on the server + // and they don't happen that often so Prometheus & Grafana have a hard time handling it + this.provingDuration = meter.createGauge(Metrics.CIRCUIT_PROVING_DURATION, { + unit: 's', + description: 'Records how long it takes to prove a circuit', + valueType: ValueType.DOUBLE, + }); + + this.witGenInputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_INPUT_SIZE, { + unit: 'By', + description: 'Records the size of the input to the witness generation', + valueType: ValueType.INT, + }); + + this.witGenOutputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_OUTPUT_SIZE, { + unit: 'By', + description: 'Records the size of the output of the witness generation', + valueType: ValueType.INT, + }); + + this.proofSize = meter.createGauge(Metrics.CIRCUIT_PROVING_PROOF_SIZE, { + unit: 'By', + description: 'Records the size of the proof generated for a circuit', + valueType: ValueType.INT, + }); + + this.circuitPublicInputCount = meter.createGauge(Metrics.CIRCUIT_PUBLIC_INPUTS_COUNT, { + description: 'Records the number of public inputs in a circuit', + valueType: ValueType.INT, + }); + + this.circuitSize = meter.createGauge(Metrics.CIRCUIT_SIZE, { + description: 'Records the size of the circuit in gates', + valueType: ValueType.INT, + }); + } + + /** + * Records the duration of a circuit operation. + * @param metric - The metric to record + * @param circuitName - The name of the circuit + * @param timerOrS - The duration + */ + recordDuration( + metric: 'simulationDuration' | 'witGenDuration' | 'provingDuration', + circuitName: CircuitName, + timerOrS: Timer | number, + ) { + const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s(); + this[metric].record(s, { + [Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName, + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + }); + } + + /** + * Records the duration of an AVM circuit operation. + * @param metric - The metric to record + * @param appCircuitName - The name of the function circuit (should be a `contract:function` string) + * @param timerOrS - The duration + */ + recordAvmDuration(metric: 'witGenDuration' | 'provingDuration', appCircuitName: string, timerOrS: Timer | number) { + const s = typeof timerOrS === 'number' ? timerOrS : timerOrS.s(); + this[metric].record(s, { + [Attributes.APP_CIRCUIT_NAME]: appCircuitName, + }); + } + + /** + * Records the size of a circuit operation. + * @param metric - Records the size of a circuit operation. + * @param circuitName - The name of the circuit + * @param size - The size + */ + recordSize( + metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount', + circuitName: CircuitName, + size: number, + ) { + this[metric].record(Math.ceil(size), { + [Attributes.PROTOCOL_CIRCUIT_NAME]: circuitName, + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + }); + } + + /** + * Records the size of an AVM circuit operation. + * @param metric - The metric to record + * @param appCircuitName - The name of the function circuit (should be a `contract:function` string) + * @param size - The size + */ + recordAvmSize( + metric: 'witGenInputSize' | 'witGenOutputSize' | 'proofSize' | 'circuitSize' | 'circuitPublicInputCount', + appCircuitName: string, + size: number, + ) { + this[metric].record(Math.ceil(size), { + [Attributes.APP_CIRCUIT_NAME]: appCircuitName, + }); + } +} diff --git a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts index 3cc080972780..ea93f78fe77f 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts +++ b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts @@ -176,7 +176,7 @@ export class BBNativeProofCreator implements ProofCreator { throw new Error(errorMessage); } - this.log.info(`Successfully verified ${circuitType} proof in ${Math.ceil(result.duration)} ms`); + this.log.info(`Successfully verified ${circuitType} proof in ${Math.ceil(result.durationMs)} ms`); } private async verifyProofFromKey( @@ -339,7 +339,7 @@ export class BBNativeProofCreator implements ProofCreator { this.log.debug(`Generated proof`, { eventName: 'circuit-proving', circuitName: 'app-circuit', - duration: provingResult.duration, + duration: provingResult.durationMs, inputSize: compressedBincodedWitness.length, proofSize: proof.binaryProof.buffer.length, appCircuitName, @@ -358,7 +358,7 @@ export class BBNativeProofCreator implements ProofCreator { this.log.debug(`Generated proof`, { circuitName: mapProtocolArtifactNameToCircuitName(circuitType), - duration: provingResult.duration, + duration: provingResult.durationMs, eventName: 'circuit-proving', inputSize: compressedBincodedWitness.length, proofSize: proof.binaryProof.buffer.length, diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 33210ed64449..7eed17fbe139 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -57,6 +57,7 @@ import { convertRootRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; import { NativeACVMSimulator } from '@aztec/simulator'; +import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-client'; import { abiEncode } from '@noir-lang/noirc_abi'; import { type Abi, type WitnessMap } from '@noir-lang/types'; @@ -78,6 +79,7 @@ import { writeProofAsFields, } from '../bb/execute.js'; import type { ACVMConfig, BBConfig } from '../config.js'; +import { ProverInstrumentation } from '../instrumentation.js'; import { PublicKernelArtifactMapping } from '../mappings/mappings.js'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; import { extractVkData } from '../verification_key/verification_key_data.js'; @@ -102,9 +104,18 @@ export class BBNativeRollupProver implements ServerCircuitProver { ServerProtocolArtifact, Promise >(); - constructor(private config: BBProverConfig) {} - static async new(config: BBProverConfig) { + private instrumentation: ProverInstrumentation; + + constructor(private config: BBProverConfig, telemetry: TelemetryClient) { + this.instrumentation = new ProverInstrumentation(telemetry, 'BBNativeRollupProver'); + } + + get tracer() { + return this.instrumentation.tracer; + } + + static async new(config: BBProverConfig, telemetry: TelemetryClient) { await fs.access(config.acvmBinaryPath, fs.constants.R_OK); await fs.mkdir(config.acvmWorkingDirectory, { recursive: true }); await fs.access(config.bbBinaryPath, fs.constants.R_OK); @@ -112,7 +123,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { logger.info(`Using native BB at ${config.bbBinaryPath} and working directory ${config.bbWorkingDirectory}`); logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`); - return new BBNativeRollupProver(config); + return new BBNativeRollupProver(config, telemetry); } /** @@ -120,6 +131,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @param inputs - Inputs to the circuit. * @returns The public inputs of the parity circuit. */ + @trackSpan('BBNativeRollupProver.getBaseParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' }) public async getBaseParityProof(inputs: BaseParityInputs): Promise> { const { circuitOutput, proof } = await this.createRecursiveProof( inputs, @@ -141,6 +153,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @param inputs - Inputs to the circuit. * @returns The public inputs of the parity circuit. */ + @trackSpan('BBNativeRollupProver.getRootParityProof', { [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' }) public async getRootParityProof( inputs: RootParityInputs, ): Promise> { @@ -164,6 +177,9 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @param inputs - The inputs to the AVM circuit. * @returns The proof. */ + @trackSpan('BBNativeRollupProver.getAvmProof', inputs => ({ + [Attributes.APP_CIRCUIT_NAME]: inputs.functionName, + })) public async getAvmProof(inputs: AvmCircuitInputs): Promise { const proofAndVk = await this.createAvmProof(inputs); await this.verifyAvmProof(proofAndVk.proof, proofAndVk.verificationKey); @@ -175,6 +191,11 @@ export class BBNativeRollupProver implements ServerCircuitProver { * @param kernelRequest - The object encapsulating the request for a proof * @returns The requested circuit's public inputs and proof */ + @trackSpan('BBNativeRollupProver.getPublicKernelProof', kernelReq => ({ + [Attributes.PROTOCOL_CIRCUIT_NAME]: mapProtocolArtifactNameToCircuitName( + PublicKernelArtifactMapping[kernelReq.type]!.artifact, + ), + })) public async getPublicKernelProof( kernelRequest: PublicKernelNonTailRequest, ): Promise> { @@ -385,11 +406,16 @@ export class BBNativeRollupProver implements ServerCircuitProver { const inputWitness = convertInput(input); const timer = new Timer(); const outputWitness = await simulator.simulateCircuit(inputWitness, artifact); - const witnessGenerationDuration = timer.ms(); const output = convertOutput(outputWitness); + + const circuitName = mapProtocolArtifactNameToCircuitName(circuitType); + this.instrumentation.recordDuration('witGenDuration', circuitName, timer); + this.instrumentation.recordSize('witGenInputSize', circuitName, input.toBuffer().length); + this.instrumentation.recordSize('witGenOutputSize', circuitName, output.toBuffer().length); + logger.debug(`Generated witness`, { - circuitName: mapProtocolArtifactNameToCircuitName(circuitType), - duration: witnessGenerationDuration, + circuitName, + duration: timer.ms(), inputSize: input.toBuffer().length, outputSize: output.toBuffer().length, eventName: 'circuit-witness-generation', @@ -439,10 +465,17 @@ export class BBNativeRollupProver implements ServerCircuitProver { const rawProof = await fs.readFile(`${provingResult.proofPath!}/${PROOF_FILENAME}`); const proof = new Proof(rawProof, vkData.numPublicInputs); - logger.info(`Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms`, { - circuitName: mapProtocolArtifactNameToCircuitName(circuitType), + const circuitName = mapProtocolArtifactNameToCircuitName(circuitType); + + this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000); + this.instrumentation.recordSize('proofSize', circuitName, proof.buffer.length); + this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs); + this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize); + + logger.info(`Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms`, { + circuitName, // does not include reading the proof from disk - duration: provingResult.duration, + duration: provingResult.durationMs, proofSize: proof.buffer.length, eventName: 'circuit-proving', // circuitOutput is the partial witness that became the input to the proof @@ -484,13 +517,19 @@ export class BBNativeRollupProver implements ServerCircuitProver { const proof = new Proof(rawProof, verificationKey.numPublicInputs); const circuitType = 'avm-circuit' as const; + const appCircuitName = 'unknown' as const; + this.instrumentation.recordAvmDuration('provingDuration', appCircuitName, provingResult.durationMs); + this.instrumentation.recordAvmSize('proofSize', appCircuitName, proof.buffer.length); + this.instrumentation.recordAvmSize('circuitPublicInputCount', appCircuitName, verificationKey.numPublicInputs); + this.instrumentation.recordAvmSize('circuitSize', appCircuitName, verificationKey.circuitSize); + logger.info( - `Generated proof for ${circuitType}(${input.functionName}) in ${Math.ceil(provingResult.duration)} ms`, + `Generated proof for ${circuitType}(${input.functionName}) in ${Math.ceil(provingResult.durationMs)} ms`, { circuitName: circuitType, appCircuitName: input.functionName, // does not include reading the proof from disk - duration: provingResult.duration, + duration: provingResult.durationMs, proofSize: proof.buffer.length, eventName: 'circuit-proving', inputSize: input.toBuffer().length, @@ -534,14 +573,19 @@ export class BBNativeRollupProver implements ServerCircuitProver { // Read the proof as fields const proof = await this.readProofAsFields(provingResult.proofPath!, circuitType, proofLength); + const circuitName = mapProtocolArtifactNameToCircuitName(circuitType); + this.instrumentation.recordDuration('provingDuration', circuitName, provingResult.durationMs / 1000); + this.instrumentation.recordSize('proofSize', circuitName, proof.binaryProof.buffer.length); + this.instrumentation.recordSize('circuitPublicInputCount', circuitName, vkData.numPublicInputs); + this.instrumentation.recordSize('circuitSize', circuitName, vkData.circuitSize); logger.info( - `Generated proof for ${circuitType} in ${Math.ceil(provingResult.duration)} ms, size: ${ + `Generated proof for ${circuitType} in ${Math.ceil(provingResult.durationMs)} ms, size: ${ proof.proof.length } fields`, { - circuitName: mapProtocolArtifactNameToCircuitName(circuitType), + circuitName, circuitSize: vkData.circuitSize, - duration: provingResult.duration, + duration: provingResult.durationMs, inputSize: output.toBuffer().length, proofSize: proof.binaryProof.buffer.length, eventName: 'circuit-proving', @@ -603,7 +647,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { throw new Error(errorMessage); } - logger.debug(`Successfully verified proof from key in ${result.duration} ms`); + logger.debug(`Successfully verified proof from key in ${result.durationMs} ms`); }; await runInDirectory(this.config.bbWorkingDirectory, operation); diff --git a/yarn-project/bb-prover/src/stats.ts b/yarn-project/bb-prover/src/stats.ts index c61b3d5ccca4..f31e611dd8cb 100644 --- a/yarn-project/bb-prover/src/stats.ts +++ b/yarn-project/bb-prover/src/stats.ts @@ -1,21 +1,7 @@ -import { type PublicKernelRequest, PublicKernelType } from '@aztec/circuit-types'; import type { CircuitName } from '@aztec/circuit-types/stats'; import { type ClientProtocolArtifact, type ServerProtocolArtifact } from '@aztec/noir-protocol-circuits-types'; -export function mapPublicKernelToCircuitName(kernelType: PublicKernelRequest['type']): CircuitName { - switch (kernelType) { - case PublicKernelType.SETUP: - return 'public-kernel-setup'; - case PublicKernelType.APP_LOGIC: - return 'public-kernel-app-logic'; - case PublicKernelType.TEARDOWN: - return 'public-kernel-teardown'; - case PublicKernelType.TAIL: - return 'public-kernel-tail'; - default: - throw new Error(`Unknown kernel type: ${kernelType}`); - } -} +export { mapPublicKernelToCircuitName } from '@aztec/circuit-types'; export function mapProtocolArtifactNameToCircuitName( artifact: ServerProtocolArtifact | ClientProtocolArtifact, diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index c4c24794e8ff..85ce58a95806 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -57,7 +57,9 @@ import { convertSimulatedPublicTailOutputFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; import { type SimulationProvider, WASMSimulator, emitCircuitSimulationStats } from '@aztec/simulator'; +import { type TelemetryClient, trackSpan } from '@aztec/telemetry-client'; +import { ProverInstrumentation } from '../instrumentation.js'; import { SimulatedPublicKernelArtifactMapping } from '../mappings/mappings.js'; import { mapPublicKernelToCircuitName } from '../stats.js'; @@ -81,11 +83,19 @@ const VERIFICATION_KEYS: Record */ export class TestCircuitProver implements ServerCircuitProver { private wasmSimulator = new WASMSimulator(); + private instrumentation: ProverInstrumentation; constructor( + telemetry: TelemetryClient, private simulationProvider?: SimulationProvider, private logger = createDebugLogger('aztec:test-prover'), - ) {} + ) { + this.instrumentation = new ProverInstrumentation(telemetry, 'TestCircuitProver'); + } + + get tracer() { + return this.instrumentation.tracer; + } public async getEmptyPrivateKernelProof( inputs: PrivateKernelEmptyInputData, @@ -111,6 +121,7 @@ export class TestCircuitProver implements ServerCircuitProver { * @param inputs - Inputs to the circuit. * @returns The public inputs of the parity circuit. */ + @trackSpan('TestCircuitProver.getBaseParityProof') public async getBaseParityProof(inputs: BaseParityInputs): Promise> { const timer = new Timer(); const witnessMap = convertBaseParityInputsToWitnessMap(inputs); @@ -125,6 +136,8 @@ export class TestCircuitProver implements ServerCircuitProver { result, ); + this.instrumentation.recordDuration('simulationDuration', 'base-parity', timer); + emitCircuitSimulationStats( 'base-parity', timer.ms(), @@ -141,6 +154,7 @@ export class TestCircuitProver implements ServerCircuitProver { * @param inputs - Inputs to the circuit. * @returns The public inputs of the parity circuit. */ + @trackSpan('TestCircuitProver.getRootParityProof') public async getRootParityProof( inputs: RootParityInputs, ): Promise> { @@ -158,6 +172,7 @@ export class TestCircuitProver implements ServerCircuitProver { result, ); + this.instrumentation.recordDuration('simulationDuration', 'root-parity', timer); emitCircuitSimulationStats( 'root-parity', timer.ms(), @@ -174,6 +189,7 @@ export class TestCircuitProver implements ServerCircuitProver { * @param input - Inputs to the circuit. * @returns The public inputs as outputs of the simulation. */ + @trackSpan('TestCircuitProver.getBaseRollupProof') public async getBaseRollupProof( input: BaseRollupInputs, ): Promise> { @@ -185,6 +201,7 @@ export class TestCircuitProver implements ServerCircuitProver { const result = convertSimulatedBaseRollupOutputsFromWitnessMap(witness); + this.instrumentation.recordDuration('simulationDuration', 'base-rollup', timer); emitCircuitSimulationStats( 'base-rollup', timer.ms(), @@ -203,6 +220,7 @@ export class TestCircuitProver implements ServerCircuitProver { * @param input - Inputs to the circuit. * @returns The public inputs as outputs of the simulation. */ + @trackSpan('TestCircuitProver.getMergeRollupProof') public async getMergeRollupProof( input: MergeRollupInputs, ): Promise> { @@ -214,6 +232,7 @@ export class TestCircuitProver implements ServerCircuitProver { const result = convertMergeRollupOutputsFromWitnessMap(witness); + this.instrumentation.recordDuration('simulationDuration', 'merge-rollup', timer); emitCircuitSimulationStats( 'merge-rollup', timer.ms(), @@ -233,6 +252,7 @@ export class TestCircuitProver implements ServerCircuitProver { * @param input - Inputs to the circuit. * @returns The public inputs as outputs of the simulation. */ + @trackSpan('TestCircuitProver.getRootRollupProof') public async getRootRollupProof( input: RootRollupInputs, ): Promise> { @@ -244,6 +264,7 @@ export class TestCircuitProver implements ServerCircuitProver { const result = convertRootRollupOutputsFromWitnessMap(witness); + this.instrumentation.recordDuration('simulationDuration', 'root-rollup', timer); emitCircuitSimulationStats( 'root-rollup', timer.ms(), @@ -258,6 +279,7 @@ export class TestCircuitProver implements ServerCircuitProver { ); } + @trackSpan('TestCircuitProver.getPublicKernelProof') public async getPublicKernelProof( kernelRequest: PublicKernelNonTailRequest, ): Promise> { @@ -274,8 +296,10 @@ export class TestCircuitProver implements ServerCircuitProver { ); const result = kernelOps.convertOutputs(witness); + const circuitName = mapPublicKernelToCircuitName(kernelRequest.type); + this.instrumentation.recordDuration('simulationDuration', circuitName, timer); emitCircuitSimulationStats( - mapPublicKernelToCircuitName(kernelRequest.type), + circuitName, timer.ms(), kernelRequest.inputs.toBuffer().length, result.toBuffer().length, @@ -289,6 +313,7 @@ export class TestCircuitProver implements ServerCircuitProver { ); } + @trackSpan('TestCircuitProver.getPublicTailProof') public async getPublicTailProof( kernelRequest: PublicKernelTailRequest, ): Promise> { @@ -301,6 +326,7 @@ export class TestCircuitProver implements ServerCircuitProver { ); const result = convertSimulatedPublicTailOutputFromWitnessMap(witness); + this.instrumentation.recordDuration('simulationDuration', 'public-kernel-tail', timer); emitCircuitSimulationStats( 'public-kernel-tail', timer.ms(), diff --git a/yarn-project/bb-prover/tsconfig.json b/yarn-project/bb-prover/tsconfig.json index d29068188938..e0e59ed584cc 100644 --- a/yarn-project/bb-prover/tsconfig.json +++ b/yarn-project/bb-prover/tsconfig.json @@ -20,6 +20,9 @@ }, { "path": "../simulator" + }, + { + "path": "../telemetry-client" } ], "include": ["src"] diff --git a/yarn-project/builder/package.json b/yarn-project/builder/package.json index 29b648700ff1..c6f153b7f050 100644 --- a/yarn-project/builder/package.json +++ b/yarn-project/builder/package.json @@ -41,7 +41,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/builder/src/contract-interface-gen/typescript.ts b/yarn-project/builder/src/contract-interface-gen/typescript.ts index 5fc2828c500b..d092f4b06889 100644 --- a/yarn-project/builder/src/contract-interface-gen/typescript.ts +++ b/yarn-project/builder/src/contract-interface-gen/typescript.ts @@ -225,7 +225,7 @@ function generateNotesGetter(input: ContractArtifact) { .map( ([name, { id }]) => `${name}: { - id: new Fr(${id.toBigInt()}n), + id: new NoteSelector(${id.value}), }`, ) .join(',\n'); @@ -281,11 +281,7 @@ function generateEvents(events: any[] | undefined) { if (payload === undefined) { return undefined; } - if ( - !eventSelector.equals( - EventSelector.fromField(payload.eventTypeId), - ) - ) { + if (!eventSelector.equals(payload.eventTypeId)) { return undefined; } if (payload.event.items.length !== fieldsLength) { @@ -349,14 +345,14 @@ import { DeployMethod, EthAddress, EthAddressLike, + EventSelector, FieldLike, Fr, - EventSelector, - FunctionSelector, FunctionSelectorLike, L1EventPayload, loadContractArtifact, NoirCompiledContract, + NoteSelector, Point, PublicKey, Wallet, diff --git a/yarn-project/circuit-types/package.json b/yarn-project/circuit-types/package.json index 8779c385af20..09e852caff31 100644 --- a/yarn-project/circuit-types/package.json +++ b/yarn-project/circuit-types/package.json @@ -36,7 +36,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts index fea25ec838de..a84039e38296 100644 --- a/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts +++ b/yarn-project/circuit-types/src/logs/encrypted_l2_note_log.ts @@ -52,6 +52,10 @@ export class EncryptedL2NoteLog { return sha256Trunc(preimage); } + public getSiloedHash(): Buffer { + return this.hash(); + } + /** * Crates a random log. * @returns A random log. 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 a176af8bf009..e45fcbef4e98 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.ts @@ -37,9 +37,8 @@ export abstract class FunctionL2Logs acc + log.length + 4, 0) + 4; + return this.getKernelLength() + 4; } /** diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts index 939ca41ea65e..d6a3dbfd1102 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.test.ts @@ -1,5 +1,6 @@ import { Fr, GrumpkinScalar } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; +import { NoteSelector } from '@aztec/foundation/abi'; import { updateInlineTestData } from '@aztec/foundation/testing'; import { Note } from '../payload.js'; @@ -20,10 +21,10 @@ describe('encrypt log incoming body', () => { const viewingPubKey = grumpkin.mul(Grumpkin.generator, viewingSecretKey); const note = Note.random(); - const noteTypeId = Fr.random(); const storageSlot = Fr.random(); + const noteTypeId = NoteSelector.random(); - const body = new EncryptedNoteLogIncomingBody(noteTypeId, storageSlot, note); + const body = new EncryptedNoteLogIncomingBody(storageSlot, noteTypeId, note); const encrypted = body.computeCiphertext(ephSecretKey, viewingPubKey); @@ -44,7 +45,7 @@ describe('encrypt log incoming body', () => { const viewingPubKey = grumpkin.mul(Grumpkin.generator, viewingSecretKey); const note = new Note([new Fr(1), new Fr(2), new Fr(3)]); - const noteTypeId = new Fr(1); + const noteTypeId = new NoteSelector(1); const storageSlot = new Fr(2); const body = new EncryptedNoteLogIncomingBody(storageSlot, noteTypeId, note); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.ts b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.ts index 83bd9edb4794..2edaba57db46 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/encrypted_log_incoming_body/encrypted_note_log_incoming_body.ts @@ -1,11 +1,12 @@ import { Fr, type GrumpkinPrivateKey, type PublicKey } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { Note } from '../payload.js'; import { EncryptedLogIncomingBody } from './encrypted_log_incoming_body.js'; export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody { - constructor(public storageSlot: Fr, public noteTypeId: Fr, public note: Note) { + constructor(public storageSlot: Fr, public noteTypeId: NoteSelector, public note: Note) { super(); } @@ -16,7 +17,8 @@ export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody { */ public toBuffer(): Buffer { const noteBufferWithoutLength = this.note.toBuffer().subarray(4); - return serializeToBuffer(this.storageSlot, this.noteTypeId, noteBufferWithoutLength); + // Note: We serialize note type to field first because that's how it's done in Noir + return serializeToBuffer(this.storageSlot, this.noteTypeId.toField(), noteBufferWithoutLength); } /** @@ -28,7 +30,7 @@ export class EncryptedNoteLogIncomingBody extends EncryptedLogIncomingBody { public static fromBuffer(buf: Buffer): EncryptedNoteLogIncomingBody { const reader = BufferReader.asReader(buf); const storageSlot = Fr.fromBuffer(reader); - const noteTypeId = Fr.fromBuffer(reader); + const noteTypeId = NoteSelector.fromField(Fr.fromBuffer(reader)); // 2 Fields (storage slot and note type id) are not included in the note buffer const fieldsInNote = reader.getLength() / 32 - 2; diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.test.ts index ea7f49391b6e..1598b9c02f1d 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.test.ts @@ -1,4 +1,5 @@ import { AztecAddress, KeyValidationRequest, computeOvskApp, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; @@ -29,7 +30,7 @@ describe('L1 Event Payload', () => { randomness = Fr.random(); maskedContractAddress = pedersenHash([contractAddress, randomness], 0); - payload = new L1EventPayload(Event.random(), contractAddress, randomness, Fr.random()); + payload = new L1EventPayload(Event.random(), contractAddress, randomness, EventSelector.random()); ovskM = GrumpkinScalar.random(); ivskM = GrumpkinScalar.random(); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts index e3cd80ba0610..741a0128475d 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_event_payload.ts @@ -1,4 +1,5 @@ import { AztecAddress, type GrumpkinPrivateKey, type KeyValidationRequest, type PublicKey } from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -25,9 +26,9 @@ export class L1EventPayload extends L1Payload { */ public randomness: Fr, /** - * Type identifier for the underlying event, (calculated as a function selector). + * Type identifier for the underlying event. */ - public eventTypeId: Fr, + public eventTypeId: EventSelector, ) { super(); } @@ -43,7 +44,7 @@ export class L1EventPayload extends L1Payload { reader.readObject(Event), reader.readObject(AztecAddress), Fr.fromBuffer(reader), - Fr.fromBuffer(reader), + reader.readObject(EventSelector), ); } @@ -60,7 +61,7 @@ export class L1EventPayload extends L1Payload { * @returns A random L1EventPayload object. */ static random() { - return new L1EventPayload(Event.random(), AztecAddress.random(), Fr.random(), Fr.random()); + return new L1EventPayload(Event.random(), AztecAddress.random(), Fr.random(), EventSelector.random()); } public encrypt(ephSk: GrumpkinPrivateKey, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { @@ -70,7 +71,7 @@ export class L1EventPayload extends L1Payload { recipient, ivpk, ovKeys, - new EncryptedEventLogIncomingBody(this.randomness, this.eventTypeId, this.event), + new EncryptedEventLogIncomingBody(this.randomness, this.eventTypeId.toField(), this.event), ); } @@ -100,9 +101,13 @@ export class L1EventPayload extends L1Payload { EncryptedEventLogIncomingBody.fromCiphertext, ); + // We instantiate selector before checking the address because instantiating the selector validates that + // the selector is valid (and that's the preferred way of detecting decryption failure). + const selector = EventSelector.fromField(incomingBody.eventTypeId); + this.ensureMatchedMaskedContractAddress(address, incomingBody.randomness, encryptedLog.maskedContractAddress); - return new L1EventPayload(incomingBody.event, address, incomingBody.randomness, incomingBody.eventTypeId); + return new L1EventPayload(incomingBody.event, address, incomingBody.randomness, selector); } /** @@ -131,8 +136,12 @@ export class L1EventPayload extends L1Payload { EncryptedEventLogIncomingBody.fromCiphertext, ); + // We instantiate selector before checking the address because instantiating the selector validates that + // the selector is valid (and that's the preferred way of detecting decryption failure). + const selector = EventSelector.fromField(incomingBody.eventTypeId); + this.ensureMatchedMaskedContractAddress(address, incomingBody.randomness, encryptedLog.maskedContractAddress); - return new L1EventPayload(incomingBody.event, address, incomingBody.randomness, incomingBody.eventTypeId); + return new L1EventPayload(incomingBody.event, address, incomingBody.randomness, selector); } } diff --git a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts index ee28010c1bfb..b0dadca6ffe2 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/l1_note_payload.ts @@ -1,4 +1,5 @@ import { AztecAddress, type GrumpkinPrivateKey, type KeyValidationRequest, type PublicKey } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -28,7 +29,7 @@ export class L1NotePayload extends L1Payload { /** * Type identifier for the underlying note, required to determine how to compute its hash and nullifier. */ - public noteTypeId: Fr, + public noteTypeId: NoteSelector, ) { super(); } @@ -44,7 +45,7 @@ export class L1NotePayload extends L1Payload { reader.readObject(Note), reader.readObject(AztecAddress), Fr.fromBuffer(reader), - Fr.fromBuffer(reader), + reader.readObject(NoteSelector), ); } @@ -62,7 +63,7 @@ export class L1NotePayload extends L1Payload { * @returns A random L1NotePayload object. */ static random(contract = AztecAddress.random()) { - return new L1NotePayload(Note.random(), contract, Fr.random(), Fr.random()); + return new L1NotePayload(Note.random(), contract, Fr.random(), NoteSelector.random()); } public encrypt(ephSk: GrumpkinPrivateKey, recipient: AztecAddress, ivpk: PublicKey, ovKeys: KeyValidationRequest) { diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts index c5c7968c965d..a7b736db73c7 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.test.ts @@ -1,4 +1,5 @@ import { AztecAddress, KeyValidationRequest, computeOvskApp, derivePublicKeyFromSecretKey } from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; @@ -86,7 +87,7 @@ describe('L1 Event Payload', () => { randomness = Fr.random(); maskedContractAddress = pedersenHash([contractAddress, randomness], 0); - const payload = new L1EventPayload(Event.random(), contractAddress, randomness, Fr.random()); + const payload = new L1EventPayload(Event.random(), contractAddress, randomness, EventSelector.random()); ovskM = GrumpkinScalar.random(); ivskM = GrumpkinScalar.random(); diff --git a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts index 4904479acdb2..c4d2ec5fe73f 100644 --- a/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts +++ b/yarn-project/circuit-types/src/logs/l1_payload/tagged_log.ts @@ -78,8 +78,6 @@ export class TaggedLog { ivsk: GrumpkinPrivateKey, payloadType: typeof L1NotePayload | typeof L1EventPayload = L1NotePayload, ): TaggedLog | undefined { - // Right now heavily abusing that we will likely fail if bad decryption - // as some field will likely end up not being in the field etc. try { if (payloadType === L1EventPayload) { const reader = BufferReader.asReader((data as EncryptedL2Log).data); @@ -96,7 +94,17 @@ export class TaggedLog { const payload = L1NotePayload.decryptAsIncoming(reader.readToEnd(), ivsk); return new TaggedLog(payload, incomingTag, outgoingTag); } - } catch (e) { + } catch (e: any) { + // Following error messages are expected to occur when decryption fails + if ( + !e.message.endsWith('is greater or equal to field modulus.') && + !e.message.startsWith('Invalid AztecAddress length') && + !e.message.startsWith('Selector must fit in') && + !e.message.startsWith('Attempted to read beyond buffer length') + ) { + // If we encounter an unexpected error, we rethrow it + throw e; + } return; } } @@ -116,8 +124,6 @@ export class TaggedLog { ovsk: GrumpkinPrivateKey, payloadType: typeof L1NotePayload | typeof L1EventPayload = L1NotePayload, ) { - // Right now heavily abusing that we will likely fail if bad decryption - // as some field will likely end up not being in the field etc. try { if (payloadType === L1EventPayload) { const reader = BufferReader.asReader((data as EncryptedL2Log).data); @@ -133,7 +139,17 @@ export class TaggedLog { const payload = L1NotePayload.decryptAsOutgoing(reader.readToEnd(), ovsk); return new TaggedLog(payload, incomingTag, outgoingTag); } - } catch (e) { + } catch (e: any) { + // Following error messages are expected to occur when decryption fails + if ( + !e.message.endsWith('is greater or equal to field modulus.') && + !e.message.startsWith('Invalid AztecAddress length') && + !e.message.startsWith('Selector must fit in') && + !e.message.startsWith('Attempted to read beyond buffer length') + ) { + // If we encounter an unexpected error, we rethrow it + throw e; + } return; } } 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 f17004efa7cb..90610fa53310 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -1,4 +1,6 @@ import { + Fr, + type LogHash, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -22,6 +24,8 @@ import { type UnencryptedL2Log } from './unencrypted_l2_log.js'; * Data container of logs emitted in 1 tx. */ export abstract class TxL2Logs { + abstract hash(): Buffer; + constructor( /** * An array containing logs emitted in individual function invocations in this tx. */ public readonly functionLogs: FunctionL2Logs[], @@ -94,6 +98,28 @@ export abstract class TxL2Logs): boolean { return isEqual(this, other); } + + /** + * Filter the logs from functions from this TxL2Logs that + * appear in the provided logHashes + * @param logHashes hashes we want to keep + * @param output our aggregation + * @returns our aggregation + */ + public filter(logHashes: LogHash[], output: TxL2Logs): TxL2Logs { + for (const fnLogs of this.functionLogs) { + let include = false; + for (const log of fnLogs.logs) { + if (logHashes.findIndex(lh => lh.value.equals(Fr.fromBuffer(log.getSiloedHash()))) !== -1) { + include = true; + } + } + if (include) { + output.addFunctionLogs([fnLogs]); + } + } + return output; + } } export class UnencryptedTxL2Logs extends TxL2Logs { @@ -156,17 +182,18 @@ export class UnencryptedTxL2Logs extends TxL2Logs { * Note: This is a TS implementation of `computeKernelUnencryptedLogsHash` function in Decoder.sol. See that function documentation * for more details. */ - public hash(): Buffer { - if (this.unrollLogs().length == 0) { + public override hash(): Buffer { + const unrolledLogs = this.unrollLogs(); + if (unrolledLogs.length == 0) { return Buffer.alloc(32); } let flattenedLogs = Buffer.alloc(0); - for (const logsFromSingleFunctionCall of this.unrollLogs()) { + for (const logsFromSingleFunctionCall of unrolledLogs) { flattenedLogs = Buffer.concat([flattenedLogs, logsFromSingleFunctionCall.getSiloedHash()]); } // pad the end of logs with 0s - for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX - this.unrollLogs().length; i++) { + for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX - unrolledLogs.length; i++) { flattenedLogs = Buffer.concat([flattenedLogs, Buffer.alloc(32)]); } @@ -234,17 +261,18 @@ export class EncryptedNoteTxL2Logs extends TxL2Logs { * Note: This is a TS implementation of `computeKernelNoteEncryptedLogsHash` function in Decoder.sol. See that function documentation * for more details. */ - public hash(): Buffer { - if (this.unrollLogs().length == 0) { + public override hash(): Buffer { + const unrolledLogs = this.unrollLogs(); + if (unrolledLogs.length == 0) { return Buffer.alloc(32); } let flattenedLogs = Buffer.alloc(0); - for (const logsFromSingleFunctionCall of this.unrollLogs()) { + for (const logsFromSingleFunctionCall of unrolledLogs) { flattenedLogs = Buffer.concat([flattenedLogs, logsFromSingleFunctionCall.hash()]); } // pad the end of logs with 0s - for (let i = 0; i < MAX_NOTE_ENCRYPTED_LOGS_PER_TX - this.unrollLogs().length; i++) { + for (let i = 0; i < MAX_NOTE_ENCRYPTED_LOGS_PER_TX - unrolledLogs.length; i++) { flattenedLogs = Buffer.concat([flattenedLogs, Buffer.alloc(32)]); } @@ -312,17 +340,18 @@ export class EncryptedTxL2Logs extends TxL2Logs { * Note: This is a TS implementation of `computeKernelEncryptedLogsHash` function in Decoder.sol. See that function documentation * for more details. */ - public hash(): Buffer { - if (this.unrollLogs().length == 0) { + public override hash(): Buffer { + const unrolledLogs = this.unrollLogs(); + if (unrolledLogs.length == 0) { return Buffer.alloc(32); } let flattenedLogs = Buffer.alloc(0); - for (const logsFromSingleFunctionCall of this.unrollLogs()) { + for (const logsFromSingleFunctionCall of unrolledLogs) { flattenedLogs = Buffer.concat([flattenedLogs, logsFromSingleFunctionCall.getSiloedHash()]); } // pad the end of logs with 0s - for (let i = 0; i < MAX_ENCRYPTED_LOGS_PER_TX - this.unrollLogs().length; i++) { + for (let i = 0; i < MAX_ENCRYPTED_LOGS_PER_TX - unrolledLogs.length; i++) { flattenedLogs = Buffer.concat([flattenedLogs, Buffer.alloc(32)]); } diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 1c4989c97b03..99df4ebcfa58 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -19,7 +19,7 @@ import { makeCombinedConstantData, makePublicCallRequest, } from '@aztec/circuits.js/testing'; -import { type ContractArtifact } from '@aztec/foundation/abi'; +import { type ContractArtifact, NoteSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; @@ -107,24 +107,50 @@ export const mockTx = ( 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 LogHash( - Fr.fromBuffer(log.hash()), - i++, - new Fr(log.toBuffer().length), - ); - } + let nonRevertibleIndex = 0; + let revertibleIndex = 0; + let functionCount = 0; + encryptedLogs.functionLogs.forEach(functionLog => { + functionLog.logs.forEach(log => { + // ts complains if we dont check .forPublic here, even though it is defined ^ + if (data.forPublic) { + const hash = new LogHash( + Fr.fromBuffer(log.getSiloedHash()), + i++, + // +4 for encoding the length of the buffer + new Fr(log.length + 4), + ); + // make the first log non-revertible + if (functionCount === 0) { + data.forPublic.endNonRevertibleData.encryptedLogsHashes[nonRevertibleIndex++] = hash; + } else { + data.forPublic.end.encryptedLogsHashes[revertibleIndex++] = hash; + } + } + }); + functionCount++; }); - unencryptedLogs.functionLogs.forEach((log, j) => { - if (data.forPublic) { - data.forPublic.end.unencryptedLogsHashes[j] = new LogHash( - Fr.fromBuffer(log.hash()), - i++, - new Fr(log.toBuffer().length), - ); - } + nonRevertibleIndex = 0; + revertibleIndex = 0; + functionCount = 0; + unencryptedLogs.functionLogs.forEach(functionLog => { + functionLog.logs.forEach(log => { + if (data.forPublic) { + const hash = new LogHash( + Fr.fromBuffer(log.getSiloedHash()), + i++, + // +4 for encoding the length of the buffer + new Fr(log.length + 4), + ); + // make the first log non-revertible + if (functionCount === 0) { + data.forPublic.endNonRevertibleData.unencryptedLogsHashes[nonRevertibleIndex++] = hash; + } else { + data.forPublic.end.unencryptedLogsHashes[revertibleIndex++] = hash; + } + } + }); + functionCount++; }); } } else { @@ -177,8 +203,10 @@ export const randomContractArtifact = (): ContractArtifact => ({ notes: {}, }); -export const randomContractInstanceWithAddress = (opts: { contractClassId?: Fr } = {}): ContractInstanceWithAddress => - SerializableContractInstance.random(opts).withAddress(AztecAddress.random()); +export const randomContractInstanceWithAddress = ( + opts: { contractClassId?: Fr } = {}, + address: AztecAddress = AztecAddress.random(), +): ContractInstanceWithAddress => SerializableContractInstance.random(opts).withAddress(address); export const randomDeployedContract = () => { const artifact = randomContractArtifact(); @@ -192,7 +220,7 @@ export const randomExtendedNote = ({ contractAddress = AztecAddress.random(), txHash = randomTxHash(), storageSlot = Fr.random(), - noteTypeId = Fr.random(), + noteTypeId = NoteSelector.random(), }: Partial = {}) => { return new ExtendedNote(note, owner, contractAddress, storageSlot, noteTypeId, txHash); }; diff --git a/yarn-project/circuit-types/src/notes/extended_note.ts b/yarn-project/circuit-types/src/notes/extended_note.ts index caee60e8be9c..bf91e2dc49dd 100644 --- a/yarn-project/circuit-types/src/notes/extended_note.ts +++ b/yarn-project/circuit-types/src/notes/extended_note.ts @@ -1,4 +1,5 @@ import { AztecAddress, Fr } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { BufferReader } from '@aztec/foundation/serialize'; import { Note } from '../logs/l1_payload/payload.js'; @@ -18,7 +19,7 @@ export class ExtendedNote { /** The specific storage location of the note on the contract. */ public storageSlot: Fr, /** The type identifier of the note on the contract. */ - public noteTypeId: Fr, + public noteTypeId: NoteSelector, /** The hash of the tx the note was created in. */ public txHash: TxHash, ) {} @@ -33,6 +34,7 @@ export class ExtendedNote { this.txHash.buffer, ]); } + static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); @@ -40,7 +42,7 @@ export class ExtendedNote { const owner = AztecAddress.fromBuffer(reader); const contractAddress = AztecAddress.fromBuffer(reader); const storageSlot = Fr.fromBuffer(reader); - const noteTypeId = Fr.fromBuffer(reader); + const noteTypeId = reader.readObject(NoteSelector); const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); return new this(note, owner, contractAddress, storageSlot, noteTypeId, txHash); diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index cf6bb9774234..d20983f261bf 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -27,6 +27,8 @@ import { makeEmptyProof, } from '@aztec/circuits.js'; +import { type CircuitName } from '../stats/stats.js'; + /** * Used to communicate to the prover which type of circuit to prove */ @@ -160,9 +162,9 @@ export function makeProcessedTx( data: kernelOutput, proof, // TODO(4712): deal with non-revertible logs here - noteEncryptedLogs: revertReason ? EncryptedNoteTxL2Logs.empty() : tx.noteEncryptedLogs, - encryptedLogs: revertReason ? EncryptedTxL2Logs.empty() : tx.encryptedLogs, - unencryptedLogs: revertReason ? UnencryptedTxL2Logs.empty() : tx.unencryptedLogs, + noteEncryptedLogs: tx.noteEncryptedLogs, + encryptedLogs: tx.encryptedLogs, + unencryptedLogs: tx.unencryptedLogs, isEmpty: false, revertReason, publicProvingRequests, @@ -304,3 +306,18 @@ export function validateProcessedTx(tx: ProcessedTx): void { validateProcessedTxLogs(tx); // TODO: validate other fields } + +export function mapPublicKernelToCircuitName(kernelType: PublicKernelRequest['type']): CircuitName { + switch (kernelType) { + case PublicKernelType.SETUP: + return 'public-kernel-setup'; + case PublicKernelType.APP_LOGIC: + return 'public-kernel-app-logic'; + case PublicKernelType.TEARDOWN: + return 'public-kernel-teardown'; + case PublicKernelType.TAIL: + return 'public-kernel-tail'; + default: + throw new Error(`Unknown kernel type: ${kernelType}`); + } +} diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index d10e8fdb5f6b..8cb40f57d623 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -3,6 +3,7 @@ import { PrivateKernelTailCircuitPublicInputs, Proof, PublicCallRequest, + type PublicKernelCircuitPublicInputs, } from '@aztec/circuits.js'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -29,15 +30,15 @@ export class Tx { /** * Encrypted note logs generated by the tx. */ - public readonly noteEncryptedLogs: EncryptedNoteTxL2Logs, + public noteEncryptedLogs: EncryptedNoteTxL2Logs, /** * Encrypted logs generated by the tx. */ - public readonly encryptedLogs: EncryptedTxL2Logs, + public encryptedLogs: EncryptedTxL2Logs, /** * Unencrypted logs generated by the tx. */ - public readonly unencryptedLogs: UnencryptedTxL2Logs, + public unencryptedLogs: UnencryptedTxL2Logs, /** * Enqueued public functions from the private circuit to be run by the sequencer. * Preimages of the public call stack entries from the private kernel circuit output. @@ -249,6 +250,37 @@ export class Tx { publicTeardownFunctionCall, ); } + + /** + * Filters out logs from functions that are not present in the provided kernel output. + * + * The purpose of this is to remove logs that got dropped due to a revert, + * in which case, we only have the kernel's hashes to go on, as opposed to + * this grouping by function maintained in this class. + * + * The logic therefore is to drop all FunctionLogs if any constituent hash + * does not appear in the provided hashes: it is impossible for part of a + * function to revert. + * + * @param logHashes the individual log hashes we want to keep + * @param out the output to put passing logs in, to keep this function abstract + */ + public filterRevertedLogs(kernelOutput: PublicKernelCircuitPublicInputs) { + this.encryptedLogs = this.encryptedLogs.filter( + kernelOutput.endNonRevertibleData.encryptedLogsHashes, + EncryptedTxL2Logs.empty(), + ); + + this.unencryptedLogs = this.unencryptedLogs.filter( + kernelOutput.endNonRevertibleData.unencryptedLogsHashes, + UnencryptedTxL2Logs.empty(), + ); + + this.noteEncryptedLogs = this.noteEncryptedLogs.filter( + kernelOutput.endNonRevertibleData.noteEncryptedLogsHashes, + EncryptedNoteTxL2Logs.empty(), + ); + } } /** Utility type for an entity that has a hash property for a txhash */ diff --git a/yarn-project/circuits.js/package.json b/yarn-project/circuits.js/package.json index 84f9e8730162..524b4a622104 100644 --- a/yarn-project/circuits.js/package.json +++ b/yarn-project/circuits.js/package.json @@ -72,7 +72,15 @@ ], "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "moduleNameMapper": { diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 77ce004e4523..f226f6d2e169 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -206,13 +206,14 @@ export enum GeneratorIndex { FUNCTION_ARGS = 44, AUTHWIT_INNER = 45, AUTHWIT_OUTER = 46, - NSK_M = 47, - IVSK_M = 48, - OVSK_M = 49, - TSK_M = 50, - PUBLIC_KEYS_HASH = 51, - NOTE_NULLIFIER = 52, - INNER_NOTE_HASH = 53, - NOTE_CONTENT_HASH = 54, - SYMMETRIC_KEY = 55, + AUTHWIT_NULLIFIER = 47, + NSK_M = 48, + IVSK_M = 49, + OVSK_M = 50, + TSK_M = 51, + PUBLIC_KEYS_HASH = 52, + NOTE_NULLIFIER = 53, + INNER_NOTE_HASH = 54, + NOTE_CONTENT_HASH = 55, + SYMMETRIC_KEY = 56, } diff --git a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap index 2d413b4089cc..10e93a7af31b 100644 --- a/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap +++ b/yarn-project/circuits.js/src/contract/__snapshots__/contract_address.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x0bed63221d281713007bfb0c063e1f61d0646404fb3701b99bb92f41b6390604"`; +exports[`ContractAddress computeContractAddressFromInstance 1`] = `"0x2a192ee63791ad5e219b63db872bf54ba245afbc2c1287f4ba036b8f58fad740"`; exports[`ContractAddress computeInitializationHash 1`] = `Fr<0x109865e4b959adba34b722e72a69baaf9ee78e31bb1042318f0d91006ed86780>`; diff --git a/yarn-project/circuits.js/src/keys/derivation.test.ts b/yarn-project/circuits.js/src/keys/derivation.test.ts index f41aa0c0d3f0..c3c1e0bb59d2 100644 --- a/yarn-project/circuits.js/src/keys/derivation.test.ts +++ b/yarn-project/circuits.js/src/keys/derivation.test.ts @@ -11,7 +11,7 @@ describe('🔑', () => { const masterOutgoingViewingPublicKey = new Point(new Fr(5), new Fr(6)); const masterTaggingPublicKey = new Point(new Fr(7), new Fr(8)); - const expected = Fr.fromString('0x1936abe4f6a920d16a9f6917f10a679507687e2cd935dd1f1cdcb1e908c027f3'); + const expected = Fr.fromString('0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717'); expect( new PublicKeys( masterNullifierPublicKey, diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index f33335f800cb..907e41ad4f2a 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -243,6 +243,7 @@ export class AvmContractInstanceHint { } } +// TODO(dbanks12): rename AvmCircuitHints export class AvmExecutionHints { public readonly storageValues: Vector; public readonly noteHashExists: Vector; @@ -267,6 +268,14 @@ export class AvmExecutionHints { this.contractInstances = new Vector(contractInstances); } + /** + * Return an empty instance. + * @returns an empty instance. + */ + empty() { + return new AvmExecutionHints([], [], [], [], [], []); + } + /** * Serializes the inputs to a buffer. * @returns - The inputs serialized to a buffer. diff --git a/yarn-project/circuits.js/src/structs/complete_address.test.ts b/yarn-project/circuits.js/src/structs/complete_address.test.ts index 25c0de180c89..4fd6d5282838 100644 --- a/yarn-project/circuits.js/src/structs/complete_address.test.ts +++ b/yarn-project/circuits.js/src/structs/complete_address.test.ts @@ -38,11 +38,11 @@ describe('CompleteAddress', () => { // docs:start:instantiate-complete-address // Typically a recipient would share their complete address with the sender const completeAddressFromString = CompleteAddress.fromString( - '0x09bc7031bb21627cce6aac1dc710ecc92acd8475149c530a4bb57df63d9d6fe902a9372135ce5b49b46102732fabd742c31642543396013dde5b460075864607264c605bc115c6cb92a4db0a6b893fd3777341078693d0af22e3ff53f4c2ee2a2fae73914fc50d325e2707a8e996f1ad498429f715f998225dc6bd2ede05aaee055ee137d28b634322e0ea98afc42dfc48833e8d2879c34d23d6d1d337069cca212af0f28b7865b339e202a0077fd3bd8dddc472d055945ad99c02dcccd28bb22bb3585fca3e5751c9913521a390458d63e4d9b292e4872582f3b13da214470c14083a4567cf4f1e92696e6c01923bc6a8b414159446268b12fe8669ce44f1f5196561aca6c654d2405a5653002cba5552b50b6ce1afc9515ed6682507abcb3010040d791aeb30138efc9c7d36b47684af2f26f686672448349f05934ae7bbbf', + '0x1de12596818ab6bc3584b943f791b206ff588d3c307358ab6918f59ed7d381bc02a9372135ce5b49b46102732fabd742c31642543396013dde5b460075864607264c605bc115c6cb92a4db0a6b893fd3777341078693d0af22e3ff53f4c2ee2a2fae73914fc50d325e2707a8e996f1ad498429f715f998225dc6bd2ede05aaee055ee137d28b634322e0ea98afc42dfc48833e8d2879c34d23d6d1d337069cca212af0f28b7865b339e202a0077fd3bd8dddc472d055945ad99c02dcccd28bb22bb3585fca3e5751c9913521a390458d63e4d9b292e4872582f3b13da214470c14083a4567cf4f1e92696e6c01923bc6a8b414159446268b12fe8669ce44f1f5196561aca6c654d2405a5653002cba5552b50b6ce1afc9515ed6682507abcb3010040d791aeb30138efc9c7d36b47684af2f26f686672448349f05934ae7bbbf', ); // Alternatively, a recipient could share the individual components with the sender - const address = Fr.fromString('0x09bc7031bb21627cce6aac1dc710ecc92acd8475149c530a4bb57df63d9d6fe9'); + const address = Fr.fromString('0x1de12596818ab6bc3584b943f791b206ff588d3c307358ab6918f59ed7d381bc'); const npkM = Point.fromString( '0x02a9372135ce5b49b46102732fabd742c31642543396013dde5b460075864607264c605bc115c6cb92a4db0a6b893fd3777341078693d0af22e3ff53f4c2ee2a', ); 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 5a679a75bf7e..56f0f95aa1dd 100644 --- a/yarn-project/circuits.js/src/structs/contract_storage_read.ts +++ b/yarn-project/circuits.js/src/structs/contract_storage_read.ts @@ -23,30 +23,19 @@ export class ContractStorageRead { /** * Side effect counter tracking position of this event in tx execution. */ - public readonly sideEffectCounter: number, + public readonly counter: number, + /** + * Contract address whose storage is being read. + */ 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: { - /** - * Storage slot we are reading from. - */ - storageSlot: Fr; - /** - * Value read from the storage slot. - */ - currentValue: Fr; - /** - * Side effect counter tracking position of this event in tx execution. - */ - sideEffectCounter: number; - contractAddress?: AztecAddress; - }) { - return new ContractStorageRead(args.storageSlot, args.currentValue, args.sideEffectCounter, args.contractAddress); + static from(args: { storageSlot: Fr; currentValue: Fr; counter: number; contractAddress?: AztecAddress }) { + return new ContractStorageRead(args.storageSlot, args.currentValue, args.counter, args.contractAddress); } toBuffer() { - return serializeToBuffer(this.storageSlot, this.currentValue, new Fr(this.sideEffectCounter)); + return serializeToBuffer(this.storageSlot, this.currentValue, new Fr(this.counter)); } static fromBuffer(buffer: Buffer | BufferReader) { @@ -59,7 +48,7 @@ export class ContractStorageRead { } isEmpty() { - return this.storageSlot.isZero() && this.currentValue.isZero() && this.sideEffectCounter == 0; + return this.storageSlot.isZero() && this.currentValue.isZero() && this.counter == 0; } toFriendlyJSON() { @@ -67,7 +56,7 @@ export class ContractStorageRead { } toFields(): Fr[] { - const fields = [this.storageSlot, this.currentValue, new Fr(this.sideEffectCounter)]; + const fields = [this.storageSlot, this.currentValue, new Fr(this.counter)]; if (fields.length !== CONTRACT_STORAGE_READ_LENGTH) { throw new Error( `Invalid number of fields for ContractStorageRead. Expected ${CONTRACT_STORAGE_READ_LENGTH}, got ${fields.length}`, @@ -81,8 +70,8 @@ export class ContractStorageRead { const storageSlot = reader.readField(); const currentValue = reader.readField(); - const sideEffectCounter = reader.readField().toNumber(); + const counter = reader.readField().toNumber(); - return new ContractStorageRead(storageSlot, currentValue, sideEffectCounter); + return new ContractStorageRead(storageSlot, currentValue, counter); } } 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 04be2dd24f9d..4d7d3d665c07 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 @@ -22,14 +22,17 @@ export class ContractStorageUpdateRequest { */ public readonly newValue: Fr, /** - * Optional side effect counter tracking position of this event in tx execution. + * Side effect counter tracking position of this event in tx execution. + */ + public readonly counter: number, + /** + * Contract address whose storage is being read. */ - 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() { - return serializeToBuffer(this.storageSlot, this.newValue, this.sideEffectCounter); + return serializeToBuffer(this.storageSlot, this.newValue, this.counter); } static fromBuffer(buffer: Buffer | BufferReader) { @@ -52,7 +55,7 @@ export class ContractStorageUpdateRequest { * @returns The array. */ static getFields(fields: FieldsOf) { - return [fields.storageSlot, fields.newValue, fields.sideEffectCounter, fields.contractAddress] as const; + return [fields.storageSlot, fields.newValue, fields.counter, fields.contractAddress] as const; } static empty() { @@ -65,12 +68,12 @@ export class ContractStorageUpdateRequest { toFriendlyJSON() { return `Slot=${this.storageSlot.toFriendlyJSON()}: ${this.newValue.toFriendlyJSON()}, sideEffectCounter=${ - this.sideEffectCounter + this.counter }`; } toFields(): Fr[] { - const fields = [this.storageSlot, this.newValue, new Fr(this.sideEffectCounter)]; + const fields = [this.storageSlot, this.newValue, new Fr(this.counter)]; if (fields.length !== CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH) { throw new Error( `Invalid number of fields for ContractStorageUpdateRequest. Expected ${CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH}, got ${fields.length}`, diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.ts index 3223909d2878..170f3dc84b65 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.ts @@ -90,15 +90,24 @@ export class PublicCallStackItem { * @returns Hash. */ public hash() { + let publicInputsToHash = this.publicInputs; if (this.isExecutionRequest) { + // An execution request (such as an enqueued call from private) is hashed with + // only the publicInput members present in a PublicCallRequest. + // This allows us to check that the request (which is created/hashed before + // side-effects and output info are unknown for public calls) matches the call + // being processed by a kernel iteration. + // WARNING: This subset of publicInputs that is set here must align with + // `parse_public_call_stack_item_from_oracle` in enqueue_public_function_call.nr + // and `PublicCallStackItem::as_execution_request()` in public_call_stack_item.ts const { callContext, argsHash } = this.publicInputs; - this.publicInputs = PublicCircuitPublicInputs.empty(); - this.publicInputs.callContext = callContext; - this.publicInputs.argsHash = argsHash; + publicInputsToHash = PublicCircuitPublicInputs.empty(); + publicInputsToHash.callContext = callContext; + publicInputsToHash.argsHash = argsHash; } return pedersenHash( - [this.contractAddress, this.functionData.hash(), this.publicInputs.hash()], + [this.contractAddress, this.functionData.hash(), publicInputsToHash.hash()], GeneratorIndex.CALL_STACK_ITEM, ); } diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index 007477eecff9..303d4d9c336e 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -37,7 +37,15 @@ ], "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "reporters": [ diff --git a/yarn-project/cli/src/cmds/add_note.ts b/yarn-project/cli/src/cmds/add_note.ts index f6359bd5c1c3..68debccd90c7 100644 --- a/yarn-project/cli/src/cmds/add_note.ts +++ b/yarn-project/cli/src/cmds/add_note.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type Fr } from '@aztec/aztec.js'; +import { type AztecAddress, type Fr, type NoteSelector } from '@aztec/aztec.js'; import { ExtendedNote, Note, type TxHash } from '@aztec/circuit-types'; import { type DebugLogger } from '@aztec/foundation/log'; @@ -9,7 +9,7 @@ export async function addNote( address: AztecAddress, contractAddress: AztecAddress, storageSlot: Fr, - noteTypeId: Fr, + noteTypeId: NoteSelector, txHash: TxHash, noteFields: string[], rpcUrl: string, diff --git a/yarn-project/cli/src/inspect.ts b/yarn-project/cli/src/inspect.ts index f8ff880f1ee1..53c424680fc3 100644 --- a/yarn-project/cli/src/inspect.ts +++ b/yarn-project/cli/src/inspect.ts @@ -142,7 +142,7 @@ export async function inspectTx( function inspectNote(note: ExtendedNote, artifactMap: ArtifactMap, log: LogFn, text = 'Note') { const artifact = artifactMap[note.contractAddress.toString()]; const contract = artifact?.name ?? note.contractAddress.toString(); - const type = artifact?.notes[note.noteTypeId.toString()]?.typ ?? note.noteTypeId.toShortString(); + const type = artifact?.notes[note.noteTypeId.toString()]?.typ ?? note.noteTypeId.toField().toShortString(); log(` ${text} type ${type} at ${contract}`); log(` Owner: ${toFriendlyAddress(note.owner, artifactMap)}`); for (const field of note.note.items) { diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index b4c138967f7c..6444cf51694b 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -40,6 +40,7 @@ "@aztec/pxe": "workspace:^", "@aztec/sequencer-client": "workspace:^", "@aztec/simulator": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", "@aztec/world-state": "workspace:^", "@jest/globals": "^29.5.0", @@ -79,7 +80,6 @@ "ts-loader": "^9.4.4", "ts-node": "^10.9.1", "tslib": "^2.4.0", - "tty-browserify": "^0.0.1", "typescript": "^5.0.4", "util": "^0.12.5", "viem": "^2.7.15", @@ -116,7 +116,15 @@ ], "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "reporters": [ diff --git a/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts b/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts index d96397f05c8a..1d465504b8bc 100644 --- a/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_aztec_js_browser.test.ts @@ -25,10 +25,12 @@ const pageLogger = createDebugLogger('aztec:e2e_aztec_browser.js:web:page'); * 2) go to `yarn-project/end-to-end` and build the web packed package with `yarn build:web`, * 3) start anvil: `anvil`, * 4) if you intend to use a remotely running environment then export the URL of your PXE e.g. `export PXE_URL='http://localhost:8080'` - * 7) go to `yarn-project/end-to-end` and run the test: `yarn test aztec_js_browser` + * 5) go to `yarn-project/end-to-end` and run the test: `yarn test aztec_js_browser` + * 6) If you get dependency error run `apt install libssn3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libxdamage1 libxkbcommon0 libpango-1.0-0 libcairo2`. * - * NOTE: If you see the logs spammed with unexpected logs there is probably a chrome process with a webpage + * NOTE 1: If you see the logs spammed with unexpected logs there is probably a chrome process with a webpage * unexpectedly running in the background. Kill it with `killall chrome` + * NOTE 2: Don't forget to run `yarn build:web` once you make changes! */ const setupApp = async () => { diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 4445829658c0..17340f066750 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -40,6 +40,7 @@ import { AvailabilityOracleAbi, InboxAbi, OutboxAbi, RollupAbi } from '@aztec/l1 import { SHA256Trunc, StandardTree } from '@aztec/merkle-tree'; import { TxProver } from '@aztec/prover-client'; import { type L1Publisher, getL1Publisher } from '@aztec/sequencer-client'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { MerkleTrees, ServerWorldStateSynchronizer, type WorldStateConfig } from '@aztec/world-state'; import { beforeEach, describe, expect, it } from '@jest/globals'; @@ -145,7 +146,7 @@ describe('L1Publisher integration', () => { }; const worldStateSynchronizer = new ServerWorldStateSynchronizer(tmpStore, builderDb, blockSource, worldStateConfig); await worldStateSynchronizer.start(); - builder = await TxProver.new(config, getMockVerificationKeys(), worldStateSynchronizer); + builder = await TxProver.new(config, getMockVerificationKeys(), worldStateSynchronizer, new NoopTelemetryClient()); l2Proof = makeEmptyProof(); publisher = getL1Publisher({ diff --git a/yarn-project/end-to-end/src/e2e_authwit.test.ts b/yarn-project/end-to-end/src/e2e_authwit.test.ts index 8200ce331b7a..471aca74685d 100644 --- a/yarn-project/end-to-end/src/e2e_authwit.test.ts +++ b/yarn-project/end-to-end/src/e2e_authwit.test.ts @@ -1,5 +1,5 @@ -import { type AccountWallet, Fr, computeInnerAuthWitHash, computeOuterAuthWitHash } from '@aztec/aztec.js'; -import { AuthRegistryContract, SchnorrAccountContract } from '@aztec/noir-contracts.js'; +import { type AccountWallet, Fr, computeAuthWitMessageHash, computeInnerAuthWitHash } from '@aztec/aztec.js'; +import { AuthRegistryContract, AuthWitTestContract } from '@aztec/noir-contracts.js'; import { getCanonicalAuthRegistry } from '@aztec/protocol-contracts/auth-registry'; import { jest } from '@jest/globals'; @@ -16,6 +16,7 @@ describe('e2e_authwit_tests', () => { let chainId: Fr; let version: Fr; + let auth: AuthWitTestContract; beforeAll(async () => { ({ wallets } = await setup(2)); @@ -26,164 +27,122 @@ describe('e2e_authwit_tests', () => { const nodeInfo = await wallets[0].getNodeInfo(); chainId = new Fr(nodeInfo.chainId); version = new Fr(nodeInfo.protocolVersion); + + auth = await AuthWitTestContract.deploy(wallets[0]).send().deployed(); }); describe('Private', () => { describe('arbitrary data', () => { it('happy path', async () => { + // What are we doing here: + // 1. We compute an inner hash which is here just a hash of random data + // 2. We then compute the outer, which is binding it to a "consumer" (here the "auth" contract) + // 3. We then create an authwit for this outer hash. + // 4. We add this authwit to the wallet[1] + // 5. We check that the authwit is valid in private for wallet[0] (check that it is signed by 0) + // 6. We check that the authwit is NOT valid in private for wallet[1] (check that it is not signed by 1) + // docs:start:compute_inner_authwit_hash const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead')]); // docs:end:compute_inner_authwit_hash // docs:start:compute_outer_authwit_hash - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); + + const intent = { consumer: auth.address, innerHash }; // docs:end:compute_outer_authwit_hash // docs:start:create_authwit - const witness = await wallets[0].createAuthWit(outerHash); + const witness = await wallets[0].createAuthWit(intent); // docs:end:create_authwit await wallets[1].addAuthWitness(witness); // Check that the authwit is valid in private for wallets[0] - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: true, isValidInPublic: false, }); // Check that the authwit is NOT valid in private for wallets[1] - expect(await wallets[0].lookupValidity(wallets[1].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[1].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); - await c.withWallet(wallets[1]).methods.spend_private_authwit(innerHash).send().wait(); + // Consume the inner hash using the wallets[0] as the "on behalf of". + await auth.withWallet(wallets[1]).methods.consume(wallets[0].getAddress(), innerHash).send().wait(); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - }); + // Try to consume the same authwit again, it should fail + await expect( + auth.withWallet(wallets[1]).methods.consume(wallets[0].getAddress(), innerHash).send().wait(), + ).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + }); describe('failure case', () => { - it('cancel before usage', async () => { - const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0xbeef')]); - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); - - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: false, - isValidInPublic: false, - }); - - const witness = await wallets[0].createAuthWit(outerHash); - await wallets[1].addAuthWitness(witness); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: true, - isValidInPublic: false, - }); - await wallets[0].cancelAuthWit(outerHash).send().wait(); - - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: false, - isValidInPublic: false, - }); - - const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); - const txCancelledAuthwit = c.withWallet(wallets[1]).methods.spend_private_authwit(innerHash).send(); - - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: false, - isValidInPublic: false, - }); - - // The transaction should be dropped because of a cancelled authwit (duplicate nullifier) - await expect(txCancelledAuthwit.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); - }); - it('invalid chain id', async () => { - const invalidChainId = Fr.random(); - const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0xbeef')]); - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), invalidChainId, version, innerHash); - const outerCorrectHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); + const intent = { consumer: auth.address, innerHash }; - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: false, - isValidInPublic: false, - }); + const messageHash = computeAuthWitMessageHash(intent, { chainId: Fr.random(), version }); + const expectedMessageHash = computeAuthWitMessageHash(intent, { chainId, version }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - const witness = await wallets[0].createAuthWit(outerHash); + const witness = await wallets[0].createAuthWit(messageHash); await wallets[1].addAuthWitness(witness); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: true, - isValidInPublic: false, - }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + + // We should NOT see it as valid, even though we have the authwit, since the chain id is wrong + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); - const txCancelledAuthwit = c.withWallet(wallets[1]).methods.spend_private_authwit(innerHash).send(); + // The transaction should be dropped because of the invalid chain id + await expect( + auth.withWallet(wallets[1]).methods.consume(wallets[0].getAddress(), innerHash).simulate(), + ).rejects.toThrow(`Unknown auth witness for message hash ${expectedMessageHash.toString()}`); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: true, - isValidInPublic: false, - }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - - // The transaction should be dropped because of the invalid chain id - await expect(txCancelledAuthwit.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); it('invalid version', async () => { - const invalidVersion = Fr.random(); - const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0xbeef')]); - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, invalidVersion, innerHash); - const outerCorrectHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); + const intent = { consumer: auth.address, innerHash }; - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: false, - isValidInPublic: false, - }); + const messageHash = computeAuthWitMessageHash(intent, { chainId, version: Fr.random() }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + const expectedMessageHash = computeAuthWitMessageHash(intent, { chainId, version }); + + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - const witness = await wallets[0].createAuthWit(outerHash); + const witness = await wallets[0].createAuthWit(messageHash); await wallets[1].addAuthWitness(witness); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: true, - isValidInPublic: false, - }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + + // We should NOT see it as valid, even though we have the authwit, since the version is wrong + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); - const txCancelledAuthwit = c.withWallet(wallets[1]).methods.spend_private_authwit(innerHash).send(); + // The transaction should be dropped because of the invalid version + await expect( + auth.withWallet(wallets[1]).methods.consume(wallets[0].getAddress(), innerHash).simulate(), + ).rejects.toThrow(`Unknown auth witness for message hash ${expectedMessageHash.toString()}`); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ - isValidInPrivate: true, - isValidInPublic: false, - }); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerCorrectHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - - // The transaction should be dropped because of the invalid version - await expect(txCancelledAuthwit.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); }); }); }); @@ -193,16 +152,18 @@ describe('e2e_authwit_tests', () => { describe('arbitrary data', () => { it('happy path', async () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0x01')]); - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + + const intent = { consumer: wallets[1].getAddress(), innerHash }; + + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); // docs:start:set_public_authwit - await wallets[0].setPublicAuthWit(outerHash, true).send().wait(); + await wallets[0].setPublicAuthWit(intent, true).send().wait(); // docs:end:set_public_authwit - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: true, }); @@ -210,7 +171,7 @@ describe('e2e_authwit_tests', () => { const registry = await AuthRegistryContract.at(getCanonicalAuthRegistry().instance.address, wallets[1]); await registry.methods.consume(wallets[0].getAddress(), innerHash).send().wait(); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); @@ -219,23 +180,23 @@ describe('e2e_authwit_tests', () => { describe('failure case', () => { it('cancel before usage', async () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0x02')]); - const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), chainId, version, innerHash); + const intent = { consumer: auth.address, innerHash }; - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); - await wallets[0].setPublicAuthWit(outerHash, true).send().wait(); + await wallets[0].setPublicAuthWit(intent, true).send().wait(); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: true, }); - await wallets[0].cancelPublicAuthWit(outerHash).send().wait(); + await wallets[0].setPublicAuthWit(intent, false).send().wait(); - expect(await wallets[0].lookupValidity(wallets[0].getAddress(), outerHash)).toEqual({ + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ isValidInPrivate: false, isValidInPublic: false, }); 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 cf6cd9fdcb16..ddbcceaca4f7 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 @@ -38,7 +38,7 @@ describe('e2e_avm_simulator', () => { }); it('PXE processes failed assertions and fills in the error message with the expression (even complex ones)', async () => { await expect(avmContract.methods.assert_nullifier_exists(123).simulate()).rejects.toThrow( - "Assertion failed: Nullifier doesn't exist! 'context.nullifier_exists(nullifier, context.this_address())'", + "Assertion failed: Nullifier doesn't exist! 'context.nullifier_exists(nullifier, context.storage_address())'", ); }); }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts index 5e336d1b63db..6c6d95ab7be4 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/burn.test.ts @@ -194,10 +194,8 @@ describe('e2e_blacklist_token_contract burn', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(wallets[0].getAddress(), amount, nonce); const messageHash = computeAuthWitMessageHash( - wallets[1].getAddress(), - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: wallets[1].getAddress(), action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); await expect(action.prove()).rejects.toThrow(`Unknown auth witness for message hash ${messageHash.toString()}`); @@ -212,10 +210,8 @@ describe('e2e_blacklist_token_contract burn', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[2]).methods.burn(wallets[0].getAddress(), amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - wallets[2].getAddress(), - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: wallets[2].getAddress(), action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts index ac8176b9e68b..75f8c919badc 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/transfer_private.test.ts @@ -136,10 +136,8 @@ describe('e2e_blacklist_token_contract transfer private', () => { .withWallet(wallets[1]) .methods.transfer(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce); const messageHash = computeAuthWitMessageHash( - wallets[1].getAddress(), - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: wallets[1].getAddress(), action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); await expect(action.prove()).rejects.toThrow(`Unknown auth witness for message hash ${messageHash.toString()}`); @@ -156,10 +154,8 @@ describe('e2e_blacklist_token_contract transfer private', () => { .withWallet(wallets[2]) .methods.transfer(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - wallets[2].getAddress(), - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: wallets[2].getAddress(), action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); const witness = await wallets[0].createAuthWit({ caller: wallets[1].getAddress(), action }); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts index 8d11daf3c5e0..4d877859f53d 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract/unshielding.test.ts @@ -113,10 +113,8 @@ describe('e2e_blacklist_token_contract unshielding', () => { .withWallet(wallets[2]) .methods.unshield(wallets[0].getAddress(), wallets[1].getAddress(), amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - wallets[2].getAddress(), - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: wallets[2].getAddress(), action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); // Both wallets are connected to same node and PXE so we could just insert directly 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 4ba3f4990f06..f65ba985a725 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 @@ -201,10 +201,11 @@ describe('e2e_cross_chain_messaging', () => { const withdrawAmount = 9n; const nonce = Fr.random(); const expectedBurnMessageHash = computeAuthWitMessageHash( - l2Bridge.address, - user1Wallet.getChainId(), - user1Wallet.getVersion(), - l2Token.methods.burn(user1Wallet.getAddress(), withdrawAmount, nonce).request(), + { + caller: l2Bridge.address, + action: l2Token.methods.burn(user1Wallet.getAddress(), withdrawAmount, nonce).request(), + }, + { chainId: user1Wallet.getChainId(), version: user1Wallet.getVersion() }, ); // Should fail as owner has not given approval to bridge burn their funds. await expect( diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index 3455b0166f6d..02122e165d12 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -1,5 +1,6 @@ import { type AccountWalletWithSecretKey, type AztecNode, Fr, L1EventPayload, TaggedLog } from '@aztec/aztec.js'; import { deriveMasterIncomingViewingSecretKey } from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; import { type ExampleEvent0, type ExampleEvent1, TestLogContract } from '@aztec/noir-contracts.js'; @@ -30,30 +31,6 @@ describe('Logs', () => { afterAll(() => teardown()); describe('functionality around emitting an encrypted log', () => { - it('emits a generic encrypted log and checks for correctness', async () => { - const randomness = Fr.random(); - const eventTypeId = Fr.random(); - const preimage = makeTuple(6, Fr.random); - - const tx = await testLogContract.methods.emit_encrypted_log(randomness, eventTypeId, preimage).send().wait(); - - const txEffect = await node.getTxEffect(tx.txHash); - - const encryptedLogs = txEffect!.encryptedLogs.unrollLogs(); - expect(encryptedLogs.length).toBe(1); - - const decryptedLog = TaggedLog.decryptAsIncoming( - encryptedLogs[0], - deriveMasterIncomingViewingSecretKey(wallets[0].getSecretKey()), - L1EventPayload, - ); - - expect(decryptedLog?.payload.contractAddress).toStrictEqual(testLogContract.address); - expect(decryptedLog?.payload.randomness).toStrictEqual(randomness); - expect(decryptedLog?.payload.eventTypeId).toStrictEqual(eventTypeId); - expect(decryptedLog?.payload.event.items).toStrictEqual(preimage); - }); - it('emits multiple events as encrypted logs and decodes them', async () => { const randomness = makeTuple(2, Fr.random); const preimage = makeTuple(4, Fr.random); @@ -74,7 +51,7 @@ describe('Logs', () => { expect(decryptedLog0?.payload.contractAddress).toStrictEqual(testLogContract.address); expect(decryptedLog0?.payload.randomness).toStrictEqual(randomness[0]); expect(decryptedLog0?.payload.eventTypeId).toStrictEqual( - new Fr(0x00000000000000000000000000000000000000000000000000000000aa533f60), + EventSelector.fromField(new Fr(0x00000000000000000000000000000000000000000000000000000000aa533f60)), ); // We decode our event into the event type @@ -97,7 +74,7 @@ describe('Logs', () => { expect(decryptedLog1?.payload.contractAddress).toStrictEqual(testLogContract.address); expect(decryptedLog1?.payload.randomness).toStrictEqual(randomness[1]); expect(decryptedLog1?.payload.eventTypeId).toStrictEqual( - new Fr(0x00000000000000000000000000000000000000000000000000000000d1be0447), + EventSelector.fromField(new Fr(0x00000000000000000000000000000000000000000000000000000000d1be0447)), ); // We check our second event, which is a different type diff --git a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts index 160c49e6d2c6..dd0bb68635cf 100644 --- a/yarn-project/end-to-end/src/e2e_fees/failures.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/failures.test.ts @@ -4,9 +4,10 @@ import { Fr, type FunctionCall, FunctionSelector, + PrivateFeePaymentMethod, PublicFeePaymentMethod, TxStatus, - computeAuthWitMessageHash, + computeSecretHash, } from '@aztec/aztec.js'; import { Gas, GasSettings } from '@aztec/circuits.js'; import { FunctionType } from '@aztec/foundation/abi'; @@ -35,6 +36,99 @@ describe('e2e_fees failures', () => { await t.teardown(); }); + it('reverts transactions but still pays fees using PrivateFeePaymentMethod', async () => { + const OutrageousPublicAmountAliceDoesNotHave = BigInt(1e8); + const PrivateMintedAlicePrivateBananas = BigInt(1e15); + + const [initialAlicePrivateBananas, initialFPCPrivateBananas] = await t.bananaPrivateBalances( + aliceAddress, + bananaFPC.address, + ); + const [initialAlicePublicBananas, initialFPCPublicBananas] = await t.bananaPublicBalances( + aliceAddress, + bananaFPC.address, + ); + const [initialAliceGas, initialFPCGas] = await t.gasBalances(aliceAddress, bananaFPC.address); + + await t.mintPrivateBananas(PrivateMintedAlicePrivateBananas, aliceAddress); + + // if we simulate locally, it throws an error + await expect( + bananaCoin.methods + // still use a public transfer so as to fail in the public app logic phase + .transfer_public(aliceAddress, sequencerAddress, OutrageousPublicAmountAliceDoesNotHave, 0) + .send({ + fee: { + gasSettings, + paymentMethod: new PrivateFeePaymentMethod(bananaCoin.address, bananaFPC.address, aliceWallet), + }, + }) + .wait(), + ).rejects.toThrow(/attempt to subtract with underflow 'hi == high'/); + + // we did not pay the fee, because we did not submit the TX + await expectMapping( + t.bananaPrivateBalances, + [aliceAddress, bananaFPC.address], + [initialAlicePrivateBananas + PrivateMintedAlicePrivateBananas, initialFPCPrivateBananas], + ); + await expectMapping( + t.bananaPublicBalances, + [aliceAddress, bananaFPC.address], + [initialAlicePublicBananas, initialFPCPublicBananas], + ); + await expectMapping(t.gasBalances, [aliceAddress, bananaFPC.address], [initialAliceGas, initialFPCGas]); + + // if we skip simulation, it includes the failed TX + const rebateSecret = Fr.random(); + const currentSequencerL1Gas = await t.getCoinbaseBalance(); + const txReceipt = await bananaCoin.methods + .transfer_public(aliceAddress, sequencerAddress, OutrageousPublicAmountAliceDoesNotHave, 0) + .send({ + skipPublicSimulation: true, + fee: { + gasSettings, + paymentMethod: new PrivateFeePaymentMethod(bananaCoin.address, bananaFPC.address, aliceWallet, rebateSecret), + }, + }) + .wait({ dontThrowOnRevert: true }); + + expect(txReceipt.status).toBe(TxStatus.APP_LOGIC_REVERTED); + const feeAmount = txReceipt.transactionFee!; + const newSequencerL1Gas = await t.getCoinbaseBalance(); + expect(newSequencerL1Gas).toEqual(currentSequencerL1Gas + feeAmount); + + // and thus we paid the fee + await expectMapping( + t.bananaPrivateBalances, + [aliceAddress, bananaFPC.address], + [ + // alice paid the maximum amount in private bananas + initialAlicePrivateBananas + PrivateMintedAlicePrivateBananas - gasSettings.getFeeLimit().toBigInt(), + initialFPCPrivateBananas, + ], + ); + await expectMapping( + t.bananaPublicBalances, + [aliceAddress, bananaFPC.address], + [initialAlicePublicBananas, initialFPCPublicBananas + feeAmount], + ); + await expectMapping(t.gasBalances, [aliceAddress, bananaFPC.address], [initialAliceGas, initialFPCGas - feeAmount]); + + // Alice can redeem her shield to get the rebate + const refund = gasSettings.getFeeLimit().toBigInt() - feeAmount; + expect(refund).toBeGreaterThan(0n); + const secretHashForRebate = computeSecretHash(rebateSecret); + await t.addPendingShieldNoteToPXE(t.aliceWallet, refund, secretHashForRebate, txReceipt.txHash); + await bananaCoin.methods.redeem_shield(aliceAddress, refund, rebateSecret).send().wait(); + + await expectMapping( + t.bananaPrivateBalances, + [aliceAddress, bananaFPC.address], + [initialAlicePrivateBananas + PrivateMintedAlicePrivateBananas - feeAmount, initialFPCPrivateBananas], + ); + }); + it('reverts transactions but still pays fees using PublicFeePaymentMethod', async () => { const OutrageousPublicAmountAliceDoesNotHave = BigInt(1e15); const PublicMintedAlicePublicBananas = BigInt(1e12); @@ -115,9 +209,6 @@ describe('e2e_fees failures', () => { [aliceAddress, bananaFPC.address, sequencerAddress], [initialAliceGas, initialFPCGas - feeAmount, initialSequencerGas], ); - - // TODO(#4712) - demonstrate reverts with the PrivateFeePaymentMethod. - // Can't do presently because all logs are "revertible" so we lose notes that get broadcasted during unshielding. }); it('fails transaction that error in setup', async () => { @@ -234,25 +325,27 @@ class BuggedSetupFeePaymentMethod extends PublicFeePaymentMethod { override getFunctionCalls(gasSettings: GasSettings): Promise { const maxFee = gasSettings.getFeeLimit(); const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - this.paymentContract, - this.wallet.getChainId(), - this.wallet.getVersion(), - { - name: 'transfer_public', - args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], - selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), - type: FunctionType.PUBLIC, - isStatic: false, - to: this.asset, - returnTypes: [], - }, - ); const tooMuchFee = new Fr(maxFee.toBigInt() * 2n); return Promise.resolve([ - this.wallet.setPublicAuthWit(messageHash, true).request(), + this.wallet + .setPublicAuthWit( + { + caller: this.paymentContract, + action: { + name: 'transfer_public', + args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce], + selector: FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'), + type: FunctionType.PUBLIC, + isStatic: false, + to: this.asset, + returnTypes: [], + }, + }, + true, + ) + .request(), { name: 'fee_entrypoint_public', to: this.paymentContract, diff --git a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts index 7e22eecf3585..9d1c00079311 100644 --- a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts @@ -5,7 +5,6 @@ import { ExtendedNote, Fr, Note, - computeAuthWitMessageHash, computeSecretHash, } from '@aztec/aztec.js'; import { LendingContract, PriceFeedContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -320,17 +319,19 @@ describe('e2e_lending_contract', () => { it('Repay: 🍌 -> 🏦', async () => { const repayAmount = 20n; - const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - wallet.getChainId(), - wallet.getVersion(), - stableCoin.methods.burn_public(lendingAccount.address, repayAmount, nonce).request(), - ); // Add it to the wallet as approved - await wallet.setPublicAuthWit(messageHash, true).send().wait(); + await wallet + .setPublicAuthWit( + { + caller: lendingContract.address, + action: stableCoin.methods.burn_public(lendingAccount.address, repayAmount, nonce).request(), + }, + true, + ) + .send() + .wait(); await lendingSim.progressTime(TIME_JUMP); lendingSim.repayPublic(lendingAccount.address, lendingAccount.address.toField(), repayAmount); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 42a5f26cb8bb..024857ab6e27 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -13,6 +13,7 @@ import { } from '@aztec/aztec.js'; import { type BootNodeConfig, BootstrapNode, createLibP2PPeerId } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import fs from 'fs'; import { mnemonicToAccount } from 'viem/accounts'; @@ -203,7 +204,11 @@ describe('e2e_p2p_network', () => { dataDirectory, bootstrapNodes: bootstrapNode ? [bootstrapNode] : [], }; - return await AztecNodeService.createAndSync(newConfig, createDebugLogger(`aztec:node-${tcpListenPort}`)); + return await AztecNodeService.createAndSync( + newConfig, + new NoopTelemetryClient(), + createDebugLogger(`aztec:node-${tcpListenPort}`), + ); }; // creates an instance of the PXE and submit a given number of transactions to it. diff --git a/yarn-project/end-to-end/src/e2e_prover/full.test.ts b/yarn-project/end-to-end/src/e2e_prover/full.test.ts index bbc1c8b74044..485c6d3d8479 100644 --- a/yarn-project/end-to-end/src/e2e_prover/full.test.ts +++ b/yarn-project/end-to-end/src/e2e_prover/full.test.ts @@ -60,8 +60,8 @@ describe('full_prover', () => { logger.info(`Verifying private kernel tail proof`); await expect(t.circuitProofVerifier?.verifyProof(privateTx)).resolves.not.toThrow(); - const sentPrivateTx = privateInteraction.send(); - const sentPublicTx = publicInteraction.send(); + const sentPrivateTx = privateInteraction.send({ skipPublicSimulation: true }); + const sentPublicTx = publicInteraction.send({ skipPublicSimulation: true }); await Promise.all([ sentPrivateTx.wait({ timeout: 1200, interval: 10 }), sentPublicTx.wait({ timeout: 1200, interval: 10 }), diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/deposits.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/deposits.test.ts index 306e9e7bb06b..60e6edc6c3f8 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/deposits.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging/deposits.test.ts @@ -1,4 +1,4 @@ -import { Fr, computeAuthWitMessageHash } from '@aztec/aztec.js'; +import { Fr } from '@aztec/aztec.js'; import { NO_L1_TO_L2_MSG_ERROR } from '../fixtures/fixtures.js'; import { PublicCrossChainMessagingContractTest } from './public_cross_chain_messaging_contract_test.js'; @@ -7,7 +7,6 @@ describe('e2e_public_cross_chain_messaging deposits', () => { const t = new PublicCrossChainMessagingContractTest('deposits'); let { - wallets, crossChainTestHarness, ethAccount, aztecNode, @@ -23,7 +22,7 @@ describe('e2e_public_cross_chain_messaging deposits', () => { await t.applyBaseSnapshots(); await t.setup(); // Have to destructure again to ensure we have latest refs. - ({ wallets, crossChainTestHarness, user1Wallet, user2Wallet } = t); + ({ crossChainTestHarness, user1Wallet, user2Wallet } = t); ethAccount = crossChainTestHarness.ethAccount; aztecNode = crossChainTestHarness.aztecNode; @@ -75,13 +74,16 @@ describe('e2e_public_cross_chain_messaging deposits', () => { // 4. Give approval to bridge to burn owner's funds: const withdrawAmount = 9n; const nonce = Fr.random(); - const burnMessageHash = computeAuthWitMessageHash( - l2Bridge.address, - wallets[0].getChainId(), - wallets[0].getVersion(), - l2Token.methods.burn_public(ownerAddress, withdrawAmount, nonce).request(), - ); - await user1Wallet.setPublicAuthWit(burnMessageHash, true).send().wait(); + await user1Wallet + .setPublicAuthWit( + { + caller: l2Bridge.address, + action: l2Token.methods.burn_public(ownerAddress, withdrawAmount, nonce).request(), + }, + true, + ) + .send() + .wait(); // 5. Withdraw owner's funds from L2 to L1 logger.verbose('5. Withdraw owner funds from L2 to L1'); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts index f736b47a64c0..1c89c74ac204 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/burn.test.ts @@ -187,10 +187,8 @@ describe('e2e_token_contract burn', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce); const messageHash = computeAuthWitMessageHash( - accounts[1].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: accounts[1].address, action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); await expect(action.simulate()).rejects.toThrow( @@ -207,10 +205,8 @@ describe('e2e_token_contract burn', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[2]).methods.burn(accounts[0].address, amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - accounts[2].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: accounts[2].address, action: action.request() }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts index a85f2de98fe6..4d1536e4df41 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts @@ -1,4 +1,10 @@ -import { AztecAddress, CompleteAddress, Fr, computeAuthWitMessageHash } from '@aztec/aztec.js'; +import { + AztecAddress, + CompleteAddress, + Fr, + computeAuthWitMessageHash, + computeInnerAuthWitHashFromAction, +} from '@aztec/aztec.js'; import { DUPLICATE_NULLIFIER_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -147,10 +153,11 @@ describe('e2e_token_contract transfer private', () => { .withWallet(wallets[1]) .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce); const messageHash = computeAuthWitMessageHash( - accounts[1].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: accounts[1].address, action: action.request() }, + { + chainId: wallets[0].getChainId(), + version: wallets[0].getVersion(), + }, ); await expect(action.simulate()).rejects.toThrow( @@ -169,10 +176,11 @@ describe('e2e_token_contract transfer private', () => { .withWallet(wallets[2]) .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - accounts[2].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: accounts[2].address, action: action.request() }, + { + chainId: wallets[0].getChainId(), + version: wallets[0].getVersion(), + }, ); const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); @@ -195,44 +203,33 @@ describe('e2e_token_contract transfer private', () => { .withWallet(wallets[1]) .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce); - const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); - await wallets[1].addAuthWitness(witness); - - await wallets[0].cancelAuthWit(witness.requestHash).send().wait(); - - // Perform the transfer, should fail because nullifier already emitted - const txCancelledAuthwit = asset - .withWallet(wallets[1]) - .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce) - .send(); - await expect(txCancelledAuthwit.wait()).rejects.toThrowError(DUPLICATE_NULLIFIER_ERROR); - }); + const intent = { caller: accounts[1].address, action }; - it('transfer on behalf of other, cancelled authwit, flow 2', async () => { - const balance0 = await asset.methods.balance_of_private(accounts[0].address).simulate(); - const amount = balance0 / 2n; - const nonce = Fr.random(); - expect(amount).toBeGreaterThan(0n); + const witness = await wallets[0].createAuthWit(intent); + await wallets[1].addAuthWitness(witness); - // We need to compute the message we want to sign and add it to the wallet as approved - const action = asset - .withWallet(wallets[1]) - .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce); + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ + isValidInPrivate: true, + isValidInPublic: false, + }); - const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); - await wallets[1].addAuthWitness(witness); + const innerHash = computeInnerAuthWitHashFromAction(accounts[1].address, action.request()); + await asset.withWallet(wallets[0]).methods.cancel_authwit(innerHash).send().wait(); - await wallets[0].cancelAuthWit({ caller: accounts[1].address, action }).send().wait(); + expect(await wallets[0].lookupValidity(wallets[0].getAddress(), intent)).toEqual({ + isValidInPrivate: false, + isValidInPublic: false, + }); // Perform the transfer, should fail because nullifier already emitted const txCancelledAuthwit = asset .withWallet(wallets[1]) .methods.transfer_from(accounts[0].address, accounts[1].address, amount, nonce) .send(); - await expect(txCancelledAuthwit.wait()).rejects.toThrow(DUPLICATE_NULLIFIER_ERROR); + await expect(txCancelledAuthwit.wait()).rejects.toThrowError(DUPLICATE_NULLIFIER_ERROR); }); - it('transfer on behalf of other, invalid spend_private_authwit on "from"', async () => { + it('transfer on behalf of other, invalid verify_private_authwit on "from"', async () => { const nonce = Fr.random(); // Should fail as the returned value from the badAccount is malformed diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts index c828a6bdb158..5ba38158564b 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_public.test.ts @@ -1,4 +1,4 @@ -import { Fr, computeAuthWitMessageHash } from '@aztec/aztec.js'; +import { Fr } from '@aztec/aztec.js'; import { U128_UNDERFLOW_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -188,7 +188,7 @@ describe('e2e_token_contract transfer public', () => { await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); - await wallets[0].cancelPublicAuthWit({ caller: accounts[1].address, action }).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, false).send().wait(); await expect( asset @@ -212,40 +212,7 @@ describe('e2e_token_contract transfer public', () => { await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, false).send().wait(); - await expect( - asset - .withWallet(wallets[1]) - .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce) - .simulate(), - ).rejects.toThrowError(/unauthorized/); - }); - - it('transfer on behalf of other, cancelled authwit, flow 3', async () => { - const balance0 = await asset.methods.balance_of_public(accounts[0].address).simulate(); - const amount = balance0 / 2n; - expect(amount).toBeGreaterThan(0n); - const nonce = Fr.random(); - - const action = asset - .withWallet(wallets[1]) - .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash( - accounts[1].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), - ); - - await wallets[0].setPublicAuthWit(messageHash, true).send().wait(); - - await wallets[0].cancelPublicAuthWit(messageHash).send().wait(); - - await expect( - asset - .withWallet(wallets[1]) - .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce) - .simulate(), - ).rejects.toThrow(/unauthorized/); + await expect(action.simulate()).rejects.toThrow(/unauthorized/); }); it('transfer on behalf of other, invalid spend_public_authwit on "from"', async () => { diff --git a/yarn-project/end-to-end/src/e2e_token_contract/unshielding.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/unshielding.test.ts index d52b3ce214e4..6507f4aeecad 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/unshielding.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/unshielding.test.ts @@ -111,10 +111,8 @@ describe('e2e_token_contract unshielding', () => { .withWallet(wallets[2]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); const expectedMessageHash = computeAuthWitMessageHash( - accounts[2].address, - wallets[0].getChainId(), - wallets[0].getVersion(), - action.request(), + { caller: accounts[2].address, action }, + { chainId: wallets[0].getChainId(), version: wallets[0].getVersion() }, ); // Both wallets are connected to same node and PXE so we could just insert directly diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index c897648c62cf..fc985e66290c 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -20,6 +20,7 @@ import { type Logger, createDebugLogger } from '@aztec/foundation/log'; import { makeBackoff, retry } from '@aztec/foundation/retry'; import { resolver, reviver } from '@aztec/foundation/serialize'; import { type PXEService, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; +import { createAndStartTelemetryClient, getConfigEnvVars as getTelemetryConfig } from '@aztec/telemetry-client/start'; import { type Anvil, createAnvil } from '@viem/anvil'; import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'; @@ -270,8 +271,9 @@ async function setupFromFresh(statePath: string | undefined, logger: Logger): Pr aztecNodeConfig.bbWorkingDirectory = bbConfig.bbWorkingDirectory; } + const telemetry = createAndStartTelemetryClient(getTelemetryConfig()); logger.verbose('Creating and synching an aztec node...'); - const aztecNode = await AztecNodeService.createAndSync(aztecNodeConfig); + const aztecNode = await AztecNodeService.createAndSync(aztecNodeConfig, telemetry); logger.verbose('Creating pxe...'); const pxeConfig = getPXEServiceConfig(); @@ -343,7 +345,8 @@ async function setupFromState(statePath: string, logger: Logger): Promise { + await telemetry.stop(); + }); +} + const getAztecUrl = () => { return PXE_URL; }; @@ -369,7 +377,7 @@ export async function setup( config.bbWorkingDirectory = bbConfig.bbWorkingDirectory; } config.l1BlockPublishRetryIntervalMS = 100; - const aztecNode = await AztecNodeService.createAndSync(config); + const aztecNode = await AztecNodeService.createAndSync(config, telemetry); const sequencer = aztecNode.getSequencer(); const prover = aztecNode.getProver(); diff --git a/yarn-project/end-to-end/src/shared/browser.ts b/yarn-project/end-to-end/src/shared/browser.ts index 86e10d417863..143698eb9967 100644 --- a/yarn-project/end-to-end/src/shared/browser.ts +++ b/yarn-project/end-to-end/src/shared/browser.ts @@ -145,14 +145,14 @@ export const browserTestSuite = ( it('Can access CompleteAddress class in browser', async () => { const result: string = await page.evaluate(() => { const completeAddress = window.AztecJs.CompleteAddress.fromString( - '0x06f73ae2ba011a157808a670dd52231347a3b46897ea00945d69fb35d08e68d02c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', + '0x0f4b920040c48062d5cd72f0f1b6f331468940ab8651420de8080dfc7fa0f3dc2c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', ); // NOTE: browser does not know how to serialize CompleteAddress for return, so return a string // otherwise returning a CompleteAddress makes result undefined. return completeAddress.toString(); }); expect(result).toBe( - '0x06f73ae2ba011a157808a670dd52231347a3b46897ea00945d69fb35d08e68d02c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', + '0x0f4b920040c48062d5cd72f0f1b6f331468940ab8651420de8080dfc7fa0f3dc2c93b9572b35f9c9e07e9003ae1ca444442a165f927bce00e347dab57cc19391148730d0deec722eb6c54747df7345bc2ab3bd8e81f438b17b81ccabd9e6a3ac0708920251ccaf6664d769cbc47c8d767f64912639e13d9f9e441b225066161900c48a65eea83f1dbf217c43daf1be6ba9cefd2754f07e3cc13e81e5432e47f30dfb47c8b1e11368bec638fd9d22c696bf9c323a0fd09050745f4b7cf150bfa529a9f3062ee5f9d0a099ac53b4e1130653fb797ed2b59914a8915951d13ad8252521211957a854707af85ad40e9ab4d474a4fcbdcbe7a47866cae0db4fd86ed2261669d85a9cfbd09365a6db5d7acfe5560104a0cb893a375d6c08ffb9cbb8270be446a16361f271ac11899ee19f990c68035da18703ba00c8e9773dfe6a784a', ); }); 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 f62fa9bc3c56..6caf5b594829 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 @@ -425,15 +425,24 @@ export const uniswapL1L2TestSuite = ( // 3. Owner gives uniswap approval to transfer funds on its behalf const nonceForWETHTransferApproval = new Fr(1n); - const transferMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - wethCrossChainHarness.l2Token.methods - .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) - .request(), - ); - await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); + + await ownerWallet + .setPublicAuthWit( + { + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods + .transfer_public( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHTransferApproval, + ) + .request(), + }, + true, + ) + .send() + .wait(); // 4. Swap on L1 - sends L2 to L1 message to withdraw WETH to L1 and another message to swap assets. const [secretForDepositingSwappedDai, secretHashForDepositingSwappedDai] = @@ -456,13 +465,7 @@ export const uniswapL1L2TestSuite = ( ownerEthAddress, nonceForSwap, ); - const swapMessageHash = computeAuthWitMessageHash( - sponsorAddress, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - action.request(), - ); - await ownerWallet.setPublicAuthWit(swapMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit({ caller: sponsorAddress, action }, true).send().wait(); // 4.2 Call swap_public from user2 on behalf of owner const uniswapL2Interaction = await action.send().wait(); @@ -619,13 +622,13 @@ export const uniswapL1L2TestSuite = ( const nonceForWETHUnshieldApproval = new Fr(2n); const expectedMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - - wethCrossChainHarness.l2Token.methods - .unshield(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHUnshieldApproval) - .request(), + { + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods + .unshield(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHUnshieldApproval) + .request(), + }, + { chainId: ownerWallet.getChainId(), version: ownerWallet.getVersion() }, ); await expect( @@ -694,16 +697,23 @@ export const uniswapL1L2TestSuite = ( // 2. Give approval to uniswap to transfer funds to itself const nonceForWETHTransferApproval = new Fr(2n); - const transferMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - - wethCrossChainHarness.l2Token.methods - .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) - .request(), - ); - await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); + await ownerWallet + .setPublicAuthWit( + { + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods + .transfer_public( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHTransferApproval, + ) + .request(), + }, + true, + ) + .send() + .wait(); // No approval to call `swap` but should work even without it: const [_, secretHashForDepositingSwappedDai] = daiCrossChainHarness.generateClaimSecret(); @@ -750,13 +760,7 @@ export const uniswapL1L2TestSuite = ( ownerEthAddress, nonceForSwap, ); - const swapMessageHash = computeAuthWitMessageHash( - approvedUser, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - action.request(), - ); - await ownerWallet.setPublicAuthWit(swapMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit({ caller: approvedUser, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrow(/unauthorized/); }); @@ -765,15 +769,23 @@ export const uniswapL1L2TestSuite = ( // swap should fail since no transfer approval to uniswap: const nonceForWETHTransferApproval = new Fr(4n); - const transferMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - wethCrossChainHarness.l2Token.methods - .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) - .request(), - ); - await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); + await ownerWallet + .setPublicAuthWit( + { + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods + .transfer_public( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHTransferApproval, + ) + .request(), + }, + true, + ) + .send() + .wait(); await expect( uniswapL2Contract.methods @@ -931,15 +943,23 @@ export const uniswapL1L2TestSuite = ( // Owner gives uniswap approval to transfer funds on its behalf const nonceForWETHTransferApproval = new Fr(5n); - const transferMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - ownerWallet.getChainId(), - ownerWallet.getVersion(), - wethCrossChainHarness.l2Token.methods - .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) - .request(), - ); - await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); + await ownerWallet + .setPublicAuthWit( + { + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods + .transfer_public( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHTransferApproval, + ) + .request(), + }, + true, + ) + .send() + .wait(); // Call swap_public on L2 const secretHashForDepositingSwappedDai = Fr.random(); diff --git a/yarn-project/end-to-end/tsconfig.json b/yarn-project/end-to-end/tsconfig.json index 7273cee65f5d..28bde215732e 100644 --- a/yarn-project/end-to-end/tsconfig.json +++ b/yarn-project/end-to-end/tsconfig.json @@ -66,6 +66,9 @@ { "path": "../simulator" }, + { + "path": "../telemetry-client" + }, { "path": "../types" }, diff --git a/yarn-project/end-to-end/webpack.config.js b/yarn-project/end-to-end/webpack.config.js index 6fe97604e7e2..88f6bb5178c1 100644 --- a/yarn-project/end-to-end/webpack.config.js +++ b/yarn-project/end-to-end/webpack.config.js @@ -64,7 +64,6 @@ export default { buffer: require.resolve('buffer/'), util: require.resolve('util/'), stream: require.resolve('stream-browserify'), - tty: require.resolve('tty-browserify'), }, }, }; diff --git a/yarn-project/entrypoints/package.json b/yarn-project/entrypoints/package.json index 63470f197896..48c6c5535a49 100644 --- a/yarn-project/entrypoints/package.json +++ b/yarn-project/entrypoints/package.json @@ -35,7 +35,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/entrypoints/src/dapp_entrypoint.ts b/yarn-project/entrypoints/src/dapp_entrypoint.ts index 18a217f2eda4..f680cb26e28e 100644 --- a/yarn-project/entrypoints/src/dapp_entrypoint.ts +++ b/yarn-project/entrypoints/src/dapp_entrypoint.ts @@ -1,4 +1,4 @@ -import { computeInnerAuthWitHash, computeOuterAuthWitHash } from '@aztec/aztec.js'; +import { computeAuthWitMessageHash, computeInnerAuthWitHash } from '@aztec/aztec.js'; import { type AuthWitnessProvider } from '@aztec/aztec.js/account'; import { type EntrypointInterface, EntrypointPayload, type ExecutionRequestInit } from '@aztec/aztec.js/entrypoint'; import { PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; @@ -34,11 +34,9 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const functionSelector = FunctionSelector.fromNameAndParameters(abi.name, abi.parameters); const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionSelector.toField(), entrypointPackedArgs.hash]); - const outerHash = computeOuterAuthWitHash( - this.dappEntrypointAddress, - new Fr(this.chainId), - new Fr(this.version), - innerHash, + const outerHash = computeAuthWitMessageHash( + { consumer: this.dappEntrypointAddress, innerHash }, + { chainId: new Fr(this.chainId), version: new Fr(this.version) }, ); const authWitness = await this.userAuthWitnessProvider.createAuthWit(outerHash); diff --git a/yarn-project/ethereum/package.json b/yarn-project/ethereum/package.json index efd72f2d3da2..b7518c9547fe 100644 --- a/yarn-project/ethereum/package.json +++ b/yarn-project/ethereum/package.json @@ -51,7 +51,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/foundation/.prettierrc.json b/yarn-project/foundation/.prettierrc.json index 0f8d94093a89..b39dea73e431 100644 --- a/yarn-project/foundation/.prettierrc.json +++ b/yarn-project/foundation/.prettierrc.json @@ -6,5 +6,5 @@ "importOrder": ["^@aztec/(.*)$", "", "^\\./|\\.\\./"], "importOrderSeparation": true, "importOrderSortSpecifiers": true, - "importOrderParserPlugins": ["importAssertions", "typescript"] + "importOrderParserPlugins": ["importAssertions", "typescript", "decorators"] } diff --git a/yarn-project/foundation/package.json b/yarn-project/foundation/package.json index ec8d34c34800..17295e60f261 100644 --- a/yarn-project/foundation/package.json +++ b/yarn-project/foundation/package.json @@ -59,7 +59,15 @@ "jest": { "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "moduleNameMapper": { diff --git a/yarn-project/foundation/src/abi/abi.ts b/yarn-project/foundation/src/abi/abi.ts index 2b6080866042..9e996fc4249b 100644 --- a/yarn-project/foundation/src/abi/abi.ts +++ b/yarn-project/foundation/src/abi/abi.ts @@ -2,6 +2,7 @@ import { inflate } from 'pako'; import { type Fr } from '../fields/fields.js'; import { type FunctionSelector } from './function_selector.js'; +import { type NoteSelector } from './note_selector.js'; /** * A basic value. @@ -275,7 +276,7 @@ export type ContractNote = { /** * Note identifier */ - id: Fr; + id: NoteSelector; /** * Type of the note (e.g., 'TransparentNote') */ diff --git a/yarn-project/foundation/src/abi/index.ts b/yarn-project/foundation/src/abi/index.ts index 476d3da88506..cab81b750c49 100644 --- a/yarn-project/foundation/src/abi/index.ts +++ b/yarn-project/foundation/src/abi/index.ts @@ -1,7 +1,8 @@ export * from './abi.js'; export * from './buffer.js'; +export * from './decoder.js'; export * from './encoder.js'; export * from './event_selector.js'; -export * from './decoder.js'; export * from './function_selector.js'; +export * from './note_selector.js'; export * from './utils.js'; diff --git a/yarn-project/foundation/src/abi/note_selector.ts b/yarn-project/foundation/src/abi/note_selector.ts new file mode 100644 index 000000000000..392399f7ee1c --- /dev/null +++ b/yarn-project/foundation/src/abi/note_selector.ts @@ -0,0 +1,73 @@ +import { toBigIntBE } from '../bigint-buffer/index.js'; +import { randomBytes } from '../crypto/index.js'; +import { type Fr } from '../fields/fields.js'; +import { BufferReader } from '../serialize/buffer_reader.js'; +import { TypeRegistry } from '../serialize/type_registry.js'; +import { Selector } from './selector.js'; + +/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */ + +/** Note selector branding */ +export interface NoteSelector { + /** Brand. */ + _branding: 'NoteSelector'; +} + +/** A note selector is the first 4 bytes of the hash of a note signature. */ +export class NoteSelector extends Selector { + /** + * Deserializes from a buffer or reader, corresponding to a write in cpp. + * @param buffer - Buffer or BufferReader to read from. + * @returns The Selector. + */ + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + const value = Number(toBigIntBE(reader.readBytes(Selector.SIZE))); + return new NoteSelector(value); + } + + static fromString(buf: string) { + const withoutPrefix = buf.replace(/^0x/i, ''); + const buffer = Buffer.from(withoutPrefix, 'hex'); + return NoteSelector.fromBuffer(buffer); + } + + /** + * Converts a field to selector. + * @param fr - The field to convert. + * @returns The selector. + */ + static fromField(fr: Fr) { + return new NoteSelector(Number(fr.toBigInt())); + } + + /** + * Creates an empty selector. + * @returns An empty selector. + */ + static empty() { + return new NoteSelector(0); + } + + /** + * Creates a random selector. + * @returns A random selector. + */ + static random() { + return NoteSelector.fromBuffer(randomBytes(Selector.SIZE)); + } + + toJSON() { + return { + type: 'NoteSelector', + value: this.toString(), + }; + } + + static fromJSON(json: any): NoteSelector { + return NoteSelector.fromString(json.value); + } +} + +// For deserializing JSON. +TypeRegistry.register('NoteSelector', NoteSelector); diff --git a/yarn-project/foundation/src/crypto/random/randomness_singleton.ts b/yarn-project/foundation/src/crypto/random/randomness_singleton.ts index 667db265df16..f226874a9216 100644 --- a/yarn-project/foundation/src/crypto/random/randomness_singleton.ts +++ b/yarn-project/foundation/src/crypto/random/randomness_singleton.ts @@ -18,10 +18,10 @@ export class RandomnessSingleton { private readonly log = createDebugLogger('aztec:randomness_singleton'), ) { if (seed !== undefined) { - this.log.verbose(`Using pseudo-randomness with seed: ${seed}`); + this.log.debug(`Using pseudo-randomness with seed: ${seed}`); this.counter = seed; } else { - this.log.verbose('Using true randomness'); + this.log.debug('Using true randomness'); } } diff --git a/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts b/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts index 9c342805d091..60d07291cc06 100644 --- a/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts +++ b/yarn-project/foundation/src/json-rpc/server/json_rpc_server.ts @@ -25,7 +25,7 @@ export class JsonRpcServer { private objectClassMap: JsonClassConverterInput, /** List of methods to disallow from calling remotely */ public readonly disallowedMethods: string[] = [], - private log = createDebugLogger('aztec:foundation:json-rpc:server'), + private log = createDebugLogger('json-rpc:server'), ) { this.proxy = new JsonProxy(handler, stringClassMap, objectClassMap); } @@ -226,7 +226,7 @@ export type ServerList = { */ export function createNamespacedJsonRpcServer( servers: ServerList, - log = createDebugLogger('aztec:foundation:json-rpc:multi-server'), + log = createDebugLogger('json-rpc:multi-server'), ): JsonRpcServer { const handler = {} as any; const disallowedMethods: string[] = []; diff --git a/yarn-project/foundation/src/log/logger.ts b/yarn-project/foundation/src/log/logger.ts index b2cfbc31b39e..3b28a279d2ca 100644 --- a/yarn-project/foundation/src/log/logger.ts +++ b/yarn-project/foundation/src/log/logger.ts @@ -1,6 +1,4 @@ import debug from 'debug'; -import isNode from 'detect-node'; -import { isatty } from 'tty'; import { type LogData, type LogFn } from './log_fn.js'; @@ -15,6 +13,9 @@ export type LogLevel = (typeof LogLevels)[number]; const envLogLevel = process.env.LOG_LEVEL?.toLowerCase() as LogLevel; const currentLevel = LogLevels.includes(envLogLevel) ? envLogLevel : DefaultLogLevel; +const namespaces = process.env.DEBUG ?? 'aztec:*'; +debug.enable(namespaces); + /** Log function that accepts an exception object */ type ErrorLogFn = (msg: string, err?: Error | unknown, data?: LogData) => void; @@ -38,9 +39,6 @@ export type DebugLogger = Logger; */ export function createDebugLogger(name: string): DebugLogger { const debugLogger = debug(name); - if (currentLevel === 'debug') { - debugLogger.enabled = true; - } const logger = { silent: () => {}, @@ -78,42 +76,11 @@ function logWithDebug(debug: debug.Debugger, level: LogLevel, msg: string, data? } msg = data ? `${msg} ${fmtLogData(data)}` : msg; - if (debug.enabled) { - if (level !== 'debug') { - msg = `${level.toUpperCase()} ${msg}`; - } - debug(msg); - } else if (LogLevels.indexOf(level) <= LogLevels.indexOf(currentLevel)) { - printLog(`${getPrefix(debug, level)} ${msg}`); + if (debug.enabled && LogLevels.indexOf(level) <= LogLevels.indexOf(currentLevel)) { + debug('[%s] %s', level.toUpperCase(), msg); } } -/** - * Returns a log prefix that emulates that of npm debug. Uses colors if in node and in a tty. - * @param debugLogger - Instance of npm debug logger. - * @param level - Intended log level (printed out if strictly above current log level). - * @returns Log prefix. - */ -function getPrefix(debugLogger: debug.Debugger, level: LogLevel) { - const levelLabel = currentLevel !== level ? ` ${level.toUpperCase()}` : ''; - const prefix = `${debugLogger.namespace.replace(/^aztec:/, '')}${levelLabel}`; - if ((!isNode || !isatty(process.stderr.fd)) && !process.env.DEBUG_COLORS) { - return prefix; - } - const colorIndex = debug.selectColor(debugLogger.namespace) as number; - const colorCode = '\u001B[3' + (colorIndex < 8 ? colorIndex : '8;5;' + colorIndex); - return ` ${colorCode};1m${prefix}\u001B[0m`; -} - -/** - * Outputs to console error. - * @param msg - What to log. - */ -function printLog(msg: string) { - // eslint-disable-next-line no-console - isNode ? process.stderr.write(msg + '\n') : console.error(msg); -} - /** * Concatenates a log message and an exception. * @param msg - Log message diff --git a/yarn-project/foundation/src/serialize/buffer_reader.test.ts b/yarn-project/foundation/src/serialize/buffer_reader.test.ts index f600942aba9f..0845ff591e29 100644 --- a/yarn-project/foundation/src/serialize/buffer_reader.test.ts +++ b/yarn-project/foundation/src/serialize/buffer_reader.test.ts @@ -173,4 +173,72 @@ describe('buffer reader', () => { expect(bufferReader.peekBytes(10)).toEqual(Buffer.from(ARRAY.slice(0, 10))); }); }); + + describe('error handling', () => { + let smallBuffer: Buffer; + let smallBufferReader: BufferReader; + + beforeEach(() => { + smallBuffer = Buffer.from([1, 2, 3]); // 3-byte buffer + smallBufferReader = new BufferReader(smallBuffer); + }); + + it('should throw error when reading number beyond buffer length', () => { + expect(() => smallBufferReader.readNumber()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading numbers beyond buffer length', () => { + expect(() => smallBufferReader.readNumbers(1)).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading UInt16 beyond buffer length', () => { + smallBufferReader.readBytes(2); + expect(() => smallBufferReader.readUInt16()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading UInt8 beyond buffer length', () => { + smallBufferReader.readBytes(3); // Read all bytes + expect(() => smallBufferReader.readUInt8()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading boolean beyond buffer length', () => { + smallBufferReader.readBytes(3); // Read all bytes + expect(() => smallBufferReader.readBoolean()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading bytes beyond buffer length', () => { + expect(() => smallBufferReader.readBytes(4)).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading buffer beyond buffer length', () => { + // First, read a number (4 bytes) which is already beyond the buffer length + expect(() => smallBufferReader.readBuffer()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when peeking beyond buffer length', () => { + expect(() => smallBufferReader.peekBytes(4)).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading vector beyond buffer length', () => { + expect(() => smallBufferReader.readVector({ fromBuffer: () => 1 })).toThrow( + 'Attempted to read beyond buffer length', + ); + }); + + it('should throw error when reading array beyond buffer length', () => { + expect(() => + smallBufferReader.readArray(4, { fromBuffer: (reader: BufferReader) => reader.readBytes(1) }), + ).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading string beyond buffer length', () => { + expect(() => smallBufferReader.readString()).toThrow('Attempted to read beyond buffer length'); + }); + + it('should throw error when reading map beyond buffer length', () => { + expect(() => smallBufferReader.readMap({ fromBuffer: () => 1 })).toThrow( + 'Attempted to read beyond buffer length', + ); + }); + }); }); diff --git a/yarn-project/foundation/src/serialize/buffer_reader.ts b/yarn-project/foundation/src/serialize/buffer_reader.ts index be1bf669a823..caee2973dfc3 100644 --- a/yarn-project/foundation/src/serialize/buffer_reader.ts +++ b/yarn-project/foundation/src/serialize/buffer_reader.ts @@ -55,6 +55,7 @@ export class BufferReader { * @returns The read 32-bit unsigned integer value. */ public readNumber(): number { + this.#rangeCheck(4); this.index += 4; return this.buffer.readUint32BE(this.index - 4); } @@ -76,6 +77,7 @@ export class BufferReader { * @returns The read 16 bit value. */ public readUInt16(): number { + this.#rangeCheck(2); this.index += 2; return this.buffer.readUInt16BE(this.index - 2); } @@ -87,6 +89,7 @@ export class BufferReader { * @returns The read 8 bit value. */ public readUInt8(): number { + this.#rangeCheck(1); this.index += 1; return this.buffer.readUInt8(this.index - 1); } @@ -99,6 +102,7 @@ export class BufferReader { * @returns A boolean value representing the byte at the current index. */ public readBoolean(): boolean { + this.#rangeCheck(1); this.index += 1; return Boolean(this.buffer.at(this.index - 1)); } @@ -112,6 +116,7 @@ export class BufferReader { * @returns A new Buffer containing the read bytes. */ public readBytes(n: number): Buffer { + this.#rangeCheck(n); this.index += n; return Buffer.from(this.buffer.subarray(this.index - n, this.index)); } @@ -215,6 +220,7 @@ export class BufferReader { public readBufferArray(size = -1): Buffer[] { const result: Buffer[] = []; const end = size >= 0 ? this.index + size : this.buffer.length; + this.#rangeCheck(end - this.index); while (this.index < end) { const item = this.readBuffer(); result.push(item); @@ -252,6 +258,7 @@ export class BufferReader { * @returns A Buffer with the next n bytes or the remaining bytes if n is not provided or exceeds the buffer length. */ public peekBytes(n?: number): Buffer { + this.#rangeCheck(n || 0); return this.buffer.subarray(this.index, n ? this.index + n : undefined); } @@ -276,6 +283,7 @@ export class BufferReader { */ public readBuffer(): Buffer { const size = this.readNumber(); + this.#rangeCheck(size); return this.readBytes(size); } @@ -311,6 +319,14 @@ export class BufferReader { public getLength(): number { return this.buffer.length; } + + #rangeCheck(numBytes: number) { + if (this.index + numBytes > this.buffer.length) { + throw new Error( + `Attempted to read beyond buffer length. Start index: ${this.index}, Num bytes to read: ${numBytes}, Buffer length: ${this.buffer.length}`, + ); + } + } } /** diff --git a/yarn-project/key-store/package.json b/yarn-project/key-store/package.json index 79ce75204c39..0bf868d644d2 100644 --- a/yarn-project/key-store/package.json +++ b/yarn-project/key-store/package.json @@ -29,7 +29,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/key-store/src/key_store.test.ts b/yarn-project/key-store/src/key_store.test.ts index 5c13479d4063..dc8edfa7275a 100644 --- a/yarn-project/key-store/src/key_store.test.ts +++ b/yarn-project/key-store/src/key_store.test.ts @@ -24,7 +24,7 @@ describe('KeyStore', () => { const { address: accountAddress } = await keyStore.addAccount(sk, partialAddress); expect(accountAddress.toString()).toMatchInlineSnapshot( - `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, + `"0x15565e4a5f3aff35f8eafa364cec1c11aaa84a5f7fcdf64a373614fdc8add52e"`, ); const { pkM: masterNullifierPublicKey } = await keyStore.getKeyValidationRequest( @@ -32,22 +32,22 @@ describe('KeyStore', () => { AztecAddress.random(), // Address is random because we are not interested in the app secret key here ); expect(masterNullifierPublicKey.toString()).toMatchInlineSnapshot( - `"0x2ef5d15dd65d29546680ab72846fb071f41cb9f2a0212215e6c560e29df4ff650ce764818364b376be92dc2f49577fe440e64a16012584f7c4ee94f7edbc323a"`, + `"0x1c088f4e4a711f236a88b55da9ddf388de0bc00d56a5ceca96cea3a5cbe75bf32db0a333ba30c36b844d9fc6d2fb0de8d10e4371f0c5baebae452d90ff366798"`, ); const masterIncomingViewingPublicKey = await keyStore.getMasterIncomingViewingPublicKey(accountAddress); expect(masterIncomingViewingPublicKey.toString()).toMatchInlineSnapshot( - `"0x1c088f4e4a711f236a88b55da9ddf388de0bc00d56a5ceca96cea3a5cbe75bf32db0a333ba30c36b844d9fc6d2fb0de8d10e4371f0c5baebae452d90ff366798"`, + `"0x232d0b445d097fbc2046012c3fc474f6a9beef97eda1d8d1f2487dbe501ee1e70e8db9a824531a14e8717dee54cbb7abfec29a88c550a49617258bd6fd858242"`, ); const masterOutgoingViewingPublicKey = await keyStore.getMasterOutgoingViewingPublicKey(accountAddress); expect(masterOutgoingViewingPublicKey.toString()).toMatchInlineSnapshot( - `"0x232d0b445d097fbc2046012c3fc474f6a9beef97eda1d8d1f2487dbe501ee1e70e8db9a824531a14e8717dee54cbb7abfec29a88c550a49617258bd6fd858242"`, + `"0x076429010fdebfa522b053267f654a4c5daf18589915d96f7e5001d63ea2033f27f915f254560c84450aa38e93c3162be52492d05b316e75f542e3b302117360"`, ); const masterTaggingPublicKey = await keyStore.getMasterTaggingPublicKey(accountAddress); expect(masterTaggingPublicKey.toString()).toMatchInlineSnapshot( - `"0x076429010fdebfa522b053267f654a4c5daf18589915d96f7e5001d63ea2033f27f915f254560c84450aa38e93c3162be52492d05b316e75f542e3b302117360"`, + `"0x07cec19d32f1cbaaacf16edc081021b696c86dff14160779373ffc77b04568e7076f25b0e7f0d02fd6433d788483e2262c1e45c5962790b40d1cd7efbd5253d3"`, ); // Arbitrary app contract address @@ -56,36 +56,36 @@ describe('KeyStore', () => { const { pkM: obtainedMasterNullifierPublicKey, skApp: appNullifierSecretKey } = await keyStore.getKeyValidationRequest(computedMasterNullifierPublicKeyHash, appAddress); expect(appNullifierSecretKey.toString()).toMatchInlineSnapshot( - `"0x230a44dfe7cfec7a735c89f7289c5cb5d2c3dc0bf5d3505917fd2476f67873a8"`, + `"0x0084c92262407236c992dcea10cf3406a642074cad6c6034d2990ffb073207a7"`, ); expect(obtainedMasterNullifierPublicKey).toEqual(masterNullifierPublicKey); const appIncomingViewingSecretKey = await keyStore.getAppIncomingViewingSecretKey(accountAddress, appAddress); expect(appIncomingViewingSecretKey.toString()).toMatchInlineSnapshot( - `"0x0084c92262407236c992dcea10cf3406a642074cad6c6034d2990ffb073207a7"`, + `"0x2639b26510f9d30b7e173d301b263b246b7a576186be1f44cd7c86bc06773f8a"`, ); const appOutgoingViewingSecretKey = await keyStore.getAppOutgoingViewingSecretKey(accountAddress, appAddress); expect(appOutgoingViewingSecretKey.toString()).toMatchInlineSnapshot( - `"0x2639b26510f9d30b7e173d301b263b246b7a576186be1f44cd7c86bc06773f8a"`, + `"0x13b400d2fccab28a04a4df9fe541d242e6b518d03137ef0ffa57c3d98cc56e67"`, ); // Returned accounts are as expected const accounts = await keyStore.getAccounts(); expect(accounts.toString()).toMatchInlineSnapshot( - `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, + `"0x15565e4a5f3aff35f8eafa364cec1c11aaa84a5f7fcdf64a373614fdc8add52e"`, ); // Manages to find master nullifer secret key for pub key const masterNullifierSecretKey = await keyStore.getMasterSecretKey(masterNullifierPublicKey); expect(masterNullifierSecretKey.toString()).toMatchInlineSnapshot( - `"0x0fde74d5e504c73b58aad420dd72590fc6004571411e7f77c45378714195a52b"`, + `"0x1f1f43082427fed511393bbabf8a471eb87af09f0e95bb740dc33e1ced1a54c1"`, ); // Manages to find master incoming viewing secret key for pub key const masterIncomingViewingSecretKey = await keyStore.getMasterSecretKey(masterIncomingViewingPublicKey); expect(masterIncomingViewingSecretKey.toString()).toMatchInlineSnapshot( - `"0x1f1f43082427fed511393bbabf8a471eb87af09f0e95bb740dc33e1ced1a54c1"`, + `"0x1d1d920024dd64e019c23de36d27aefe4d9d4d05983b99cf85bea9e85fd60020"`, ); }); @@ -98,7 +98,7 @@ describe('KeyStore', () => { const { address: accountAddress } = await keyStore.addAccount(sk, partialAddress); expect(accountAddress.toString()).toMatchInlineSnapshot( - `"0x1a8a9a1d91cbb353d8df4f1bbfd0283f7fc63766f671edd9443a1270a7b2a954"`, + `"0x15565e4a5f3aff35f8eafa364cec1c11aaa84a5f7fcdf64a373614fdc8add52e"`, ); // Arbitrary fixed values @@ -146,21 +146,21 @@ describe('KeyStore', () => { appAddress, ); expect(appNullifierSecretKey0.toString()).toMatchInlineSnapshot( - `"0x296e42f1039b62290372d608fcab55b00a3f96c1c8aa347b2a830639c5a12757"`, + `"0x21e3ca4bc7ae2b5e9fe343f4eec5c0aa7391857333821a4b0a1c7d4cb0055bf0"`, ); const { skApp: appNullifierSecretKey1 } = await keyStore.getKeyValidationRequest( newComputedMasterNullifierPublicKeyHashes[1], appAddress, ); expect(appNullifierSecretKey1.toString()).toMatchInlineSnapshot( - `"0x019f2a705b68683f1d86da639a543411fa779af41896c3920d0c2d5226c686dd"`, + `"0x0900aea4825d057e5bc916063a535520a7c6283740eaf218cd6961b10cba46fd"`, ); const { skApp: appNullifierSecretKey2 } = await keyStore.getKeyValidationRequest( newComputedMasterNullifierPublicKeyHashes[2], appAddress, ); expect(appNullifierSecretKey2.toString()).toMatchInlineSnapshot( - `"0x117445c8819c06b9a0889e5cce1f550e32ec6993c23f57bc9fc5cda05df520ae"`, + `"0x27ccbe41ff5f33fa78348533da9d4a79e8fea8805771e61748ea42be4202f168"`, ); expect(appNullifierSecretKey0).toEqual(computeAppNullifierSecretKey(newMasterNullifierSecretKeys[0], appAddress)); diff --git a/yarn-project/kv-store/package.json b/yarn-project/kv-store/package.json index 0fcb06fd0e39..2ca6477b1498 100644 --- a/yarn-project/kv-store/package.json +++ b/yarn-project/kv-store/package.json @@ -28,7 +28,15 @@ "workerThreads": true, "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/merkle-tree/package.json b/yarn-project/merkle-tree/package.json index 8d19e74c5a5c..0446f9a9d02c 100644 --- a/yarn-project/merkle-tree/package.json +++ b/yarn-project/merkle-tree/package.json @@ -31,7 +31,15 @@ "testTimeout": 15000, "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/merkle-tree/src/snapshots/indexed_tree_snapshot.test.ts b/yarn-project/merkle-tree/src/snapshots/indexed_tree_snapshot.test.ts index aa374542a9f6..75679d4904a3 100644 --- a/yarn-project/merkle-tree/src/snapshots/indexed_tree_snapshot.test.ts +++ b/yarn-project/merkle-tree/src/snapshots/indexed_tree_snapshot.test.ts @@ -44,7 +44,7 @@ describe('IndexedTreeSnapshotBuilder', () => { describe('getSnapshot', () => { it('returns historical leaf data', async () => { - await tree.appendLeaves([Buffer.from('a'), Buffer.from('b'), Buffer.from('c')]); + await tree.appendLeaves([Fr.random().toBuffer(), Fr.random().toBuffer(), Fr.random().toBuffer()]); await tree.commit(); const expectedLeavesAtBlock1 = await Promise.all([ tree.getLatestLeafPreimageCopy(0n, false), @@ -59,7 +59,7 @@ describe('IndexedTreeSnapshotBuilder', () => { await snapshotBuilder.snapshot(1); - await tree.appendLeaves([Buffer.from('d'), Buffer.from('e'), Buffer.from('f')]); + await tree.appendLeaves([Fr.random().toBuffer(), Fr.random().toBuffer(), Fr.random().toBuffer()]); await tree.commit(); const expectedLeavesAtBlock2 = [ tree.getLatestLeafPreimageCopy(0n, false), @@ -98,12 +98,12 @@ describe('IndexedTreeSnapshotBuilder', () => { describe('findIndexOfPreviousValue', () => { it('returns the index of the leaf with the closest value to the given value', async () => { - await tree.appendLeaves([Buffer.from('a'), Buffer.from('f'), Buffer.from('d')]); + await tree.appendLeaves([Fr.random().toBuffer(), Fr.random().toBuffer(), Fr.random().toBuffer()]); await tree.commit(); const snapshot = await snapshotBuilder.snapshot(1); const historicalPrevValue = tree.findIndexOfPreviousKey(2n, false); - await tree.appendLeaves([Buffer.from('c'), Buffer.from('b'), Buffer.from('e')]); + await tree.appendLeaves([Fr.random().toBuffer(), Fr.random().toBuffer(), Fr.random().toBuffer()]); await tree.commit(); expect(snapshot.findIndexOfPreviousKey(2n)).toEqual(historicalPrevValue); diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index 138a17712476..881226f0a933 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -29,7 +29,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index 1565d1820945..dab1d3a0e72f 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -33,7 +33,15 @@ ], "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "reporters": [ diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index 0685ef195c3c..b6ba9bd4097e 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -572,7 +572,7 @@ export function convertSimulatedPublicSetupInputsToWitnessMap(inputs: PublicKern } /** - * Converts the inputs of the public setup circuit into a witness map + * Converts the inputs of the public app logic circuit into a witness map * @param inputs - The public kernel inputs. * @returns The witness map */ 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 bc8db0da20f0..c276fc8a16d3 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -1826,7 +1826,7 @@ export function mapStorageUpdateRequestToNoir( return { storage_slot: mapFieldToNoir(storageUpdateRequest.storageSlot), new_value: mapFieldToNoir(storageUpdateRequest.newValue), - counter: mapNumberToNoir(storageUpdateRequest.sideEffectCounter), + counter: mapNumberToNoir(storageUpdateRequest.counter), }; } /** @@ -1855,7 +1855,7 @@ export function mapStorageReadToNoir(storageRead: ContractStorageRead): StorageR return { storage_slot: mapFieldToNoir(storageRead.storageSlot), current_value: mapFieldToNoir(storageRead.currentValue), - counter: mapNumberToNoir(storageRead.sideEffectCounter), + counter: mapNumberToNoir(storageRead.counter), }; } /** diff --git a/yarn-project/p2p-bootstrap/package.json b/yarn-project/p2p-bootstrap/package.json index 86c7b7ff4c5d..9e9d564c9aee 100644 --- a/yarn-project/p2p-bootstrap/package.json +++ b/yarn-project/p2p-bootstrap/package.json @@ -55,7 +55,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 30a9520f63cc..3595f7a102bc 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = < { let txPool: AztecKVTxPool; beforeEach(() => { - txPool = new AztecKVTxPool(openTmpStore()); + txPool = new AztecKVTxPool(openTmpStore(), new NoopTelemetryClient()); }); describeTxPool(() => txPool); diff --git a/yarn-project/p2p/src/tx_pool/aztec_kv_tx_pool.ts b/yarn-project/p2p/src/tx_pool/aztec_kv_tx_pool.ts index 13729720692e..f3756f837131 100644 --- a/yarn-project/p2p/src/tx_pool/aztec_kv_tx_pool.ts +++ b/yarn-project/p2p/src/tx_pool/aztec_kv_tx_pool.ts @@ -2,7 +2,9 @@ import { Tx, TxHash } from '@aztec/circuit-types'; import { type TxAddedToPoolStats } from '@aztec/circuit-types/stats'; import { type Logger, createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore, type AztecMap } from '@aztec/kv-store'; +import { type TelemetryClient } from '@aztec/telemetry-client'; +import { TxPoolInstrumentation } from './instrumentation.js'; import { type TxPool } from './tx_pool.js'; /** @@ -18,15 +20,18 @@ export class AztecKVTxPool implements TxPool { #log: Logger; + #metrics: TxPoolInstrumentation; + /** * Class constructor for in-memory TxPool. Initiates our transaction pool as a JS Map. * @param store - A KV store. * @param log - A logger. */ - constructor(store: AztecKVStore, log = createDebugLogger('aztec:tx_pool')) { + constructor(store: AztecKVStore, telemetry: TelemetryClient, log = createDebugLogger('aztec:tx_pool')) { this.#txs = store.openMap('txs'); this.#store = store; this.#log = log; + this.#metrics = new TxPoolInstrumentation(telemetry, 'AztecKVTxPool'); } /** @@ -44,8 +49,8 @@ export class AztecKVTxPool implements TxPool { * @param txs - An array of txs to be added to the pool. * @returns Empty promise. */ - public async addTxs(txs: Tx[]): Promise { - const txHashes = await Promise.all(txs.map(tx => tx.getTxHash())); + public addTxs(txs: Tx[]): Promise { + const txHashes = txs.map(tx => tx.getTxHash()); return this.#store.transaction(() => { for (const [i, tx] of txs.entries()) { const txHash = txHashes[i]; @@ -56,6 +61,8 @@ export class AztecKVTxPool implements TxPool { void this.#txs.set(txHash.toString(), tx.toBuffer()); } + + this.#metrics.recordTxs(txs); }); } @@ -69,6 +76,8 @@ export class AztecKVTxPool implements TxPool { for (const hash of txHashes) { void this.#txs.delete(hash.toString()); } + + this.#metrics.removeTxs(txHashes.length); }); } diff --git a/yarn-project/p2p/src/tx_pool/instrumentation.ts b/yarn-project/p2p/src/tx_pool/instrumentation.ts new file mode 100644 index 000000000000..099afe225222 --- /dev/null +++ b/yarn-project/p2p/src/tx_pool/instrumentation.ts @@ -0,0 +1,58 @@ +import { type Tx } from '@aztec/circuit-types'; +import { type Histogram, Metrics, type TelemetryClient, type UpDownCounter } from '@aztec/telemetry-client'; + +/** + * Instrumentation class for the TxPool. + */ +export class TxPoolInstrumentation { + /** The number of txs in the mempool */ + private txInMempool: UpDownCounter; + /** Tracks tx size */ + private txSize: Histogram; + + constructor(telemetry: TelemetryClient, name: string) { + const meter = telemetry.getMeter(name); + this.txInMempool = meter.createUpDownCounter(Metrics.MEMPOOL_TX_COUNT, { + description: 'The current number of transactions in the mempool', + }); + + this.txSize = meter.createHistogram(Metrics.MEMPOOL_TX_SIZE, { + unit: 'By', + description: 'The size of transactions in the mempool', + advice: { + explicitBucketBoundaries: [ + 5_000, // 5KB + 10_000, + 20_000, + 50_000, + 75_000, + 100_000, // 100KB + 200_000, + ], + }, + }); + } + + /** + * Updates the metrics with the new transactions. + * @param txs - The transactions to record + */ + public recordTxs(txs: Tx[]) { + for (const tx of txs) { + this.txSize.record(tx.getSize()); + } + + this.txInMempool.add(txs.length); + } + + /** + * Updates the metrics by removing transactions from the mempool. + * @param count - The number of transactions to remove from the mempool + */ + public removeTxs(count = 1) { + if (count < 0) { + throw new Error('Count must be positive'); + } + this.txInMempool.add(-1 * count); + } +} diff --git a/yarn-project/p2p/src/tx_pool/memory_tx_pool.test.ts b/yarn-project/p2p/src/tx_pool/memory_tx_pool.test.ts index fb910b4755cb..c4435a5613a5 100644 --- a/yarn-project/p2p/src/tx_pool/memory_tx_pool.test.ts +++ b/yarn-project/p2p/src/tx_pool/memory_tx_pool.test.ts @@ -1,10 +1,12 @@ +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; + import { InMemoryTxPool } from './index.js'; import { describeTxPool } from './tx_pool_test_suite.js'; describe('In-Memory TX pool', () => { let inMemoryTxPool: InMemoryTxPool; beforeEach(() => { - inMemoryTxPool = new InMemoryTxPool(); + inMemoryTxPool = new InMemoryTxPool(new NoopTelemetryClient()); }); describeTxPool(() => inMemoryTxPool); diff --git a/yarn-project/p2p/src/tx_pool/memory_tx_pool.ts b/yarn-project/p2p/src/tx_pool/memory_tx_pool.ts index 858af51370c4..924f907214f2 100644 --- a/yarn-project/p2p/src/tx_pool/memory_tx_pool.ts +++ b/yarn-project/p2p/src/tx_pool/memory_tx_pool.ts @@ -1,7 +1,9 @@ import { Tx, TxHash } from '@aztec/circuit-types'; import { type TxAddedToPoolStats } from '@aztec/circuit-types/stats'; import { createDebugLogger } from '@aztec/foundation/log'; +import { type TelemetryClient } from '@aztec/telemetry-client'; +import { TxPoolInstrumentation } from './instrumentation.js'; import { type TxPool } from './tx_pool.js'; /** @@ -13,12 +15,15 @@ export class InMemoryTxPool implements TxPool { */ private txs: Map; + private metrics: TxPoolInstrumentation; + /** * Class constructor for in-memory TxPool. Initiates our transaction pool as a JS Map. * @param log - A logger. */ - constructor(private log = createDebugLogger('aztec:tx_pool')) { + constructor(telemetry: TelemetryClient, private log = createDebugLogger('aztec:tx_pool')) { this.txs = new Map(); + this.metrics = new TxPoolInstrumentation(telemetry, 'InMemoryTxPool'); } /** @@ -37,6 +42,7 @@ export class InMemoryTxPool implements TxPool { * @returns Empty promise. */ public addTxs(txs: Tx[]): Promise { + this.metrics.recordTxs(txs); for (const tx of txs) { const txHash = tx.getTxHash(); this.log.debug(`Adding tx with id ${txHash.toString()}`, { @@ -54,6 +60,7 @@ export class InMemoryTxPool implements TxPool { * @returns The number of transactions that was deleted from the pool. */ public deleteTxs(txHashes: TxHash[]): Promise { + this.metrics.removeTxs(txHashes.length); for (const txHash of txHashes) { this.txs.delete(txHash.toBigInt()); } diff --git a/yarn-project/p2p/tsconfig.json b/yarn-project/p2p/tsconfig.json index 4e0866fd5215..fcbafbb11d0d 100644 --- a/yarn-project/p2p/tsconfig.json +++ b/yarn-project/p2p/tsconfig.json @@ -17,6 +17,9 @@ }, { "path": "../kv-store" + }, + { + "path": "../telemetry-client" } ], "include": ["src"] diff --git a/yarn-project/package.common.json b/yarn-project/package.common.json index 6fcf1a283151..7ef660b828e2 100644 --- a/yarn-project/package.common.json +++ b/yarn-project/package.common.json @@ -20,7 +20,19 @@ }, "jest": { "extensionsToTreatAsEsm": [".ts"], - "transform": { "^.+\\.tsx?$": ["@swc/jest"] }, + "transform": { + "^.+\\.tsx?$": [ + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } + ] + }, "moduleNameMapper": { "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" }, diff --git a/yarn-project/package.json b/yarn-project/package.json index 388c8f4d6df4..f9a72eb8eea4 100644 --- a/yarn-project/package.json +++ b/yarn-project/package.json @@ -52,7 +52,8 @@ "scripts", "types", "txe", - "world-state" + "world-state", + "telemetry-client" ], "prettier": "@aztec/foundation/prettier", "devDependencies": { diff --git a/yarn-project/protocol-contracts/package.json b/yarn-project/protocol-contracts/package.json index d05a83250fd3..48007fea086f 100644 --- a/yarn-project/protocol-contracts/package.json +++ b/yarn-project/protocol-contracts/package.json @@ -40,7 +40,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/prover-client/package.json b/yarn-project/prover-client/package.json index 85080060741f..04cc3185a956 100644 --- a/yarn-project/prover-client/package.json +++ b/yarn-project/prover-client/package.json @@ -34,7 +34,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -57,6 +65,7 @@ "@aztec/kv-store": "workspace:^", "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/simulator": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/world-state": "workspace:^", "@noir-lang/types": "portal:../../noir/packages/types", "commander": "^9.0.0", diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 1af8c556c48f..507068e36ae5 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -31,6 +31,7 @@ import { WASMSimulator, type WorldStatePublicDB, } from '@aztec/simulator'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import * as fs from 'fs/promises'; @@ -85,7 +86,7 @@ export class TestContext { logger: DebugLogger, proverCount = 4, createProver: (bbConfig: BBProverConfig) => Promise = _ => - Promise.resolve(new TestCircuitProver(new WASMSimulator())), + Promise.resolve(new TestCircuitProver(new NoopTelemetryClient(), new WASMSimulator())), blockNumber = 3, ) { const globalVariables = makeGlobals(blockNumber); @@ -95,6 +96,7 @@ export class TestContext { const publicWorldStateDB = mock(); const publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); const actualDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); + const telemetry = new NoopTelemetryClient(); const processor = new PublicProcessor( actualDb, publicExecutor, @@ -103,6 +105,7 @@ export class TestContext { Header.empty(), publicContractsDB, publicWorldStateDB, + telemetry, ); let localProver: ServerCircuitProver; @@ -112,7 +115,7 @@ export class TestContext { acvmBinaryPath: config?.expectedAcvmPath, }); if (!config) { - localProver = new TestCircuitProver(simulationProvider); + localProver = new TestCircuitProver(new NoopTelemetryClient(), simulationProvider); } else { const bbConfig: BBProverConfig = { acvmBinaryPath: config.expectedAcvmPath, @@ -124,7 +127,7 @@ export class TestContext { } const queue = new MemoryProvingQueue(); - const orchestrator = new ProvingOrchestrator(actualDb, queue); + const orchestrator = new ProvingOrchestrator(actualDb, queue, telemetry); const agent = new ProverAgent(localProver, proverCount); queue.start(); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 99526b8dfd1b..c6159039a723 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -9,6 +9,7 @@ import { type TxEffect, makeEmptyProcessedTx, makePaddingProcessedTx, + mapPublicKernelToCircuitName, toTxEffect, } from '@aztec/circuit-types'; import { @@ -20,6 +21,7 @@ import { type PublicInputsAndRecursiveProof, type ServerCircuitProver, } from '@aztec/circuit-types/interfaces'; +import { type CircuitName } from '@aztec/circuit-types/stats'; import { AGGREGATION_OBJECT_LENGTH, AvmCircuitInputs, @@ -53,6 +55,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; import { BufferReader, type Tuple } from '@aztec/foundation/serialize'; import { pushTestData } from '@aztec/foundation/testing'; +import { Attributes, type TelemetryClient, type Tracer, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client'; import { type MerkleTreeOperations } from '@aztec/world-state'; import { inspect } from 'util'; @@ -91,7 +94,16 @@ export class ProvingOrchestrator { private pendingProvingJobs: AbortController[] = []; private paddingTx: PaddingProcessedTx | undefined = undefined; - constructor(private db: MerkleTreeOperations, private prover: ServerCircuitProver, private initialHeader?: Header) {} + public readonly tracer: Tracer; + + constructor( + private db: MerkleTreeOperations, + private prover: ServerCircuitProver, + telemetryClient: TelemetryClient, + private initialHeader?: Header, + ) { + this.tracer = telemetryClient.getTracer('ProvingOrchestrator'); + } /** * Resets the orchestrator's cached padding tx. @@ -108,6 +120,10 @@ export class ProvingOrchestrator { * @param verificationKeys - The private kernel verification keys * @returns A proving ticket, containing a promise notifying of proving completion */ + @trackSpan('ProvingOrchestrator.startNewBlock', (numTxs, globalVariables) => ({ + [Attributes.BLOCK_SIZE]: numTxs, + [Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber(), + })) public async startNewBlock( numTxs: number, globalVariables: GlobalVariables, @@ -193,6 +209,9 @@ export class ProvingOrchestrator { * The interface to add a simulated transaction to the scheduler * @param tx - The transaction to be proven */ + @trackSpan('ProvingOrchestrator.addNewTx', tx => ({ + [Attributes.TX_HASH]: tx.hash.toString(), + })) public async addNewTx(tx: ProcessedTx): Promise { if (!this.provingState) { throw new Error(`Invalid proving state, call startNewBlock before adding transactions`); @@ -213,6 +232,17 @@ export class ProvingOrchestrator { /** * Marks the block as full and pads it to the full power of 2 block size, no more transactions will be accepted. */ + @trackSpan('ProvingOrchestrator.setBlockCompleted', function () { + if (!this.provingState) { + return {}; + } + + return { + [Attributes.BLOCK_NUMBER]: this.provingState!.globalVariables.blockNumber.toNumber(), + [Attributes.BLOCK_SIZE]: this.provingState!.totalNumTxs, + [Attributes.BLOCK_TXS_COUNT]: this.provingState!.transactionsReceived, + }; + }) public async setBlockCompleted() { if (!this.provingState) { throw new Error(`Invalid proving state, call startNewBlock before adding transactions or completing the block`); @@ -264,18 +294,26 @@ export class ProvingOrchestrator { logger.debug(`Enqueuing deferred proving for padding txs to enqueue ${txInputs.length} paddings`); this.deferredProving( provingState, - signal => - this.prover.getEmptyPrivateKernelProof( - { - // Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx - // which gets cached across multiple runs of the orchestrator with different proving states. If they were to change, - // we'd have to clear out the paddingTx here and regenerate it when they do. - chainId: unprovenPaddingTx.data.constants.txContext.chainId, - version: unprovenPaddingTx.data.constants.txContext.version, - header: unprovenPaddingTx.data.constants.historicalHeader, - }, - signal, - ), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getEmptyPrivateKernelProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'private-kernel-empty' as CircuitName, + }, + signal => + this.prover.getEmptyPrivateKernelProof( + { + // Chain id and version should not change even if the proving state does, so it's safe to use them for the padding tx + // which gets cached across multiple runs of the orchestrator with different proving states. If they were to change, + // we'd have to clear out the paddingTx here and regenerate it when they do. + chainId: unprovenPaddingTx.data.constants.txContext.chainId, + version: unprovenPaddingTx.data.constants.txContext.version, + header: unprovenPaddingTx.data.constants.historicalHeader, + }, + signal, + ), + ), result => { logger.debug(`Completed proof for padding tx, now enqueuing ${txInputs.length} padding txs`); this.paddingTx = makePaddingProcessedTx(result); @@ -319,6 +357,13 @@ export class ProvingOrchestrator { * Performs the final tree update for the block and returns the fully proven block. * @returns The fully proven block and proof. */ + @trackSpan('ProvingOrchestrator.finaliseBlock', function () { + return { + [Attributes.BLOCK_NUMBER]: this.provingState!.globalVariables.blockNumber.toNumber(), + [Attributes.BLOCK_TXS_COUNT]: this.provingState!.transactionsReceived, + [Attributes.BLOCK_SIZE]: this.provingState!.totalNumTxs, + }; + }) public async finaliseBlock() { try { if ( @@ -496,6 +541,9 @@ export class ProvingOrchestrator { } // Updates the merkle trees for a transaction. The first enqueued job for a transaction + @trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx) => ({ + [Attributes.TX_HASH]: tx.hash.toString(), + })) private async prepareBaseRollupInputs( provingState: ProvingState | undefined, tx: ProcessedTx, @@ -593,7 +641,16 @@ export class ProvingOrchestrator { this.deferredProving( provingState, - signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getBaseRollupProof', + { + [Attributes.TX_HASH]: tx.processedTx.hash.toString(), + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-rollup' as CircuitName, + }, + signal => this.prover.getBaseRollupProof(tx.baseRollupInputs, signal), + ), result => { logger.debug(`Completed proof for base rollup for tx ${tx.processedTx.hash.toString()}`); validatePartialState(result.inputs.end, tx.treeSnapshots); @@ -622,7 +679,15 @@ export class ProvingOrchestrator { this.deferredProving( provingState, - signal => this.prover.getMergeRollupProof(inputs, signal), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getMergeRollupProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup' as CircuitName, + }, + signal => this.prover.getMergeRollupProof(inputs, signal), + ), result => { this.storeAndExecuteNextMergeLevel(provingState, level, index, [ result.inputs, @@ -658,7 +723,15 @@ export class ProvingOrchestrator { this.deferredProving( provingState, - signal => this.prover.getRootRollupProof(inputs, signal), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getRootRollupProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup' as CircuitName, + }, + signal => this.prover.getRootRollupProof(inputs, signal), + ), result => { provingState.rootRollupPublicInputs = result.inputs; provingState.finalAggregationObject = extractAggregationObject( @@ -680,7 +753,15 @@ export class ProvingOrchestrator { private enqueueBaseParityCircuit(provingState: ProvingState, inputs: BaseParityInputs, index: number) { this.deferredProving( provingState, - signal => this.prover.getBaseParityProof(inputs, signal), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getBaseParityProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity' as CircuitName, + }, + signal => this.prover.getBaseParityProof(inputs, signal), + ), rootInput => { provingState.setRootParityInputs(rootInput, index); if (provingState.areRootParityInputsReady()) { @@ -701,7 +782,15 @@ export class ProvingOrchestrator { private enqueueRootParityCircuit(provingState: ProvingState | undefined, inputs: RootParityInputs) { this.deferredProving( provingState, - signal => this.prover.getRootParityProof(inputs, signal), + wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getRootParityProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity' as CircuitName, + }, + signal => this.prover.getRootParityProof(inputs, signal), + ), async rootInput => { provingState!.finalRootParityInput = rootInput; await this.checkAndEnqueueRootRollup(provingState); @@ -770,26 +859,34 @@ export class ProvingOrchestrator { if (publicFunction.vmRequest) { // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined. // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit. - const doAvmProving = async (signal: AbortSignal) => { - const inputs: AvmCircuitInputs = new AvmCircuitInputs( - publicFunction.vmRequest!.functionName, - publicFunction.vmRequest!.bytecode, - publicFunction.vmRequest!.calldata, - publicFunction.vmRequest!.kernelRequest.inputs.publicCall.callStackItem.publicInputs, - publicFunction.vmRequest!.avmHints, - ); - try { - return await this.prover.getAvmProof(inputs, signal); - } catch (err) { - if (process.env.AVM_PROVING_STRICT) { - throw err; - } else { - logger.warn(`Error thrown when proving AVM circuit: ${err}`); - logger.warn(`AVM_PROVING_STRICT is off, faking AVM proof and carrying on...`); - return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() }; + const doAvmProving = wrapCallbackInSpan( + this.tracer, + 'ProvingOrchestrator.prover.getAvmProof', + { + [Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(), + [Attributes.APP_CIRCUIT_NAME]: publicFunction.vmRequest!.functionName, + }, + async (signal: AbortSignal) => { + const inputs: AvmCircuitInputs = new AvmCircuitInputs( + publicFunction.vmRequest!.functionName, + publicFunction.vmRequest!.bytecode, + publicFunction.vmRequest!.calldata, + publicFunction.vmRequest!.kernelRequest.inputs.publicCall.callStackItem.publicInputs, + publicFunction.vmRequest!.avmHints, + ); + try { + return await this.prover.getAvmProof(inputs, signal); + } catch (err) { + if (process.env.AVM_PROVING_STRICT) { + throw err; + } else { + logger.warn(`Error thrown when proving AVM circuit: ${err}`); + logger.warn(`AVM_PROVING_STRICT is off, faking AVM proof and carrying on...`); + return { proof: makeEmptyProof(), verificationKey: VerificationKeyData.makeFake() }; + } } - } - }; + }, + ); this.deferredProving(provingState, doAvmProving, proofAndVk => { logger.debug(`Proven VM for function index ${functionIndex} of tx index ${txIndex}`); this.checkAndEnqueuePublicKernel(provingState, txIndex, functionIndex, proofAndVk.proof); @@ -835,13 +932,25 @@ export class ProvingOrchestrator { this.deferredProving( provingState, - (signal): Promise> => { - if (request.type === PublicKernelType.TAIL) { - return this.prover.getPublicTailProof(request, signal); - } else { - return this.prover.getPublicKernelProof(request, signal); - } - }, + wrapCallbackInSpan( + this.tracer, + request.type === PublicKernelType.TAIL + ? 'ProvingOrchestrator.prover.getPublicTailProof' + : 'ProvingOrchestrator.prover.getPublicKernelProof', + { + [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server', + [Attributes.PROTOCOL_CIRCUIT_NAME]: mapPublicKernelToCircuitName(request.type), + }, + ( + signal, + ): Promise> => { + if (request.type === PublicKernelType.TAIL) { + return this.prover.getPublicTailProof(request, signal); + } else { + return this.prover.getPublicKernelProof(request, signal); + } + }, + ), result => { const nextKernelRequest = txProvingState.getNextPublicKernelFromKernelProof( functionIndex, @@ -880,5 +989,9 @@ function extractAggregationObject(proof: Proof, numPublicInputs: number): Fr[] { Fr.SIZE_IN_BYTES * (numPublicInputs - AGGREGATION_OBJECT_LENGTH), Fr.SIZE_IN_BYTES * numPublicInputs, ); + // TODO(#7159): Remove the following workaround + if (buffer.length === 0) { + return Array.from({ length: AGGREGATION_OBJECT_LENGTH }, () => Fr.ZERO); + } return BufferReader.asReader(buffer).readArray(AGGREGATION_OBJECT_LENGTH, Fr); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 2c6a6b52118a..d53cb3aff117 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -2,6 +2,7 @@ import { PROVING_STATUS, type ServerCircuitProver } from '@aztec/circuit-types'; import { getMockVerificationKeys } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { WASMSimulator } from '@aztec/simulator'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; @@ -28,8 +29,8 @@ describe('prover/orchestrator/failures', () => { let mockProver: ServerCircuitProver; beforeEach(() => { - mockProver = new TestCircuitProver(new WASMSimulator()); - orchestrator = new ProvingOrchestrator(context.actualDb, mockProver); + mockProver = new TestCircuitProver(new NoopTelemetryClient(), new WASMSimulator()); + orchestrator = new ProvingOrchestrator(context.actualDb, mockProver, new NoopTelemetryClient()); }); it.each([ diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts index 3e68baee196b..5814ae93b20e 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts @@ -10,6 +10,7 @@ import { range } from '@aztec/foundation/array'; import { createDebugLogger } from '@aztec/foundation/log'; import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise'; import { sleep } from '@aztec/foundation/sleep'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; @@ -141,8 +142,8 @@ describe('prover/orchestrator/lifecycle', () => { }, 60000); it('cancels proving requests', async () => { - const prover: ServerCircuitProver = new TestCircuitProver(); - const orchestrator = new ProvingOrchestrator(context.actualDb, prover); + const prover: ServerCircuitProver = new TestCircuitProver(new NoopTelemetryClient()); + const orchestrator = new ProvingOrchestrator(context.actualDb, prover, new NoopTelemetryClient()); const spy = jest.spyOn(prover, 'getBaseParityProof'); const deferredPromises: PromiseWithResolvers[] = []; diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts index 07158f9aeec0..e139b16d18f5 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_workflow.test.ts @@ -11,6 +11,7 @@ import { makeGlobalVariables, makeRootParityInput } from '@aztec/circuits.js/tes import { promiseWithResolvers } from '@aztec/foundation/promise'; import { sleep } from '@aztec/foundation/sleep'; import { openTmpStore } from '@aztec/kv-store/utils'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -25,7 +26,7 @@ describe('prover/orchestrator', () => { beforeEach(async () => { actualDb = await MerkleTrees.new(openTmpStore()).then(t => t.asLatest()); mockProver = mock(); - orchestrator = new ProvingOrchestrator(actualDb, mockProver); + orchestrator = new ProvingOrchestrator(actualDb, mockProver, new NoopTelemetryClient()); }); it('calls root parity circuit only when ready', async () => { diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index 0f41135091fe..2bc202a947b0 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -1,6 +1,7 @@ import { BBNativeRollupProver, type BBProverConfig } from '@aztec/bb-prover'; import { makePaddingProcessedTx } from '@aztec/circuit-types'; import { createDebugLogger } from '@aztec/foundation/log'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { TestContext } from '../mocks/test_context.js'; import { buildBaseRollupInput } from '../orchestrator/block-building-helpers.js'; @@ -13,7 +14,7 @@ describe('prover/bb_prover/base-rollup', () => { beforeAll(async () => { const buildProver = async (bbConfig: BBProverConfig) => { - prover = await BBNativeRollupProver.new(bbConfig); + prover = await BBNativeRollupProver.new(bbConfig, new NoopTelemetryClient()); return prover; }; context = await TestContext.new(logger, 1, buildProver); diff --git a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts index f7e6ad999104..5b6791a1e58c 100644 --- a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts @@ -4,6 +4,7 @@ import { Fr, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, getMockVerificationKeys } from import { makeTuple } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { TestContext } from '../mocks/test_context.js'; @@ -14,7 +15,7 @@ describe('prover/bb_prover/full-rollup', () => { beforeAll(async () => { const buildProver = async (bbConfig: BBProverConfig) => { - prover = await BBNativeRollupProver.new(bbConfig); + prover = await BBNativeRollupProver.new(bbConfig, new NoopTelemetryClient()); return prover; }; logger = createDebugLogger('aztec:bb-prover-full-rollup'); diff --git a/yarn-project/prover-client/src/test/bb_prover_parity.test.ts b/yarn-project/prover-client/src/test/bb_prover_parity.test.ts index 595723e49db8..b43f1c8aafd9 100644 --- a/yarn-project/prover-client/src/test/bb_prover_parity.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_parity.test.ts @@ -15,6 +15,7 @@ import { makeTuple } from '@aztec/foundation/array'; import { randomBytes } from '@aztec/foundation/crypto'; import { createDebugLogger } from '@aztec/foundation/log'; import { type Tuple } from '@aztec/foundation/serialize'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { TestContext } from '../mocks/test_context.js'; @@ -27,7 +28,7 @@ describe('prover/bb_prover/parity', () => { beforeAll(async () => { const buildProver = async (bbConfig: BBProverConfig) => { bbConfig.circuitFilter = ['BaseParityArtifact', 'RootParityArtifact']; - bbProver = await BBNativeRollupProver.new(bbConfig); + bbProver = await BBNativeRollupProver.new(bbConfig, new NoopTelemetryClient()); return bbProver; }; context = await TestContext.new(logger, 1, buildProver); diff --git a/yarn-project/prover-client/src/tx-prover/tx-prover.ts b/yarn-project/prover-client/src/tx-prover/tx-prover.ts index 6008cfe9db52..09392412912c 100644 --- a/yarn-project/prover-client/src/tx-prover/tx-prover.ts +++ b/yarn-project/prover-client/src/tx-prover/tx-prover.ts @@ -9,6 +9,7 @@ import { } from '@aztec/circuit-types/interfaces'; import { type Fr, type GlobalVariables, type Header, type VerificationKeys } from '@aztec/circuits.js'; import { NativeACVMSimulator } from '@aztec/simulator'; +import { type TelemetryClient } from '@aztec/telemetry-client'; import { type WorldStateSynchronizer } from '@aztec/world-state'; import { type ProverClientConfig } from '../config.js'; @@ -28,11 +29,17 @@ export class TxProver implements ProverClient { private config: ProverClientConfig, private worldStateSynchronizer: WorldStateSynchronizer, private vks: VerificationKeys, + private telemetry: TelemetryClient, private agent?: ProverAgent, initialHeader?: Header, ) { this.queue = new MemoryProvingQueue(config.proverJobTimeoutMs, config.proverJobPollIntervalMs); - this.orchestrator = new ProvingOrchestrator(worldStateSynchronizer.getLatest(), this.queue, initialHeader); + this.orchestrator = new ProvingOrchestrator( + worldStateSynchronizer.getLatest(), + this.queue, + telemetry, + initialHeader, + ); } async updateProverConfig(config: Partial): Promise { @@ -43,7 +50,7 @@ export class TxProver implements ProverClient { } if (newConfig.realProofs !== this.config.realProofs && this.agent) { - const circuitProver = await TxProver.buildCircuitProver(newConfig); + const circuitProver = await TxProver.buildCircuitProver(newConfig, this.telemetry); this.agent.setCircuitProver(circuitProver); } @@ -95,31 +102,35 @@ export class TxProver implements ProverClient { config: ProverClientConfig, vks: VerificationKeys, worldStateSynchronizer: WorldStateSynchronizer, + telemetry: TelemetryClient, initialHeader?: Header, ) { const agent = config.proverAgentEnabled ? new ProverAgent( - await TxProver.buildCircuitProver(config), + await TxProver.buildCircuitProver(config, telemetry), config.proverAgentConcurrency, config.proverAgentPollInterval, ) : undefined; - const prover = new TxProver(config, worldStateSynchronizer, vks, agent, initialHeader); + const prover = new TxProver(config, worldStateSynchronizer, vks, telemetry, agent, initialHeader); await prover.start(); return prover; } - private static async buildCircuitProver(config: ProverClientConfig): Promise { + private static async buildCircuitProver( + config: ProverClientConfig, + telemetry: TelemetryClient, + ): Promise { if (config.realProofs) { - return await BBNativeRollupProver.new(config); + return await BBNativeRollupProver.new(config, telemetry); } const simulationProvider = config.acvmBinaryPath ? new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath) : undefined; - return new TestCircuitProver(simulationProvider); + return new TestCircuitProver(telemetry, simulationProvider); } /** diff --git a/yarn-project/prover-client/tsconfig.json b/yarn-project/prover-client/tsconfig.json index 5f4666ebf030..9a0e67ac6c26 100644 --- a/yarn-project/prover-client/tsconfig.json +++ b/yarn-project/prover-client/tsconfig.json @@ -27,6 +27,9 @@ { "path": "../simulator" }, + { + "path": "../telemetry-client" + }, { "path": "../world-state" } diff --git a/yarn-project/pxe/package.json b/yarn-project/pxe/package.json index 9d3e04fee0ce..588fb9fec9b6 100644 --- a/yarn-project/pxe/package.json +++ b/yarn-project/pxe/package.json @@ -32,7 +32,15 @@ "workerThreads": true, "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/pxe/src/database/deferred_note_dao.test.ts b/yarn-project/pxe/src/database/deferred_note_dao.test.ts index d3c1e5d520b6..efe57f5a6819 100644 --- a/yarn-project/pxe/src/database/deferred_note_dao.test.ts +++ b/yarn-project/pxe/src/database/deferred_note_dao.test.ts @@ -1,5 +1,6 @@ import { Note, randomTxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { randomInt } from '@aztec/foundation/crypto'; import { DeferredNoteDao } from './deferred_note_dao.js'; @@ -10,7 +11,7 @@ export const randomDeferredNoteDao = ({ contractAddress = AztecAddress.random(), txHash = randomTxHash(), storageSlot = Fr.random(), - noteTypeId = Fr.random(), + noteTypeId = NoteSelector.random(), newNoteHashes = [Fr.random(), Fr.random()], dataStartIndexForTx = randomInt(100), }: Partial = {}) => { diff --git a/yarn-project/pxe/src/database/deferred_note_dao.ts b/yarn-project/pxe/src/database/deferred_note_dao.ts index 6e73db1e2379..d1d0c551209e 100644 --- a/yarn-project/pxe/src/database/deferred_note_dao.ts +++ b/yarn-project/pxe/src/database/deferred_note_dao.ts @@ -1,5 +1,6 @@ import { Note, TxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point, type PublicKey, Vector } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; /** @@ -18,7 +19,7 @@ export class DeferredNoteDao { /** The specific storage location of the note on the contract. */ public storageSlot: Fr, /** The type ID of the note on the contract. */ - public noteTypeId: Fr, + public noteTypeId: NoteSelector, /** The hash of the tx the note was created in. Equal to the first nullifier */ public txHash: TxHash, /** New note hashes in this transaction, one of which belongs to this note */ @@ -46,7 +47,7 @@ export class DeferredNoteDao { reader.readObject(Note), reader.readObject(AztecAddress), reader.readObject(Fr), - reader.readObject(Fr), + reader.readObject(NoteSelector), reader.readObject(TxHash), reader.readVector(Fr), reader.readNumber(), diff --git a/yarn-project/pxe/src/database/incoming_note_dao.test.ts b/yarn-project/pxe/src/database/incoming_note_dao.test.ts index ae8d562a381c..f20e957fc1b8 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.test.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.test.ts @@ -1,5 +1,6 @@ import { Note, randomTxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { IncomingNoteDao } from './incoming_note_dao.js'; @@ -8,7 +9,7 @@ export const randomIncomingNoteDao = ({ contractAddress = AztecAddress.random(), txHash = randomTxHash(), storageSlot = Fr.random(), - noteTypeId = Fr.random(), + noteTypeId = NoteSelector.random(), nonce = Fr.random(), innerNoteHash = Fr.random(), siloedNullifier = Fr.random(), diff --git a/yarn-project/pxe/src/database/incoming_note_dao.ts b/yarn-project/pxe/src/database/incoming_note_dao.ts index 6db39e1b4554..0a128a742599 100644 --- a/yarn-project/pxe/src/database/incoming_note_dao.ts +++ b/yarn-project/pxe/src/database/incoming_note_dao.ts @@ -1,5 +1,6 @@ import { Note, TxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point, type PublicKey } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type NoteData } from '@aztec/simulator'; @@ -16,7 +17,7 @@ export class IncomingNoteDao implements NoteData { /** The specific storage location of the note on the contract. */ public storageSlot: Fr, /** The note type identifier for the contract. */ - public noteTypeId: Fr, + public noteTypeId: NoteSelector, /** The hash of the tx the note was created in. */ public txHash: TxHash, /** The nonce of the note. */ @@ -57,8 +58,8 @@ export class IncomingNoteDao implements NoteData { const note = Note.fromBuffer(reader); const contractAddress = AztecAddress.fromBuffer(reader); const storageSlot = Fr.fromBuffer(reader); - const noteTypeId = Fr.fromBuffer(reader); - const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); + const noteTypeId = reader.readObject(NoteSelector); + const txHash = reader.readObject(TxHash); const nonce = Fr.fromBuffer(reader); const innerNoteHash = Fr.fromBuffer(reader); const siloedNullifier = Fr.fromBuffer(reader); diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts index 166a5e9b51be..9e7241760ffa 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.test.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.test.ts @@ -1,5 +1,6 @@ import { Note, randomTxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { OutgoingNoteDao } from './outgoing_note_dao.js'; @@ -8,7 +9,7 @@ export const randomOutgoingNoteDao = ({ contractAddress = AztecAddress.random(), txHash = randomTxHash(), storageSlot = Fr.random(), - noteTypeId = Fr.random(), + noteTypeId = NoteSelector.random(), nonce = Fr.random(), innerNoteHash = Fr.random(), index = Fr.random().toBigInt(), diff --git a/yarn-project/pxe/src/database/outgoing_note_dao.ts b/yarn-project/pxe/src/database/outgoing_note_dao.ts index e7e2b8c263df..03075f9f7df4 100644 --- a/yarn-project/pxe/src/database/outgoing_note_dao.ts +++ b/yarn-project/pxe/src/database/outgoing_note_dao.ts @@ -1,5 +1,6 @@ import { Note, TxHash } from '@aztec/circuit-types'; import { AztecAddress, Fr, Point, type PublicKey } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -15,7 +16,7 @@ export class OutgoingNoteDao { /** The specific storage location of the note on the contract. */ public storageSlot: Fr, /** The note type identifier for the contract. */ - public noteTypeId: Fr, + public noteTypeId: NoteSelector, /** The hash of the tx the note was created in. */ public txHash: TxHash, /** The nonce of the note. */ @@ -50,7 +51,7 @@ export class OutgoingNoteDao { const note = Note.fromBuffer(reader); const contractAddress = AztecAddress.fromBuffer(reader); const storageSlot = Fr.fromBuffer(reader); - const noteTypeId = Fr.fromBuffer(reader); + const noteTypeId = reader.readObject(NoteSelector); const txHash = new TxHash(reader.readBytes(TxHash.SIZE)); const nonce = Fr.fromBuffer(reader); const innerNoteHash = Fr.fromBuffer(reader); diff --git a/yarn-project/pxe/src/index.ts b/yarn-project/pxe/src/index.ts index 7c62b24d3ff1..86b3f1205e7a 100644 --- a/yarn-project/pxe/src/index.ts +++ b/yarn-project/pxe/src/index.ts @@ -11,3 +11,4 @@ export * from '@aztec/foundation/aztec-address'; export * from '@aztec/key-store'; export * from './database/index.js'; export { ContractDataOracle } from './contract_data_oracle/index.js'; +export { PrivateFunctionsTree } from './contract_data_oracle/private_functions_tree.js'; diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index e96547fbbd7a..e60353cd405f 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -21,6 +21,7 @@ import { makeRecursiveProof, } from '@aztec/circuits.js'; import { makeTxRequest } from '@aztec/circuits.js/testing'; +import { NoteSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; @@ -45,7 +46,7 @@ describe('Kernel Prover', () => { .map(() => ({ note: new Note([Fr.random(), Fr.random(), Fr.random()]), storageSlot: Fr.random(), - noteTypeId: Fr.random(), + noteTypeId: NoteSelector.random(), owner: { x: Fr.random(), y: Fr.random() }, })); diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index 61b1a820ba0a..859309439d06 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -151,18 +151,17 @@ export class NoteProcessor { const outgoingTaggedNote = TaggedLog.decryptAsOutgoing(log.data, ovskM)!; if (incomingTaggedNote || outgoingTaggedNote) { - // TODO(#7053): Re-enable this check - // if ( - // incomingTaggedNote && - // outgoingTaggedNote && - // !incomingTaggedNote.payload.equals(outgoingTaggedNote.payload) - // ) { - // throw new Error( - // `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify( - // incomingTaggedNote.payload, - // )}, Outgoing: ${JSON.stringify(outgoingTaggedNote.payload)}`, - // ); - // } + if ( + incomingTaggedNote && + outgoingTaggedNote && + !incomingTaggedNote.payload.equals(outgoingTaggedNote.payload) + ) { + throw new Error( + `Incoming and outgoing note payloads do not match. Incoming: ${JSON.stringify( + incomingTaggedNote.payload, + )}, Outgoing: ${JSON.stringify(outgoingTaggedNote.payload)}`, + ); + } const payload = incomingTaggedNote?.payload || outgoingTaggedNote?.payload; diff --git a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts index b8e2500c57fa..f429337c7630 100644 --- a/yarn-project/pxe/src/pxe_http/pxe_http_server.ts +++ b/yarn-project/pxe/src/pxe_http/pxe_http_server.ts @@ -18,6 +18,7 @@ import { UnencryptedL2BlockL2Logs, } from '@aztec/circuit-types'; import { FunctionSelector } from '@aztec/circuits.js'; +import { NoteSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr, GrumpkinScalar, Point } from '@aztec/foundation/fields'; @@ -49,6 +50,7 @@ export function createPXERpcServer(pxeService: PXE): JsonRpcServer { L2Block, TxEffect, LogId, + NoteSelector, }, { SimulatedTx, Tx, TxReceipt, EncryptedNoteL2BlockL2Logs, UnencryptedL2BlockL2Logs, NullifierMembershipWitness }, ['start', 'stop'], diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 5422eea4f00b..cf351c5bf9bf 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -35,13 +35,7 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash'; -import { - type ContractArtifact, - type DecodedReturn, - EventSelector, - FunctionSelector, - encodeArguments, -} from '@aztec/foundation/abi'; +import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { type Fq, Fr, type Point } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -859,7 +853,7 @@ export class PXEService implements PXE { if (visibleEvent.payload === undefined) { return undefined; } - if (!EventSelector.fromField(visibleEvent.payload.eventTypeId).equals(eventMetadata.eventSelector)) { + if (!visibleEvent.payload.eventTypeId.equals(eventMetadata.eventSelector)) { return undefined; } if (visibleEvent.payload.event.items.length !== eventMetadata.fieldNames.length) { diff --git a/yarn-project/scripts/package.json b/yarn-project/scripts/package.json index e7a327778e69..0f5849a2ab2e 100644 --- a/yarn-project/scripts/package.json +++ b/yarn-project/scripts/package.json @@ -59,7 +59,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/sequencer-client/package.json b/yarn-project/sequencer-client/package.json index a84790233700..96574ecbb1bc 100644 --- a/yarn-project/sequencer-client/package.json +++ b/yarn-project/sequencer-client/package.json @@ -35,6 +35,7 @@ "@aztec/p2p": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/simulator": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", "@aztec/world-state": "workspace:^", "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js", @@ -78,7 +79,15 @@ ], "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "moduleNameMapper": { diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index dae754f04a4e..5250d962acac 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -2,6 +2,7 @@ import { type L1ToL2MessageSource, type L2BlockSource } from '@aztec/circuit-typ import { type BlockProver } from '@aztec/circuit-types/interfaces'; import { type P2P } from '@aztec/p2p'; import { PublicProcessorFactory, type SimulationProvider } from '@aztec/simulator'; +import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ContractDataSource } from '@aztec/types/contracts'; import { type WorldStateSynchronizer } from '@aztec/world-state'; @@ -38,12 +39,18 @@ export class SequencerClient { l1ToL2MessageSource: L1ToL2MessageSource, prover: BlockProver, simulationProvider: SimulationProvider, + telemetryClient: TelemetryClient, ) { const publisher = getL1Publisher(config); const globalsBuilder = getGlobalVariableBuilder(config); const merkleTreeDb = worldStateSynchronizer.getLatest(); - const publicProcessorFactory = new PublicProcessorFactory(merkleTreeDb, contractDataSource, simulationProvider); + const publicProcessorFactory = new PublicProcessorFactory( + merkleTreeDb, + contractDataSource, + simulationProvider, + telemetryClient, + ); const sequencer = new Sequencer( publisher, @@ -55,6 +62,7 @@ export class SequencerClient { l1ToL2MessageSource, publicProcessorFactory, new TxValidatorFactory(merkleTreeDb, contractDataSource, !!config.enforceFees), + telemetryClient, config, ); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 4292e85e8383..a0bdf943af37 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -27,6 +27,7 @@ import { randomBytes } from '@aztec/foundation/crypto'; import { type Writeable } from '@aztec/foundation/types'; import { type P2P, P2PClientState } from '@aztec/p2p'; import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type ContractDataSource } from '@aztec/types/contracts'; import { type MerkleTreeOperations, WorldStateRunningState, type WorldStateSynchronizer } from '@aztec/world-state'; @@ -115,6 +116,7 @@ describe('sequencer', () => { l1ToL2MessageSource, publicProcessorFactory, new TxValidatorFactory(merkleTreeOps, contractSource, false), + new NoopTelemetryClient(), ); }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index aaa1831c190f..0a4414537807 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -13,13 +13,14 @@ import { PROVING_STATUS, } from '@aztec/circuit-types/interfaces'; import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats'; -import { AztecAddress, EthAddress, type Proof } from '@aztec/circuits.js'; +import { AztecAddress, EthAddress, type GlobalVariables, type Header, type Proof } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; import { Timer, elapsed } from '@aztec/foundation/timer'; import { type P2P } from '@aztec/p2p'; import { type PublicProcessorFactory } from '@aztec/simulator'; +import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { type WorldStateStatus, type WorldStateSynchronizer } from '@aztec/world-state'; import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js'; @@ -50,6 +51,8 @@ export class Sequencer { private allowedInTeardown: AllowedElement[] = []; private maxBlockSizeInBytes: number = 1024 * 1024; + public readonly tracer: Tracer; + constructor( private publisher: L1Publisher, private globalsBuilder: GlobalVariableBuilder, @@ -60,10 +63,12 @@ export class Sequencer { private l1ToL2MessageSource: L1ToL2MessageSource, private publicProcessorFactory: PublicProcessorFactory, private txValidatorFactory: TxValidatorFactory, + telemetry: TelemetryClient, config: SequencerConfig = {}, private log = createDebugLogger('aztec:sequencer'), ) { this.updateConfig(config); + this.tracer = telemetry.getTracer('Sequencer'); this.log.verbose(`Initialized sequencer with ${this.minTxsPerBLock}-${this.maxTxsPerBlock} txs per block.`); } @@ -174,7 +179,6 @@ export class Sequencer { return; } - const workTimer = new Timer(); this.state = SequencerState.WAITING_FOR_TXS; // Get txs to build the new block @@ -184,19 +188,6 @@ export class Sequencer { } this.log.debug(`Retrieved ${pendingTxs.length} txs from P2P pool`); - /** - * We'll call this function before running expensive operations to avoid wasted work. - */ - const assertBlockHeight = async () => { - const currentBlockNumber = await this.l2BlockSource.getBlockNumber(); - if (currentBlockNumber + 1 !== newBlockNumber) { - throw new Error('New block was emitted while building block'); - } - if (!(await this.publisher.isItMyTurnToSubmit(newBlockNumber))) { - throw new Error(`Not this sequencer turn to submit block`); - } - }; - const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables( new Fr(newBlockNumber), this._coinbase, @@ -220,72 +211,7 @@ export class Sequencer { return; } - this.log.info(`Building block ${newBlockNumber} with ${validTxs.length} transactions`); - this.state = SequencerState.CREATING_BLOCK; - - // Get l1 to l2 messages from the contract - this.log.debug('Requesting L1 to L2 messages from contract'); - const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(newBlockNumber)); - this.log.verbose(`Retrieved ${l1ToL2Messages.length} L1 to L2 messages for block ${newBlockNumber}`); - - // We create a fresh processor each time to reset any cached state (eg storage writes) - const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); - - const blockBuildingTimer = new Timer(); - - // We must initialise the block to be a power of 2 in size - const numRealTxs = validTxs.length; - const pow2 = Math.log2(numRealTxs); - // TODO turn this back into a Math.ceil once we can pad blocks to the next-power-of-2 with empty txs - const totalTxs = 2 ** Math.ceil(pow2); - const blockSize = Math.max(2, totalTxs); - const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages); - - const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() => - processor.process(validTxs, blockSize, this.prover, this.txValidatorFactory.validatorForProcessedTxs()), - ); - if (failedTxs.length > 0) { - const failedTxData = failedTxs.map(fail => fail.tx); - this.log.debug(`Dropping failed txs ${Tx.getHashes(failedTxData).join(', ')}`); - await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData)); - } - - if (processedTxs.length === 0) { - this.log.verbose('No txs processed correctly to build block. Exiting'); - this.prover.cancelBlock(); - return; - } - - await assertBlockHeight(); - - // All real transactions have been added, set the block as full and complete the proving. - await this.prover.setBlockCompleted(); - - // Here we are now waiting for the block to be proven. - // TODO(@PhilWindle) We should probably periodically check for things like another - // block being published before ours instead of just waiting on our block - const result = await blockTicket.provingPromise; - if (result.status === PROVING_STATUS.FAILURE) { - throw new Error(`Block proving failed, reason: ${result.reason}`); - } - - await assertBlockHeight(); - - // Block is proven, now finalise and publish! - const { block, aggregationObject, proof } = await this.prover.finaliseBlock(); - - await assertBlockHeight(); - - this.log.verbose(`Assembled block ${block.number}`, { - eventName: 'l2-block-built', - duration: workTimer.ms(), - publicProcessDuration: publicProcessorDuration, - rollupCircuitsDuration: blockBuildingTimer.ms(), - ...block.getStats(), - } satisfies L2BlockBuiltStats); - - await this.publishL2Block(block, aggregationObject, proof); - this.log.info(`Submitted rollup block ${block.number} with ${processedTxs.length} transactions`); + await this.buildBlockAndPublish(validTxs, newGlobalVariables, historicalHeader); } catch (err) { if (BlockProofError.isBlockProofError(err)) { const txHashes = err.txHashes.filter(h => !h.isZero()); @@ -299,10 +225,100 @@ export class Sequencer { } } + @trackSpan('Sequencer.buildBlockAndPublish', (_validTxs, newGlobalVariables, _historicalHeader) => ({ + [Attributes.BLOCK_NUMBER]: newGlobalVariables.blockNumber.toNumber(), + })) + private async buildBlockAndPublish( + validTxs: Tx[], + newGlobalVariables: GlobalVariables, + historicalHeader: Header | undefined, + ): Promise { + const workTimer = new Timer(); + this.state = SequencerState.CREATING_BLOCK; + this.log.info(`Building block ${newGlobalVariables.blockNumber.toNumber()} with ${validTxs.length} transactions`); + + const assertBlockHeight = async () => { + const currentBlockNumber = await this.l2BlockSource.getBlockNumber(); + if (currentBlockNumber + 1 !== newGlobalVariables.blockNumber.toNumber()) { + throw new Error('New block was emitted while building block'); + } + if (!(await this.publisher.isItMyTurnToSubmit(newGlobalVariables.blockNumber.toNumber()))) { + throw new Error(`Not this sequencer turn to submit block`); + } + }; + + // Get l1 to l2 messages from the contract + this.log.debug('Requesting L1 to L2 messages from contract'); + const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(newGlobalVariables.blockNumber.toBigInt()); + this.log.verbose( + `Retrieved ${l1ToL2Messages.length} L1 to L2 messages for block ${newGlobalVariables.blockNumber.toNumber()}`, + ); + + // We create a fresh processor each time to reset any cached state (eg storage writes) + const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); + + const numRealTxs = validTxs.length; + const pow2 = Math.log2(numRealTxs); + const totalTxs = 2 ** Math.ceil(pow2); + const blockSize = Math.max(2, totalTxs); + + const blockBuildingTimer = new Timer(); + const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages); + + const [publicProcessorDuration, [processedTxs, failedTxs]] = await elapsed(() => + processor.process(validTxs, blockSize, this.prover, this.txValidatorFactory.validatorForProcessedTxs()), + ); + if (failedTxs.length > 0) { + const failedTxData = failedTxs.map(fail => fail.tx); + this.log.debug(`Dropping failed txs ${Tx.getHashes(failedTxData).join(', ')}`); + await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData)); + } + + if (processedTxs.length === 0) { + this.log.verbose('No txs processed correctly to build block. Exiting'); + this.prover.cancelBlock(); + return; + } + + await assertBlockHeight(); + + // All real transactions have been added, set the block as full and complete the proving. + await this.prover.setBlockCompleted(); + + // Here we are now waiting for the block to be proven. + // TODO(@PhilWindle) We should probably periodically check for things like another + // block being published before ours instead of just waiting on our block + const result = await blockTicket.provingPromise; + if (result.status === PROVING_STATUS.FAILURE) { + throw new Error(`Block proving failed, reason: ${result.reason}`); + } + + await assertBlockHeight(); + + // Block is proven, now finalise and publish! + const { block, aggregationObject, proof } = await this.prover.finaliseBlock(); + + await assertBlockHeight(); + + this.log.verbose(`Assembled block ${block.number}`, { + eventName: 'l2-block-built', + duration: workTimer.ms(), + publicProcessDuration: publicProcessorDuration, + rollupCircuitsDuration: blockBuildingTimer.ms(), + ...block.getStats(), + } satisfies L2BlockBuiltStats); + + await this.publishL2Block(block, aggregationObject, proof); + this.log.info(`Submitted rollup block ${block.number} with ${processedTxs.length} transactions`); + } + /** * Publishes the L2Block to the rollup contract. * @param block - The L2Block to be published. */ + @trackSpan('Sequencer.publishL2Block', block => ({ + [Attributes.BLOCK_NUMBER]: block.number, + })) protected async publishL2Block(block: L2Block, aggregationObject: Fr[], proof: Proof) { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; diff --git a/yarn-project/sequencer-client/tsconfig.json b/yarn-project/sequencer-client/tsconfig.json index 4ec1ceda8672..b4140a80da44 100644 --- a/yarn-project/sequencer-client/tsconfig.json +++ b/yarn-project/sequencer-client/tsconfig.json @@ -39,6 +39,9 @@ { "path": "../simulator" }, + { + "path": "../telemetry-client" + }, { "path": "../types" }, diff --git a/yarn-project/simulator/package.json b/yarn-project/simulator/package.json index f99e74aa4b27..8356b976f28b 100644 --- a/yarn-project/simulator/package.json +++ b/yarn-project/simulator/package.json @@ -32,7 +32,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ @@ -53,6 +61,7 @@ "@aztec/foundation": "workspace:^", "@aztec/noir-protocol-circuits-types": "workspace:^", "@aztec/protocol-contracts": "workspace:^", + "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", "@aztec/world-state": "workspace:^", "@noir-lang/acvm_js": "portal:../../noir/packages/acvm_js", diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index 590f0542e1b6..d2cd8ddf7d1c 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -1,6 +1,6 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types'; import { KeyValidationRequest } from '@aztec/circuits.js'; -import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; +import { EventSelector, FunctionSelector, NoteSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; @@ -49,6 +49,14 @@ export class Oracle { return toACVMField(await this.typedOracle.getContractAddress()); } + async getVersion(): Promise { + return toACVMField(await this.typedOracle.getVersion()); + } + + async getChainId(): Promise { + return toACVMField(await this.typedOracle.getChainId()); + } + async getKeyValidationRequest([pkMHash]: ACVMField[]): Promise { const { pkM, skApp } = await this.typedOracle.getKeyValidationRequest(fromACVMField(pkMHash)); @@ -244,7 +252,7 @@ export class Oracle { ): ACVMField { this.typedOracle.notifyCreatedNote( fromACVMField(storageSlot), - fromACVMField(noteTypeId), + NoteSelector.fromField(fromACVMField(noteTypeId)), note.map(fromACVMField), fromACVMField(innerNoteHash), +counter, @@ -357,7 +365,7 @@ export class Oracle { const encLog = this.typedOracle.computeEncryptedNoteLog( AztecAddress.fromString(contractAddress), Fr.fromString(storageSlot), - Fr.fromString(noteTypeId), + NoteSelector.fromField(Fr.fromString(noteTypeId)), ovKeys, ivpkM, preimage.map(fromACVMField), diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 41fd2f7e37b9..690ccf8ac868 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -16,7 +16,7 @@ import { type PrivateCallStackItem, type PublicCallRequest, } from '@aztec/circuits.js'; -import { type FunctionSelector } from '@aztec/foundation/abi'; +import { type FunctionSelector, type NoteSelector } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type ContractInstance } from '@aztec/types/contracts'; @@ -90,6 +90,14 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getContractAddress'); } + getChainId(): Promise { + throw new OracleMethodNotAvailableError('getChainId'); + } + + getVersion(): Promise { + throw new OracleMethodNotAvailableError('getVersion'); + } + getKeyValidationRequest(_pkMHash: Fr): Promise { throw new OracleMethodNotAvailableError('getKeyValidationRequest'); } @@ -156,7 +164,13 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getNotes'); } - notifyCreatedNote(_storageSlot: Fr, _noteTypeId: Fr, _note: Fr[], _innerNoteHash: Fr, _counter: number): void { + notifyCreatedNote( + _storageSlot: Fr, + _noteTypeId: NoteSelector, + _note: Fr[], + _innerNoteHash: Fr, + _counter: number, + ): void { throw new OracleMethodNotAvailableError('notifyCreatedNote'); } @@ -211,7 +225,7 @@ export abstract class TypedOracle { computeEncryptedNoteLog( _contractAddress: AztecAddress, _storageSlot: Fr, - _noteTypeId: Fr, + _noteTypeId: NoteSelector, _ovKeys: KeyValidationRequest, _ivpkM: PublicKey, _preimage: Fr[], diff --git a/yarn-project/simulator/src/avm/avm_context.test.ts b/yarn-project/simulator/src/avm/avm_context.test.ts index bea44afec382..a96d88983061 100644 --- a/yarn-project/simulator/src/avm/avm_context.test.ts +++ b/yarn-project/simulator/src/avm/avm_context.test.ts @@ -16,6 +16,7 @@ describe('Avm Context', () => { allSameExcept(context.environment, { address: newAddress, storageAddress: newAddress, + contractCallDepth: Fr.ONE, // Calldata also includes AvmContextInputs calldata: anyAvmContextInputs().concat(newCalldata), isStaticCall: false, @@ -46,6 +47,7 @@ describe('Avm Context', () => { allSameExcept(context.environment, { address: newAddress, storageAddress: newAddress, + contractCallDepth: Fr.ONE, // Calldata also includes AvmContextInputs calldata: anyAvmContextInputs().concat(newCalldata), isStaticCall: true, diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.test.ts b/yarn-project/simulator/src/avm/avm_execution_environment.test.ts index 68bde3962fb5..e13f3f248d71 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.test.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.test.ts @@ -16,6 +16,7 @@ describe('Execution Environment', () => { allSameExcept(executionEnvironment, { address: newAddress, storageAddress: newAddress, + contractCallDepth: Fr.ONE, // Calldata also includes AvmContextInputs calldata: anyAvmContextInputs().concat(calldata), }), @@ -30,6 +31,7 @@ describe('Execution Environment', () => { expect(newExecutionEnvironment).toEqual( allSameExcept(executionEnvironment, { address: newAddress, + contractCallDepth: Fr.ONE, isDelegateCall: true, // Calldata also includes AvmContextInputs calldata: anyAvmContextInputs().concat(calldata), @@ -49,6 +51,7 @@ describe('Execution Environment', () => { allSameExcept(executionEnvironment, { address: newAddress, storageAddress: newAddress, + contractCallDepth: Fr.ONE, isStaticCall: true, // Calldata also includes AvmContextInputs calldata: anyAvmContextInputs().concat(calldata), diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.ts b/yarn-project/simulator/src/avm/avm_execution_environment.ts index 411b9d60ff49..c4794b1a02b7 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.ts @@ -19,6 +19,7 @@ export class AvmContextInputs { */ // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3992): gas not implemented export class AvmExecutionEnvironment { + private readonly calldataPrefixLength; constructor( public readonly address: AztecAddress, public readonly storageAddress: AztecAddress, @@ -45,8 +46,9 @@ export class AvmExecutionEnvironment { temporaryFunctionSelector.toField(), computeVarArgsHash(calldata), isStaticCall, - ); - this.calldata = [...inputs.toFields(), ...calldata]; + ).toFields(); + this.calldata = [...inputs, ...calldata]; + this.calldataPrefixLength = inputs.length; } private deriveEnvironmentForNestedCallInternal( @@ -62,7 +64,7 @@ export class AvmExecutionEnvironment { /*sender=*/ this.address, this.feePerL2Gas, this.feePerDaGas, - this.contractCallDepth, + this.contractCallDepth.add(Fr.ONE), this.header, this.globals, isStaticCall, @@ -109,4 +111,9 @@ export class AvmExecutionEnvironment { ): AvmExecutionEnvironment { throw new Error('Delegate calls not supported!'); } + + public getCalldataWithoutPrefix(): Fr[] { + // clip off the first few entries + return this.calldata.slice(this.calldataPrefixLength); + } } diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 1614305b0bea..e28d9d9b8e7a 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -1,15 +1,16 @@ -import { UnencryptedL2Log } from '@aztec/circuit-types'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { EventSelector, FunctionSelector } from '@aztec/foundation/abi'; +import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { keccak256, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundation/crypto'; import { Fq, Fr } from '@aztec/foundation/fields'; import { type Fieldable } from '@aztec/foundation/serialize'; -import { jest } from '@jest/globals'; +import { mock } from 'jest-mock-extended'; +import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; import { isAvmBytecode, markBytecodeAsAvm } from '../public/transitional_adaptors.js'; +import { type AvmExecutionEnvironment } from './avm_execution_environment.js'; import { AvmMachineState } from './avm_machine_state.js'; import { type MemoryValue, TypeTag, type Uint8 } from './avm_memory_types.js'; import { AvmSimulator } from './avm_simulator.js'; @@ -19,12 +20,26 @@ import { initContext, initExecutionEnvironment, initGlobalVariables, + initHostStorage, initMachineState, + initPersistableStateManager, randomMemoryBytes, randomMemoryFields, } from './fixtures/index.js'; +import { type HostStorage } from './journal/host_storage.js'; +import { type AvmPersistableStateManager } from './journal/journal.js'; import { Add, CalldataCopy, Return } from './opcodes/index.js'; import { encodeToBytecode } from './serialization/bytecode_serialization.js'; +import { + mockGetBytecode, + mockGetContractInstance, + mockL1ToL2MessageExists, + mockNoteHashExists, + mockNullifierExists, + mockStorageRead, + mockStorageReadWithMap, + mockTraceFork, +} from './test_utils.js'; describe('AVM simulator: injected bytecode', () => { let calldata: Fr[]; @@ -314,634 +329,565 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); }); - describe('Tree access (notes & nullifiers)', () => { - it(`Note hash exists (it does not)`, async () => { - const noteHash = new Fr(42); - const leafIndex = new Fr(7); - const calldata = [noteHash, leafIndex]; - - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('note_hash_exists'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=false*/ new Fr(0)]); + it('conversions', async () => { + const calldata: Fr[] = [new Fr(0b1011101010100)]; + const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - // Note hash existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.noteHashChecks).toEqual([expect.objectContaining({ noteHash, leafIndex, exists: false })]); - }); + const bytecode = getAvmTestContractBytecode('to_radix_le'); + const results = await new AvmSimulator(context).executeBytecode(bytecode); - it(`Note hash exists (it does)`, async () => { - const noteHash = new Fr(42); - const leafIndex = new Fr(7); - const calldata = [noteHash, leafIndex]; + expect(results.reverted).toBe(false); + const expectedResults = Buffer.concat('0010101011'.split('').map(c => new Fr(Number(c)).toBuffer())); + const resultBuffer = Buffer.concat(results.output.map(f => f.toBuffer())); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - // note hash exists! - jest - .spyOn(context.persistableState.hostStorage.commitmentsDb, 'getCommitmentIndex') - .mockReturnValue(Promise.resolve(BigInt(7))); - const bytecode = getAvmTestContractBytecode('note_hash_exists'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(resultBuffer.equals(expectedResults)).toBe(true); + }); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=true*/ new Fr(1)]); + describe('Side effects, world state, nested calls', () => { + const address = new Fr(1); + // TODO(dbanks12): should be able to make address and storage address different + const storageAddress = new Fr(1); + const sender = new Fr(42); + const leafIndex = new Fr(7); + const slotNumber = 1; // must update Noir contract if changing this + const slot = new Fr(slotNumber); + const listSlotNumber0 = 2; // must update Noir contract if changing this + const listSlotNumber1 = listSlotNumber0 + 1; + const listSlot0 = new Fr(listSlotNumber0); + const listSlot1 = new Fr(listSlotNumber1); + const value0 = new Fr(420); + const value1 = new Fr(69); + + let hostStorage: HostStorage; + let trace: PublicSideEffectTraceInterface; + let persistableState: AvmPersistableStateManager; + + beforeEach(() => { + hostStorage = initHostStorage(); + trace = mock(); + persistableState = initPersistableStateManager({ hostStorage, trace }); + }); + + const createContext = (calldata: Fr[] = []) => { + return initContext({ + persistableState, + env: initExecutionEnvironment({ address, storageAddress, sender, calldata }), + }); + }; - // Note hash existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.noteHashChecks).toEqual([expect.objectContaining({ noteHash, leafIndex, exists: true })]); + // Will check existence at leafIndex, but nothing may be found there and/or something may be found at mockAtLeafIndex + describe.each([ + [/*mockAtLeafIndex=*/ undefined], // doesn't exist at all + [/*mockAtLeafIndex=*/ leafIndex], // should be found! + [/*mockAtLeafIndex=*/ leafIndex.add(Fr.ONE)], // won't be found! (checking leafIndex+1, but it exists at leafIndex) + ])('Note hash checks', (mockAtLeafIndex?: Fr) => { + const expectFound = mockAtLeafIndex !== undefined && mockAtLeafIndex.equals(leafIndex); + const existsElsewhere = mockAtLeafIndex !== undefined && !mockAtLeafIndex.equals(leafIndex); + const existsStr = expectFound ? 'DOES exist' : 'does NOT exist'; + const foundAtStr = existsElsewhere + ? `at leafIndex=${mockAtLeafIndex.toNumber()} (exists at leafIndex=${leafIndex.toNumber()})` + : ''; + it(`Should return ${expectFound} (and be traced) when noteHash ${existsStr} ${foundAtStr}`, async () => { + const calldata = [value0, leafIndex]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('note_hash_exists'); + if (mockAtLeafIndex !== undefined) { + mockNoteHashExists(hostStorage, mockAtLeafIndex, value0); + } + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([expectFound ? Fr.ONE : Fr.ZERO]); + + expect(trace.traceNoteHashCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNoteHashCheck).toHaveBeenCalledWith( + storageAddress, + /*noteHash=*/ value0, + leafIndex, + /*exists=*/ expectFound, + ); + }); }); - it(`Emit unencrypted logs (should be traced)`, async () => { - const context = initContext(); - const bytecode = getAvmTestContractBytecode('emit_unencrypted_log'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - - const expectedFields = [new Fr(10), new Fr(20), new Fr(30)]; - const expectedString = 'Hello, world!'.split('').map(c => new Fr(c.charCodeAt(0))); - const expectedCompressedString = Buffer.from( - '\0A long time ago, in a galaxy fa' + '\0r far away...\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', - ); - expect(context.persistableState.flush().newLogs).toEqual([ - new UnencryptedL2Log( - context.environment.address, - new EventSelector(5), - Buffer.concat(expectedFields.map(f => f.toBuffer())), - ), - new UnencryptedL2Log( - context.environment.address, - new EventSelector(5), - Buffer.concat(expectedString.map(f => f.toBuffer())), - ), - new UnencryptedL2Log(context.environment.address, new EventSelector(5), expectedCompressedString), - ]); + describe.each([[/*exists=*/ false], [/*exists=*/ true]])('Nullifier checks', (exists: boolean) => { + const existsStr = exists ? 'DOES exist' : 'does NOT exist'; + it(`Should return ${exists} (and be traced) when noteHash ${existsStr}`, async () => { + const calldata = [value0]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('nullifier_exists'); + + if (exists) { + mockNullifierExists(hostStorage, leafIndex, value0); + } + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([exists ? Fr.ONE : Fr.ZERO]); + + expect(trace.traceNullifierCheck).toHaveBeenCalledTimes(1); + const isPending = false; + // leafIndex is returned from DB call for nullifiers, so it is absent on DB miss + const tracedLeafIndex = exists && !isPending ? leafIndex : Fr.ZERO; + expect(trace.traceNullifierCheck).toHaveBeenCalledWith( + storageAddress, + value0, + tracedLeafIndex, + exists, + isPending, + ); + }); }); - it(`Emit note hash (should be traced)`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; - - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('new_note_hash'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - - expect(context.persistableState.flush().newNoteHashes).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - noteHash: utxo, - }), - ]); + // Will check existence at leafIndex, but nothing may be found there and/or something may be found at mockAtLeafIndex + describe.each([ + [/*mockAtLeafIndex=*/ undefined], // doesn't exist at all + [/*mockAtLeafIndex=*/ leafIndex], // should be found! + [/*mockAtLeafIndex=*/ leafIndex.add(Fr.ONE)], // won't be found! (checking leafIndex+1, but it exists at leafIndex) + ])('L1ToL2 message checks', (mockAtLeafIndex?: Fr) => { + const expectFound = mockAtLeafIndex !== undefined && mockAtLeafIndex.equals(leafIndex); + const existsElsewhere = mockAtLeafIndex !== undefined && !mockAtLeafIndex.equals(leafIndex); + const existsStr = expectFound ? 'DOES exist' : 'does NOT exist'; + const foundAtStr = existsElsewhere + ? `at leafIndex=${mockAtLeafIndex.toNumber()} (exists at leafIndex=${leafIndex.toNumber()})` + : ''; + + it(`Should return ${expectFound} (and be traced) when noteHash ${existsStr} ${foundAtStr}`, async () => { + const calldata = [value0, leafIndex]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('l1_to_l2_msg_exists'); + if (mockAtLeafIndex !== undefined) { + mockL1ToL2MessageExists(hostStorage, mockAtLeafIndex, value0, /*valueAtOtherIndices=*/ value1); + } + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([expectFound ? Fr.ONE : Fr.ZERO]); + + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith( + address, + /*noteHash=*/ value0, + leafIndex, + /*exists=*/ expectFound, + ); + }); }); - it(`Emit nullifier (should be traced)`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; + it('Should append a new note hash correctly', async () => { + const calldata = [value0]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('new_note_hash'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('new_nullifier'); const results = await new AvmSimulator(context).executeBytecode(bytecode); - expect(results.reverted).toBe(false); + expect(results.output).toEqual([]); - expect(context.persistableState.flush().newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - }), - ]); + expect(trace.traceNewNoteHash).toHaveBeenCalledTimes(1); + expect(trace.traceNewNoteHash).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); }); - it(`Nullifier exists (it does not)`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; + it('Should append a new nullifier correctly', async () => { + const calldata = [value0]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('new_nullifier'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('nullifier_exists'); const results = await new AvmSimulator(context).executeBytecode(bytecode); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=false*/ new Fr(0)]); - - // Nullifier existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.nullifierChecks).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - exists: false, - counter: expect.any(Fr), - isPending: false, - leafIndex: expect.any(Fr), - }), - ]); - }); + expect(results.output).toEqual([]); - it(`Nullifier exists (it does)`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; - - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - // nullifier exists! - jest - .spyOn(context.persistableState.hostStorage.commitmentsDb, 'getNullifierIndex') - .mockReturnValue(Promise.resolve(BigInt(42))); - const bytecode = getAvmTestContractBytecode('nullifier_exists'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=true*/ new Fr(1)]); - - // Nullifier existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.nullifierChecks).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - exists: true, - counter: expect.any(Fr), - isPending: false, - leafIndex: expect.any(Fr), - }), - ]); + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(1); + expect(trace.traceNewNullifier).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); }); - it(`Emits a nullifier and checks its existence`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; - - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('emit_nullifier_and_check'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - // Nullifier existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - }), - ]); - expect(trace.nullifierChecks).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - exists: true, - counter: expect.any(Fr), - isPending: true, - leafIndex: expect.any(Fr), - }), - ]); + describe('Cached nullifiers', () => { + it(`Emits a nullifier and checks its existence`, async () => { + const calldata = [value0]; + + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('emit_nullifier_and_check'); + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + + // New nullifier and nullifier existence check should be traced + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(1); + expect(trace.traceNewNullifier).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); + expect(trace.traceNullifierCheck).toHaveBeenCalledTimes(1); + // leafIndex is returned from DB call for nullifiers, so it is absent on DB miss + expect(trace.traceNullifierCheck).toHaveBeenCalledWith( + storageAddress, + value0, + /*leafIndex=*/ Fr.ZERO, + /*exists=*/ true, + /*isPending=*/ true, + ); + }); + it(`Emits same nullifier twice (expect failure)`, async () => { + const calldata = [value0]; + + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('nullifier_collision'); + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(true); + expect(results.revertReason?.message).toMatch(/Attempted to emit duplicate nullifier/); + + // Nullifier should be traced exactly once + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(1); + expect(trace.traceNewNullifier).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); + }); }); - it(`Emits same nullifier twice (should fail)`, async () => { - const utxo = new Fr(42); - const calldata = [utxo]; + describe('Unencrypted Logs', () => { + it(`Emit unencrypted logs (should be traced)`, async () => { + const context = createContext(); + const bytecode = getAvmTestContractBytecode('emit_unencrypted_log'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('nullifier_collision'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); - expect(results.reverted).toBe(true); - expect(results.revertReason?.message).toMatch(/Attempted to emit duplicate nullifier/); - // Only the first nullifier should be in the trace, second one failed to add - expect(context.persistableState.flush().newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - nullifier: utxo, - }), - ]); - }); - }); + const eventSelector = new Fr(5); + const expectedFields = [new Fr(10), new Fr(20), new Fr(30)]; + const expectedString = 'Hello, world!'.split('').map(c => new Fr(c.charCodeAt(0))); + const expectedCompressedString = [ + '\0A long time ago, in a galaxy fa', + '\0r far away...\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + ].map(s => new Fr(Buffer.from(s))); - describe('Test tree access (l1ToL2 messages)', () => { - it(`Message exists (it does not)`, async () => { - const msgHash = new Fr(42); - const leafIndex = new Fr(24); - const calldata = [msgHash, leafIndex]; - - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - const bytecode = getAvmTestContractBytecode('l1_to_l2_msg_exists'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=false*/ new Fr(0)]); - // Message existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.l1ToL2MessageChecks.length).toEqual(1); - expect(trace.l1ToL2MessageChecks[0].exists).toEqual(false); + expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(3); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedFields); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedString); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedCompressedString); + }); }); - it(`Message exists (it does)`, async () => { - const msgHash = new Fr(42); - const leafIndex = new Fr(24); - const calldata = [msgHash, leafIndex]; + describe('Public storage accesses', () => { + it('Should set value in storage (single)', async () => { + const calldata = [value0]; - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - 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); + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('set_storage_single'); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*exists=false*/ new Fr(1)]); - // Message existence check should be in trace - const trace = context.persistableState.flush(); - expect(trace.l1ToL2MessageChecks.length).toEqual(1); - expect(trace.l1ToL2MessageChecks[0].exists).toEqual(true); - }); - }); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); - describe('Storage accesses', () => { - it('Should set value in storage (single)', async () => { - const slot = 1n; - const address = AztecAddress.fromField(new Fr(420)); - const value = new Fr(88); - const calldata = [value]; + expect(await context.persistableState.peekStorage(storageAddress, slot)).toEqual(value0); - const context = initContext({ - env: initExecutionEnvironment({ calldata, address, storageAddress: address }), + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, slot, value0); }); - const bytecode = getAvmTestContractBytecode('set_storage_single'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - expect(results.reverted).toBe(false); + it('Should read value in storage (single)', async () => { + const context = createContext(); + mockStorageRead(hostStorage, value0); - // World state - const worldState = context.persistableState.flush(); - const storageSlot = worldState.currentStorageValue.get(address.toBigInt())!; - const adminSlotValue = storageSlot.get(slot); - expect(adminSlotValue).toEqual(value); - - // Tracing - expect(worldState.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: value, - }), - ]); - }); + const bytecode = getAvmTestContractBytecode('read_storage_single'); - it('Should read value in storage (single)', async () => { - const slot = 1n; - const value = new Fr(12345); - const address = AztecAddress.fromField(new Fr(420)); - const storage = new Map([[slot, value]]); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0]); - const context = initContext({ - env: initExecutionEnvironment({ storageAddress: address }), + expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + slot, + value0, + /*exists=*/ true, + /*cached=*/ false, + ); }); - jest - .spyOn(context.persistableState.hostStorage.publicStateDb, 'storageRead') - .mockImplementation((_address, slot) => Promise.resolve(storage.get(slot.toBigInt())!)); - const bytecode = getAvmTestContractBytecode('read_storage_single'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - // Get contract function artifact - expect(results.reverted).toBe(false); - expect(results.output).toEqual([value]); - - // Tracing - const worldState = context.persistableState.flush(); - expect(worldState.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: value, - exists: true, - }), - ]); - }); + it('Should set and read a value from storage (single)', async () => { + const calldata = [value0]; + + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('set_read_storage_single'); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0]); + + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, slot, value0); + expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + slot, + value0, + /*exists=*/ true, + /*cached=*/ true, + ); + }); - it('Should set and read a value from storage (single)', async () => { - const slot = 1n; - const value = new Fr(12345); - const address = AztecAddress.fromField(new Fr(420)); - const calldata = [value]; + it('Should set a value in storage (list)', async () => { + const calldata = [value0, value1]; - const context = initContext({ - env: initExecutionEnvironment({ calldata, address, storageAddress: address }), - }); - const bytecode = getAvmTestContractBytecode('set_read_storage_single'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('set_storage_list'); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([value]); - - // Test read trace - const worldState = context.persistableState.flush(); - expect(worldState.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: value, - exists: true, - }), - ]); - expect(worldState.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: value, - }), - ]); - }); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); - it('Should set a value in storage (list)', async () => { - const slot = 2n; - const sender = AztecAddress.fromField(new Fr(1)); - const address = AztecAddress.fromField(new Fr(420)); - const calldata = [new Fr(1), new Fr(2)]; + expect(await context.persistableState.peekStorage(address, listSlot0)).toEqual(calldata[0]); + expect(await context.persistableState.peekStorage(address, listSlot1)).toEqual(calldata[1]); - const context = initContext({ - env: initExecutionEnvironment({ sender, address, calldata, storageAddress: address }), + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(2); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, listSlot0, value0); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, listSlot1, value1); }); - const bytecode = getAvmTestContractBytecode('set_storage_list'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - expect(results.reverted).toBe(false); + it('Should read a value in storage (list)', async () => { + const context = createContext(); + const mockedStorage = new Map([ + [listSlot0.toBigInt(), value0], + [listSlot1.toBigInt(), value1], + ]); + mockStorageReadWithMap(hostStorage, mockedStorage); + + const bytecode = getAvmTestContractBytecode('read_storage_list'); + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0, value1]); + + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + listSlot0, + value0, + /*exists=*/ true, + /*cached=*/ false, + ); + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + listSlot1, + value1, + /*exists=*/ true, + /*cached=*/ false, + ); + }); - const worldState = context.persistableState.flush(); - const storageSlot = worldState.currentStorageValue.get(address.toBigInt())!; - expect(storageSlot.get(slot)).toEqual(calldata[0]); - expect(storageSlot.get(slot + 1n)).toEqual(calldata[1]); - - // Tracing - expect(worldState.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: calldata[0], - }), - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot + 1n), - value: calldata[1], - }), - ]); - }); + it('Should set a value in storage (map)', async () => { + const calldata = [storageAddress, value0]; - it('Should read a value in storage (list)', async () => { - const slot = 2n; - const address = AztecAddress.fromField(new Fr(420)); - const values = [new Fr(1), new Fr(2)]; - const storage = new Map([ - [slot, values[0]], - [slot + 1n, values[1]], - ]); + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('set_storage_map'); - const context = initContext({ - env: initExecutionEnvironment({ address, storageAddress: address }), - }); - jest - .spyOn(context.persistableState.hostStorage.publicStateDb, 'storageRead') - .mockImplementation((_address, slot) => Promise.resolve(storage.get(slot.toBigInt())!)); - const bytecode = getAvmTestContractBytecode('read_storage_list'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); - expect(results.reverted).toBe(false); - expect(results.output).toEqual(values); - - // Tracing - const worldState = context.persistableState.flush(); - expect(worldState.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot), - value: values[0], - exists: true, - }), - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slot + 1n), - value: values[1], - exists: true, - }), - ]); - }); + // returns the storage slot for modified key + const mapSlotNumber = results.output[0].toBigInt(); + const mapSlot = new Fr(mapSlotNumber); - it('Should set a value in storage (map)', async () => { - const address = AztecAddress.fromField(new Fr(420)); - const value = new Fr(12345); - const calldata = [address.toField(), value]; + expect(await context.persistableState.peekStorage(storageAddress, mapSlot)).toEqual(value0); - const context = initContext({ - env: initExecutionEnvironment({ address, calldata, storageAddress: address }), + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, mapSlot, value0); }); - const bytecode = getAvmTestContractBytecode('set_storage_map'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - expect(results.reverted).toBe(false); - // returns the storage slot for modified key - const slotNumber = results.output[0].toBigInt(); - - const worldState = context.persistableState.flush(); - const storageSlot = worldState.currentStorageValue.get(address.toBigInt())!; - expect(storageSlot.get(slotNumber)).toEqual(value); - - // Tracing - expect(worldState.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slotNumber), - value: value, - }), - ]); - }); + it('Should read-add-set a value in storage (map)', async () => { + const calldata = [storageAddress, value0]; - it('Should read-add-set a value in storage (map)', async () => { - const address = AztecAddress.fromField(new Fr(420)); - const value = new Fr(12345); - const calldata = [address.toField(), value]; + const context = createContext(calldata); + const bytecode = getAvmTestContractBytecode('add_storage_map'); - const context = initContext({ - env: initExecutionEnvironment({ address, calldata, storageAddress: address }), - }); - const bytecode = getAvmTestContractBytecode('add_storage_map'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); - expect(results.reverted).toBe(false); - // returns the storage slot for modified key - const slotNumber = results.output[0].toBigInt(); - - const worldState = context.persistableState.flush(); - const storageSlot = worldState.currentStorageValue.get(address.toBigInt())!; - expect(storageSlot.get(slotNumber)).toEqual(value); - - // Tracing - expect(worldState.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slotNumber), - value: Fr.ZERO, - exists: false, - }), - ]); - expect(worldState.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: address, - slot: new Fr(slotNumber), - value: value, - }), - ]); - }); + // returns the storage slot for modified key + const mapSlotNumber = results.output[0].toBigInt(); + const mapSlot = new Fr(mapSlotNumber); - it('Should read value in storage (map)', async () => { - const value = new Fr(12345); - const address = AztecAddress.fromField(new Fr(420)); - const calldata = [address.toField()]; + expect(await context.persistableState.peekStorage(storageAddress, mapSlot)).toEqual(value0); - const context = initContext({ - env: initExecutionEnvironment({ calldata, address, storageAddress: address }), + expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + mapSlot, + Fr.ZERO, + /*exists=*/ false, + /*cached=*/ false, + ); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(1); + expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, mapSlot, value0); }); - jest - .spyOn(context.persistableState.hostStorage.publicStateDb, 'storageRead') - .mockReturnValue(Promise.resolve(value)); - const bytecode = getAvmTestContractBytecode('read_storage_map'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - // Get contract function artifact - expect(results.reverted).toBe(false); - expect(results.output).toEqual([value]); - - // Tracing - const worldState = context.persistableState.flush(); - expect(worldState.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: address, - // slot depends on pedersen hash of key, etc. - value: value, - exists: true, - }), - ]); + it('Should read value in storage (map)', async () => { + const calldata = [storageAddress]; + + const context = createContext(calldata); + mockStorageRead(hostStorage, value0); + const bytecode = getAvmTestContractBytecode('read_storage_map'); + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0]); + + expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(1); + // slot is the result of a pedersen hash and is therefore not known in the test + expect(trace.tracePublicStorageRead).toHaveBeenCalledWith( + storageAddress, + expect.anything(), + value0, + /*exists=*/ true, + /*cached=*/ false, + ); + }); }); - }); - - describe('Contract', () => { - it(`GETCONTRACTINSTANCE deserializes correctly`, async () => { - const context = initContext(); - const contractInstance = { - address: AztecAddress.random(), - version: 1 as const, - salt: new Fr(0x123), - deployer: AztecAddress.fromBigInt(0x456n), - contractClassId: new Fr(0x789), - initializationHash: new Fr(0x101112), - publicKeysHash: new Fr(0x161718), - }; - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getContractInstance') - .mockReturnValue(Promise.resolve(contractInstance)); - const bytecode = getAvmTestContractBytecode('test_get_contract_instance_raw'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); + describe('Contract Instance Retrieval', () => { + it(`Can getContractInstance`, async () => { + const context = createContext(); + // Contract instance must match noir + const contractInstance = { + address: AztecAddress.random(), + version: 1 as const, + salt: new Fr(0x123), + deployer: AztecAddress.fromBigInt(0x456n), + contractClassId: new Fr(0x789), + initializationHash: new Fr(0x101112), + publicKeysHash: new Fr(0x161718), + }; + mockGetContractInstance(hostStorage, contractInstance); + + const bytecode = getAvmTestContractBytecode('test_get_contract_instance_raw'); + + const results = await new AvmSimulator(context).executeBytecode(bytecode); + expect(results.reverted).toBe(false); + + expect(trace.traceGetContractInstance).toHaveBeenCalledTimes(1); + expect(trace.traceGetContractInstance).toHaveBeenCalledWith({ exists: true, ...contractInstance }); + }); }); - }); - - describe('Nested external calls', () => { - it(`Nested call with not enough gas`, async () => { - const gas = [/*l2=*/ 5, /*da=*/ 10000].map(g => new Fr(g)); - const calldata: Fr[] = [new Fr(1), new Fr(2), ...gas]; - const callBytecode = getAvmTestContractBytecode('nested_call_to_add_with_gas'); - const addBytecode = getAvmTestContractBytecode('add_args_return'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(addBytecode)); - const results = await new AvmSimulator(context).executeBytecode(callBytecode); + describe('Nested external calls', () => { + const expectTracedNestedCall = ( + environment: AvmExecutionEnvironment, + nestedTrace: PublicSideEffectTraceInterface, + isStaticCall: boolean = false, + ) => { + expect(trace.traceNestedCall).toHaveBeenCalledTimes(1); + expect(trace.traceNestedCall).toHaveBeenCalledWith( + /*nestedCallTrace=*/ nestedTrace, + /*nestedEnvironment=*/ expect.objectContaining({ + sender: environment.address, // sender is top-level call + contractCallDepth: new Fr(1), // top call is depth 0, nested is depth 1 + header: environment.header, // just confirming that nested env looks roughly right + globals: environment.globals, // just confirming that nested env looks roughly right + isStaticCall: isStaticCall, + // TODO(7121): can't check calldata like this since it is modified on environment construction + // with AvmContextInputs. These should eventually go away. + //calldata: expect.arrayContaining(environment.calldata), // top-level call forwards args + }), + /*startGasLeft=*/ expect.anything(), + /*endGasLeft=*/ expect.anything(), + /*bytecode=*/ expect.anything(), //decompressBytecodeIfCompressed(addBytecode), + /*avmCallResults=*/ expect.anything(), // we don't have the NESTED call's results to check + /*functionName=*/ expect.anything(), + ); + }; - // TODO: change this once we don't force rethrowing of exceptions. - // Outer frame should not revert, but inner should, so the forwarded return value is 0 - // expect(results.revertReason).toBeUndefined(); - // expect(results.reverted).toBe(false); - expect(results.reverted).toBe(true); - expect(results.revertReason?.message).toEqual('Not enough L2GAS gas left'); - }); + it(`Nested call`, async () => { + const calldata = [value0, value1]; + const context = createContext(calldata); + const callBytecode = getAvmTestContractBytecode('nested_call_to_add'); + const addBytecode = getAvmTestContractBytecode('add_args_return'); + mockGetBytecode(hostStorage, addBytecode); + const nestedTrace = mock(); + mockTraceFork(trace, nestedTrace); - it(`Nested call`, async () => { - const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const callBytecode = getAvmTestContractBytecode('nested_call_to_add'); - const addBytecode = getAvmTestContractBytecode('add_args_return'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(addBytecode)); + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0.add(value1)]); - const results = await new AvmSimulator(context).executeBytecode(callBytecode); + expectTracedNestedCall(context.environment, nestedTrace); + }); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([new Fr(3)]); - }); + it(`Nested static call`, async () => { + const calldata = [value0, value1]; + const context = createContext(calldata); + const callBytecode = getAvmTestContractBytecode('nested_static_call_to_add'); + const addBytecode = getAvmTestContractBytecode('add_args_return'); + mockGetBytecode(hostStorage, addBytecode); + const nestedTrace = mock(); + mockTraceFork(trace, nestedTrace); - it(`Nested static call`, async () => { - const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const callBytecode = getAvmTestContractBytecode('nested_static_call_to_add'); - const addBytecode = getAvmTestContractBytecode('add_args_return'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(addBytecode)); + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + expect(results.reverted).toBe(false); + expect(results.output).toEqual([value0.add(value1)]); - const results = await new AvmSimulator(context).executeBytecode(callBytecode); + expectTracedNestedCall(context.environment, nestedTrace, /*isStaticCall=*/ true); + }); - expect(results.reverted).toBe(false); - expect(results.output).toEqual([/*result=*/ new Fr(3)]); - }); + it(`Nested call with not enough gas (expect failure)`, async () => { + const gas = [/*l2=*/ 5, /*da=*/ 10000].map(g => new Fr(g)); + const calldata: Fr[] = [value0, value1, ...gas]; + const context = createContext(calldata); + const callBytecode = getAvmTestContractBytecode('nested_call_to_add_with_gas'); + const addBytecode = getAvmTestContractBytecode('add_args_return'); + mockGetBytecode(hostStorage, addBytecode); + mockTraceFork(trace); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + // TODO(7141): change this once we don't force rethrowing of exceptions. + // Outer frame should not revert, but inner should, so the forwarded return value is 0 + // expect(results.revertReason).toBeUndefined(); + // expect(results.reverted).toBe(false); + expect(results.reverted).toBe(true); + expect(results.revertReason?.message).toEqual('Not enough L2GAS gas left'); + + // Nested call should NOT have been made and therefore should not be traced + expect(trace.traceNestedCall).toHaveBeenCalledTimes(0); + }); - it(`Nested static call which modifies storage`, async () => { - const callBytecode = getAvmTestContractBytecode('nested_static_call_to_set_storage'); - const nestedBytecode = getAvmTestContractBytecode('set_storage_single'); - const context = initContext(); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(nestedBytecode)); + it(`Nested static call which modifies storage (expect failure)`, async () => { + const context = createContext(); + const callBytecode = getAvmTestContractBytecode('nested_static_call_to_set_storage'); + const nestedBytecode = getAvmTestContractBytecode('set_storage_single'); + mockGetBytecode(hostStorage, nestedBytecode); + mockTraceFork(trace); - const results = await new AvmSimulator(context).executeBytecode(callBytecode); + const results = await new AvmSimulator(context).executeBytecode(callBytecode); - expect(results.reverted).toBe(true); // The outer call should revert. - expect(results.revertReason?.message).toEqual( - 'Static call cannot update the state, emit L2->L1 messages or generate logs', - ); - }); + expect(results.reverted).toBe(true); // The outer call should revert. + expect(results.revertReason?.message).toEqual( + 'Static call cannot update the state, emit L2->L1 messages or generate logs', + ); - it(`Nested calls rethrow exceptions`, async () => { - const calldata: Fr[] = [new Fr(1), new Fr(2)]; - const callBytecode = getAvmTestContractBytecode('nested_call_to_add'); - // We actually don't pass the function ADD, but it's ok because the signature is the same. - const nestedBytecode = getAvmTestContractBytecode('assert_same'); - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(nestedBytecode)); + // TODO(7141): external call doesn't recover from nested exception until + // we support recoverability of reverts (here and in kernel) + //expectTracedNestedCall(context.environment, results, nestedTrace, /*isStaticCall=*/true); - const results = await new AvmSimulator(context).executeBytecode(callBytecode); + // Nested call should NOT have been able to write storage + expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(0); + }); - expect(results.reverted).toBe(true); // The outer call should revert. - expect(results.revertReason?.message).toEqual('Assertion failed: Values are not equal'); + it(`Nested calls rethrow exceptions`, async () => { + const calldata = [value0, value1]; + const context = createContext(calldata); + const callBytecode = getAvmTestContractBytecode('nested_call_to_add'); + // We actually don't pass the function ADD, but it's ok because the signature is the same. + const nestedBytecode = getAvmTestContractBytecode('assert_same'); + mockGetBytecode(hostStorage, nestedBytecode); + + const results = await new AvmSimulator(context).executeBytecode(callBytecode); + expect(results.reverted).toBe(true); // The outer call should revert. + expect(results.revertReason?.message).toEqual('Assertion failed: Values are not equal'); + }); }); }); - - it('conversions', async () => { - const calldata: Fr[] = [new Fr(0b1011101010100)]; - const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - - const bytecode = getAvmTestContractBytecode('to_radix_le'); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - const expectedResults = Buffer.concat('0010101011'.split('').map(c => new Fr(Number(c)).toBuffer())); - const resultBuffer = Buffer.concat(results.output.map(f => f.toBuffer())); - - expect(resultBuffer.equals(expectedResults)).toBe(true); - }); }); function sha256FromMemoryBytes(bytes: Uint8[]): Fr[] { diff --git a/yarn-project/simulator/src/avm/avm_simulator.ts b/yarn-project/simulator/src/avm/avm_simulator.ts index 6d0eb154332b..64d13a2ffbe9 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.ts @@ -29,10 +29,9 @@ export class AvmSimulator { * Fetch the bytecode and execute it in the current context. */ public async execute(): Promise { - const selector = this.context.environment.temporaryFunctionSelector; - const bytecode = await this.context.persistableState.hostStorage.contractsDb.getBytecode( + const bytecode = await this.context.persistableState.getBytecode( this.context.environment.address, - selector, + this.context.environment.temporaryFunctionSelector, ); // This assumes that we will not be able to send messages to accounts without code diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index b96be7f003c3..d7926c28dfe0 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -4,20 +4,21 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; import { AvmTestContractArtifact } from '@aztec/noir-contracts.js'; -import { SerializableContractInstance } from '@aztec/types/contracts'; import { strict as assert } from 'assert'; import { mock } from 'jest-mock-extended'; import merge from 'lodash.merge'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; import { AvmContext } from '../avm_context.js'; import { AvmContextInputs, AvmExecutionEnvironment } from '../avm_execution_environment.js'; import { AvmMachineState } from '../avm_machine_state.js'; import { Field, Uint8 } from '../avm_memory_types.js'; import { HostStorage } from '../journal/host_storage.js'; import { AvmPersistableStateManager } from '../journal/journal.js'; -import { type TracedContractInstance } from '../journal/trace_types.js'; +import { NullifierManager } from '../journal/nullifiers.js'; +import { PublicStorage } from '../journal/public_storage.js'; /** * Create a new AVM context with default values. @@ -28,7 +29,7 @@ export function initContext(overrides?: { machineState?: AvmMachineState; }): AvmContext { return new AvmContext( - overrides?.persistableState || initMockPersistableStateManager(), + overrides?.persistableState || initPersistableStateManager(), overrides?.env || initExecutionEnvironment(), overrides?.machineState || initMachineState(), ); @@ -47,9 +48,20 @@ export function initHostStorage(overrides?: { ); } -/** Creates an empty state manager with mocked storage. */ -export function initMockPersistableStateManager(): AvmPersistableStateManager { - return new AvmPersistableStateManager(initHostStorage()); +/** Creates an empty state manager with mocked host storage. */ +export function initPersistableStateManager(overrides?: { + hostStorage?: HostStorage; + trace?: PublicSideEffectTraceInterface; + publicStorage?: PublicStorage; + nullifiers?: NullifierManager; +}): AvmPersistableStateManager { + const hostStorage = overrides?.hostStorage || initHostStorage(); + return new AvmPersistableStateManager( + hostStorage, + overrides?.trace || mock(), + overrides?.publicStorage || new PublicStorage(hostStorage.publicStateDb), + overrides?.nullifiers || new NullifierManager(hostStorage.commitmentsDb), + ); } /** @@ -138,14 +150,3 @@ export function getAvmTestContractBytecode(functionName: string): Buffer { ); return artifact.bytecode; } - -export function randomTracedContractInstance(): TracedContractInstance { - const instance = SerializableContractInstance.random(); - const address = AztecAddress.random(); - return { exists: true, ...instance, address }; -} - -export function emptyTracedContractInstance(withAddress?: AztecAddress): TracedContractInstance { - const instance = SerializableContractInstance.empty().withAddress(withAddress ?? AztecAddress.zero()); - return { exists: false, ...instance }; -} diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index 77b7b3732b68..7d001d3ee6ac 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -1,445 +1,431 @@ -import { UnencryptedL2Log } from '@aztec/circuit-types'; -import { AztecAddress, EthAddress } from '@aztec/circuits.js'; -import { EventSelector } from '@aztec/foundation/abi'; +import { randomContractInstanceWithAddress } from '@aztec/circuit-types'; 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 { emptyTracedContractInstance, randomTracedContractInstance } from '../fixtures/index.js'; -import { HostStorage } from './host_storage.js'; -import { AvmPersistableStateManager, type JournalData } from './journal.js'; +import { SerializableContractInstance } from '@aztec/types/contracts'; + +import { mock } from 'jest-mock-extended'; + +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; +import { initHostStorage, initPersistableStateManager } from '../fixtures/index.js'; +import { + mockGetContractInstance, + mockL1ToL2MessageExists, + mockNoteHashExists, + mockNullifierExists, + mockStorageRead, +} from '../test_utils.js'; +import { type HostStorage } from './host_storage.js'; +import { type AvmPersistableStateManager } from './journal.js'; describe('journal', () => { - let publicDb: MockProxy; - let contractsDb: MockProxy; - let commitmentsDb: MockProxy; - let journal: AvmPersistableStateManager; + const address = Fr.random(); + const utxo = Fr.random(); + const leafIndex = Fr.random(); - beforeEach(() => { - publicDb = mock(); - commitmentsDb = mock(); - contractsDb = mock(); + let hostStorage: HostStorage; + let trace: PublicSideEffectTraceInterface; + let persistableState: AvmPersistableStateManager; - const hostStorage = new HostStorage(publicDb, contractsDb, commitmentsDb); - journal = new AvmPersistableStateManager(hostStorage); + beforeEach(() => { + hostStorage = initHostStorage(); + trace = mock(); + persistableState = initPersistableStateManager({ hostStorage, trace }); }); describe('Public Storage', () => { it('When reading from storage, should check the cache first, and be appended to read/write journal', async () => { // Store a different value in storage vs the cache, and make sure the cache is returned - const contractAddress = new Fr(1); - const key = new Fr(2); + const slot = new Fr(2); const storedValue = new Fr(420); const cachedValue = new Fr(69); - publicDb.storageRead.mockResolvedValue(Promise.resolve(storedValue)); + mockStorageRead(hostStorage, storedValue); // Get the cache first - const cacheMissResult = await journal.readStorage(contractAddress, key); + const cacheMissResult = await persistableState.readStorage(address, slot); expect(cacheMissResult).toEqual(storedValue); // Write to storage - journal.writeStorage(contractAddress, key, cachedValue); + persistableState.writeStorage(address, slot, cachedValue); // Get the storage value - const cachedResult = await journal.readStorage(contractAddress, key); + const cachedResult = await persistableState.readStorage(address, slot); expect(cachedResult).toEqual(cachedValue); + // confirm that peek works + expect(await persistableState.peekStorage(address, slot)).toEqual(cachedResult); // We expect the journal to store the access in [storedVal, cachedVal] - [time0, time1] - const { storageReads, storageWrites }: JournalData = journal.flush(); - expect(storageReads).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: storedValue, - }), - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: cachedValue, - }), - ]); - expect(storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - slot: key, - value: cachedValue, - }), - ]); + expect(trace.tracePublicStorageRead).toHaveBeenCalledTimes(2); + expect(trace.tracePublicStorageRead).toHaveBeenNthCalledWith( + /*nthCall=*/ 1, + address, + slot, + storedValue, + /*exists=*/ true, + /*cached=*/ false, + ); + expect(trace.tracePublicStorageRead).toHaveBeenNthCalledWith( + /*nthCall=*/ 2, + address, + slot, + cachedValue, + /*exists=*/ true, + /*cached=*/ true, + ); }); }); describe('UTXOs & messages', () => { - it('Should maintain commitments', () => { - const utxo = new Fr(1); - const address = new Fr(1234); - journal.writeNoteHash(address, utxo); - - const journalUpdates = journal.flush(); - expect(journalUpdates.newNoteHashes).toEqual([ - expect.objectContaining({ noteHash: utxo, storageAddress: address }), - ]); - }); - it('checkNullifierExists works for missing nullifiers', async () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - const exists = await journal.checkNullifierExists(contractAddress, utxo); + it('checkNoteHashExists works for missing note hashes', async () => { + const exists = await persistableState.checkNoteHashExists(address, utxo, leafIndex); expect(exists).toEqual(false); - - const journalUpdates = journal.flush(); - expect(journalUpdates.nullifierChecks).toEqual([expect.objectContaining({ nullifier: utxo, exists: false })]); + expect(trace.traceNoteHashCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNoteHashCheck).toHaveBeenCalledWith(address, utxo, leafIndex, exists); }); - it('checkNullifierExists works for existing nullifiers', async () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - const storedLeafIndex = BigInt(42); - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); - const exists = await journal.checkNullifierExists(contractAddress, utxo); + it('checkNoteHashExists works for existing note hashes', async () => { + mockNoteHashExists(hostStorage, leafIndex, utxo); + const exists = await persistableState.checkNoteHashExists(address, utxo, leafIndex); expect(exists).toEqual(true); - - const journalUpdates = journal.flush(); - expect(journalUpdates.nullifierChecks).toEqual([expect.objectContaining({ nullifier: utxo, exists: true })]); + expect(trace.traceNoteHashCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNoteHashCheck).toHaveBeenCalledWith(address, utxo, leafIndex, exists); }); - it('Should maintain nullifiers', async () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - await journal.writeNullifier(contractAddress, utxo); - - const journalUpdates = journal.flush(); - expect(journalUpdates.newNullifiers).toEqual([ - expect.objectContaining({ storageAddress: contractAddress, nullifier: utxo }), - ]); + + it('writeNoteHash works', () => { + persistableState.writeNoteHash(address, utxo); + expect(trace.traceNewNoteHash).toHaveBeenCalledTimes(1); + expect(trace.traceNewNoteHash).toHaveBeenCalledWith(expect.objectContaining(address), /*noteHash=*/ utxo); }); - it('checkL1ToL2MessageExists works for missing message', async () => { - const msgHash = new Fr(2); - const leafIndex = new Fr(42); - const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); + it('checkNullifierExists works for missing nullifiers', async () => { + const exists = await persistableState.checkNullifierExists(address, utxo); expect(exists).toEqual(false); - - const journalUpdates = journal.flush(); - expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: false }), - ]); + expect(trace.traceNullifierCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNullifierCheck).toHaveBeenCalledWith( + address, + utxo, + /*leafIndex=*/ Fr.ZERO, + exists, + /*isPending=*/ false, + ); }); - it('checkL1ToL2MessageExists works for existing msgHash', async () => { - const msgHash = new Fr(2); - const leafIndex = new Fr(42); - commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash); - const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); + it('checkNullifierExists works for existing nullifiers', async () => { + mockNullifierExists(hostStorage, leafIndex, utxo); + const exists = await persistableState.checkNullifierExists(address, utxo); expect(exists).toEqual(true); + expect(trace.traceNullifierCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNullifierCheck).toHaveBeenCalledWith(address, utxo, leafIndex, exists, /*isPending=*/ false); + }); - const journalUpdates = journal.flush(); - expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: true }), - ]); + it('writeNullifier works', async () => { + await persistableState.writeNullifier(address, utxo); + expect(trace.traceNewNullifier).toHaveBeenCalledWith(expect.objectContaining(address), /*nullifier=*/ utxo); }); - it('Should maintain nullifiers', async () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - await journal.writeNullifier(contractAddress, utxo); - - const journalUpdates = journal.flush(); - expect(journalUpdates.newNullifiers).toEqual([ - expect.objectContaining({ storageAddress: contractAddress, nullifier: utxo }), - ]); + + it('checkL1ToL2MessageExists works for missing message', async () => { + const exists = await persistableState.checkL1ToL2MessageExists(address, utxo, leafIndex); + expect(exists).toEqual(false); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith(address, utxo, leafIndex, exists); }); - it('Should maintain l1 messages', () => { - const recipient = EthAddress.fromField(new Fr(1)); - const msgHash = new Fr(2); - journal.writeL1Message(recipient, msgHash); - const journalUpdates = journal.flush(); - expect(journalUpdates.newL1Messages).toEqual([expect.objectContaining({ recipient, content: msgHash })]); + it('checkL1ToL2MessageExists works for existing message', async () => { + mockL1ToL2MessageExists(hostStorage, leafIndex, utxo); + const exists = await persistableState.checkL1ToL2MessageExists(address, utxo, leafIndex); + expect(exists).toEqual(true); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith(address, utxo, leafIndex, exists); }); - describe('Getting contract instances', () => { - it('Should get contract instance', async () => { - const contractAddress = AztecAddress.fromField(new Fr(2)); - const instance = randomTracedContractInstance(); - instance.exists = true; - contractsDb.getContractInstance.mockResolvedValue(Promise.resolve(instance)); - await journal.getContractInstance(contractAddress); - expect(journal.trace.gotContractInstances).toEqual([instance]); - }); - it('Can get undefined contract instance', async () => { - const contractAddress = AztecAddress.fromField(new Fr(2)); - await journal.getContractInstance(contractAddress); - const emptyInstance = emptyTracedContractInstance(AztecAddress.fromField(contractAddress)); - expect(journal.trace.gotContractInstances).toEqual([emptyInstance]); - }); + it('Should maintain l1 messages', () => { + const recipient = new Fr(1); + persistableState.writeL2ToL1Message(recipient, utxo); + expect(trace.traceNewL2ToL1Message).toHaveBeenCalledTimes(1); + expect(trace.traceNewL2ToL1Message).toHaveBeenCalledWith(recipient, utxo); }); }); - it('Should merge two successful journals together', async () => { - // Fundamentally checking that insert ordering of public storage is preserved upon journal merge - // time | journal | op | value - // t0 -> journal0 -> write | 1 - // t1 -> journal1 -> write | 2 - // merge journals - // t2 -> journal0 -> read | 2 - - const contractAddress = new Fr(1); - const aztecContractAddress = AztecAddress.fromField(contractAddress); - const key = new Fr(2); - const value = new Fr(1); - const valueT1 = new Fr(2); - const recipient = EthAddress.fromField(new Fr(42)); - const commitment = new Fr(10); - const commitmentT1 = new Fr(20); - const log = { address: 10n, selector: 5, data: [new Fr(5), new Fr(6)] }; - const logT1 = { address: 20n, selector: 8, data: [new Fr(7), new Fr(8)] }; - const index = new Fr(42); - const indexT1 = new Fr(24); - const instance = emptyTracedContractInstance(aztecContractAddress); - - journal.writeStorage(contractAddress, key, value); - await journal.readStorage(contractAddress, key); - journal.writeNoteHash(contractAddress, commitment); - journal.writeLog(new Fr(log.address), new Fr(log.selector), log.data); - journal.writeL1Message(recipient, commitment); - await journal.writeNullifier(contractAddress, commitment); - await journal.checkNullifierExists(contractAddress, commitment); - await journal.checkL1ToL2MessageExists(commitment, index); - await journal.getContractInstance(aztecContractAddress); - - const childJournal = new AvmPersistableStateManager(journal.hostStorage, journal); - childJournal.writeStorage(contractAddress, key, valueT1); - await childJournal.readStorage(contractAddress, key); - childJournal.writeNoteHash(contractAddress, commitmentT1); - childJournal.writeLog(new Fr(logT1.address), new Fr(logT1.selector), logT1.data); - childJournal.writeL1Message(recipient, commitmentT1); - await childJournal.writeNullifier(contractAddress, commitmentT1); - await childJournal.checkNullifierExists(contractAddress, commitmentT1); - await childJournal.checkL1ToL2MessageExists(commitmentT1, indexT1); - await childJournal.getContractInstance(aztecContractAddress); - - journal.acceptNestedCallState(childJournal); - - const result = await journal.readStorage(contractAddress, key); - expect(result).toEqual(valueT1); - - // Check that the storage is merged by reading from the journal - // Check that the UTXOs are merged - const journalUpdates: JournalData = journal.flush(); - - // Check storage reads order is preserved upon merge - // We first read value from t0, then value from t1 - expect(journalUpdates.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: value, - }), - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: valueT1, - }), - // Read a third time to check storage - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: valueT1, - }), - ]); - - // We first write value from t0, then value from t1 - expect(journalUpdates.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - slot: key, - value: value, - }), - expect.objectContaining({ - storageAddress: contractAddress, - slot: key, - value: valueT1, - }), - ]); - - expect(journalUpdates.newNoteHashes).toEqual([ - expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), - expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), - ]); - expect(journalUpdates.newLogs).toEqual([ - new UnencryptedL2Log( - AztecAddress.fromBigInt(log.address), - new EventSelector(log.selector), - Buffer.concat(log.data.map(f => f.toBuffer())), - ), - new UnencryptedL2Log( - AztecAddress.fromBigInt(logT1.address), - new EventSelector(logT1.selector), - Buffer.concat(logT1.data.map(f => f.toBuffer())), - ), - ]); - expect(journalUpdates.newL1Messages).toEqual([ - expect.objectContaining({ recipient, content: commitment }), - expect.objectContaining({ recipient, content: commitmentT1 }), - ]); - expect(journalUpdates.nullifierChecks).toEqual([ - expect.objectContaining({ nullifier: commitment, exists: true }), - expect.objectContaining({ nullifier: commitmentT1, exists: true }), - ]); - expect(journalUpdates.newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: commitment, - }), - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: commitmentT1, - }), - ]); - expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: index, msgHash: commitment, exists: false }), - expect.objectContaining({ leafIndex: indexT1, msgHash: commitmentT1, exists: false }), - ]); - expect(journal.trace.gotContractInstances).toEqual([instance, instance]); - }); + describe('Getting contract instances', () => { + it('Should get contract instance', async () => { + const contractInstance = randomContractInstanceWithAddress(/*(base instance) opts=*/ {}, /*address=*/ address); + mockGetContractInstance(hostStorage, contractInstance); + await persistableState.getContractInstance(address); + expect(trace.traceGetContractInstance).toHaveBeenCalledTimes(1); + expect(trace.traceGetContractInstance).toHaveBeenCalledWith({ exists: true, ...contractInstance }); + }); + it('Can get undefined contract instance', async () => { + const emptyContractInstance = SerializableContractInstance.empty().withAddress(address); + await persistableState.getContractInstance(address); - it('Should merge failed journals together', async () => { - // Checking public storage update journals are preserved upon journal merge, - // But the latest state is not - - // time | journal | op | value - // t0 -> journal0 -> write | 1 - // t1 -> journal1 -> write | 2 - // merge journals - // t2 -> journal0 -> read | 1 - - const contractAddress = new Fr(1); - const aztecContractAddress = AztecAddress.fromField(contractAddress); - const key = new Fr(2); - const value = new Fr(1); - const valueT1 = new Fr(2); - const recipient = EthAddress.fromField(new Fr(42)); - const commitment = new Fr(10); - const commitmentT1 = new Fr(20); - const log = { address: 10n, selector: 5, data: [new Fr(5), new Fr(6)] }; - const logT1 = { address: 20n, selector: 8, data: [new Fr(7), new Fr(8)] }; - const index = new Fr(42); - const indexT1 = new Fr(24); - const instance = emptyTracedContractInstance(aztecContractAddress); - - journal.writeStorage(contractAddress, key, value); - await journal.readStorage(contractAddress, key); - journal.writeNoteHash(contractAddress, commitment); - await journal.writeNullifier(contractAddress, commitment); - await journal.checkNullifierExists(contractAddress, commitment); - await journal.checkL1ToL2MessageExists(commitment, index); - journal.writeLog(new Fr(log.address), new Fr(log.selector), log.data); - journal.writeL1Message(recipient, commitment); - await journal.getContractInstance(aztecContractAddress); - - const childJournal = new AvmPersistableStateManager(journal.hostStorage, journal); - childJournal.writeStorage(contractAddress, key, valueT1); - await childJournal.readStorage(contractAddress, key); - childJournal.writeNoteHash(contractAddress, commitmentT1); - await childJournal.writeNullifier(contractAddress, commitmentT1); - await childJournal.checkNullifierExists(contractAddress, commitmentT1); - await journal.checkL1ToL2MessageExists(commitmentT1, indexT1); - childJournal.writeLog(new Fr(logT1.address), new Fr(logT1.selector), logT1.data); - childJournal.writeL1Message(recipient, commitmentT1); - await childJournal.getContractInstance(aztecContractAddress); - - journal.rejectNestedCallState(childJournal); - - // Check that the storage is reverted by reading from the journal - const result = await journal.readStorage(contractAddress, key); - expect(result).toEqual(value); // rather than valueT1 - - const journalUpdates: JournalData = journal.flush(); - - // Reads and writes should be preserved - // Check storage reads order is preserved upon merge - // We first read value from t0, then value from t1 - expect(journalUpdates.storageReads).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: value, - }), - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: valueT1, - }), - // Read a third time to check storage - expect.objectContaining({ - storageAddress: contractAddress, - exists: true, - slot: key, - value: value, - }), - ]); - - // We first write value from t0, then value from t1 - expect(journalUpdates.storageWrites).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - slot: key, - value: value, - }), - expect.objectContaining({ - storageAddress: contractAddress, - slot: key, - value: valueT1, - }), - ]); - - // Check that the world state _traces_ are merged even on rejection - expect(journalUpdates.newNoteHashes).toEqual([ - expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), - expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), - ]); - expect(journalUpdates.nullifierChecks).toEqual([ - expect.objectContaining({ nullifier: commitment, exists: true }), - expect.objectContaining({ nullifier: commitmentT1, exists: true }), - ]); - expect(journalUpdates.newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: commitment, - }), - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: commitmentT1, - }), - ]); - expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: index, msgHash: commitment, exists: false }), - expect.objectContaining({ leafIndex: indexT1, msgHash: commitmentT1, exists: false }), - ]); - - // Check that rejected Accrued Substate is absent - expect(journalUpdates.newLogs).toEqual([ - new UnencryptedL2Log( - AztecAddress.fromBigInt(log.address), - new EventSelector(log.selector), - Buffer.concat(log.data.map(f => f.toBuffer())), - ), - ]); - expect(journalUpdates.newL1Messages).toEqual([expect.objectContaining({ recipient, content: commitment })]); - expect(journal.trace.gotContractInstances).toEqual([instance, instance]); + expect(trace.traceGetContractInstance).toHaveBeenCalledTimes(1); + expect(trace.traceGetContractInstance).toHaveBeenCalledWith({ exists: false, ...emptyContractInstance }); + }); }); - it('Can fork and merge journals', () => { - const rootJournal = new AvmPersistableStateManager(journal.hostStorage); - const childJournal = rootJournal.fork(); - - expect(() => rootJournal.acceptNestedCallState(childJournal)); - expect(() => rootJournal.rejectNestedCallState(childJournal)); - }); + //it('Should merge two successful journals together', async () => { + // // Fundamentally checking that insert ordering of public storage is preserved upon journal merge + // // time | journal | op | value + // // t0 -> journal0 -> write | 1 + // // t1 -> journal1 -> write | 2 + // // merge journals + // // t2 -> journal0 -> read | 2 + + // const contractAddress = new Fr(1); + // const aztecContractAddress = AztecAddress.fromField(contractAddress); + // const key = new Fr(2); + // const value = new Fr(1); + // const valueT1 = new Fr(2); + // const recipient = EthAddress.fromField(new Fr(42)); + // const commitment = new Fr(10); + // const commitmentT1 = new Fr(20); + // const log = { address: 10n, selector: 5, data: [new Fr(5), new Fr(6)] }; + // const logT1 = { address: 20n, selector: 8, data: [new Fr(7), new Fr(8)] }; + // const index = new Fr(42); + // const indexT1 = new Fr(24); + // const instance = emptyTracedContractInstance(aztecContractAddress); + + // persistableState.writeStorage(contractAddress, key, value); + // await persistableState.readStorage(contractAddress, key); + // persistableState.writeNoteHash(contractAddress, commitment); + // persistableState.writeUnencryptedLog(new Fr(log.address), new Fr(log.selector), log.data); + // persistableState.writeL2ToL1Message(recipient, commitment); + // await persistableState.writeNullifier(contractAddress, commitment); + // await persistableState.checkNullifierExists(contractAddress, commitment); + // await persistableState.checkL1ToL2MessageExists(commitment, index); + // await persistableState.getContractInstance(aztecContractAddress); + + // const childJournal = new AvmPersistableStateManager(persistableState.hostStorage, persistableState); + // childJournal.writeStorage(contractAddress, key, valueT1); + // await childJournal.readStorage(contractAddress, key); + // childJournal.writeNoteHash(contractAddress, commitmentT1); + // childJournal.writeUnencryptedLog(new Fr(logT1.address), new Fr(logT1.selector), logT1.data); + // childJournal.writeL2ToL1Message(recipient, commitmentT1); + // await childJournal.writeNullifier(contractAddress, commitmentT1); + // await childJournal.checkNullifierExists(contractAddress, commitmentT1); + // await childJournal.checkL1ToL2MessageExists(commitmentT1, indexT1); + // await childJournal.getContractInstance(aztecContractAddress); + + // persistableState.acceptNestedCallState(childJournal); + + // const result = await persistableState.readStorage(contractAddress, key); + // expect(result).toEqual(valueT1); + + // // Check that the storage is merged by reading from the journal + // // Check that the UTXOs are merged + // const journalUpdates: JournalData = persistableState.getTrace()(); + + // // Check storage reads order is preserved upon merge + // // We first read value from t0, then value from t1 + // expect(journalUpdates.storageReads).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: value, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: valueT1, + // }), + // // Read a third time to check storage + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: valueT1, + // }), + // ]); + + // // We first write value from t0, then value from t1 + // expect(journalUpdates.storageWrites).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // slot: key, + // value: value, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // slot: key, + // value: valueT1, + // }), + // ]); + + // expect(journalUpdates.newNoteHashes).toEqual([ + // expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), + // expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), + // ]); + // expect(journalUpdates.newLogs).toEqual([ + // new UnencryptedL2Log( + // AztecAddress.fromBigInt(log.address), + // new EventSelector(log.selector), + // Buffer.concat(log.data.map(f => f.toBuffer())), + // ), + // new UnencryptedL2Log( + // AztecAddress.fromBigInt(logT1.address), + // new EventSelector(logT1.selector), + // Buffer.concat(logT1.data.map(f => f.toBuffer())), + // ), + // ]); + // expect(journalUpdates.newL1Messages).toEqual([ + // expect.objectContaining({ recipient, content: commitment }), + // expect.objectContaining({ recipient, content: commitmentT1 }), + // ]); + // expect(journalUpdates.nullifierChecks).toEqual([ + // expect.objectContaining({ nullifier: commitment, exists: true }), + // expect.objectContaining({ nullifier: commitmentT1, exists: true }), + // ]); + // expect(journalUpdates.newNullifiers).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // nullifier: commitment, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // nullifier: commitmentT1, + // }), + // ]); + // expect(journalUpdates.l1ToL2MessageChecks).toEqual([ + // expect.objectContaining({ leafIndex: index, msgHash: commitment, exists: false }), + // expect.objectContaining({ leafIndex: indexT1, msgHash: commitmentT1, exists: false }), + // ]); + // expect(persistableState.trace.gotContractInstances).toEqual([instance, instance]); + //}); + + //it('Should merge failed journals together', async () => { + // // Checking public storage update journals are preserved upon journal merge, + // // But the latest state is not + + // // time | journal | op | value + // // t0 -> journal0 -> write | 1 + // // t1 -> journal1 -> write | 2 + // // merge journals + // // t2 -> journal0 -> read | 1 + + // const contractAddress = new Fr(1); + // const aztecContractAddress = AztecAddress.fromField(contractAddress); + // const key = new Fr(2); + // const value = new Fr(1); + // const valueT1 = new Fr(2); + // const recipient = EthAddress.fromField(new Fr(42)); + // const commitment = new Fr(10); + // const commitmentT1 = new Fr(20); + // const log = { address: 10n, selector: 5, data: [new Fr(5), new Fr(6)] }; + // const logT1 = { address: 20n, selector: 8, data: [new Fr(7), new Fr(8)] }; + // const index = new Fr(42); + // const indexT1 = new Fr(24); + // const instance = emptyTracedContractInstance(aztecContractAddress); + + // persistableState.writeStorage(contractAddress, key, value); + // await persistableState.readStorage(contractAddress, key); + // persistableState.writeNoteHash(contractAddress, commitment); + // await persistableState.writeNullifier(contractAddress, commitment); + // await persistableState.checkNullifierExists(contractAddress, commitment); + // await persistableState.checkL1ToL2MessageExists(commitment, index); + // persistableState.writeUnencryptedLog(new Fr(log.address), new Fr(log.selector), log.data); + // persistableState.writeL2ToL1Message(recipient, commitment); + // await persistableState.getContractInstance(aztecContractAddress); + + // const childJournal = new AvmPersistableStateManager(persistableState.hostStorage, persistableState); + // childJournal.writeStorage(contractAddress, key, valueT1); + // await childJournal.readStorage(contractAddress, key); + // childJournal.writeNoteHash(contractAddress, commitmentT1); + // await childJournal.writeNullifier(contractAddress, commitmentT1); + // await childJournal.checkNullifierExists(contractAddress, commitmentT1); + // await persistableState.checkL1ToL2MessageExists(commitmentT1, indexT1); + // childJournal.writeUnencryptedLog(new Fr(logT1.address), new Fr(logT1.selector), logT1.data); + // childJournal.writeL2ToL1Message(recipient, commitmentT1); + // await childJournal.getContractInstance(aztecContractAddress); + + // persistableState.rejectNestedCallState(childJournal); + + // // Check that the storage is reverted by reading from the journal + // const result = await persistableState.readStorage(contractAddress, key); + // expect(result).toEqual(value); // rather than valueT1 + + // const journalUpdates: JournalData = persistableState.getTrace()(); + + // // Reads and writes should be preserved + // // Check storage reads order is preserved upon merge + // // We first read value from t0, then value from t1 + // expect(journalUpdates.storageReads).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: value, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: valueT1, + // }), + // // Read a third time to check storage + // expect.objectContaining({ + // storageAddress: contractAddress, + // exists: true, + // slot: key, + // value: value, + // }), + // ]); + + // // We first write value from t0, then value from t1 + // expect(journalUpdates.storageWrites).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // slot: key, + // value: value, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // slot: key, + // value: valueT1, + // }), + // ]); + + // // Check that the world state _traces_ are merged even on rejection + // expect(journalUpdates.newNoteHashes).toEqual([ + // expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), + // expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), + // ]); + // expect(journalUpdates.nullifierChecks).toEqual([ + // expect.objectContaining({ nullifier: commitment, exists: true }), + // expect.objectContaining({ nullifier: commitmentT1, exists: true }), + // ]); + // expect(journalUpdates.newNullifiers).toEqual([ + // expect.objectContaining({ + // storageAddress: contractAddress, + // nullifier: commitment, + // }), + // expect.objectContaining({ + // storageAddress: contractAddress, + // nullifier: commitmentT1, + // }), + // ]); + // expect(journalUpdates.l1ToL2MessageChecks).toEqual([ + // expect.objectContaining({ leafIndex: index, msgHash: commitment, exists: false }), + // expect.objectContaining({ leafIndex: indexT1, msgHash: commitmentT1, exists: false }), + // ]); + + // // Check that rejected Accrued Substate is absent + // expect(journalUpdates.newLogs).toEqual([ + // new UnencryptedL2Log( + // AztecAddress.fromBigInt(log.address), + // new EventSelector(log.selector), + // Buffer.concat(log.data.map(f => f.toBuffer())), + // ), + // ]); + // expect(journalUpdates.newL1Messages).toEqual([expect.objectContaining({ recipient, content: commitment })]); + // expect(persistableState.trace.gotContractInstances).toEqual([instance, instance]); + //}); + + //it('Can fork and merge journals', () => { + // const rootJournal = new AvmPersistableStateManager(persistableState.hostStorage); + // const childJournal = rootJournal.fork(); + + // expect(() => rootJournal.acceptNestedCallState(childJournal)); + // expect(() => rootJournal.rejectNestedCallState(childJournal)); + //}); }); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index dd028a63db97..06e6465385fc 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -1,139 +1,69 @@ -// TODO(5818): Rename file and all uses of "journal" -import { UnencryptedL2Log } from '@aztec/circuit-types'; -import { - AztecAddress, - ContractStorageRead, - ContractStorageUpdateRequest, - EthAddress, - L2ToL1Message, - LogHash, - NoteHash, - Nullifier, - ReadRequest, -} from '@aztec/circuits.js'; -import { EventSelector } from '@aztec/foundation/abi'; -import { Fr } from '@aztec/foundation/fields'; +import { AztecAddress, type FunctionSelector, type Gas } from '@aztec/circuits.js'; +import { type Fr } from '@aztec/foundation/fields'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { SerializableContractInstance } from '@aztec/types/contracts'; -import { type PublicExecutionResult } from '../../index.js'; +import { type TracedContractInstance } from '../../public/side_effect_trace.js'; +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; +import { type AvmExecutionEnvironment } from '../avm_execution_environment.js'; +import { type AvmContractCallResults } from '../avm_message_call_result.js'; import { type HostStorage } from './host_storage.js'; -import { Nullifiers } from './nullifiers.js'; +import { NullifierManager } from './nullifiers.js'; import { PublicStorage } from './public_storage.js'; -import { WorldStateAccessTrace } from './trace.js'; -import { - type TracedContractInstance, - type TracedL1toL2MessageCheck, - type TracedNoteHash, - type TracedNoteHashCheck, - type TracedNullifier, - type TracedNullifierCheck, - type TracedPublicStorageRead, - type TracedPublicStorageWrite, - type TracedUnencryptedL2Log, -} from './trace_types.js'; - -// TODO:(5818): do we need this type anymore? -/** - * Data held within the journal - */ -export type JournalData = { - storageWrites: TracedPublicStorageWrite[]; - storageReads: TracedPublicStorageRead[]; - - noteHashChecks: TracedNoteHashCheck[]; - newNoteHashes: TracedNoteHash[]; - nullifierChecks: TracedNullifierCheck[]; - newNullifiers: TracedNullifier[]; - l1ToL2MessageChecks: TracedL1toL2MessageCheck[]; - - newL1Messages: L2ToL1Message[]; - newLogs: UnencryptedL2Log[]; - newLogsHashes: TracedUnencryptedL2Log[]; - /** contract address -\> key -\> value */ - currentStorageValue: Map>; - - sideEffectCounter: number; -}; - -// TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit -export type PartialPublicExecutionResult = { - noteHashReadRequests: ReadRequest[]; - nullifierReadRequests: ReadRequest[]; - nullifierNonExistentReadRequests: ReadRequest[]; - l1ToL2MsgReadRequests: ReadRequest[]; - newNoteHashes: NoteHash[]; - newL2ToL1Messages: L2ToL1Message[]; - startSideEffectCounter: number; - newNullifiers: Nullifier[]; - contractStorageReads: ContractStorageRead[]; - contractStorageUpdateRequests: ContractStorageUpdateRequest[]; - unencryptedLogsHashes: LogHash[]; - unencryptedLogs: UnencryptedL2Log[]; - allUnencryptedLogs: UnencryptedL2Log[]; - nestedExecutions: PublicExecutionResult[]; -}; /** * A class to manage persistable AVM state for contract calls. * Maintains a cache of the current world state, - * a trace of all world state accesses, and a list of accrued substate items. + * a trace of all side effects. * - * The simulator should make any world state and accrued substate queries through this object. + * The simulator should make any world state / tree queries through this object. * * Manages merging of successful/reverted child state into current state. */ export class AvmPersistableStateManager { private readonly log: DebugLogger = createDebugLogger('aztec:avm_simulator:state_manager'); - /** Reference to node storage */ - public readonly hostStorage: HostStorage; - - // TODO(5818): make members private once this is not used in transitional_adaptors.ts. - /** World State */ - /** Public storage, including cached writes */ - public publicStorage: PublicStorage; - /** Nullifier set, including cached/recently-emitted nullifiers */ - public nullifiers: Nullifiers; - /** World State Access Trace */ - public trace: WorldStateAccessTrace; + constructor( + /** Reference to node storage */ + private hostStorage: HostStorage, + /** Side effect trace */ + private trace: PublicSideEffectTraceInterface, + /** Public storage, including cached writes */ + public readonly publicStorage: PublicStorage, + /** Nullifier set, including cached/recently-emitted nullifiers */ + private readonly nullifiers: NullifierManager, + ) {} - /** Accrued Substate **/ - public newL1Messages: L2ToL1Message[] = []; - public newLogs: UnencryptedL2Log[] = []; - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - public transitionalExecutionResult: PartialPublicExecutionResult; - - constructor(hostStorage: HostStorage, parent?: AvmPersistableStateManager) { - this.hostStorage = hostStorage; - this.publicStorage = new PublicStorage(hostStorage.publicStateDb, parent?.publicStorage); - this.nullifiers = new Nullifiers(hostStorage.commitmentsDb, parent?.nullifiers); - this.trace = new WorldStateAccessTrace(parent?.trace); - - this.transitionalExecutionResult = { - noteHashReadRequests: [], - nullifierReadRequests: [], - nullifierNonExistentReadRequests: [], - l1ToL2MsgReadRequests: [], - newNoteHashes: [], - newL2ToL1Messages: [], - startSideEffectCounter: this.trace.accessCounter, - newNullifiers: [], - contractStorageReads: [], - contractStorageUpdateRequests: [], - unencryptedLogsHashes: [], - unencryptedLogs: [], - allUnencryptedLogs: [], - nestedExecutions: [], - }; + /** + * Create a new state manager with some preloaded pending siloed nullifiers + */ + public static newWithPendingSiloedNullifiers( + hostStorage: HostStorage, + trace: PublicSideEffectTraceInterface, + pendingSiloedNullifiers: Fr[], + ) { + const parentNullifiers = NullifierManager.newWithPendingSiloedNullifiers( + hostStorage.commitmentsDb, + pendingSiloedNullifiers, + ); + return new AvmPersistableStateManager( + hostStorage, + trace, + /*publicStorage=*/ new PublicStorage(hostStorage.publicStateDb), + /*nullifiers=*/ parentNullifiers.fork(), + ); } /** * Create a new state manager forked from this one */ public fork() { - return new AvmPersistableStateManager(this.hostStorage, this); + return new AvmPersistableStateManager( + this.hostStorage, + this.trace.fork(), + this.publicStorage.fork(), + this.nullifiers.fork(), + ); } /** @@ -147,13 +77,6 @@ export class AvmPersistableStateManager { this.log.debug(`Storage write (address=${storageAddress}, slot=${slot}): value=${value}`); // Cache storage writes for later reference/reads this.publicStorage.write(storageAddress, slot, value); - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.contractStorageUpdateRequests.push( - new ContractStorageUpdateRequest(slot, value, this.trace.accessCounter, storageAddress), - ); - - // Trace all storage writes (even reverted ones) this.trace.tracePublicStorageWrite(storageAddress, slot, value); } @@ -169,14 +92,22 @@ export class AvmPersistableStateManager { this.log.debug( `Storage read (address=${storageAddress}, slot=${slot}): value=${value}, exists=${exists}, cached=${cached}`, ); + this.trace.tracePublicStorageRead(storageAddress, slot, value, exists, cached); + return Promise.resolve(value); + } - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.contractStorageReads.push( - new ContractStorageRead(slot, value, this.trace.accessCounter, storageAddress), + /** + * Read from public storage, don't trace the read. + * + * @param storageAddress - the address of the contract whose storage is being read from + * @param slot - the slot in the contract's storage being read from + * @returns the latest value written to slot, or 0 if never written to before + */ + public async peekStorage(storageAddress: Fr, slot: Fr): Promise { + const { value, exists, cached } = await this.publicStorage.read(storageAddress, slot); + this.log.debug( + `Storage peek (address=${storageAddress}, slot=${slot}): value=${value}, exists=${exists}, cached=${cached}`, ); - - // We want to keep track of all performed reads (even reverted ones) - this.trace.tracePublicStorageRead(storageAddress, slot, value, exists, cached); return Promise.resolve(value); } @@ -193,11 +124,7 @@ export class AvmPersistableStateManager { const gotLeafIndex = await this.hostStorage.commitmentsDb.getCommitmentIndex(noteHash); const exists = gotLeafIndex === leafIndex.toBigInt(); this.log.debug(`noteHashes(${storageAddress})@${noteHash} ?? leafIndex: ${leafIndex}, exists: ${exists}.`); - - // TODO: include exists here also - This can for sure come from the trace??? - this.transitionalExecutionResult.noteHashReadRequests.push(new ReadRequest(noteHash, this.trace.accessCounter)); - - this.trace.traceNoteHashCheck(storageAddress, noteHash, exists, leafIndex); + this.trace.traceNoteHashCheck(storageAddress, noteHash, leafIndex, exists); return Promise.resolve(exists); } @@ -206,9 +133,6 @@ export class AvmPersistableStateManager { * @param noteHash - the unsiloed note hash to write */ public writeNoteHash(storageAddress: Fr, noteHash: Fr) { - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.newNoteHashes.push(new NoteHash(noteHash, this.trace.accessCounter)); - this.log.debug(`noteHashes(${storageAddress}) += @${noteHash}.`); this.trace.traceNewNoteHash(storageAddress, noteHash); } @@ -222,19 +146,9 @@ export class AvmPersistableStateManager { public async checkNullifierExists(storageAddress: Fr, nullifier: Fr): Promise { const [exists, isPending, leafIndex] = await this.nullifiers.checkExists(storageAddress, nullifier); this.log.debug( - `nullifiers(${storageAddress})@${nullifier} ?? leafIndex: ${leafIndex}, pending: ${isPending}, exists: ${exists}.`, + `nullifiers(${storageAddress})@${nullifier} ?? leafIndex: ${leafIndex}, exists: ${exists}, pending: ${isPending}.`, ); - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - if (exists) { - this.transitionalExecutionResult.nullifierReadRequests.push(new ReadRequest(nullifier, this.trace.accessCounter)); - } else { - this.transitionalExecutionResult.nullifierNonExistentReadRequests.push( - new ReadRequest(nullifier, this.trace.accessCounter), - ); - } - - this.trace.traceNullifierCheck(storageAddress, nullifier, exists, isPending, leafIndex); + this.trace.traceNullifierCheck(storageAddress, nullifier, leafIndex, exists, isPending); return Promise.resolve(exists); } @@ -244,11 +158,6 @@ export class AvmPersistableStateManager { * @param nullifier - the unsiloed nullifier to write */ public async writeNullifier(storageAddress: Fr, nullifier: Fr) { - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.newNullifiers.push( - new Nullifier(nullifier, this.trace.accessCounter, /*noteHash=*/ Fr.ZERO), - ); - this.log.debug(`nullifiers(${storageAddress}) += ${nullifier}.`); // Cache pending nullifiers for later access await this.nullifiers.append(storageAddress, nullifier); @@ -262,16 +171,13 @@ export class AvmPersistableStateManager { * @param msgLeafIndex - the message leaf index to use in the check * @returns exists - whether the message exists in the L1 to L2 Messages tree */ - public async checkL1ToL2MessageExists(msgHash: Fr, msgLeafIndex: Fr): Promise { + public async checkL1ToL2MessageExists(contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr): Promise { 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.transitionalExecutionResult.l1ToL2MsgReadRequests.push(new ReadRequest(msgHash, this.trace.accessCounter)); - - this.trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, exists); + this.trace.traceL1ToL2MessageCheck(contractAddress, msgHash, msgLeafIndex, exists); return Promise.resolve(exists); } @@ -280,40 +186,27 @@ export class AvmPersistableStateManager { * @param recipient - L1 contract address to send the message to. * @param content - Message content. */ - public writeL1Message(recipient: EthAddress | Fr, content: Fr) { + public writeL2ToL1Message(recipient: Fr, content: Fr) { this.log.debug(`L1Messages(${recipient}) += ${content}.`); - const recipientAddress = recipient instanceof EthAddress ? recipient : EthAddress.fromField(recipient); - const message = new L2ToL1Message(recipientAddress, content, 0); - this.newL1Messages.push(message); - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.newL2ToL1Messages.push(message); + this.trace.traceNewL2ToL1Message(recipient, content); } - public writeLog(contractAddress: Fr, event: Fr, log: Fr[]) { + /** + * Write an unencrypted log + * @param contractAddress - address of the contract that emitted the log + * @param event - log event selector + * @param log - log contents + */ + public writeUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]) { this.log.debug(`UnencryptedL2Log(${contractAddress}) += event ${event} with ${log.length} fields.`); - const ulog = new UnencryptedL2Log( - AztecAddress.fromField(contractAddress), - EventSelector.fromField(event), - Buffer.concat(log.map(f => f.toBuffer())), - ); - const logHash = Fr.fromBuffer(ulog.hash()); - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.unencryptedLogs.push(ulog); - this.transitionalExecutionResult.allUnencryptedLogs.push(ulog); - // this duplicates exactly what happens in the trace just for the purpose of transitional integration with the kernel - this.transitionalExecutionResult.unencryptedLogsHashes.push( - // TODO(6578): explain magic number 4 here - new LogHash(logHash, this.trace.accessCounter, new Fr(ulog.length + 4)), - ); - // TODO(6206): likely need to track this here and not just in the transitional logic. - - // TODO(6205): why are logs pushed here but logs hashes are traced? - this.newLogs.push(ulog); - this.trace.traceNewLog(logHash); + this.trace.traceUnencryptedLog(contractAddress, event, log); } + /** + * Get a contract instance. + * @param contractAddress - address of the contract instance to retrieve. + * @returns the contract instance with an "exists" flag + */ public async getContractInstance(contractAddress: Fr): Promise { let exists = true; const aztecAddress = AztecAddress.fromField(contractAddress); @@ -322,59 +215,57 @@ export class AvmPersistableStateManager { instance = SerializableContractInstance.empty().withAddress(aztecAddress); exists = false; } + this.log.debug( + `Get Contract instance (address=${contractAddress}): exists=${exists}, instance=${JSON.stringify(instance)}`, + ); const tracedInstance = { ...instance, exists }; this.trace.traceGetContractInstance(tracedInstance); return Promise.resolve(tracedInstance); } /** - * Accept nested world state modifications, merging in its trace and accrued substate + * Accept nested world state modifications */ - public acceptNestedCallState(nestedJournal: AvmPersistableStateManager) { - // Merge Public Storage - this.publicStorage.acceptAndMerge(nestedJournal.publicStorage); - - // Merge World State Access Trace - this.trace.acceptAndMerge(nestedJournal.trace); - - // Accrued Substate - this.newL1Messages.push(...nestedJournal.newL1Messages); - this.newLogs.push(...nestedJournal.newLogs); - - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit - this.transitionalExecutionResult.allUnencryptedLogs.push( - ...nestedJournal.transitionalExecutionResult.allUnencryptedLogs, - ); + public acceptNestedCallState(nestedState: AvmPersistableStateManager) { + this.publicStorage.acceptAndMerge(nestedState.publicStorage); + this.nullifiers.acceptAndMerge(nestedState.nullifiers); } /** - * Reject nested world state, merging in its trace, but not accepting any state modifications + * Get a contract's bytecode from the contracts DB */ - public rejectNestedCallState(nestedJournal: AvmPersistableStateManager) { - // Merge World State Access Trace - this.trace.acceptAndMerge(nestedJournal.trace); + public async getBytecode(contractAddress: AztecAddress, selector: FunctionSelector): Promise { + return await this.hostStorage.contractsDb.getBytecode(contractAddress, selector); } - // TODO:(5818): do we need this type anymore? /** - * Access the current state of the journal - * - * @returns a JournalData object + * Accept the nested call's state and trace the nested call */ - public flush(): JournalData { - return { - noteHashChecks: this.trace.noteHashChecks, - newNoteHashes: this.trace.newNoteHashes, - nullifierChecks: this.trace.nullifierChecks, - newNullifiers: this.trace.newNullifiers, - 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, - sideEffectCounter: this.trace.accessCounter, - }; + public async processNestedCall( + nestedState: AvmPersistableStateManager, + success: boolean, + nestedEnvironment: AvmExecutionEnvironment, + startGasLeft: Gas, + endGasLeft: Gas, + bytecode: Buffer, + avmCallResults: AvmContractCallResults, + ) { + if (success) { + this.acceptNestedCallState(nestedState); + } + const functionName = + (await nestedState.hostStorage.contractsDb.getDebugFunctionName( + nestedEnvironment.address, + nestedEnvironment.temporaryFunctionSelector, + )) ?? `${nestedEnvironment.address}:${nestedEnvironment.temporaryFunctionSelector}`; + this.trace.traceNestedCall( + nestedState.trace, + nestedEnvironment, + startGasLeft, + endGasLeft, + bytecode, + avmCallResults, + functionName, + ); } } diff --git a/yarn-project/simulator/src/avm/journal/nullifiers.test.ts b/yarn-project/simulator/src/avm/journal/nullifiers.test.ts index f8cec85bd92b..8a215a542288 100644 --- a/yarn-project/simulator/src/avm/journal/nullifiers.test.ts +++ b/yarn-project/simulator/src/avm/journal/nullifiers.test.ts @@ -3,15 +3,15 @@ import { Fr } from '@aztec/foundation/fields'; import { type MockProxy, mock } from 'jest-mock-extended'; import { type CommitmentsDB } from '../../index.js'; -import { Nullifiers } from './nullifiers.js'; +import { NullifierManager } from './nullifiers.js'; describe('avm nullifier caching', () => { let commitmentsDb: MockProxy; - let nullifiers: Nullifiers; + let nullifiers: NullifierManager; beforeEach(() => { commitmentsDb = mock(); - nullifiers = new Nullifiers(commitmentsDb); + nullifiers = new NullifierManager(commitmentsDb); }); describe('Nullifier caching and existence checks', () => { @@ -42,7 +42,7 @@ describe('avm nullifier caching', () => { const nullifier = new Fr(2); const storedLeafIndex = BigInt(420); - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); + commitmentsDb.getNullifierIndex.mockResolvedValue(storedLeafIndex); const [exists, isPending, gotIndex] = await nullifiers.checkExists(contractAddress, nullifier); // exists (in host), not pending, tree index retrieved from host @@ -53,7 +53,7 @@ describe('avm nullifier caching', () => { it('Existence check works on fallback to parent (gets value, exists, is pending)', async () => { const contractAddress = new Fr(1); const nullifier = new Fr(2); - const childNullifiers = new Nullifiers(commitmentsDb, nullifiers); + const childNullifiers = nullifiers.fork(); // Write to parent cache await nullifiers.append(contractAddress, nullifier); @@ -67,8 +67,8 @@ describe('avm nullifier caching', () => { it('Existence check works on fallback to grandparent (gets value, exists, is pending)', async () => { const contractAddress = new Fr(1); const nullifier = new Fr(2); - const childNullifiers = new Nullifiers(commitmentsDb, nullifiers); - const grandChildNullifiers = new Nullifiers(commitmentsDb, childNullifiers); + const childNullifiers = nullifiers.fork(); + const grandChildNullifiers = childNullifiers.fork(); // Write to parent cache await nullifiers.append(contractAddress, nullifier); @@ -99,7 +99,7 @@ describe('avm nullifier caching', () => { // Append a nullifier to parent await nullifiers.append(contractAddress, nullifier); - const childNullifiers = new Nullifiers(commitmentsDb, nullifiers); + const childNullifiers = nullifiers.fork(); // Can't append again in child await expect(childNullifiers.append(contractAddress, nullifier)).rejects.toThrow( `Nullifier ${nullifier} at contract ${contractAddress} already exists in parent cache or host.`, @@ -111,7 +111,7 @@ describe('avm nullifier caching', () => { const storedLeafIndex = BigInt(420); // Nullifier exists in host - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); + commitmentsDb.getNullifierIndex.mockResolvedValue(storedLeafIndex); // Can't append to cache await expect(nullifiers.append(contractAddress, nullifier)).rejects.toThrow( `Nullifier ${nullifier} at contract ${contractAddress} already exists in parent cache or host.`, @@ -128,7 +128,7 @@ describe('avm nullifier caching', () => { // Append a nullifier to parent await nullifiers.append(contractAddress, nullifier0); - const childNullifiers = new Nullifiers(commitmentsDb, nullifiers); + const childNullifiers = nullifiers.fork(); // Append a nullifier to child await childNullifiers.append(contractAddress, nullifier1); @@ -149,7 +149,7 @@ describe('avm nullifier caching', () => { await nullifiers.append(contractAddress, nullifier); // Create child cache, don't derive from parent so we can concoct a collision on merge - const childNullifiers = new Nullifiers(commitmentsDb); + const childNullifiers = new NullifierManager(commitmentsDb); // Append a nullifier to child await childNullifiers.append(contractAddress, nullifier); diff --git a/yarn-project/simulator/src/avm/journal/nullifiers.ts b/yarn-project/simulator/src/avm/journal/nullifiers.ts index e580c1a885c1..a4d23a357e21 100644 --- a/yarn-project/simulator/src/avm/journal/nullifiers.ts +++ b/yarn-project/simulator/src/avm/journal/nullifiers.ts @@ -9,17 +9,29 @@ import type { CommitmentsDB } from '../../index.js'; * Maintains a nullifier cache, and ensures that existence checks fall back to the correct source. * When a contract call completes, its cached nullifier set can be merged into its parent's. */ -export class Nullifiers { - /** Cached nullifiers. */ - public cache: NullifierCache; - +export class NullifierManager { constructor( /** Reference to node storage. Checked on parent cache-miss. */ private readonly hostNullifiers: CommitmentsDB, - /** Parent's nullifiers. Checked on this' cache-miss. */ - private readonly parent?: Nullifiers | undefined, - ) { - this.cache = new NullifierCache(); + /** Cached nullifiers. */ + private readonly cache: NullifierCache = new NullifierCache(), + /** Parent nullifier manager to fall back on */ + private readonly parent?: NullifierManager, + ) {} + + /** + * Create a new nullifiers manager with some preloaded pending siloed nullifiers + */ + public static newWithPendingSiloedNullifiers(hostNullifiers: CommitmentsDB, pendingSiloedNullifiers: Fr[]) { + const cache = new NullifierCache(pendingSiloedNullifiers); + return new NullifierManager(hostNullifiers, cache); + } + + /** + * Create a new nullifiers manager forked from this one + */ + public fork() { + return new NullifierManager(this.hostNullifiers, new NullifierCache(), this); } /** @@ -92,7 +104,7 @@ export class Nullifiers { * * @param incomingNullifiers - the incoming cached nullifiers to merge into this instance's */ - public acceptAndMerge(incomingNullifiers: Nullifiers) { + public acceptAndMerge(incomingNullifiers: NullifierManager) { this.cache.acceptAndMerge(incomingNullifiers.cache); } } @@ -111,6 +123,15 @@ export class NullifierCache { private cachePerContract: Map> = new Map(); private siloedNullifiers: Set = new Set(); + /** + * @parem siloedNullifierFrs: optional list of pending siloed nullifiers to initialize this cache with + */ + constructor(siloedNullifierFrs?: Fr[]) { + if (siloedNullifierFrs !== undefined) { + siloedNullifierFrs.forEach(nullifier => this.siloedNullifiers.add(nullifier.toBigInt())); + } + } + /** * Check whether a nullifier exists in the cache. * @@ -147,10 +168,6 @@ export class NullifierCache { nullifiersForContract.add(nullifier.toBigInt()); } - public appendSiloed(siloedNullifier: Fr) { - this.siloedNullifiers.add(siloedNullifier.toBigInt()); - } - /** * Merge another cache's nullifiers into this instance's. * diff --git a/yarn-project/simulator/src/avm/journal/public_storage.test.ts b/yarn-project/simulator/src/avm/journal/public_storage.test.ts index 1d6359caef95..3b20b5cae3ba 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.test.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.test.ts @@ -44,7 +44,7 @@ describe('avm public storage', () => { const slot = new Fr(2); const storedValue = new Fr(420); // ensure that fallback to host gets a value - publicDb.storageRead.mockResolvedValue(Promise.resolve(storedValue)); + publicDb.storageRead.mockResolvedValue(storedValue); const { exists, value: gotValue, cached } = await publicStorage.read(contractAddress, slot); // it exists in the host, so it must've been written before @@ -90,7 +90,7 @@ describe('avm public storage', () => { const parentValue = new Fr(69); const cachedValue = new Fr(1337); - publicDb.storageRead.mockResolvedValue(Promise.resolve(storedValue)); + publicDb.storageRead.mockResolvedValue(storedValue); const childStorage = new PublicStorage(publicDb, publicStorage); // Cache miss falls back to host diff --git a/yarn-project/simulator/src/avm/journal/public_storage.ts b/yarn-project/simulator/src/avm/journal/public_storage.ts index 6019934c201d..4dee472ab240 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.ts @@ -27,6 +27,13 @@ export class PublicStorage { this.cache = new PublicStorageCache(); } + /** + * Create a new public storage manager forked from this one + */ + public fork() { + return new PublicStorage(this.hostPublicStorage, this); + } + /** * Get the pending storage. */ @@ -71,6 +78,9 @@ export class PublicStorage { // Finally try the host's Aztec state (a trip to the database) if (!value) { value = await this.hostPublicStorage.storageRead(storageAddress, slot); + // TODO(dbanks12): if value retrieved from host storage, we can cache it here + // any future reads to the same slot can read from cache instead of more expensive + // DB access } else { cached = true; } diff --git a/yarn-project/simulator/src/avm/journal/trace.test.ts b/yarn-project/simulator/src/avm/journal/trace.test.ts deleted file mode 100644 index a143ce4e3be4..000000000000 --- a/yarn-project/simulator/src/avm/journal/trace.test.ts +++ /dev/null @@ -1,294 +0,0 @@ -import { Fr } from '@aztec/foundation/fields'; - -import { randomTracedContractInstance } from '../fixtures/index.js'; -import { WorldStateAccessTrace } from './trace.js'; -import { type TracedL1toL2MessageCheck, type TracedNullifier, type TracedNullifierCheck } from './trace_types.js'; - -describe('world state access trace', () => { - let trace: WorldStateAccessTrace; - - beforeEach(() => { - trace = new WorldStateAccessTrace(); - }); - - describe('Basic tracing', () => { - it('Should trace note hash checks', () => { - const contractAddress = new Fr(1); - const noteHash = new Fr(2); - const exists = true; - const leafIndex = new Fr(42); - - trace.traceNoteHashCheck(contractAddress, noteHash, exists, leafIndex); - - expect(trace.noteHashChecks).toEqual([ - { - // callPointer: expect.any(Fr), - storageAddress: contractAddress, - noteHash: noteHash, - exists: exists, - counter: Fr.ZERO, // 0th access - // endLifetime: expect.any(Fr), - leafIndex: leafIndex, - }, - ]); - expect(trace.getAccessCounter()).toBe(1); - }); - it('Should trace note hashes', () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - - trace.traceNewNoteHash(contractAddress, utxo); - - expect(trace.newNoteHashes).toEqual([ - expect.objectContaining({ storageAddress: contractAddress, noteHash: utxo }), - ]); - expect(trace.getAccessCounter()).toEqual(1); - }); - it('Should trace nullifier checks', () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - const exists = true; - const isPending = false; - const leafIndex = new Fr(42); - trace.traceNullifierCheck(contractAddress, utxo, exists, isPending, leafIndex); - const expectedCheck: TracedNullifierCheck = { - // callPointer: Fr.ZERO, - storageAddress: contractAddress, - nullifier: utxo, - exists: exists, - counter: Fr.ZERO, // 0th access - // endLifetime: Fr.ZERO, - isPending: isPending, - leafIndex: leafIndex, - }; - expect(trace.nullifierChecks).toEqual([expectedCheck]); - expect(trace.getAccessCounter()).toEqual(1); - }); - it('Should trace nullifiers', () => { - const contractAddress = new Fr(1); - const utxo = new Fr(2); - trace.traceNewNullifier(contractAddress, utxo); - const expectedNullifier: TracedNullifier = { - // callPointer: Fr.ZERO, - storageAddress: contractAddress, - nullifier: utxo, - counter: new Fr(0), - // endLifetime: Fr.ZERO, - }; - expect(trace.newNullifiers).toEqual([expectedNullifier]); - expect(trace.getAccessCounter()).toEqual(1); - }); - it('Should trace L1ToL2 Message checks', () => { - const utxo = new Fr(2); - const exists = true; - const leafIndex = new Fr(42); - trace.traceL1ToL2MessageCheck(utxo, leafIndex, exists); - const expectedCheck: TracedL1toL2MessageCheck = { - leafIndex: leafIndex, - msgHash: utxo, - exists: exists, - counter: new Fr(0), - }; - expect(trace.l1ToL2MessageChecks).toEqual([expectedCheck]); - expect(trace.getAccessCounter()).toEqual(1); - }); - it('Should trace get contract instance', () => { - const instance = randomTracedContractInstance(); - trace.traceGetContractInstance(instance); - expect(trace.gotContractInstances).toEqual([instance]); - expect(trace.getAccessCounter()).toEqual(1); - }); - }); - - it('Access counter should properly count accesses', () => { - const contractAddress = new Fr(1); - const slot = new Fr(2); - const value = new Fr(1); - const nullifier = new Fr(20); - const nullifierExists = false; - const nullifierIsPending = false; - const nullifierLeafIndex = Fr.ZERO; - const noteHash = new Fr(10); - const noteHashLeafIndex = new Fr(88); - const noteHashExists = false; - const msgExists = false; - const msgLeafIndex = Fr.ZERO; - const msgHash = new Fr(10); - const instance = randomTracedContractInstance(); - - let counter = 0; - trace.tracePublicStorageWrite(contractAddress, slot, value); - counter++; - trace.tracePublicStorageRead(contractAddress, slot, value, /*exists=*/ true, /*cached=*/ true); - counter++; - trace.traceNoteHashCheck(contractAddress, noteHash, noteHashExists, noteHashLeafIndex); - counter++; - trace.traceNewNoteHash(contractAddress, noteHash); - counter++; - trace.traceNullifierCheck(contractAddress, nullifier, nullifierExists, nullifierIsPending, nullifierLeafIndex); - counter++; - trace.traceNewNullifier(contractAddress, nullifier); - counter++; - trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, msgExists); - counter++; - trace.tracePublicStorageWrite(contractAddress, slot, value); - counter++; - trace.tracePublicStorageRead(contractAddress, slot, value, /*exists=*/ true, /*cached=*/ true); - counter++; - trace.traceNewNoteHash(contractAddress, noteHash); - counter++; - trace.traceNullifierCheck(contractAddress, nullifier, nullifierExists, nullifierIsPending, nullifierLeafIndex); - counter++; - trace.traceNewNullifier(contractAddress, nullifier); - counter++; - trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, msgExists); - counter++; - trace.traceGetContractInstance(instance); - counter++; - expect(trace.getAccessCounter()).toEqual(counter); - }); - - it('Should merge two traces together', () => { - const contractAddress = new Fr(1); - const slot = new Fr(2); - const value = new Fr(1); - const valueT1 = new Fr(2); - - const noteHash = new Fr(10); - const noteHashExists = false; - const noteHashLeafIndex = new Fr(88); - const noteHashT1 = new Fr(11); - const noteHashExistsT1 = true; - const noteHashLeafIndexT1 = new Fr(7); - - const nullifierExists = false; - const nullifierIsPending = false; - const nullifierLeafIndex = Fr.ZERO; - const nullifier = new Fr(10); - const nullifierT1 = new Fr(20); - const nullifierExistsT1 = true; - const nullifierIsPendingT1 = false; - const nullifierLeafIndexT1 = new Fr(42); - - const msgExists = false; - const msgLeafIndex = Fr.ZERO; - const msgHash = new Fr(10); - const msgHashT1 = new Fr(20); - const msgExistsT1 = true; - const msgLeafIndexT1 = new Fr(42); - - const instance = randomTracedContractInstance(); - const instanceT1 = randomTracedContractInstance(); - - const expectedMessageCheck = { - leafIndex: msgLeafIndex, - msgHash: msgHash, - exists: msgExists, - }; - const expectedMessageCheckT1 = { - leafIndex: msgLeafIndexT1, - msgHash: msgHashT1, - exists: msgExistsT1, - }; - - trace.tracePublicStorageWrite(contractAddress, slot, value); - trace.tracePublicStorageRead(contractAddress, slot, value, /*exists=*/ true, /*cached=*/ true); - trace.traceNoteHashCheck(contractAddress, noteHash, noteHashExists, noteHashLeafIndex); - trace.traceNewNoteHash(contractAddress, noteHash); - trace.traceNullifierCheck(contractAddress, nullifier, nullifierExists, nullifierIsPending, nullifierLeafIndex); - trace.traceNewNullifier(contractAddress, nullifier); - trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, msgExists); - trace.traceGetContractInstance(instance); - - const childTrace = new WorldStateAccessTrace(trace); - childTrace.tracePublicStorageWrite(contractAddress, slot, valueT1); - childTrace.tracePublicStorageRead(contractAddress, slot, valueT1, /*exists=*/ true, /*cached=*/ true); - childTrace.traceNoteHashCheck(contractAddress, noteHashT1, noteHashExistsT1, noteHashLeafIndexT1); - childTrace.traceNewNoteHash(contractAddress, nullifierT1); - childTrace.traceNullifierCheck( - contractAddress, - nullifierT1, - nullifierExistsT1, - nullifierIsPendingT1, - nullifierLeafIndexT1, - ); - childTrace.traceNewNullifier(contractAddress, nullifierT1); - childTrace.traceL1ToL2MessageCheck(msgHashT1, msgLeafIndexT1, msgExistsT1); - childTrace.traceGetContractInstance(instanceT1); - - const childCounterBeforeMerge = childTrace.getAccessCounter(); - trace.acceptAndMerge(childTrace); - expect(trace.getAccessCounter()).toEqual(childCounterBeforeMerge); - - expect(trace.publicStorageReads).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - slot: slot, - value: value, - exists: true, - cached: true, - }), - expect.objectContaining({ - storageAddress: contractAddress, - slot: slot, - value: valueT1, - exists: true, - cached: true, - }), - ]); - expect(trace.publicStorageWrites).toEqual([ - expect.objectContaining({ storageAddress: contractAddress, slot: slot, value: value }), - expect.objectContaining({ storageAddress: contractAddress, slot: slot, value: valueT1 }), - ]); - expect(trace.newNoteHashes).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - noteHash: nullifier, - }), - expect.objectContaining({ - storageAddress: contractAddress, - noteHash: nullifierT1, - }), - ]); - expect(trace.newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: nullifier, - }), - expect.objectContaining({ - storageAddress: contractAddress, - nullifier: nullifierT1, - }), - ]); - expect(trace.nullifierChecks).toEqual([ - expect.objectContaining({ - nullifier: nullifier, - exists: nullifierExists, - isPending: nullifierIsPending, - leafIndex: nullifierLeafIndex, - }), - expect.objectContaining({ - nullifier: nullifierT1, - exists: nullifierExistsT1, - isPending: nullifierIsPendingT1, - leafIndex: nullifierLeafIndexT1, - }), - ]); - expect(trace.noteHashChecks).toEqual([ - expect.objectContaining({ noteHash: noteHash, exists: noteHashExists, leafIndex: noteHashLeafIndex }), - expect.objectContaining({ noteHash: noteHashT1, exists: noteHashExistsT1, leafIndex: noteHashLeafIndexT1 }), - ]); - expect( - trace.l1ToL2MessageChecks.map(c => ({ - leafIndex: c.leafIndex, - msgHash: c.msgHash, - exists: c.exists, - })), - ).toEqual([expectedMessageCheck, expectedMessageCheckT1]); - expect(trace.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: msgLeafIndex, msgHash: msgHash, exists: msgExists }), - expect.objectContaining({ leafIndex: msgLeafIndexT1, msgHash: msgHashT1, exists: msgExistsT1 }), - ]); - expect(trace.gotContractInstances).toEqual([instance, instanceT1]); - }); -}); diff --git a/yarn-project/simulator/src/avm/journal/trace.ts b/yarn-project/simulator/src/avm/journal/trace.ts deleted file mode 100644 index 608f738ccc34..000000000000 --- a/yarn-project/simulator/src/avm/journal/trace.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { Fr } from '@aztec/foundation/fields'; - -import { - type TracedContractInstance, - type TracedL1toL2MessageCheck, - type TracedNoteHash, - type TracedNoteHashCheck, - type TracedNullifier, - type TracedNullifierCheck, - type TracedPublicStorageRead, - type TracedPublicStorageWrite, - type TracedUnencryptedL2Log, -} from './trace_types.js'; - -export class WorldStateAccessTrace { - public accessCounter: number; - - public publicStorageReads: TracedPublicStorageRead[] = []; - public publicStorageWrites: TracedPublicStorageWrite[] = []; - - public noteHashChecks: TracedNoteHashCheck[] = []; - public newNoteHashes: TracedNoteHash[] = []; - public nullifierChecks: TracedNullifierCheck[] = []; - public newNullifiers: TracedNullifier[] = []; - public l1ToL2MessageChecks: TracedL1toL2MessageCheck[] = []; - public newLogsHashes: TracedUnencryptedL2Log[] = []; - public gotContractInstances: TracedContractInstance[] = []; - - //public contractCalls: TracedContractCall[] = []; - //public archiveChecks: TracedArchiveLeafCheck[] = []; - - constructor(parentTrace?: WorldStateAccessTrace) { - this.accessCounter = parentTrace ? parentTrace.accessCounter : 0; - // TODO(4805): consider tracking the parent's trace vector lengths so we can enforce limits - } - - public getAccessCounter() { - return this.accessCounter; - } - - public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, exists: boolean, cached: boolean) { - // TODO(4805): check if some threshold is reached for max storage reads - // (need access to parent length, or trace needs to be initialized with parent's contents) - const traced: TracedPublicStorageRead = { - // callPointer: Fr.ZERO, - storageAddress, - slot, - value, - exists, - cached, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - }; - this.publicStorageReads.push(traced); - this.incrementAccessCounter(); - } - - public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr) { - // TODO(4805): check if some threshold is reached for max storage writes - // (need access to parent length, or trace needs to be initialized with parent's contents) - const traced: TracedPublicStorageWrite = { - // callPointer: Fr.ZERO, - storageAddress, - slot, - value, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - }; - this.publicStorageWrites.push(traced); - this.incrementAccessCounter(); - } - - public traceNoteHashCheck(storageAddress: Fr, noteHash: Fr, exists: boolean, leafIndex: Fr) { - const traced: TracedNoteHashCheck = { - // callPointer: Fr.ZERO, - storageAddress, - noteHash, - exists, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - leafIndex, - }; - this.noteHashChecks.push(traced); - this.incrementAccessCounter(); - } - - public traceNewNoteHash(storageAddress: Fr, noteHash: Fr) { - // TODO(4805): check if some threshold is reached for max new note hash - const traced: TracedNoteHash = { - // callPointer: Fr.ZERO, - storageAddress, - noteHash, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - }; - this.newNoteHashes.push(traced); - this.incrementAccessCounter(); - } - - public traceNullifierCheck(storageAddress: Fr, nullifier: Fr, exists: boolean, isPending: boolean, leafIndex: Fr) { - // TODO(4805): check if some threshold is reached for max new nullifier - const traced: TracedNullifierCheck = { - // callPointer: Fr.ZERO, - storageAddress, - nullifier, - exists, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - isPending, - leafIndex, - }; - this.nullifierChecks.push(traced); - this.incrementAccessCounter(); - } - - public traceNewNullifier(storageAddress: Fr, nullifier: Fr) { - // TODO(4805): check if some threshold is reached for max new nullifier - const tracedNullifier: TracedNullifier = { - // callPointer: Fr.ZERO, - storageAddress, - nullifier, - counter: new Fr(this.accessCounter), - // endLifetime: Fr.ZERO, - }; - this.newNullifiers.push(tracedNullifier); - this.incrementAccessCounter(); - } - - public traceL1ToL2MessageCheck(msgHash: Fr, msgLeafIndex: Fr, exists: boolean) { - // TODO(4805): check if some threshold is reached for max message reads - const traced: TracedL1toL2MessageCheck = { - //callPointer: Fr.ZERO, // FIXME - leafIndex: msgLeafIndex, - msgHash: msgHash, - exists: exists, - counter: new Fr(this.accessCounter), - //endLifetime: Fr.ZERO, // FIXME - }; - this.l1ToL2MessageChecks.push(traced); - this.incrementAccessCounter(); - } - - public traceNewLog(logHash: Fr) { - const traced: TracedUnencryptedL2Log = { - logHash, - counter: new Fr(this.accessCounter), - }; - this.newLogsHashes.push(traced); - this.incrementAccessCounter(); - } - - public traceGetContractInstance(instance: TracedContractInstance) { - this.gotContractInstances.push(instance); - this.incrementAccessCounter(); - } - - private incrementAccessCounter() { - this.accessCounter++; - } - - /** - * Merges another trace into this one - * - * @param incomingTrace - the incoming trace to merge into this instance - */ - public acceptAndMerge(incomingTrace: WorldStateAccessTrace) { - // Merge storage read and write journals - this.publicStorageReads.push(...incomingTrace.publicStorageReads); - this.publicStorageWrites.push(...incomingTrace.publicStorageWrites); - // Merge new note hashes and nullifiers - this.noteHashChecks.push(...incomingTrace.noteHashChecks); - this.newNoteHashes.push(...incomingTrace.newNoteHashes); - this.nullifierChecks.push(...incomingTrace.nullifierChecks); - this.newNullifiers.push(...incomingTrace.newNullifiers); - this.l1ToL2MessageChecks.push(...incomingTrace.l1ToL2MessageChecks); - this.newLogsHashes.push(...incomingTrace.newLogsHashes); - this.gotContractInstances.push(...incomingTrace.gotContractInstances); - // 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 deleted file mode 100644 index db57e53998ba..000000000000 --- a/yarn-project/simulator/src/avm/journal/trace_types.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { type Fr } from '@aztec/foundation/fields'; -import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; - -//export type TracedContractCall = { -// callPointer: Fr; -// address: Fr; -// storageAddress: Fr; -// endLifetime: Fr; -//}; - -export type TracedPublicStorageRead = { - // callPointer: Fr; - storageAddress: Fr; - exists: boolean; - cached: boolean; - slot: Fr; - value: Fr; - counter: Fr; - // endLifetime: Fr; -}; - -export type TracedPublicStorageWrite = { - // callPointer: Fr; - storageAddress: Fr; - slot: Fr; - value: Fr; - counter: Fr; - // endLifetime: Fr; -}; - -export type TracedNoteHashCheck = { - // callPointer: Fr; - storageAddress: Fr; - leafIndex: Fr; - noteHash: Fr; - exists: boolean; - counter: Fr; - // endLifetime: Fr; -}; - -export type TracedNoteHash = { - // callPointer: Fr; - storageAddress: Fr; - noteHash: Fr; - counter: Fr; - // endLifetime: Fr; -}; - -export type TracedNullifierCheck = { - // callPointer: Fr; - storageAddress: Fr; - nullifier: Fr; - exists: boolean; - counter: Fr; - // endLifetime: Fr; - // the fields below are relevant only to the public kernel - // and are therefore omitted from VM inputs - isPending: boolean; - leafIndex: Fr; -}; - -export type TracedNullifier = { - // callPointer: Fr; - storageAddress: Fr; - nullifier: Fr; - counter: Fr; - // endLifetime: Fr; -}; - -export type TracedL1toL2MessageCheck = { - //callPointer: Fr; - leafIndex: Fr; - msgHash: Fr; - exists: boolean; - counter: Fr; - //endLifetime: Fr; -}; - -export type TracedUnencryptedL2Log = { - //callPointer: Fr; - logHash: Fr; - counter: Fr; - //endLifetime: Fr; -}; - -//export type TracedArchiveLeafCheck = { -// leafIndex: Fr; -// leaf: Fr; -//}; - -export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress; 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 5f4ac1eae0da..9f71a34a6f62 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -1,15 +1,20 @@ -import { UnencryptedL2Log } from '@aztec/circuit-types'; -import { EthAddress, Fr } from '@aztec/circuits.js'; -import { EventSelector } from '@aztec/foundation/abi'; +import { Fr } from '@aztec/circuits.js'; import { mock } from 'jest-mock-extended'; -import { type CommitmentsDB } from '../../index.js'; +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; import { type AvmContext } from '../avm_context.js'; import { Field, Uint8, Uint32 } from '../avm_memory_types.js'; import { InstructionExecutionError, StaticCallAlterationError } from '../errors.js'; -import { initContext, initExecutionEnvironment, initHostStorage } from '../fixtures/index.js'; -import { AvmPersistableStateManager } from '../journal/journal.js'; +import { + initContext, + initExecutionEnvironment, + initHostStorage, + initPersistableStateManager, +} from '../fixtures/index.js'; +import { type HostStorage } from '../journal/host_storage.js'; +import { type AvmPersistableStateManager } from '../journal/journal.js'; +import { mockL1ToL2MessageExists, mockNoteHashExists, mockNullifierExists } from '../test_utils.js'; import { EmitNoteHash, EmitNullifier, @@ -21,10 +26,27 @@ import { } from './accrued_substate.js'; describe('Accrued Substate', () => { + let hostStorage: HostStorage; + let trace: PublicSideEffectTraceInterface; + let persistableState: AvmPersistableStateManager; let context: AvmContext; + const address = new Fr(1); + const storageAddress = new Fr(2); + const sender = new Fr(42); + const value0 = new Fr(69); // noteHash or nullifier... + const value0Offset = 100; + const value1 = new Fr(420); + const value1Offset = 200; + const leafIndex = new Fr(7); + const leafIndexOffset = 1; + const existsOffset = 2; + beforeEach(() => { - context = initContext(); + hostStorage = initHostStorage(); + trace = mock(); + persistableState = initPersistableStateManager({ hostStorage, trace }); + context = initContext({ persistableState, env: initExecutionEnvironment({ address, storageAddress, sender }) }); }); describe('NoteHashExists', () => { @@ -47,82 +69,43 @@ describe('Accrued Substate', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should correctly return false when noteHash does not exist', async () => { - const noteHash = new Field(69n); - const noteHashOffset = 0; - const leafIndex = new Field(7n); - const leafIndexOffset = 1; - const existsOffset = 2; - - // mock host storage this so that persistable state's getCommitmentIndex returns UNDEFINED - const commitmentsDb = mock(); - commitmentsDb.getCommitmentIndex.mockResolvedValue(Promise.resolve(undefined)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - - context.machineState.memory.set(noteHashOffset, noteHash); - context.machineState.memory.set(leafIndexOffset, leafIndex); - await new NoteHashExists(/*indirect=*/ 0, noteHashOffset, leafIndexOffset, existsOffset).execute(context); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(0)); - - const journalState = context.persistableState.flush(); - expect(journalState.noteHashChecks).toEqual([ - expect.objectContaining({ exists: false, leafIndex: leafIndex.toFr(), noteHash: noteHash.toFr() }), - ]); - }); - - it('Should correctly return false when note hash exists at a different leaf index', async () => { - const noteHash = new Field(69n); - const noteHashOffset = 0; - const leafIndex = new Field(7n); - const storedLeafIndex = 88n; - const leafIndexOffset = 1; - const existsOffset = 2; - - const commitmentsDb = mock(); - commitmentsDb.getCommitmentIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - - context.machineState.memory.set(noteHashOffset, noteHash); - context.machineState.memory.set(leafIndexOffset, leafIndex); - await new NoteHashExists(/*indirect=*/ 0, noteHashOffset, leafIndexOffset, existsOffset).execute(context); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(0)); - - const journalState = context.persistableState.flush(); - expect(journalState.noteHashChecks).toEqual([ - expect.objectContaining({ exists: false, leafIndex: leafIndex.toFr(), noteHash: noteHash.toFr() }), - ]); - }); - - it('Should correctly return true when note hash exists at the given leaf index', async () => { - const noteHash = new Field(69n); - const noteHashOffset = 0; - const leafIndex = new Field(7n); - const storedLeafIndex = 7n; - const leafIndexOffset = 1; - const existsOffset = 2; - - const commitmentsDb = mock(); - commitmentsDb.getCommitmentIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - - context.machineState.memory.set(noteHashOffset, noteHash); - context.machineState.memory.set(leafIndexOffset, leafIndex); - await new NoteHashExists(/*indirect=*/ 0, noteHashOffset, leafIndexOffset, existsOffset).execute(context); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(1)); - - const journalState = context.persistableState.flush(); - expect(journalState.noteHashChecks).toEqual([ - expect.objectContaining({ exists: true, leafIndex: leafIndex.toFr(), noteHash: noteHash.toFr() }), - ]); + // Will check existence at leafIndex, but nothing may be found there and/or something may be found at mockAtLeafIndex + describe.each([ + [/*mockAtLeafIndex=*/ undefined], // doesn't exist at all + [/*mockAtLeafIndex=*/ leafIndex], // should be found! + [/*mockAtLeafIndex=*/ leafIndex.add(Fr.ONE)], // won't be found! (checking leafIndex+1, but it exists at leafIndex) + ])('Note hash checks', (mockAtLeafIndex?: Fr) => { + const expectFound = mockAtLeafIndex !== undefined && mockAtLeafIndex.equals(leafIndex); + const existsElsewhere = mockAtLeafIndex !== undefined && !mockAtLeafIndex.equals(leafIndex); + const existsStr = expectFound ? 'DOES exist' : 'does NOT exist'; + const foundAtStr = existsElsewhere + ? `at leafIndex=${mockAtLeafIndex.toNumber()} (exists at leafIndex=${leafIndex.toNumber()})` + : ''; + it(`Should return ${expectFound} (and be traced) when noteHash ${existsStr} ${foundAtStr}`, async () => { + if (mockAtLeafIndex !== undefined) { + mockNoteHashExists(hostStorage, mockAtLeafIndex, value0); + } + + context.machineState.memory.set(value0Offset, new Field(value0)); // noteHash + context.machineState.memory.set(leafIndexOffset, new Field(leafIndex)); + await new NoteHashExists( + /*indirect=*/ 0, + /*noteHashOffset=*/ value0Offset, + leafIndexOffset, + existsOffset, + ).execute(context); + + const gotExists = context.machineState.memory.getAs(existsOffset); + expect(gotExists).toEqual(new Uint8(expectFound ? 1 : 0)); + + expect(trace.traceNoteHashCheck).toHaveBeenCalledTimes(1); + expect(trace.traceNoteHashCheck).toHaveBeenCalledWith( + storageAddress, + /*noteHash=*/ value0, + leafIndex, + /*exists=*/ expectFound, + ); + }); }); }); @@ -140,18 +123,13 @@ describe('Accrued Substate', () => { }); it('Should append a new note hash correctly', async () => { - const value = new Field(69n); - context.machineState.memory.set(0, value); - - await new EmitNoteHash(/*indirect=*/ 0, /*offset=*/ 0).execute(context); - - const journalState = context.persistableState.flush(); - expect(journalState.newNoteHashes).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress, - noteHash: value.toFr(), - }), - ]); + context.machineState.memory.set(value0Offset, new Field(value0)); + await new EmitNoteHash(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context); + expect(trace.traceNewNoteHash).toHaveBeenCalledTimes(1); + expect(trace.traceNewNoteHash).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*noteHash=*/ value0, + ); }); }); @@ -175,57 +153,39 @@ describe('Accrued Substate', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should correctly show false when nullifier does not exist', async () => { - const value = new Field(69n); - const nullifierOffset = 0; - const addressOffset = 1; - const existsOffset = 2; - - // mock host storage this so that persistable state's checkNullifierExists returns UNDEFINED - const commitmentsDb = mock(); - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(undefined)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - const address = new Field(context.environment.storageAddress.toField()); - - context.machineState.memory.set(nullifierOffset, value); - context.machineState.memory.set(addressOffset, address); - await new NullifierExists(/*indirect=*/ 0, nullifierOffset, addressOffset, existsOffset).execute(context); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(0)); - - const journalState = context.persistableState.flush(); - expect(journalState.nullifierChecks).toEqual([ - expect.objectContaining({ nullifier: value.toFr(), storageAddress: address.toFr(), exists: false }), - ]); - }); - - it('Should correctly show true when nullifier exists', async () => { - const value = new Field(69n); - const nullifierOffset = 0; - const addressOffset = 1; - const existsOffset = 2; - const storedLeafIndex = BigInt(42); - - // mock host storage this so that persistable state's checkNullifierExists returns true - const commitmentsDb = mock(); - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - const address = new Field(context.environment.storageAddress.toField()); - - context.machineState.memory.set(nullifierOffset, value); - context.machineState.memory.set(addressOffset, address); - await new NullifierExists(/*indirect=*/ 0, nullifierOffset, addressOffset, existsOffset).execute(context); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(1)); - - const journalState = context.persistableState.flush(); - expect(journalState.nullifierChecks).toEqual([ - expect.objectContaining({ nullifier: value.toFr(), storageAddress: address.toFr(), exists: true }), - ]); + describe.each([[/*exists=*/ false], [/*exists=*/ true]])('Nullifier checks', (exists: boolean) => { + const existsStr = exists ? 'DOES exist' : 'does NOT exist'; + it(`Should return ${exists} (and be traced) when noteHash ${existsStr}`, async () => { + const storageAddressOffset = 1; + + if (exists) { + mockNullifierExists(hostStorage, leafIndex, value0); + } + + context.machineState.memory.set(value0Offset, new Field(value0)); // nullifier + context.machineState.memory.set(storageAddressOffset, new Field(storageAddress)); + await new NullifierExists( + /*indirect=*/ 0, + /*nullifierOffset=*/ value0Offset, + storageAddressOffset, + existsOffset, + ).execute(context); + + const gotExists = context.machineState.memory.getAs(existsOffset); + expect(gotExists).toEqual(new Uint8(exists ? 1 : 0)); + + expect(trace.traceNullifierCheck).toHaveBeenCalledTimes(1); + const isPending = false; + // leafIndex is returned from DB call for nullifiers, so it is absent on DB miss + const tracedLeafIndex = exists && !isPending ? leafIndex : Fr.ZERO; + expect(trace.traceNullifierCheck).toHaveBeenCalledWith( + storageAddress, + value0, + tracedLeafIndex, + exists, + isPending, + ); + }); }); }); @@ -243,52 +203,39 @@ describe('Accrued Substate', () => { }); it('Should append a new nullifier correctly', async () => { - const value = new Field(69n); - context.machineState.memory.set(0, value); - - await new EmitNullifier(/*indirect=*/ 0, /*offset=*/ 0).execute(context); - - const journalState = context.persistableState.flush(); - expect(journalState.newNullifiers).toEqual([ - expect.objectContaining({ - storageAddress: context.environment.storageAddress.toField(), - nullifier: value.toFr(), - }), - ]); + context.machineState.memory.set(value0Offset, new Field(value0)); + await new EmitNullifier(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context); + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(1); + expect(trace.traceNewNullifier).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); }); it('Nullifier collision reverts (same nullifier emitted twice)', async () => { - const value = new Field(69n); - context.machineState.memory.set(0, value); - - await new EmitNullifier(/*indirect=*/ 0, /*offset=*/ 0).execute(context); - await expect(new EmitNullifier(/*indirect=*/ 0, /*offset=*/ 0).execute(context)).rejects.toThrow( + context.machineState.memory.set(value0Offset, new Field(value0)); + await new EmitNullifier(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context); + await expect(new EmitNullifier(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context)).rejects.toThrow( new InstructionExecutionError( - `Attempted to emit duplicate nullifier ${value.toFr()} (storage address: ${ - context.environment.storageAddress - }).`, + `Attempted to emit duplicate nullifier ${value0} (storage address: ${storageAddress}).`, ), ); + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(1); + expect(trace.traceNewNullifier).toHaveBeenCalledWith( + expect.objectContaining(storageAddress), + /*nullifier=*/ value0, + ); }); it('Nullifier collision reverts (nullifier exists in host state)', async () => { - const value = new Field(69n); - const storedLeafIndex = BigInt(42); - - // Mock the nullifiers db to return a stored leaf index - const commitmentsDb = mock(); - commitmentsDb.getNullifierIndex.mockResolvedValue(Promise.resolve(storedLeafIndex)); - const hostStorage = initHostStorage({ commitmentsDb }); - context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); - - context.machineState.memory.set(0, value); - await expect(new EmitNullifier(/*indirect=*/ 0, /*offset=*/ 0).execute(context)).rejects.toThrow( + mockNullifierExists(hostStorage, leafIndex); // db will say that nullifier already exists + context.machineState.memory.set(value0Offset, new Field(value0)); + await expect(new EmitNullifier(/*indirect=*/ 0, /*offset=*/ value0Offset).execute(context)).rejects.toThrow( new InstructionExecutionError( - `Attempted to emit duplicate nullifier ${value.toFr()} (storage address: ${ - context.environment.storageAddress - }).`, + `Attempted to emit duplicate nullifier ${value0} (storage address: ${storageAddress}).`, ), ); + expect(trace.traceNewNullifier).toHaveBeenCalledTimes(0); // the only attempt should fail before tracing }); }); @@ -312,77 +259,44 @@ describe('Accrued Substate', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should correctly show false when L1ToL2 message does not exist', async () => { - const msgHash = new Field(69n); - const leafIndex = new Field(42n); - const msgHashOffset = 0; - const msgLeafIndexOffset = 1; - const existsOffset = 2; - - 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 }), - ]); - }); - - it('Should correctly show true when L1ToL2 message exists', async () => { - const msgHash = new Field(69n); - const leafIndex = new Field(42n); - const msgHashOffset = 0; - const msgLeafIndexOffset = 1; - const existsOffset = 2; - - // mock commitments db to show message exists - const commitmentsDb = mock(); - commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash.toFr()); - 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); - - const exists = context.machineState.memory.getAs(existsOffset); - expect(exists).toEqual(new Uint8(1)); - - const journalState = context.persistableState.flush(); - expect(journalState.l1ToL2MessageChecks).toEqual([ - 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 }), - ]); + // Will check existence at leafIndex, but nothing may be found there and/or something may be found at mockAtLeafIndex + describe.each([ + [/*mockAtLeafIndex=*/ undefined], // doesn't exist at all + [/*mockAtLeafIndex=*/ leafIndex], // should be found! + [/*mockAtLeafIndex=*/ leafIndex.add(Fr.ONE)], // won't be found! (checking leafIndex+1, but it exists at leafIndex) + ])('L1ToL2 message checks', (mockAtLeafIndex?: Fr) => { + const expectFound = mockAtLeafIndex !== undefined && mockAtLeafIndex.equals(leafIndex); + const existsElsewhere = mockAtLeafIndex !== undefined && !mockAtLeafIndex.equals(leafIndex); + const existsStr = expectFound ? 'DOES exist' : 'does NOT exist'; + const foundAtStr = existsElsewhere + ? `at leafIndex=${mockAtLeafIndex.toNumber()} (exists at leafIndex=${leafIndex.toNumber()})` + : ''; + + it(`Should return ${expectFound} (and be traced) when noteHash ${existsStr} ${foundAtStr}`, async () => { + if (mockAtLeafIndex !== undefined) { + mockL1ToL2MessageExists(hostStorage, mockAtLeafIndex, value0, /*valueAtOtherIndices=*/ value1); + } + + context.machineState.memory.set(value0Offset, new Field(value0)); // noteHash + context.machineState.memory.set(leafIndexOffset, new Field(leafIndex)); + await new L1ToL2MessageExists( + /*indirect=*/ 0, + /*msgHashOffset=*/ value0Offset, + leafIndexOffset, + existsOffset, + ).execute(context); + + const gotExists = context.machineState.memory.getAs(existsOffset); + expect(gotExists).toEqual(new Uint8(expectFound ? 1 : 0)); + + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); + expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith( + address, + /*noteHash=*/ value0, + leafIndex, + /*exists=*/ expectFound, + ); + }); }); }); @@ -408,12 +322,15 @@ describe('Accrued Substate', () => { it('Should append unencrypted logs correctly', async () => { const startOffset = 0; - const eventSelector = 5; + const eventSelector = new Fr(5); const eventSelectorOffset = 10; const logSizeOffset = 20; - const values = [new Field(69n), new Field(420n), new Field(Field.MODULUS - 1n)]; - context.machineState.memory.setSlice(startOffset, values); + const values = [new Fr(69n), new Fr(420n), new Fr(Fr.MODULUS - 1n)]; + context.machineState.memory.setSlice( + startOffset, + values.map(f => new Field(f)), + ); context.machineState.memory.set(eventSelectorOffset, new Field(eventSelector)); context.machineState.memory.set(logSizeOffset, new Uint32(values.length)); @@ -424,11 +341,8 @@ describe('Accrued Substate', () => { logSizeOffset, ).execute(context); - const journalState = context.persistableState.flush(); - const expectedLog = Buffer.concat(values.map(v => v.toFr().toBuffer())); - expect(journalState.newLogs).toEqual([ - new UnencryptedL2Log(context.environment.address, new EventSelector(eventSelector), expectedLog), - ]); + expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(1); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, values); }); }); @@ -450,25 +364,18 @@ describe('Accrued Substate', () => { expect(inst.serialize()).toEqual(buf); }); - it('Should append l2 to l1 messages correctly', async () => { - const recipientOffset = 0; - const recipient = new Fr(42); - const contentOffset = 1; - const content = new Fr(69); - - context.machineState.memory.set(recipientOffset, new Field(recipient)); - context.machineState.memory.set(contentOffset, new Field(content)); - + it('Should append l2 to l1 message correctly', async () => { + // recipient: value0 + // content: value1 + context.machineState.memory.set(value0Offset, new Field(value0)); + context.machineState.memory.set(value1Offset, new Field(value1)); await new SendL2ToL1Message( /*indirect=*/ 0, - /*recipientOffset=*/ recipientOffset, - /*contentOffset=*/ contentOffset, + /*recipientOffset=*/ value0Offset, + /*contentOffset=*/ value1Offset, ).execute(context); - - const journalState = context.persistableState.flush(); - expect(journalState.newL1Messages).toEqual([ - expect.objectContaining({ recipient: EthAddress.fromField(recipient), content }), - ]); + expect(trace.traceNewL2ToL1Message).toHaveBeenCalledTimes(1); + expect(trace.traceNewL2ToL1Message).toHaveBeenCalledWith(/*recipient=*/ value0, /*content=*/ value1); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts index c227710208fd..97a21cf14409 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts @@ -201,7 +201,11 @@ export class L1ToL2MessageExists extends Instruction { const msgHash = memory.get(msgHashOffset).toFr(); const msgLeafIndex = memory.get(msgLeafIndexOffset).toFr(); - const exists = await context.persistableState.checkL1ToL2MessageExists(msgHash, msgLeafIndex); + const exists = await context.persistableState.checkL1ToL2MessageExists( + context.environment.address, + msgHash, + msgLeafIndex, + ); memory.set(existsOffset, exists ? new Uint8(1) : new Uint8(0)); memory.assert(memoryOperations); @@ -252,7 +256,7 @@ export class EmitUnencryptedLog extends Instruction { const memoryOperations = { reads: 2 + logSize, indirect: this.indirect }; context.machineState.consumeGas(this.gasCost(memoryOperations)); const log = memory.getSlice(logOffset, logSize).map(f => f.toFr()); - context.persistableState.writeLog(contractAddress, event, log); + context.persistableState.writeUnencryptedLog(contractAddress, event, log); memory.assert(memoryOperations); context.machineState.incrementPc(); @@ -285,7 +289,7 @@ export class SendL2ToL1Message extends Instruction { const recipient = memory.get(recipientOffset).toFr(); const content = memory.get(contentOffset).toFr(); - context.persistableState.writeL1Message(recipient, content); + context.persistableState.writeL2ToL1Message(recipient, content); memory.assert(memoryOperations); context.machineState.incrementPc(); diff --git a/yarn-project/simulator/src/avm/opcodes/contract.test.ts b/yarn-project/simulator/src/avm/opcodes/contract.test.ts index 105d9ef579c5..ced3a000d64f 100644 --- a/yarn-project/simulator/src/avm/opcodes/contract.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/contract.test.ts @@ -1,21 +1,31 @@ -import { AztecAddress, Fr } from '@aztec/circuits.js'; -import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; +import { randomContractInstanceWithAddress } from '@aztec/circuit-types'; +import { AztecAddress } from '@aztec/circuits.js'; +import { SerializableContractInstance } from '@aztec/types/contracts'; import { mock } from 'jest-mock-extended'; -import { type PublicContractsDB } from '../../public/db_interfaces.js'; +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; import { type AvmContext } from '../avm_context.js'; import { Field } from '../avm_memory_types.js'; -import { initContext, initHostStorage } from '../fixtures/index.js'; -import { AvmPersistableStateManager } from '../journal/journal.js'; +import { initContext, initHostStorage, initPersistableStateManager } from '../fixtures/index.js'; +import { type HostStorage } from '../journal/host_storage.js'; +import { type AvmPersistableStateManager } from '../journal/journal.js'; +import { mockGetContractInstance } from '../test_utils.js'; import { GetContractInstance } from './contract.js'; describe('Contract opcodes', () => { - let context: AvmContext; const address = AztecAddress.random(); - beforeEach(async () => { - context = initContext(); + let hostStorage: HostStorage; + let trace: PublicSideEffectTraceInterface; + let persistableState: AvmPersistableStateManager; + let context: AvmContext; + + beforeEach(() => { + hostStorage = initHostStorage(); + trace = mock(); + persistableState = initPersistableStateManager({ hostStorage, trace }); + context = initContext({ persistableState }); }); describe('GETCONTRACTINSTANCE', () => { @@ -37,22 +47,10 @@ describe('Contract opcodes', () => { }); it('should copy contract instance to memory if found', async () => { - context.machineState.memory.set(0, new Field(address.toField())); - - const contractInstance = { - address: address, - version: 1 as const, - salt: new Fr(20), - contractClassId: new Fr(30), - initializationHash: new Fr(40), - publicKeysHash: new Fr(50), - deployer: AztecAddress.random(), - } as ContractInstanceWithAddress; - - const contractsDb = mock(); - contractsDb.getContractInstance.mockResolvedValue(Promise.resolve(contractInstance)); - context.persistableState = new AvmPersistableStateManager(initHostStorage({ contractsDb })); + const contractInstance = randomContractInstanceWithAddress(/*(base instance) opts=*/ {}, /*address=*/ address); + mockGetContractInstance(hostStorage, contractInstance); + context.machineState.memory.set(0, new Field(address.toField())); await new GetContractInstance(/*indirect=*/ 0, /*addressOffset=*/ 0, /*dstOffset=*/ 1).execute(context); const actual = context.machineState.memory.getSlice(1, 6); @@ -64,9 +62,13 @@ describe('Contract opcodes', () => { new Field(contractInstance.initializationHash), new Field(contractInstance.publicKeysHash), ]); + + expect(trace.traceGetContractInstance).toHaveBeenCalledTimes(1); + expect(trace.traceGetContractInstance).toHaveBeenCalledWith({ exists: true, ...contractInstance }); }); it('should return zeroes if not found', async () => { + const emptyContractInstance = SerializableContractInstance.empty().withAddress(address); context.machineState.memory.set(0, new Field(address.toField())); await new GetContractInstance(/*indirect=*/ 0, /*addressOffset=*/ 0, /*dstOffset=*/ 1).execute(context); @@ -80,6 +82,9 @@ describe('Contract opcodes', () => { new Field(0), new Field(0), ]); + + expect(trace.traceGetContractInstance).toHaveBeenCalledTimes(1); + expect(trace.traceGetContractInstance).toHaveBeenCalledWith({ exists: false, ...emptyContractInstance }); }); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index 6dd086bc78d3..19da62cc3a19 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -1,16 +1,16 @@ import { Fr } from '@aztec/foundation/fields'; -import { jest } from '@jest/globals'; import { mock } from 'jest-mock-extended'; -import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; +import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; import { markBytecodeAsAvm } from '../../public/transitional_adaptors.js'; import { type AvmContext } from '../avm_context.js'; import { Field, Uint8, Uint32 } from '../avm_memory_types.js'; -import { adjustCalldataIndex, initContext } from '../fixtures/index.js'; -import { HostStorage } from '../journal/host_storage.js'; -import { AvmPersistableStateManager } from '../journal/journal.js'; +import { adjustCalldataIndex, initContext, initHostStorage, initPersistableStateManager } from '../fixtures/index.js'; +import { type HostStorage } from '../journal/host_storage.js'; +import { type AvmPersistableStateManager } from '../journal/journal.js'; import { encodeToBytecode } from '../serialization/bytecode_serialization.js'; +import { mockGetBytecode, mockTraceFork } from '../test_utils.js'; import { L2GasLeft } from './context_getters.js'; import { Call, Return, Revert, StaticCall } from './external_calls.js'; import { type Instruction } from './instruction.js'; @@ -19,14 +19,16 @@ import { SStore } from './storage.js'; describe('External Calls', () => { let context: AvmContext; + let hostStorage: HostStorage; + let trace: PublicSideEffectTraceInterface; + let persistableState: AvmPersistableStateManager; beforeEach(() => { - const contractsDb = mock(); - const commitmentsDb = mock(); - const publicStateDb = mock(); - const hostStorage = new HostStorage(publicStateDb, contractsDb, commitmentsDb); - const journal = new AvmPersistableStateManager(hostStorage); - context = initContext({ persistableState: journal }); + hostStorage = initHostStorage(); + trace = mock(); + persistableState = initPersistableStateManager({ hostStorage, trace }); + context = initContext({ persistableState: persistableState }); + mockTraceFork(trace); // make sure trace.fork() works on nested call }); describe('Call', () => { @@ -66,11 +68,16 @@ describe('External Calls', () => { const addrOffset = 2; const addr = new Fr(123456n); const argsOffset = 3; - const args = [new Field(1n), new Field(2n), new Field(3n)]; + const valueToStore = new Fr(42); + const valueOffset = 0; // 0th entry in calldata to nested call + const slot = new Fr(100); + const slotOffset = 1; // 1st entry in calldata to nested call + const args = [new Field(valueToStore), new Field(slot), new Field(3n)]; const argsSize = args.length; const argsSizeOffset = 20; const retOffset = 7; const retSize = 2; + const expectedRetValue = args.slice(0, retSize); const successOffset = 6; // const otherContextInstructionsL2GasCost = 780; // Includes the cost of the call itself @@ -82,10 +89,11 @@ describe('External Calls', () => { /*copySize=*/ argsSize, /*dstOffset=*/ 0, ), - new SStore(/*indirect=*/ 0, /*srcOffset=*/ 0, /*size=*/ 1, /*slotOffset=*/ 0), + new SStore(/*indirect=*/ 0, /*srcOffset=*/ valueOffset, /*size=*/ 1, /*slotOffset=*/ slotOffset), new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 2), ]), ); + mockGetBytecode(hostStorage, otherContextInstructionsBytecode); const { l2GasLeft: initialL2Gas, daGasLeft: initialDaGas } = context.machineState; @@ -94,9 +102,6 @@ describe('External Calls', () => { context.machineState.memory.set(2, new Field(addr)); context.machineState.memory.set(argsSizeOffset, new Uint32(argsSize)); context.machineState.memory.setSlice(3, args); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(otherContextInstructionsBytecode)); const instruction = new Call( /*indirect=*/ 0, @@ -115,18 +120,10 @@ describe('External Calls', () => { expect(successValue).toEqual(new Uint8(1n)); const retValue = context.machineState.memory.getSlice(retOffset, retSize); - expect(retValue).toEqual([new Field(1n), new Field(2n)]); + expect(retValue).toEqual(expectedRetValue); // Check that the storage call has been merged into the parent journal - const { currentStorageValue } = context.persistableState.flush(); - expect(currentStorageValue.size).toEqual(1); - - const nestedContractWrites = currentStorageValue.get(addr.toBigInt()); - expect(nestedContractWrites).toBeDefined(); - - const slotNumber = 1n; - const expectedStoredValue = new Fr(1n); - expect(nestedContractWrites!.get(slotNumber)).toEqual(expectedStoredValue); + expect(await context.persistableState.peekStorage(addr, slot)).toEqual(valueToStore); expect(context.machineState.l2GasLeft).toBeLessThan(initialL2Gas); expect(context.machineState.daGasLeft).toEqual(initialDaGas); @@ -150,6 +147,7 @@ describe('External Calls', () => { new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 1), ]), ); + mockGetBytecode(hostStorage, otherContextInstructionsBytecode); const { l2GasLeft: initialL2Gas, daGasLeft: initialDaGas } = context.machineState; @@ -157,9 +155,6 @@ describe('External Calls', () => { context.machineState.memory.set(1, new Field(daGas)); context.machineState.memory.set(2, new Field(addr)); context.machineState.memory.set(argsSizeOffset, new Uint32(argsSize)); - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(otherContextInstructionsBytecode)); const instruction = new Call( /*indirect=*/ 0, @@ -239,10 +234,7 @@ describe('External Calls', () => { ]; const otherContextInstructionsBytecode = markBytecodeAsAvm(encodeToBytecode(otherContextInstructions)); - - jest - .spyOn(context.persistableState.hostStorage.contractsDb, 'getBytecode') - .mockReturnValue(Promise.resolve(otherContextInstructionsBytecode)); + mockGetBytecode(hostStorage, otherContextInstructionsBytecode); const instruction = new StaticCall( /*indirect=*/ 0, diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.ts index 20f72557b3ce..3830d4db0e98 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.ts @@ -1,7 +1,6 @@ import { FunctionSelector, Gas } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { convertAvmResultsToPxResult, createPublicExecution } from '../../public/transitional_adaptors.js'; import type { AvmContext } from '../avm_context.js'; import { gasLeftToGas } from '../avm_gas.js'; import { Field, TypeTag, Uint8 } from '../avm_memory_types.js'; @@ -24,7 +23,6 @@ abstract class ExternalCall extends Instruction { OperandType.UINT32, OperandType.UINT32, OperandType.UINT32, - /* temporary function selector */ OperandType.UINT32, ]; @@ -37,8 +35,8 @@ abstract class ExternalCall extends Instruction { private retOffset: number, private retSize: number, private successOffset: number, - // Function selector is temporary since eventually public contract bytecode will be one blob - // containing all functions, and function selector will become an application-level mechanism + // NOTE: Function selector is likely temporary since eventually public contract bytecode will be one + // blob containing all functions, and function selector will become an application-level mechanism // (e.g. first few bytes of calldata + compiler-generated jump table) private functionSelectorOffset: number, ) { @@ -81,7 +79,6 @@ abstract class ExternalCall extends Instruction { const allocatedGas = { l2Gas: allocatedL2Gas, daGas: allocatedDaGas }; context.machineState.consumeGas(allocatedGas); - // TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit const nestedContext = context.createNestedContractCallContext( callAddress.toFr(), calldata, @@ -89,38 +86,9 @@ abstract class ExternalCall extends Instruction { callType, FunctionSelector.fromField(functionSelector), ); - const startSideEffectCounter = nestedContext.persistableState.trace.accessCounter; - const oldStyleExecution = createPublicExecution(startSideEffectCounter, nestedContext.environment, calldata); const simulator = new AvmSimulator(nestedContext); const nestedCallResults: AvmContractCallResults = await simulator.execute(); - const functionName = - (await nestedContext.persistableState.hostStorage.contractsDb.getDebugFunctionName( - nestedContext.environment.address, - nestedContext.environment.temporaryFunctionSelector, - )) ?? `${nestedContext.environment.address}:${nestedContext.environment.temporaryFunctionSelector}`; - const pxResults = convertAvmResultsToPxResult( - nestedCallResults, - startSideEffectCounter, - oldStyleExecution, - Gas.from(allocatedGas), - nestedContext, - simulator.getBytecode(), - functionName, - ); - // store the old PublicExecutionResult object to maintain a recursive data structure for the old kernel - context.persistableState.transitionalExecutionResult.nestedExecutions.push(pxResults); - // END TRANSITIONAL - - // const nestedContext = context.createNestedContractCallContext( - // callAddress.toFr(), - // calldata, - // allocatedGas, - // this.type, - // FunctionSelector.fromField(functionSelector), - // ); - // const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute(); - const success = !nestedCallResults.reverted; // TRANSITIONAL: We rethrow here so that the MESSAGE gets propagated. @@ -149,12 +117,16 @@ abstract class ExternalCall extends Instruction { // Refund unused gas context.machineState.refundGas(gasLeftToGas(nestedContext.machineState)); - // TODO: Should we merge the changes from a nested call in the case of a STATIC call? - if (success) { - context.persistableState.acceptNestedCallState(nestedContext.persistableState); - } else { - context.persistableState.rejectNestedCallState(nestedContext.persistableState); - } + // Accept the nested call's state and trace the nested call + await context.persistableState.processNestedCall( + /*nestedState=*/ nestedContext.persistableState, + /*success=*/ success, + /*nestedEnvironment=*/ nestedContext.environment, + /*startGasLeft=*/ Gas.from(allocatedGas), + /*endGasLeft=*/ Gas.from(nestedContext.machineState.gasLeft), + /*bytecode=*/ simulator.getBytecode()!, + /*avmCallResults=*/ nestedCallResults, + ); memory.assert(memoryOperations); context.machineState.incrementPc(); diff --git a/yarn-project/simulator/src/avm/opcodes/storage.test.ts b/yarn-project/simulator/src/avm/opcodes/storage.test.ts index 2bd18ebc1972..7ddaa9cb5bbe 100644 --- a/yarn-project/simulator/src/avm/opcodes/storage.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/storage.test.ts @@ -12,13 +12,13 @@ import { SLoad, SStore } from './storage.js'; describe('Storage Instructions', () => { let context: AvmContext; - let journal: MockProxy; + let persistableState: MockProxy; const address = AztecAddress.random(); beforeEach(async () => { - journal = mock(); + persistableState = mock(); context = initContext({ - persistableState: journal, + persistableState: persistableState, env: initExecutionEnvironment({ address, storageAddress: address }), }); }); @@ -52,12 +52,12 @@ describe('Storage Instructions', () => { await new SStore(/*indirect=*/ 0, /*srcOffset=*/ 1, /*size=*/ 1, /*slotOffset=*/ 0).execute(context); - expect(journal.writeStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt()), new Fr(b.toBigInt())); + expect(persistableState.writeStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt()), new Fr(b.toBigInt())); }); it('Should not be able to write to storage in a static call', async () => { context = initContext({ - persistableState: journal, + persistableState: persistableState, env: initExecutionEnvironment({ address, storageAddress: address, isStaticCall: true }), }); @@ -96,7 +96,7 @@ describe('Storage Instructions', () => { it('Sload should Read into storage', async () => { // Mock response const expectedResult = new Fr(1n); - journal.readStorage.mockReturnValueOnce(Promise.resolve(expectedResult)); + persistableState.readStorage.mockResolvedValueOnce(expectedResult); const a = new Field(1n); const b = new Field(2n); @@ -106,7 +106,7 @@ describe('Storage Instructions', () => { await new SLoad(/*indirect=*/ 0, /*slotOffset=*/ 0, /*size=*/ 1, /*dstOffset=*/ 1).execute(context); - expect(journal.readStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt())); + expect(persistableState.readStorage).toHaveBeenCalledWith(address, new Fr(a.toBigInt())); const actual = context.machineState.memory.get(1); expect(actual).toEqual(new Field(expectedResult)); diff --git a/yarn-project/simulator/src/avm/test_utils.ts b/yarn-project/simulator/src/avm/test_utils.ts new file mode 100644 index 000000000000..ce65116d5b87 --- /dev/null +++ b/yarn-project/simulator/src/avm/test_utils.ts @@ -0,0 +1,53 @@ +import { Fr } from '@aztec/circuits.js'; +import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; + +import { type jest } from '@jest/globals'; +import { mock } from 'jest-mock-extended'; + +import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../public/db_interfaces.js'; +import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; +import { type HostStorage } from './journal/host_storage.js'; + +export function mockGetBytecode(hs: HostStorage, bytecode: Buffer) { + (hs as jest.Mocked).contractsDb.getBytecode.mockResolvedValue(bytecode); +} + +export function mockTraceFork(trace: PublicSideEffectTraceInterface, nestedTrace?: PublicSideEffectTraceInterface) { + (trace as jest.Mocked).fork.mockReturnValue( + nestedTrace ?? mock(), + ); +} + +export function mockStorageRead(hs: HostStorage, value: Fr) { + (hs.publicStateDb as jest.Mocked).storageRead.mockResolvedValue(value); +} + +export function mockStorageReadWithMap(hs: HostStorage, mockedStorage: Map) { + (hs.publicStateDb as jest.Mocked).storageRead.mockImplementation((_address, slot) => + Promise.resolve(mockedStorage.get(slot.toBigInt()) ?? Fr.ZERO), + ); +} + +export function mockNoteHashExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) { + (hs.commitmentsDb as jest.Mocked).getCommitmentIndex.mockResolvedValue(leafIndex.toBigInt()); +} + +export function mockNullifierExists(hs: HostStorage, leafIndex: Fr, _value?: Fr) { + (hs.commitmentsDb as jest.Mocked).getNullifierIndex.mockResolvedValue(leafIndex.toBigInt()); +} + +export function mockL1ToL2MessageExists(hs: HostStorage, leafIndex: Fr, value: Fr, valueAtOtherIndices?: Fr) { + (hs.commitmentsDb as jest.Mocked).getL1ToL2LeafValue.mockImplementation((index: bigint) => { + if (index == leafIndex.toBigInt()) { + return Promise.resolve(value); + } else { + // any indices other than mockAtLeafIndex will return a different value + // (or undefined if no value is specified for other indices) + return Promise.resolve(valueAtOtherIndices!); + } + }); +} + +export function mockGetContractInstance(hs: HostStorage, contractInstance: ContractInstanceWithAddress) { + (hs.contractsDb as jest.Mocked).getContractInstance.mockResolvedValue(contractInstance); +} diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index ab66af72af13..7da0e48928de 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -22,7 +22,13 @@ import { } from '@aztec/circuits.js'; import { Aes128 } from '@aztec/circuits.js/barretenberg'; import { computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; -import { type FunctionAbi, type FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi'; +import { + EventSelector, + type FunctionAbi, + type FunctionArtifact, + type NoteSelector, + countArgumentsSize, +} from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { pedersenHash } from '@aztec/foundation/crypto'; import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields'; @@ -288,7 +294,7 @@ export class ClientExecutionContext extends ViewDataOracle { */ public override notifyCreatedNote( storageSlot: Fr, - noteTypeId: Fr, + noteTypeId: NoteSelector, noteItems: Fr[], innerNoteHash: Fr, counter: number, @@ -382,7 +388,7 @@ export class ClientExecutionContext extends ViewDataOracle { preimage: Fr[], ) { const event = new Event(preimage); - const l1EventPayload = new L1EventPayload(event, contractAddress, randomness, eventTypeId); + const l1EventPayload = new L1EventPayload(event, contractAddress, randomness, EventSelector.fromField(eventTypeId)); const taggedEvent = new TaggedLog(l1EventPayload); const ephSk = GrumpkinScalar.random(); @@ -404,7 +410,7 @@ export class ClientExecutionContext extends ViewDataOracle { public override computeEncryptedNoteLog( contractAddress: AztecAddress, storageSlot: Fr, - noteTypeId: Fr, + noteTypeId: NoteSelector, ovKeys: KeyValidationRequest, ivpkM: Point, preimage: Fr[], diff --git a/yarn-project/simulator/src/client/execution_result.ts b/yarn-project/simulator/src/client/execution_result.ts index 0328e04ede3f..518b3ea7ed1a 100644 --- a/yarn-project/simulator/src/client/execution_result.ts +++ b/yarn-project/simulator/src/client/execution_result.ts @@ -8,6 +8,7 @@ import { type UnencryptedL2Log, } from '@aztec/circuit-types'; import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js'; +import { type NoteSelector } from '@aztec/foundation/abi'; import { type Fr } from '@aztec/foundation/fields'; import { type ACVMField } from '../acvm/index.js'; @@ -21,7 +22,7 @@ export interface NoteAndSlot { /** The storage slot of the note. */ storageSlot: Fr; /** The note type identifier. */ - noteTypeId: Fr; + noteTypeId: NoteSelector; } export class CountedLog implements IsEmpty { diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index 5946f7c05283..c46153495fbc 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -33,7 +33,13 @@ import { } from '@aztec/circuits.js'; import { computeNoteHashNonce, computeSecretHash, computeVarArgsHash } from '@aztec/circuits.js/hash'; import { makeHeader } from '@aztec/circuits.js/testing'; -import { type FunctionArtifact, FunctionSelector, encodeArguments, getFunctionArtifact } from '@aztec/foundation/abi'; +import { + type FunctionArtifact, + FunctionSelector, + type NoteSelector, + encodeArguments, + getFunctionArtifact, +} from '@aztec/foundation/abi'; import { asyncMap } from '@aztec/foundation/async-map'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { times } from '@aztec/foundation/collection'; @@ -326,7 +332,7 @@ describe('Private Execution test suite', () => { const mockFirstNullifier = new Fr(1111); let currentNoteIndex = 0n; - const buildNote = (amount: bigint, ownerNpkMHash: Fr, storageSlot: Fr, noteTypeId: Fr) => { + const buildNote = (amount: bigint, ownerNpkMHash: Fr, storageSlot: Fr, noteTypeId: NoteSelector) => { // WARNING: this is not actually how nonces are computed! // For the purpose of this test we use a mocked firstNullifier and and a random number // to compute the nonce. Proper nonces are only enforced later by the kernel/later circuits @@ -847,7 +853,6 @@ describe('Private Execution test suite', () => { const secret = new Fr(1n); const secretHash = computeSecretHash(secret); const note = new Note([secretHash]); - // @todo @LHerskind (#6001) Need to investigate why this was working with `new Fr(5)` as the `example_set = 2` should have caused a failure. const storageSlot = TestContractArtifact.storageLayout['example_set'].slot; oracle.getNotes.mockResolvedValue([ { diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 0be77660a6a4..e72c4ef7e975 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -5,6 +5,7 @@ import { type FunctionArtifact, FunctionSelector, FunctionType, + type NoteSelector, encodeArguments, } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; @@ -140,7 +141,7 @@ export class AcirSimulator { contractAddress: AztecAddress, nonce: Fr, storageSlot: Fr, - noteTypeId: Fr, + noteTypeId: NoteSelector, computeNullifier: boolean, note: Note, ) { @@ -210,7 +211,12 @@ export class AcirSimulator { * @param note - The note. * @returns The note hash. */ - public async computeInnerNoteHash(contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: Fr, note: Note) { + public async computeInnerNoteHash( + contractAddress: AztecAddress, + storageSlot: Fr, + noteTypeId: NoteSelector, + note: Note, + ) { const { innerNoteHash } = await this.computeNoteHashAndOptionallyANullifier( contractAddress, Fr.ZERO, diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index 0f97b50ec429..fbca7486e34e 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -20,6 +20,8 @@ describe('Unconstrained Execution test suite', () => { node = mock(); node.getBlockNumber.mockResolvedValue(42); + node.getChainId.mockResolvedValue(1); + node.getVersion.mockResolvedValue(1); acirSimulator = new AcirSimulator(oracle, node); }); diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index f70e8db09b80..fd1710205dcc 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -42,6 +42,14 @@ export class ViewDataOracle extends TypedOracle { return Promise.resolve(this.contractAddress); } + public override getChainId(): Promise { + return Promise.resolve(this.aztecNode.getChainId().then(id => new Fr(id))); + } + + public override getVersion(): Promise { + return Promise.resolve(this.aztecNode.getVersion().then(v => new Fr(v))); + } + /** * Retrieve keys associated with a specific master public key and app address. * @param pkMHash - The master public key hash. diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index 9c51ebbc1844..7bbd49b1f7a5 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -143,7 +143,7 @@ export class PublicExecutionResultBuilder { endGasLeft: Gas.test(), transactionFee: Fr.ZERO, calldata: [], - avmHints: AvmExecutionHints.empty(), + avmCircuitHints: AvmExecutionHints.empty(), functionName: 'unknown', ...overrides, }; diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index 1b2833e58751..fecc49988d2f 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -266,13 +266,15 @@ export abstract class AbstractPhaseManager { const isExecutionRequest = !isPublicExecutionResult(current); const result = isExecutionRequest ? await this.publicExecutor.simulate( - current, + /*executionRequest=*/ current, this.globalVariables, /*availableGas=*/ this.getAvailableGas(tx, kernelPublicOutput), tx.data.constants.txContext, /*pendingNullifiers=*/ this.getSiloedPendingNullifiers(kernelPublicOutput), transactionFee, /*startSideEffectCounter=*/ AbstractPhaseManager.getMaxSideEffectCounter(kernelPublicOutput) + 1, + // NOTE: startSideEffectCounter is not the same as the executionRequest's sideEffectCounter + // (which counts the request itself) ) : current; @@ -320,7 +322,7 @@ export abstract class AbstractPhaseManager { calldata: result.calldata, bytecode: result.bytecode!, inputs: privateInputs, - avmHints: result.avmHints, + avmHints: result.avmCircuitHints, }; provingInformationList.push(publicProvingInformation); diff --git a/yarn-project/simulator/src/public/app_logic_phase_manager.ts b/yarn-project/simulator/src/public/app_logic_phase_manager.ts index bf25c580cdb7..de2628b6beab 100644 --- a/yarn-project/simulator/src/public/app_logic_phase_manager.ts +++ b/yarn-project/simulator/src/public/app_logic_phase_manager.ts @@ -47,6 +47,7 @@ export class AppLogicPhaseManager extends AbstractPhaseManager { // if so, this is removing contracts deployed in private setup await this.publicContractsDB.removeNewContracts(tx); await this.publicStateDB.rollbackToCheckpoint(); + tx.filterRevertedLogs(kernelOutput); } else { tx.unencryptedLogs.addFunctionLogs(newUnencryptedLogs); // TODO(#6470): we should be adding contracts deployed in those logs to the publicContractsDB diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index 2d28731f6214..e5ca2cecd53b 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -20,16 +20,37 @@ import { type Gas } from '../avm/avm_gas.js'; export interface PublicExecutionResult { /** The execution that triggered this result. */ execution: PublicExecution; + + /** The side effect counter at the start of the function call. */ + startSideEffectCounter: Fr; + /** The side effect counter after executing this function call */ + endSideEffectCounter: Fr; + /** How much gas was available for this public execution. */ + startGasLeft: Gas; + /** How much gas was left after this public execution. */ + endGasLeft: Gas; + /** Transaction fee set for this tx. */ + transactionFee: Fr; + + /** Bytecode used for this execution. */ + bytecode?: Buffer; + /** Calldata used for this execution. */ + calldata: Fr[]; /** The return values of the function. */ returnValues: Fr[]; + /** Whether the execution reverted. */ + reverted: boolean; + /** The revert reason if the execution reverted. */ + revertReason?: SimulationError; + + /** The contract storage reads performed by the function. */ + contractStorageReads: ContractStorageRead[]; + /** The contract storage update requests performed by the function. */ + contractStorageUpdateRequests: ContractStorageUpdateRequest[]; /** The new note hashes to be inserted into the note hashes tree. */ newNoteHashes: NoteHash[]; /** The new l2 to l1 messages generated in this call. */ newL2ToL1Messages: L2ToL1Message[]; - /** The side effect counter at the start of the function call. */ - startSideEffectCounter: Fr; - /** The side effect counter after executing this function call */ - endSideEffectCounter: Fr; /** The new nullifiers to be inserted into the nullifier tree. */ newNullifiers: Nullifier[]; /** The note hash read requests emitted in this call. */ @@ -40,12 +61,6 @@ export interface PublicExecutionResult { nullifierNonExistentReadRequests: ReadRequest[]; /** L1 to L2 message read requests emitted in this call. */ l1ToL2MsgReadRequests: ReadRequest[]; - /** The contract storage reads performed by the function. */ - contractStorageReads: ContractStorageRead[]; - /** The contract storage update requests performed by the function. */ - 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. @@ -61,22 +76,15 @@ export interface PublicExecutionResult { * Useful for maintaining correct ordering in ts. */ allUnencryptedLogs: UnencryptedFunctionL2Logs; - /** Whether the execution reverted. */ - reverted: boolean; - /** The revert reason if the execution reverted. */ - revertReason?: SimulationError; - /** How much gas was available for this public execution. */ - startGasLeft: Gas; - /** How much gas was left after this public execution. */ - endGasLeft: Gas; - /** Transaction fee set for this tx. */ - transactionFee: Fr; - /** Bytecode used for this execution. */ - bytecode?: Buffer; - /** Calldata used for this execution. */ - calldata: Fr[]; + + // TODO(dbanks12): add contract instance read requests + + /** The results of nested calls. */ + nestedExecutions: this[]; + /** Hints for proving AVM execution. */ - avmHints: AvmExecutionHints; + avmCircuitHints: AvmExecutionHints; + /** The name of the function that was executed. Only used for logging. */ functionName: string; } diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 45885d23de62..8486fb8d80e8 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -1,5 +1,5 @@ import { type AvmSimulationStats } from '@aztec/circuit-types/stats'; -import { Fr, type Gas, type GlobalVariables, type Header, type Nullifier, type TxContext } from '@aztec/circuits.js'; +import { Fr, Gas, type GlobalVariables, type Header, type Nullifier, type TxContext } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -10,7 +10,8 @@ import { HostStorage } from '../avm/journal/host_storage.js'; import { AvmPersistableStateManager } from '../avm/journal/index.js'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js'; import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js'; -import { convertAvmResultsToPxResult, createAvmExecutionEnvironment } from './transitional_adaptors.js'; +import { PublicSideEffectTrace } from './side_effect_trace.js'; +import { createAvmExecutionEnvironment } from './transitional_adaptors.js'; /** * Handles execution of public functions. @@ -27,54 +28,57 @@ export class PublicExecutor { /** * Executes a public execution request. - * @param execution - The execution to run. + * @param executionRequest - The execution to run. * @param globalVariables - The global variables to use. - * @returns The result of the run plus all nested runs. + * @param availableGas - The gas available at the start of this enqueued call. + * @param txContext - Transaction context. + * @param pendingSiloedNullifiers - The pending nullifier set from earlier parts of this TX. + * @param transactionFee - Fee offered for this TX. + * @param startSideEffectCounter - The counter of the first side-effect generated by this simulation. + * @returns The result of execution, including the results of all nested calls. */ public async simulate( - execution: PublicExecution, + executionRequest: PublicExecution, globalVariables: GlobalVariables, availableGas: Gas, txContext: TxContext, - pendingNullifiers: Nullifier[], + pendingSiloedNullifiers: Nullifier[], transactionFee: Fr = Fr.ZERO, startSideEffectCounter: number = 0, ): Promise { - const address = execution.contractAddress; - const selector = execution.functionSelector; - const startGas = availableGas; + const address = executionRequest.contractAddress; + const selector = executionRequest.functionSelector; const fnName = (await this.contractsDb.getDebugFunctionName(address, selector)) ?? `${address}:${selector}`; PublicExecutor.log.verbose(`[AVM] Executing public external function ${fnName}.`); const timer = new Timer(); - // Temporary code to construct the AVM context - // These data structures will permeate across the simulator when the public executor is phased out const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb); + const trace = new PublicSideEffectTrace(startSideEffectCounter); + const avmPersistableState = AvmPersistableStateManager.newWithPendingSiloedNullifiers( + hostStorage, + trace, + pendingSiloedNullifiers.map(n => n.value), + ); - const worldStateJournal = new AvmPersistableStateManager(hostStorage); - for (const nullifier of pendingNullifiers) { - worldStateJournal.nullifiers.cache.appendSiloed(nullifier.value); - } - worldStateJournal.trace.accessCounter = startSideEffectCounter; - - const executionEnv = createAvmExecutionEnvironment( - execution, + const avmExecutionEnv = createAvmExecutionEnvironment( + executionRequest, this.header, globalVariables, txContext.gasSettings, transactionFee, ); - const machineState = new AvmMachineState(startGas); - const avmContext = new AvmContext(worldStateJournal, executionEnv, machineState); + const avmMachineState = new AvmMachineState(availableGas); + const avmContext = new AvmContext(avmPersistableState, avmExecutionEnv, avmMachineState); const simulator = new AvmSimulator(avmContext); const avmResult = await simulator.execute(); - const bytecode = simulator.getBytecode(); + const bytecode = simulator.getBytecode()!; // Commit the journals state to the DBs since this is a top-level execution. // Observe that this will write all the state changes to the DBs, not only the latest for each slot. // However, the underlying DB keep a cache and will only write the latest state to disk. + // TODO(dbanks12): this should be unnecessary here or should be exposed by state manager await avmContext.persistableState.publicStorage.commitToDB(); PublicExecutor.log.verbose( @@ -89,28 +93,30 @@ export class PublicExecutor { } satisfies AvmSimulationStats, ); - const executionResult = convertAvmResultsToPxResult( - avmResult, - startSideEffectCounter, - execution, - startGas, - avmContext, + const publicExecutionResult = trace.toPublicExecutionResult( + avmExecutionEnv, + /*startGasLeft=*/ availableGas, + /*endGasLeft=*/ Gas.from(avmContext.machineState.gasLeft), bytecode, + avmResult, fnName, + /*requestSideEffectCounter=*/ executionRequest.callContext.sideEffectCounter, + // NOTE: startSideEffectCounter is not the same as the executionRequest's sideEffectCounter + // (which counts the request itself) ); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5818): is this really needed? // should already be handled in simulation. - if (execution.callContext.isStaticCall) { + if (executionRequest.callContext.isStaticCall) { checkValidStaticCall( - executionResult.newNoteHashes, - executionResult.newNullifiers, - executionResult.contractStorageUpdateRequests, - executionResult.newL2ToL1Messages, - executionResult.unencryptedLogs, + publicExecutionResult.newNoteHashes, + publicExecutionResult.newNullifiers, + publicExecutionResult.contractStorageUpdateRequests, + publicExecutionResult.newL2ToL1Messages, + publicExecutionResult.unencryptedLogs, ); } - return executionResult; + return publicExecutionResult; } } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 5040854a83a6..362fd788e1db 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -45,6 +45,7 @@ import { WASMSimulator, computeFeePayerBalanceLeafSlot, } from '@aztec/simulator'; +import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MerkleTreeOperations, type TreeInfo } from '@aztec/world-state'; import { jest } from '@jest/globals'; @@ -95,6 +96,7 @@ describe('public_processor', () => { Header.empty(), publicContractsDB, publicWorldStateDB, + new NoopTelemetryClient(), ); }); @@ -219,6 +221,7 @@ describe('public_processor', () => { header, publicContractsDB, publicWorldStateDB, + new NoopTelemetryClient(), ); }); @@ -230,6 +233,7 @@ describe('public_processor', () => { it('runs a tx with enqueued public calls', async function () { const tx = mockTxWithPartialState({ + hasLogs: true, numberOfRevertiblePublicCallRequests: 2, publicTeardownCallRequest: PublicCallRequest.empty(), }); @@ -253,6 +257,10 @@ describe('public_processor', () => { expect(publicWorldStateDB.commit).toHaveBeenCalledTimes(1); expect(publicWorldStateDB.rollbackToCommit).toHaveBeenCalledTimes(0); + // we keep the logs + expect(processed[0].encryptedLogs.getTotalLogCount()).toBe(6); + expect(processed[0].unencryptedLogs.getTotalLogCount()).toBe(2); + expect(prover.addNewTx).toHaveBeenCalledWith(processed[0]); }); @@ -346,7 +354,7 @@ describe('public_processor', () => { expect(prover.addNewTx).toHaveBeenCalledTimes(0); }); - it('rolls back app logic db updates on failed public execution, but persists setup/teardown', async function () { + it('rolls back app logic db updates on failed public execution, but persists setup', async function () { const baseContractAddressSeed = 0x200; const baseContractAddress = makeAztecAddress(baseContractAddressSeed); const publicCallRequests: PublicCallRequest[] = [ @@ -360,6 +368,7 @@ describe('public_processor', () => { const teardown = publicCallRequests.pop()!; // Remove the last call request to test that the processor can handle this const tx = mockTxWithPartialState({ + hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, publicCallRequests, @@ -469,8 +478,10 @@ describe('public_processor', () => { expect(txEffect.publicDataWrites[4]).toEqual( new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotC), fr(0x201)), ); - expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); - expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); + + // we keep the non-revertible logs + expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); + expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(1); expect(prover.addNewTx).toHaveBeenCalledWith(processed[0]); }); @@ -589,6 +600,7 @@ describe('public_processor', () => { const teardown = publicCallRequests.pop()!; const tx = mockTxWithPartialState({ + hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, publicCallRequests, @@ -689,8 +701,10 @@ describe('public_processor', () => { expect(txEffect.publicDataWrites[1]).toEqual( new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), ); - expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); - expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); + + // we keep the non-revertible logs + expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); + expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(1); expect(processed[0].data.revertCode).toEqual(RevertCode.TEARDOWN_REVERTED); @@ -711,6 +725,7 @@ describe('public_processor', () => { const teardown = publicCallRequests.pop()!; const tx = mockTxWithPartialState({ + hasLogs: true, numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, publicCallRequests, @@ -812,8 +827,10 @@ describe('public_processor', () => { expect(txEffect.publicDataWrites[1]).toEqual( new PublicDataWrite(computePublicDataTreeLeafSlot(baseContractAddress, contractSlotA), fr(0x102)), ); - expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(0); - expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(0); + + // we keep the non-revertible logs + expect(txEffect.encryptedLogs.getTotalLogCount()).toBe(3); + expect(txEffect.unencryptedLogs.getTotalLogCount()).toBe(1); expect(processed[0].data.revertCode).toEqual(RevertCode.BOTH_REVERTED); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index f5f5bd3749ca..fa15414db153 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -30,6 +30,7 @@ import { computeFeePayerBalanceLeafSlot, computeFeePayerBalanceStorageSlot, } from '@aztec/simulator'; +import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { type ContractDataSource } from '@aztec/types/contracts'; import { type MerkleTreeOperations } from '@aztec/world-state'; @@ -47,6 +48,7 @@ export class PublicProcessorFactory { private merkleTree: MerkleTreeOperations, private contractDataSource: ContractDataSource, private simulator: SimulationProvider, + private telemetryClient: TelemetryClient, ) {} /** @@ -74,6 +76,7 @@ export class PublicProcessorFactory { historicalHeader, publicContractsDB, worldStatePublicDB, + this.telemetryClient, ); } } @@ -83,6 +86,7 @@ export class PublicProcessorFactory { * any public function calls in them. Txs with private calls only are unaffected. */ export class PublicProcessor { + public readonly tracer: Tracer; constructor( protected db: MerkleTreeOperations, protected publicExecutor: PublicExecutor, @@ -91,9 +95,11 @@ export class PublicProcessor { protected historicalHeader: Header, protected publicContractsDB: ContractsDataSourcePublicDB, protected publicStateDB: PublicStateDB, - + telemetryClient: TelemetryClient, private log = createDebugLogger('aztec:sequencer:public-processor'), - ) {} + ) { + this.tracer = telemetryClient.getTracer('PublicProcessor'); + } /** * Run each tx through the public circuit and the public kernel circuit if needed. @@ -208,6 +214,9 @@ export class PublicProcessor { return finalPublicDataUpdateRequests; } + @trackSpan('PublicProcessor.processTxWithPublicCalls', tx => ({ + [Attributes.TX_HASH]: tx.getTxHash().toString(), + })) private async processTxWithPublicCalls(tx: Tx): Promise<[ProcessedTx, NestedProcessReturnValues[]]> { let returnValues: NestedProcessReturnValues[] = []; const publicProvingRequests: PublicProvingRequest[] = []; diff --git a/yarn-project/simulator/src/public/side_effect_trace.test.ts b/yarn-project/simulator/src/public/side_effect_trace.test.ts new file mode 100644 index 000000000000..fbfb42b2e5f4 --- /dev/null +++ b/yarn-project/simulator/src/public/side_effect_trace.test.ts @@ -0,0 +1,284 @@ +import { UnencryptedL2Log } from '@aztec/circuit-types'; +import { AztecAddress, EthAddress, Gas, L2ToL1Message } from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; +import { Fr } from '@aztec/foundation/fields'; +import { SerializableContractInstance } from '@aztec/types/contracts'; + +import { randomBytes, randomInt } from 'crypto'; + +import { Selector } from '../../../foundation/src/abi/selector.js'; +import { AvmContractCallResults } from '../avm/avm_message_call_result.js'; +import { initExecutionEnvironment } from '../avm/fixtures/index.js'; +import { PublicSideEffectTrace, type TracedContractInstance } from './side_effect_trace.js'; + +function randomTracedContractInstance(): TracedContractInstance { + const instance = SerializableContractInstance.random(); + const address = AztecAddress.random(); + return { exists: true, ...instance, address }; +} + +describe('Side Effect Trace', () => { + const address = Fr.random(); + const utxo = Fr.random(); + const leafIndex = Fr.random(); + const slot = Fr.random(); + const value = Fr.random(); + const recipient = Fr.random(); + const content = Fr.random(); + const event = new Fr(randomBytes(Selector.SIZE).readUint32BE()); + const log = [Fr.random(), Fr.random(), Fr.random()]; + + const startGasLeft = Gas.fromFields([new Fr(randomInt(10000)), new Fr(randomInt(10000))]); + const endGasLeft = Gas.fromFields([new Fr(randomInt(10000)), new Fr(randomInt(10000))]); + const transactionFee = Fr.random(); + const calldata = [Fr.random(), Fr.random(), Fr.random(), Fr.random()]; + const bytecode = randomBytes(100); + const returnValues = [Fr.random(), Fr.random()]; + + const avmEnvironment = initExecutionEnvironment({ + address, + calldata, + transactionFee, + }); + const reverted = false; + const avmCallResults = new AvmContractCallResults(reverted, returnValues); + + let startCounter: number; + let startCounterFr: Fr; + let startCounterPlus1: number; + let trace: PublicSideEffectTrace; + + beforeEach(() => { + startCounter = randomInt(/*max=*/ 1000000); + startCounterFr = new Fr(startCounter); + startCounterPlus1 = startCounter + 1; + trace = new PublicSideEffectTrace(startCounter); + }); + + const toPxResult = (trc: PublicSideEffectTrace) => { + return trc.toPublicExecutionResult(avmEnvironment, startGasLeft, endGasLeft, bytecode, avmCallResults); + }; + + it('Should trace storage reads', () => { + const exists = true; + const cached = false; + trace.tracePublicStorageRead(address, slot, value, exists, cached); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.contractStorageReads).toEqual([ + { + storageSlot: slot, + currentValue: value, + counter: startCounter, + contractAddress: AztecAddress.fromField(address), + //exists: exists, + //cached: cached, + }, + ]); + expect(pxResult.avmCircuitHints.storageValues.items).toEqual([{ key: startCounterFr, value: value }]); + }); + + it('Should trace storage writes', () => { + trace.tracePublicStorageWrite(address, slot, value); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.contractStorageUpdateRequests).toEqual([ + { + storageSlot: slot, + newValue: value, + counter: startCounter, + contractAddress: AztecAddress.fromField(address), + }, + ]); + }); + + it('Should trace note hash checks', () => { + const exists = true; + trace.traceNoteHashCheck(address, utxo, leafIndex, exists); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.noteHashReadRequests).toEqual([ + { + //storageAddress: contractAddress, + value: utxo, + //exists: exists, + counter: startCounter, + //leafIndex: leafIndex, + }, + ]); + expect(pxResult.avmCircuitHints.noteHashExists.items).toEqual([{ key: startCounterFr, value: new Fr(exists) }]); + }); + + it('Should trace note hashes', () => { + trace.traceNewNoteHash(address, utxo); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.newNoteHashes).toEqual([ + { + //storageAddress: contractAddress, + value: utxo, + counter: startCounter, + }, + ]); + }); + + it('Should trace nullifier checks', () => { + const exists = true; + const isPending = false; + trace.traceNullifierCheck(address, utxo, leafIndex, exists, isPending); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.nullifierReadRequests).toEqual([ + { + value: utxo, + counter: startCounter, + }, + ]); + expect(pxResult.nullifierNonExistentReadRequests).toEqual([]); + expect(pxResult.avmCircuitHints.nullifierExists.items).toEqual([{ key: startCounterFr, value: new Fr(exists) }]); + }); + + it('Should trace non-existent nullifier checks', () => { + const exists = false; + const isPending = false; + trace.traceNullifierCheck(address, utxo, leafIndex, exists, isPending); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.nullifierReadRequests).toEqual([]); + expect(pxResult.nullifierNonExistentReadRequests).toEqual([ + { + value: utxo, + counter: startCounter, + }, + ]); + expect(pxResult.avmCircuitHints.nullifierExists.items).toEqual([{ key: startCounterFr, value: new Fr(exists) }]); + }); + + it('Should trace nullifiers', () => { + trace.traceNewNullifier(address, utxo); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.newNullifiers).toEqual([ + { + value: utxo, + counter: startCounter, + noteHash: Fr.ZERO, + }, + ]); + }); + + it('Should trace L1ToL2 Message checks', () => { + const exists = true; + trace.traceL1ToL2MessageCheck(address, utxo, leafIndex, exists); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.l1ToL2MsgReadRequests).toEqual([ + { + value: utxo, + counter: startCounter, + }, + ]); + expect(pxResult.avmCircuitHints.l1ToL2MessageExists.items).toEqual([ + { + key: startCounterFr, + value: new Fr(exists), + }, + ]); + }); + + it('Should trace new L2ToL1 messages', () => { + trace.traceNewL2ToL1Message(recipient, content); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + expect(pxResult.newL2ToL1Messages).toEqual([ + new L2ToL1Message(EthAddress.fromField(recipient), content, startCounter), + ]); + }); + + it('Should trace new unencrypted logs', () => { + trace.traceUnencryptedLog(address, event, log); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + const expectLog = new UnencryptedL2Log( + AztecAddress.fromField(address), + EventSelector.fromField(event), + Buffer.concat(log.map(f => f.toBuffer())), + ); + expect(pxResult.unencryptedLogs.logs).toEqual([expectLog]); + expect(pxResult.allUnencryptedLogs.logs).toEqual([expectLog]); + expect(pxResult.unencryptedLogsHashes).toEqual([ + expect.objectContaining({ + counter: startCounter, + }), + ]); + }); + + it('Should trace get contract instance', () => { + const instance = randomTracedContractInstance(); + const { version: _, ...instanceWithoutVersion } = instance; + trace.traceGetContractInstance(instance); + expect(trace.getCounter()).toBe(startCounterPlus1); + + const pxResult = toPxResult(trace); + // TODO(dbanks12): process contract instance read requests in public kernel + //expect(pxResult.gotContractInstances).toEqual([instance]); + expect(pxResult.avmCircuitHints.contractInstances.items).toEqual([ + { + // hint omits "version" and has "exists" as an Fr + ...instanceWithoutVersion, + exists: new Fr(instance.exists), + }, + ]); + }); + + it('Should trace nested calls', () => { + const existsDefault = true; + const cached = false; + const isPending = false; + + const nestedTrace = new PublicSideEffectTrace(startCounter); + let testCounter = startCounter; + nestedTrace.tracePublicStorageRead(address, slot, value, existsDefault, cached); + testCounter++; + nestedTrace.tracePublicStorageWrite(address, slot, value); + testCounter++; + nestedTrace.traceNoteHashCheck(address, utxo, leafIndex, existsDefault); + testCounter++; + nestedTrace.traceNewNoteHash(address, utxo); + testCounter++; + nestedTrace.traceNullifierCheck(address, utxo, leafIndex, /*exists=*/ true, isPending); + testCounter++; + nestedTrace.traceNullifierCheck(address, utxo, leafIndex, /*exists=*/ false, isPending); + testCounter++; + nestedTrace.traceNewNullifier(address, utxo); + testCounter++; + nestedTrace.traceL1ToL2MessageCheck(address, utxo, leafIndex, existsDefault); + testCounter++; + nestedTrace.traceNewL2ToL1Message(recipient, content); + testCounter++; + nestedTrace.traceUnencryptedLog(address, event, log); + testCounter++; + + trace.traceNestedCall(nestedTrace, avmEnvironment, startGasLeft, endGasLeft, bytecode, avmCallResults); + // parent trace adopts nested call's counter + expect(trace.getCounter()).toBe(testCounter); + + // get parent trace as result + const parentPxResult = toPxResult(trace); + const childPxResult = toPxResult(nestedTrace); + expect(parentPxResult.nestedExecutions).toEqual([childPxResult]); + + // parent absorb's child's unencryptedLogs into all* + expect(parentPxResult.allUnencryptedLogs).toEqual(childPxResult.allUnencryptedLogs); + }); +}); diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts new file mode 100644 index 000000000000..64e32718a599 --- /dev/null +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -0,0 +1,323 @@ +import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types'; +import { + AvmContractInstanceHint, + AvmExecutionHints, + AvmExternalCallHint, + AvmKeyValueHint, + AztecAddress, + CallContext, + ContractStorageRead, + ContractStorageUpdateRequest, + EthAddress, + Gas, + L2ToL1Message, + LogHash, + NoteHash, + Nullifier, + ReadRequest, +} from '@aztec/circuits.js'; +import { EventSelector } from '@aztec/foundation/abi'; +import { Fr } from '@aztec/foundation/fields'; +import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; + +import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; +import { type AvmContractCallResults } from '../avm/avm_message_call_result.js'; +import { createSimulationError } from '../common/errors.js'; +import { type PublicExecution, type PublicExecutionResult } from './execution.js'; +import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js'; + +export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress; + +export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { + /** The side effect counter increments with every call to the trace. */ + private sideEffectCounter: number; // kept as number until finalized for efficiency + + private contractStorageReads: ContractStorageRead[] = []; + private contractStorageUpdateRequests: ContractStorageUpdateRequest[] = []; + + private noteHashReadRequests: ReadRequest[] = []; + private newNoteHashes: NoteHash[] = []; + + private nullifierReadRequests: ReadRequest[] = []; + private nullifierNonExistentReadRequests: ReadRequest[] = []; + private newNullifiers: Nullifier[] = []; + + private l1ToL2MsgReadRequests: ReadRequest[] = []; + private newL2ToL1Messages: L2ToL1Message[] = []; + + private unencryptedLogs: UnencryptedL2Log[] = []; + private allUnencryptedLogs: UnencryptedL2Log[] = []; + private unencryptedLogsHashes: LogHash[] = []; + + private gotContractInstances: ContractInstanceWithAddress[] = []; + + private nestedExecutions: PublicExecutionResult[] = []; + + private avmCircuitHints: AvmExecutionHints; + + constructor( + /** The counter of this trace's first side effect. */ + public readonly startSideEffectCounter: number = 0, + ) { + this.sideEffectCounter = startSideEffectCounter; + this.avmCircuitHints = AvmExecutionHints.empty(); + } + + public fork() { + return new PublicSideEffectTrace(this.sideEffectCounter); + } + + public getCounter() { + return this.sideEffectCounter; + } + + private incrementSideEffectCounter() { + this.sideEffectCounter++; + } + + public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, _exists: boolean, _cached: boolean) { + // TODO(4805): check if some threshold is reached for max storage reads + // (need access to parent length, or trace needs to be initialized with parent's contents) + // NOTE: exists and cached are unused for now but may be used for optimizations or kernel hints later + this.contractStorageReads.push( + new ContractStorageRead(slot, value, this.sideEffectCounter, AztecAddress.fromField(storageAddress)), + ); + this.avmCircuitHints.storageValues.items.push( + new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value), + ); + this.incrementSideEffectCounter(); + } + + public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr) { + // TODO(4805): check if some threshold is reached for max storage writes + // (need access to parent length, or trace needs to be initialized with parent's contents) + this.contractStorageUpdateRequests.push( + new ContractStorageUpdateRequest(slot, value, this.sideEffectCounter, storageAddress), + ); + this.incrementSideEffectCounter(); + } + + public traceNoteHashCheck(_storageAddress: Fr, noteHash: Fr, _leafIndex: Fr, exists: boolean) { + // TODO(4805): check if some threshold is reached for max note hash checks + // NOTE: storageAddress is unused but will be important when an AVM circuit processes an entire enqueued call + // TODO(dbanks12): leafIndex is unused for now but later must be used by kernel to constrain that the kernel + // is in fact checking the leaf indicated by the user + this.noteHashReadRequests.push(new ReadRequest(noteHash, this.sideEffectCounter)); + this.avmCircuitHints.noteHashExists.items.push( + new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), + ); + this.incrementSideEffectCounter(); + } + + public traceNewNoteHash(_storageAddress: Fr, noteHash: Fr) { + // TODO(4805): check if some threshold is reached for max new note hash + // NOTE: storageAddress is unused but will be important when an AVM circuit processes an entire enqueued call + // TODO(dbanks12): non-existent note hashes should emit a read request of the note hash that actually + // IS there, and the AVM circuit should accept THAT noteHash as a hint. The circuit will then compare + // the noteHash against the one provided by the user code to determine what to return to the user (exists or not), + // and will then propagate the actually-present noteHash to its public inputs. + this.newNoteHashes.push(new NoteHash(noteHash, this.sideEffectCounter)); + this.incrementSideEffectCounter(); + } + + public traceNullifierCheck(_storageAddress: Fr, nullifier: Fr, _leafIndex: Fr, exists: boolean, _isPending: boolean) { + // TODO(4805): check if some threshold is reached for max new nullifier + // NOTE: storageAddress is unused but will be important when an AVM circuit processes an entire enqueued call + // NOTE: isPending and leafIndex are unused for now but may be used for optimizations or kernel hints later + const readRequest = new ReadRequest(nullifier, this.sideEffectCounter); + if (exists) { + this.nullifierReadRequests.push(readRequest); + } else { + this.nullifierNonExistentReadRequests.push(readRequest); + } + this.avmCircuitHints.nullifierExists.items.push( + new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), + ); + this.incrementSideEffectCounter(); + } + + public traceNewNullifier(_storageAddress: Fr, nullifier: Fr) { + // TODO(4805): check if some threshold is reached for max new nullifier + // NOTE: storageAddress is unused but will be important when an AVM circuit processes an entire enqueued call + this.newNullifiers.push(new Nullifier(nullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); + this.incrementSideEffectCounter(); + } + + public traceL1ToL2MessageCheck(_contractAddress: Fr, msgHash: Fr, _msgLeafIndex: Fr, exists: boolean) { + // TODO(4805): check if some threshold is reached for max message reads + // NOTE: contractAddress is unused but will be important when an AVM circuit processes an entire enqueued call + // TODO(dbanks12): leafIndex is unused for now but later must be used by kernel to constrain that the kernel + // is in fact checking the leaf indicated by the user + this.l1ToL2MsgReadRequests.push(new ReadRequest(msgHash, this.sideEffectCounter)); + this.avmCircuitHints.l1ToL2MessageExists.items.push( + new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), + ); + this.incrementSideEffectCounter(); + } + + public traceNewL2ToL1Message(recipient: Fr, content: Fr) { + // TODO(4805): check if some threshold is reached for max messages + const recipientAddress = EthAddress.fromField(recipient); + this.newL2ToL1Messages.push(new L2ToL1Message(recipientAddress, content, this.sideEffectCounter)); + this.incrementSideEffectCounter(); + } + + public traceUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]) { + // TODO(4805): check if some threshold is reached for max logs + const ulog = new UnencryptedL2Log( + AztecAddress.fromField(contractAddress), + EventSelector.fromField(event), + Buffer.concat(log.map(f => f.toBuffer())), + ); + const basicLogHash = Fr.fromBuffer(ulog.hash()); + this.unencryptedLogs.push(ulog); + this.allUnencryptedLogs.push(ulog); + // TODO(6578): explain magic number 4 here + this.unencryptedLogsHashes.push(new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4))); + this.incrementSideEffectCounter(); + } + + public traceGetContractInstance(instance: TracedContractInstance) { + // TODO(4805): check if some threshold is reached for max contract instance retrievals + this.gotContractInstances.push(instance); + this.avmCircuitHints.contractInstances.items.push( + new AvmContractInstanceHint( + instance.address, + new Fr(instance.exists ? 1 : 0), + instance.salt, + instance.deployer, + instance.contractClassId, + instance.initializationHash, + instance.publicKeysHash, + ), + ); + this.incrementSideEffectCounter(); + } + + /** + * Trace a nested call. + * Accept some results from a finished nested call's trace into this one. + */ + public traceNestedCall( + /** The trace of the nested call. */ + nestedCallTrace: PublicSideEffectTrace, + /** The execution environment of the nested call. */ + nestedEnvironment: AvmExecutionEnvironment, + /** How much gas was available for this public execution. */ + startGasLeft: Gas, + /** How much gas was left after this public execution. */ + endGasLeft: Gas, + /** Bytecode used for this execution. */ + bytecode: Buffer, + /** The call's results */ + avmCallResults: AvmContractCallResults, + /** Function name for logging */ + functionName: string = 'unknown', + ) { + const result = nestedCallTrace.toPublicExecutionResult( + nestedEnvironment, + startGasLeft, + endGasLeft, + bytecode, + avmCallResults, + functionName, + ); + this.sideEffectCounter = result.endSideEffectCounter.toNumber(); + // when a nested call returns, caller accepts its updated counter + this.allUnencryptedLogs.push(...result.allUnencryptedLogs.logs); + // NOTE: eventually if the AVM circuit processes an entire enqueued call, + // this function will accept all of the nested's side effects into this instance + this.nestedExecutions.push(result); + + const gasUsed = new Gas( + result.startGasLeft.daGas - result.endGasLeft.daGas, + result.startGasLeft.l2Gas - result.endGasLeft.l2Gas, + ); + this.avmCircuitHints.externalCalls.items.push( + new AvmExternalCallHint(/*success=*/ new Fr(result.reverted ? 0 : 1), result.returnValues, gasUsed), + ); + } + + /** + * Convert this trace to a PublicExecutionResult for use externally to the simulator. + */ + public toPublicExecutionResult( + /** The execution environment of the nested call. */ + avmEnvironment: AvmExecutionEnvironment, + /** How much gas was available for this public execution. */ + startGasLeft: Gas, + /** How much gas was left after this public execution. */ + endGasLeft: Gas, + /** Bytecode used for this execution. */ + bytecode: Buffer, + /** The call's results */ + avmCallResults: AvmContractCallResults, + /** Function name for logging */ + functionName: string = 'unknown', + /** The side effect counter of the execution request itself */ + requestSideEffectCounter: number = this.startSideEffectCounter, + ): PublicExecutionResult { + return { + execution: createPublicExecutionRequest(requestSideEffectCounter, avmEnvironment), + + startSideEffectCounter: new Fr(this.startSideEffectCounter), + endSideEffectCounter: new Fr(this.sideEffectCounter), + startGasLeft, + endGasLeft, + transactionFee: avmEnvironment.transactionFee, + + bytecode, + calldata: avmEnvironment.calldata, + returnValues: avmCallResults.output, + reverted: avmCallResults.reverted, + revertReason: avmCallResults.revertReason ? createSimulationError(avmCallResults.revertReason) : undefined, + + contractStorageReads: this.contractStorageReads, + contractStorageUpdateRequests: this.contractStorageUpdateRequests, + noteHashReadRequests: this.noteHashReadRequests, + newNoteHashes: this.newNoteHashes, + nullifierReadRequests: this.nullifierReadRequests, + nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests, + newNullifiers: this.newNullifiers, + l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests, + newL2ToL1Messages: this.newL2ToL1Messages, + // correct the type on these now that they are finalized (lists won't grow) + unencryptedLogs: new UnencryptedFunctionL2Logs(this.unencryptedLogs), + allUnencryptedLogs: new UnencryptedFunctionL2Logs(this.allUnencryptedLogs), + unencryptedLogsHashes: this.unencryptedLogsHashes, + // TODO(dbanks12): process contract instance read requests in public kernel + //gotContractInstances: this.gotContractInstances, + + nestedExecutions: this.nestedExecutions, + + avmCircuitHints: this.avmCircuitHints, + + functionName, + }; + } +} + +/** + * Helper function to create a public execution request from an AVM execution environment + */ +function createPublicExecutionRequest( + requestSideEffectCounter: number, + avmEnvironment: AvmExecutionEnvironment, +): PublicExecution { + const callContext = CallContext.from({ + msgSender: avmEnvironment.sender, + storageContractAddress: avmEnvironment.storageAddress, + functionSelector: avmEnvironment.temporaryFunctionSelector, + isDelegateCall: avmEnvironment.isDelegateCall, + isStaticCall: avmEnvironment.isStaticCall, + sideEffectCounter: requestSideEffectCounter, + }); + const execution: PublicExecution = { + contractAddress: avmEnvironment.address, + functionSelector: avmEnvironment.temporaryFunctionSelector, + callContext, + // execution request does not contain AvmContextInputs prefix + args: avmEnvironment.getCalldataWithoutPrefix(), + }; + return execution; +} diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts new file mode 100644 index 000000000000..60dd0b1107d4 --- /dev/null +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -0,0 +1,41 @@ +import { type Gas } from '@aztec/circuits.js'; +import { type Fr } from '@aztec/foundation/fields'; + +import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; +import { type AvmContractCallResults } from '../avm/avm_message_call_result.js'; +import { type TracedContractInstance } from './side_effect_trace.js'; + +export interface PublicSideEffectTraceInterface { + fork(): PublicSideEffectTraceInterface; + getCounter(): number; + tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, exists: boolean, cached: boolean): void; + tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr): void; + traceNoteHashCheck(storageAddress: Fr, noteHash: Fr, leafIndex: Fr, exists: boolean): void; + traceNewNoteHash(storageAddress: Fr, noteHash: Fr): void; + traceNullifierCheck(storageAddress: Fr, nullifier: Fr, leafIndex: Fr, exists: boolean, isPending: boolean): void; + traceNewNullifier(storageAddress: Fr, nullifier: Fr): void; + traceL1ToL2MessageCheck(contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr, exists: boolean): void; + // TODO(dbanks12): should new message accept contract address as arg? + traceNewL2ToL1Message(recipient: Fr, content: Fr): void; + traceUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]): void; + // TODO(dbanks12): odd that getContractInstance is a one-off in that it accepts an entire object instead of components + traceGetContractInstance(instance: TracedContractInstance): void; + traceNestedCall( + /** The trace of the nested call. */ + nestedCallTrace: PublicSideEffectTraceInterface, + /** The execution environment of the nested call. */ + nestedEnvironment: AvmExecutionEnvironment, + /** How much gas was available for this public execution. */ + // TODO(dbanks12): consider moving to AvmExecutionEnvironment + startGasLeft: Gas, + /** How much gas was left after this public execution. */ + // TODO(dbanks12): consider moving to AvmContractCallResults + endGasLeft: Gas, + /** Bytecode used for this execution. */ + bytecode: Buffer, + /** The call's results */ + avmCallResults: AvmContractCallResults, + /** Function name */ + functionName: string, + ): void; +} diff --git a/yarn-project/simulator/src/public/teardown_phase_manager.ts b/yarn-project/simulator/src/public/teardown_phase_manager.ts index bd1eafbcba96..14eb475746ae 100644 --- a/yarn-project/simulator/src/public/teardown_phase_manager.ts +++ b/yarn-project/simulator/src/public/teardown_phase_manager.ts @@ -44,6 +44,7 @@ export class TeardownPhaseManager extends AbstractPhaseManager { ); if (revertReason) { await this.publicStateDB.rollbackToCheckpoint(); + tx.filterRevertedLogs(kernelOutput); } else { // TODO(#6464): Should we allow emitting contracts in the public teardown phase? // if so, we should insert them here diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 36d0f2ade12b..9cea3c780753 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -1,29 +1,13 @@ // All code in this file needs to die once the public executor is phased out in favor of the AVM. -import { UnencryptedFunctionL2Logs } from '@aztec/circuit-types'; -import { - AvmContractInstanceHint, - AvmExecutionHints, - AvmExternalCallHint, - AvmKeyValueHint, - CallContext, - Gas, - type GasSettings, - type GlobalVariables, - type Header, -} from '@aztec/circuits.js'; +import { type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { promisify } from 'util'; import { gunzip } from 'zlib'; -import { type AvmContext } from '../avm/avm_context.js'; import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { type AvmContractCallResults } from '../avm/avm_message_call_result.js'; -import { type PartialPublicExecutionResult } from '../avm/journal/journal.js'; -import { type WorldStateAccessTrace } from '../avm/journal/trace.js'; import { Mov } from '../avm/opcodes/memory.js'; -import { createSimulationError } from '../common/errors.js'; -import { type PublicExecution, type PublicExecutionResult } from './execution.js'; +import { type PublicExecution } from './execution.js'; /** * Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment @@ -57,90 +41,6 @@ export function createAvmExecutionEnvironment( ); } -export function createPublicExecution( - startSideEffectCounter: number, - avmEnvironment: AvmExecutionEnvironment, - calldata: Fr[], -): PublicExecution { - const callContext = CallContext.from({ - msgSender: avmEnvironment.sender, - storageContractAddress: avmEnvironment.storageAddress, - functionSelector: avmEnvironment.temporaryFunctionSelector, - isDelegateCall: avmEnvironment.isDelegateCall, - isStaticCall: avmEnvironment.isStaticCall, - sideEffectCounter: startSideEffectCounter, - }); - const execution: PublicExecution = { - contractAddress: avmEnvironment.address, - callContext, - args: calldata, - functionSelector: avmEnvironment.temporaryFunctionSelector, - }; - return execution; -} - -function computeHints(trace: WorldStateAccessTrace, executionResult: PartialPublicExecutionResult): AvmExecutionHints { - return new AvmExecutionHints( - trace.publicStorageReads.map(read => new AvmKeyValueHint(read.counter, read.value)), - trace.noteHashChecks.map(check => new AvmKeyValueHint(check.counter, new Fr(check.exists ? 1 : 0))), - trace.nullifierChecks.map(check => new AvmKeyValueHint(check.counter, new Fr(check.exists ? 1 : 0))), - trace.l1ToL2MessageChecks.map(check => new AvmKeyValueHint(check.counter, new Fr(check.exists ? 1 : 0))), - executionResult.nestedExecutions.map(nested => { - const gasUsed = new Gas( - nested.startGasLeft.daGas - nested.endGasLeft.daGas, - nested.startGasLeft.l2Gas - nested.endGasLeft.l2Gas, - ); - return new AvmExternalCallHint(/*success=*/ new Fr(nested.reverted ? 0 : 1), nested.returnValues, gasUsed); - }), - trace.gotContractInstances.map( - instance => - new AvmContractInstanceHint( - instance.address, - new Fr(instance.exists ? 1 : 0), - instance.salt, - instance.deployer, - instance.contractClassId, - instance.initializationHash, - instance.publicKeysHash, - ), - ), - ); -} - -export function convertAvmResultsToPxResult( - avmResult: AvmContractCallResults, - startSideEffectCounter: number, - fromPx: PublicExecution, - startGas: Gas, - endAvmContext: AvmContext, - bytecode: Buffer | undefined, - functionName: string, -): PublicExecutionResult { - const endPersistableState = endAvmContext.persistableState; - const endMachineState = endAvmContext.machineState; - - return { - ...endPersistableState.transitionalExecutionResult, // includes nestedExecutions - functionName: functionName, - execution: fromPx, - returnValues: avmResult.output, - startSideEffectCounter: new Fr(startSideEffectCounter), - endSideEffectCounter: new Fr(endPersistableState.trace.accessCounter), - unencryptedLogs: new UnencryptedFunctionL2Logs(endPersistableState.transitionalExecutionResult.unencryptedLogs), - allUnencryptedLogs: new UnencryptedFunctionL2Logs( - endPersistableState.transitionalExecutionResult.allUnencryptedLogs, - ), - reverted: avmResult.reverted, - revertReason: avmResult.revertReason ? createSimulationError(avmResult.revertReason) : undefined, - startGasLeft: startGas, - endGasLeft: endMachineState.gasLeft, - transactionFee: endAvmContext.environment.transactionFee, - bytecode: bytecode, - calldata: endAvmContext.environment.calldata, - avmHints: computeHints(endPersistableState.trace, endPersistableState.transitionalExecutionResult), - }; -} - const AVM_MAGIC_SUFFIX = Buffer.from([ Mov.opcode, // opcode 0x00, // indirect diff --git a/yarn-project/simulator/tsconfig.json b/yarn-project/simulator/tsconfig.json index effb5a7151c9..60a3f7e62deb 100644 --- a/yarn-project/simulator/tsconfig.json +++ b/yarn-project/simulator/tsconfig.json @@ -21,6 +21,9 @@ { "path": "../protocol-contracts" }, + { + "path": "../telemetry-client" + }, { "path": "../types" }, diff --git a/yarn-project/telemetry-client/.eslintrc.cjs b/yarn-project/telemetry-client/.eslintrc.cjs new file mode 100644 index 000000000000..e659927475c0 --- /dev/null +++ b/yarn-project/telemetry-client/.eslintrc.cjs @@ -0,0 +1 @@ +module.exports = require('@aztec/foundation/eslint'); diff --git a/yarn-project/telemetry-client/package.json b/yarn-project/telemetry-client/package.json new file mode 100644 index 000000000000..d937716d35f9 --- /dev/null +++ b/yarn-project/telemetry-client/package.json @@ -0,0 +1,77 @@ +{ + "name": "@aztec/telemetry-client", + "inherits": [ + "../package.common.json" + ], + "type": "module", + "exports": { + ".": "./dest/index.js", + "./start": "./dest/start.js", + "./noop": "./dest/noop.js" + }, + "scripts": { + "build": "yarn clean && tsc -b", + "build:dev": "tsc -b --watch", + "clean": "rm -rf ./dest .tsbuildinfo", + "formatting": "run -T prettier --check ./src && run -T eslint ./src", + "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", + "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests" + }, + "engines": { + "node": ">=18" + }, + "files": [ + "dest", + "src", + "!*.test.*" + ], + "dependencies": { + "@aztec/foundation": "workspace:^", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.52.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.52.0", + "@opentelemetry/host-metrics": "^0.35.2", + "@opentelemetry/resources": "^1.25.0", + "@opentelemetry/sdk-metrics": "^1.25.0", + "@opentelemetry/sdk-trace-node": "^1.25.0", + "@opentelemetry/semantic-conventions": "^1.25.0" + }, + "devDependencies": { + "@jest/globals": "^29.5.0", + "@types/jest": "^29.5.0", + "jest": "^29.5.0", + "ts-node": "^10.9.1", + "typescript": "^5.0.4" + }, + "jest": { + "extensionsToTreatAsEsm": [ + ".ts" + ], + "transform": { + "^.+\\.tsx?$": [ + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } + ] + }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.[cm]?js$": "$1" + }, + "reporters": [ + [ + "default", + { + "summaryThreshold": 9999 + } + ] + ], + "testRegex": "./src/.*\\.test\\.(js|mjs|ts)$", + "rootDir": "./src" + } +} diff --git a/yarn-project/telemetry-client/src/attributes.ts b/yarn-project/telemetry-client/src/attributes.ts new file mode 100644 index 000000000000..d4df0253436d --- /dev/null +++ b/yarn-project/telemetry-client/src/attributes.ts @@ -0,0 +1,49 @@ +/** + * @overview This file contains the custom attributes used in telemetry events. + * Attribute names exist in a global namespace, alongside metric names. Use this file to ensure that attribute names are unique. + * + * To define a new attribute follow these steps: + * 1. Make sure it's not a semantic attribute that's already been defined by {@link @opentelemetry/semantic-conventions | OpenTelemetry} (e.g. `service.name`) + * 2. Come up with a unique name for it so that it doesn't clash with other attributes or metrics. + * 3. Prefix the attribute name with `aztec` to make it clear that it's a custom attribute. + * 4. Add a description of what the attribute represents and examples of what it might contain. + * 5. Start using it. + * + * @note Attributes and metric names exist in a hierarchy of namespaces. If a name has been used as a namespace, then it can not be used as a name for an attribute or metric. + * @example If `aztec.circuit.name` has been defined as an attribute then `aztec.circuit` alone can not be re-used for a metric or attribute because it is already a namespace. + * @see {@link https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/} + */ + +/** + * The name of the protocol circuit being run (e.g. public-kernel-setup or base-rollup) + * @see {@link @aztec/circuit-types/stats:CircuitName} + */ +export const PROTOCOL_CIRCUIT_NAME = 'aztec.circuit.protocol_circuit_name'; + +/** + * The type of protocol circuit being run: server or client + */ +export const PROTOCOL_CIRCUIT_TYPE = 'aztec.circuit.protocol_circuit_type'; + +/** + * For an app circuit, the contract:function being run (e.g. Token:transfer) + */ +export const APP_CIRCUIT_NAME = 'aztec.circuit.app_circuit_name'; + +/** + * The type of app circuit being run: server or client + */ +export const APP_CIRCUIT_TYPE = 'aztec.circuit.app_circuit_type'; + +/** The block number */ +export const BLOCK_NUMBER = 'aztec.block.number'; +/** The parent's block number */ +export const BLOCK_PARENT = 'aztec.block.parent'; +/** How many txs are being processed to build this block */ +export const BLOCK_CANDIDATE_TXS_COUNT = 'aztec.block.candidate_txs_count'; +/** How many actual txs were included in this block */ +export const BLOCK_TXS_COUNT = 'aztec.block.txs_count'; +/** The block size (power of 2) */ +export const BLOCK_SIZE = 'aztec.block.size'; +/** The tx hash */ +export const TX_HASH = 'aztec.tx.hash'; diff --git a/yarn-project/telemetry-client/src/index.ts b/yarn-project/telemetry-client/src/index.ts new file mode 100644 index 000000000000..f84f46bf75cf --- /dev/null +++ b/yarn-project/telemetry-client/src/index.ts @@ -0,0 +1 @@ +export * from './telemetry.js'; diff --git a/yarn-project/telemetry-client/src/metrics.ts b/yarn-project/telemetry-client/src/metrics.ts new file mode 100644 index 000000000000..e5487ef41b3a --- /dev/null +++ b/yarn-project/telemetry-client/src/metrics.ts @@ -0,0 +1,30 @@ +/** + * @file Metric names used in Aztec. + * Metric names must be unique and not clash with {@link attributes.ts | Attribute names}. + * Prefix metric names with `aztec` and use dots `.` to separate namespaces. + * + * @see {@link https://opentelemetry.io/docs/specs/semconv/general/metrics/ | OpenTelemetry Metrics} for naming conventions. + */ + +/** How long it takes to simulate a circuit */ +export const CIRCUIT_SIMULATION_DURATION = 'aztec.circuit.simulation.duration'; +export const CIRCUIT_SIMULATION_INPUT_SIZE = 'aztec.circuit.simulation.input_size'; +export const CIRCUIT_SIMULATION_OUTPUT_SIZE = 'aztec.circuit.simulation.output_size'; + +export const CIRCUIT_WITNESS_GEN_DURATION = 'aztec.circuit.witness_generation.duration'; +export const CIRCUIT_WITNESS_GEN_INPUT_SIZE = 'aztec.circuit.witness_generation.input_size'; +export const CIRCUIT_WITNESS_GEN_OUTPUT_SIZE = 'aztec.circuit.witness_generation.output_size'; + +export const CIRCUIT_PROVING_DURATION = 'aztec.circuit.proving.duration'; +export const CIRCUIT_PROVING_INPUT_SIZE = 'aztec.circuit.proving.input_size'; +export const CIRCUIT_PROVING_PROOF_SIZE = 'aztec.circuit.proving.proof_size'; + +export const CIRCUIT_PUBLIC_INPUTS_COUNT = 'aztec.circuit.public_inputs_count'; +export const CIRCUIT_GATE_COUNT = 'aztec.circuit.gate_count'; +export const CIRCUIT_SIZE = 'aztec.circuit.size'; + +export const MEMPOOL_TX_COUNT = 'aztec.mempool.tx_count'; +export const MEMPOOL_TX_SIZE = 'aztec.mempool.tx_size'; + +export const ARCHIVER_BLOCK_HEIGHT = 'aztec.archiver.block_height'; +export const ARCHIVER_BLOCK_SIZE = 'aztec.archiver.block_size'; diff --git a/yarn-project/telemetry-client/src/noop.ts b/yarn-project/telemetry-client/src/noop.ts new file mode 100644 index 000000000000..e4ab8162ffb5 --- /dev/null +++ b/yarn-project/telemetry-client/src/noop.ts @@ -0,0 +1,83 @@ +import { type Meter, type Span, type SpanContext, type Tracer, createNoopMeter } from '@opentelemetry/api'; + +import { type TelemetryClient } from './telemetry.js'; + +export class NoopTelemetryClient implements TelemetryClient { + getMeter(): Meter { + return createNoopMeter(); + } + + getTracer(): Tracer { + return new NoopTracer(); + } + + stop(): Promise { + return Promise.resolve(); + } +} + +// @opentelemetry/api internally uses NoopTracer and NoopSpan but they're not exported +// make our own versions +// https://github.com/open-telemetry/opentelemetry-js/issues/4518#issuecomment-2179405444 +class NoopTracer implements Tracer { + startSpan(): Span { + return new NoopSpan(); + } + + startActiveSpan any>(_name: string, ...args: (unknown | F)[]): ReturnType { + // there are three different signatures for startActiveSpan, grab the function, we don't care about the rest + const fn = args.find(arg => typeof arg === 'function') as F; + return fn(new NoopSpan()); + } +} + +class NoopSpan implements Span { + private recording: boolean = true; + addEvent(): this { + return this; + } + + addLink(): this { + return this; + } + + addLinks(): this { + return this; + } + + end(): void { + this.recording = false; + } + + isRecording(): boolean { + return this.recording; + } + + recordException(): void { + return; + } + + setAttribute(): this { + return this; + } + + setAttributes(): this { + return this; + } + + setStatus(): this { + return this; + } + + spanContext(): SpanContext { + return { + spanId: '', + traceId: '', + traceFlags: 0, + }; + } + + updateName(): this { + return this; + } +} diff --git a/yarn-project/telemetry-client/src/otel.ts b/yarn-project/telemetry-client/src/otel.ts new file mode 100644 index 000000000000..6ed1ce012181 --- /dev/null +++ b/yarn-project/telemetry-client/src/otel.ts @@ -0,0 +1,71 @@ +import { type Meter, type Tracer, type TracerProvider } from '@opentelemetry/api'; +import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; +import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; +import { HostMetrics } from '@opentelemetry/host-metrics'; +import { Resource } from '@opentelemetry/resources'; +import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; +import { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; +import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; + +import { type TelemetryClient } from './telemetry.js'; + +export class OpenTelemetryClient implements TelemetryClient { + hostMetrics: HostMetrics | undefined; + protected constructor( + private resource: Resource, + private meterProvider: MeterProvider, + private traceProvider: TracerProvider, + ) {} + + getMeter(name: string): Meter { + return this.meterProvider.getMeter(name, this.resource.attributes[SEMRESATTRS_SERVICE_VERSION] as string); + } + + getTracer(name: string): Tracer { + return this.traceProvider.getTracer(name, this.resource.attributes[SEMRESATTRS_SERVICE_VERSION] as string); + } + + public start() { + this.hostMetrics = new HostMetrics({ + name: this.resource.attributes[SEMRESATTRS_SERVICE_NAME] as string, + meterProvider: this.meterProvider, + }); + + this.hostMetrics.start(); + } + + public async stop() { + await Promise.all([this.meterProvider.shutdown()]); + } + + public static createAndStart(name: string, version: string, collectorBaseUrl: URL): OpenTelemetryClient { + const resource = new Resource({ + [SEMRESATTRS_SERVICE_NAME]: name, + [SEMRESATTRS_SERVICE_VERSION]: version, + }); + + const tracerProvider = new NodeTracerProvider({ + resource, + }); + tracerProvider.addSpanProcessor( + new BatchSpanProcessor(new OTLPTraceExporter({ url: new URL('/v1/traces', collectorBaseUrl).href })), + ); + tracerProvider.register(); + + const meterProvider = new MeterProvider({ + resource, + readers: [ + new PeriodicExportingMetricReader({ + exporter: new OTLPMetricExporter({ + url: new URL('/v1/metrics', collectorBaseUrl).href, + }), + }), + ], + }); + + const service = new OpenTelemetryClient(resource, meterProvider, tracerProvider); + service.start(); + + return service; + } +} diff --git a/yarn-project/telemetry-client/src/start.ts b/yarn-project/telemetry-client/src/start.ts new file mode 100644 index 000000000000..f83baa83400b --- /dev/null +++ b/yarn-project/telemetry-client/src/start.ts @@ -0,0 +1,27 @@ +import { NoopTelemetryClient } from './noop.js'; +import { OpenTelemetryClient } from './otel.js'; +import { type TelemetryClient } from './telemetry.js'; + +export interface TelemetryClientConfig { + collectorBaseUrl?: URL; + serviceName: string; + serviceVersion: string; +} + +export function createAndStartTelemetryClient(config: TelemetryClientConfig): TelemetryClient { + if (config.collectorBaseUrl) { + return OpenTelemetryClient.createAndStart(config.serviceName, config.serviceVersion, config.collectorBaseUrl); + } else { + return new NoopTelemetryClient(); + } +} + +export function getConfigEnvVars(): TelemetryClientConfig { + const { TEL_COLLECTOR_BASE_URL, TEL_SERVICE_NAME = 'aztec', TEL_SERVICE_VERSION = '0.0.0' } = process.env; + + return { + collectorBaseUrl: TEL_COLLECTOR_BASE_URL ? new URL(TEL_COLLECTOR_BASE_URL) : undefined, + serviceName: TEL_SERVICE_NAME, + serviceVersion: TEL_SERVICE_VERSION, + }; +} diff --git a/yarn-project/telemetry-client/src/telemetry.ts b/yarn-project/telemetry-client/src/telemetry.ts new file mode 100644 index 000000000000..bf56bf51af59 --- /dev/null +++ b/yarn-project/telemetry-client/src/telemetry.ts @@ -0,0 +1,180 @@ +import { + type AttributeValue, + type MetricOptions, + type Gauge as OtelGauge, + type Histogram as OtelHistogram, + type UpDownCounter as OtelUpDownCounter, + type Span, + SpanStatusCode, + Tracer, +} from '@opentelemetry/api'; + +import * as Attributes from './attributes.js'; +import * as Metrics from './metrics.js'; + +export { ValueType, Span } from '@opentelemetry/api'; + +type ValuesOf = T extends Record ? U : never; + +/** Global registry of attributes */ +type Attributes = Partial, AttributeValue>>; +export { Attributes }; + +/** Global registry of metrics */ +type Metrics = (typeof Metrics)[keyof typeof Metrics]; +export { Metrics }; + +export type Gauge = OtelGauge; +export type Histogram = OtelHistogram; +export type UpDownCounter = OtelUpDownCounter; + +export { Tracer }; + +// INTERNAL NOTE: this interface is the same as opentelemetry's Meter, but with proper types +/** + * A meter that provides instruments for recording metrics. + */ +export interface Meter { + /** + * Creates a new gauge instrument. A gauge is a metric that represents a single numerical value that can arbitrarily go up and down. + * @param name - The name of the gauge + * @param options - The options for the gauge + */ + createGauge(name: Metrics, options?: MetricOptions): Gauge; + + /** + * Creates a new histogram instrument. A histogram is a metric that samples observations (usually things like request durations or response sizes) and counts them in configurable buckets. + * @param name - The name of the histogram + * @param options - The options for the histogram + */ + createHistogram(name: Metrics, options?: MetricOptions): Histogram; + + /** + * Creates a new counter instrument. A counter can go up or down with a delta from the previous value. + * @param name - The name of the counter + * @param options - The options for the counter + */ + createUpDownCounter(name: Metrics, options?: MetricOptions): UpDownCounter; +} + +/** + * A telemetry client that provides meters for recording metrics. + */ +export interface TelemetryClient { + /** + * Creates a new meter + * @param name - The name of the meter. + */ + getMeter(name: string): Meter; + + /** + * Creates a new tracer + * @param name - The name of the tracer. + */ + getTracer(name: string): Tracer; + + /** + * Stops the telemetry client. + */ + stop(): Promise; +} + +/** Objects that adhere to this interface can use @trackSpan */ +export interface Traceable { + tracer: Tracer; +} + +type SpanDecorator any> = ( + originalMethod: F, + context: ClassMethodDecoratorContext, +) => F; + +/** + * Starts a new span whenever the decorated method is called. + * @param spanName - The name of the span to create. Can be a string or a function that returns a string. + * @param attributes - Initial attributes to set on the span. If a function is provided, it will be called with the arguments of the method. + * @param extraAttributes - Extra attributes to set on the span after the method is called. Will be called with the return value of the method. Note: if the function throws then this will not be called. + * @returns A decorator that wraps the method in a span. + * + * @privateRemarks + * This code looks complex but it's not that difficult: + * - decorators are functions that _replace_ a method with a different implementation + * - normal decorators can't take function arguments, but if we write a function that returns a decorator, we can pass arguments to that function + * + * The trackSpan function takes a span's name and some attributes and builds a decorator that wraps a method in a span with the given name and props + * The decorator can currently only be applied to methods on classes that have a `tracer` property. The compiler will enforce this. + */ +export function trackSpan any>( + spanName: string | ((this: T, ...args: Parameters) => string), + attributes?: Attributes | ((this: T, ...args: Parameters) => Attributes), + extraAttributes?: (this: T, returnValue: Awaited>) => Attributes, +): SpanDecorator { + // the return value of trackSpan is a decorator + return (originalMethod: F, _context: ClassMethodDecoratorContext) => { + // the return value of the decorator replaces the original method + // in this wrapper method we start a span, call the original method, and then end the span + return function replacementMethod(this: T, ...args: Parameters): Promise>> { + const name = typeof spanName === 'function' ? spanName.call(this, ...args) : spanName; + const currentAttrs = typeof attributes === 'function' ? attributes.call(this, ...args) : attributes; + + // run originalMethod wrapped in an active span + // "active" means the span will be alive for the duration of the function execution + // and if any other spans are started during the execution of originalMethod, they will be children of this span + // behind the scenes this uses AsyncLocalStorage https://nodejs.org/dist/latest-v18.x/docs/api/async_context.html + return this.tracer.startActiveSpan(name, async (span: Span) => { + span.setAttributes(currentAttrs ?? {}); + + try { + const res = await originalMethod.call(this, ...args); + const extraAttrs = extraAttributes?.call(this, res); + span.setAttributes(extraAttrs ?? {}); + return res; + } catch (err) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: String(err), + }); + throw err; + } finally { + span.end(); + } + }); + } as F; + }; +} + +/** + * Runs an event callback in a span. The span is started immediately and completes once the callback finishes running. + * The span will have two events added: 'callbackStart' and 'callbackEnd' to mark the start and end of the callback. + * + * @param tracer - The tracer instance to use + * @param spanName - The name of the span to create + * @param attributes - Initial attributes to set on the span + * @param callback - The callback to wrap in a span + * + * @returns - A new function that wraps the callback in a span + */ +export function wrapCallbackInSpan any>( + tracer: Tracer, + spanName: string, + attributes: Attributes, + callback: F, +): F { + const span = tracer.startSpan(spanName, { attributes }); + return (async (...args: Parameters) => { + try { + span.addEvent('callbackStart'); + const res = await callback(...args); + return res; + } catch (err) { + span.setStatus({ + code: SpanStatusCode.ERROR, + message: String(err), + }); + throw err; + } finally { + span.addEvent('callbackEnd'); + span.end(); + } + }) as F; +} diff --git a/yarn-project/telemetry-client/tsconfig.json b/yarn-project/telemetry-client/tsconfig.json new file mode 100644 index 000000000000..63f8ab3e9f75 --- /dev/null +++ b/yarn-project/telemetry-client/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "..", + "compilerOptions": { + "outDir": "dest", + "rootDir": "src", + "tsBuildInfoFile": ".tsbuildinfo" + }, + "references": [ + { + "path": "../foundation" + } + ], + "include": ["src"] +} diff --git a/yarn-project/txe/package.json b/yarn-project/txe/package.json index 5658cd3b454e..f77a47b7f62a 100644 --- a/yarn-project/txe/package.json +++ b/yarn-project/txe/package.json @@ -18,7 +18,8 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "start": "DEBUG='aztec:*' && node ./dest/bin/index.js" + "dev": "DEBUG='aztec:*' && node ./dest/bin/index.js", + "start": "node ./dest/bin/index.js" }, "inherits": [ "../package.common.json" @@ -32,7 +33,15 @@ "workerThreads": true, "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/txe/src/bin/index.ts b/yarn-project/txe/src/bin/index.ts index 149347621599..f46cd541c958 100644 --- a/yarn-project/txe/src/bin/index.ts +++ b/yarn-project/txe/src/bin/index.ts @@ -1,4 +1,5 @@ #!/usr/bin/env -S node --no-warnings +import { Fr } from '@aztec/foundation/fields'; import { JsonRpcServer } from '@aztec/foundation/json-rpc/server'; import { type Logger, createDebugLogger } from '@aztec/foundation/log'; @@ -32,25 +33,20 @@ class TXEDispatcher { function: functionName, inputs, }: TXEForeignCallInput): Promise { - this.logger.debug( - `Calling ${functionName} with inputs: ${JSON.stringify(inputs, null, 2)} on session ${sessionId}`, - ); + this.logger.debug(`Calling ${functionName} on session ${sessionId}`); if (!TXESessions.has(sessionId) && functionName != 'reset') { - this.logger.debug(`Creating new session ${sessionId}`); + this.logger.info(`Creating new session ${sessionId}`); TXESessions.set(sessionId, await TXEService.init(logger)); } if (functionName === 'reset') { TXESessions.delete(sessionId) && - this.logger.debug(`Called reset on session ${sessionId}, yeeting it out of existence`); + this.logger.info(`Called reset on session ${sessionId}, yeeting it out of existence`); return toForeignCallResult([]); } else { const txeService = TXESessions.get(sessionId); const response = await (txeService as any)[functionName](...inputs); - this.logger.debug( - `${sessionId}:${functionName}(${JSON.stringify(inputs, null, 2)}) -> ${JSON.stringify(response, null, 2)}`, - ); return response; } } @@ -63,10 +59,11 @@ class TXEDispatcher { * @returns A running http server. */ export function startTXEHttpServer(dispatcher: TXEDispatcher, port: string | number): http.Server { - const txeServer = new JsonRpcServer(dispatcher, {}, {}, ['init']); + const txeServer = new JsonRpcServer(dispatcher, { Fr }, {}, ['init']); const app = txeServer.getApp(); const httpServer = http.createServer(app.callback()); + httpServer.timeout = 1e3 * 60 * 5; // 5 minutes httpServer.listen(port); return httpServer; diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 09115f3ebab2..567bf0a656dc 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -1,4 +1,5 @@ import { + AuthWitness, L1NotePayload, MerkleTreeId, Note, @@ -11,9 +12,11 @@ import { } from '@aztec/circuit-types'; import { type CircuitWitnessGenerationStats } from '@aztec/circuit-types/stats'; import { - type CompleteAddress, + CallContext, FunctionData, - type Header, + Gas, + GlobalVariables, + Header, type KeyValidationRequest, NULLIFIER_SUBTREE_HEIGHT, type NULLIFIER_TREE_HEIGHT, @@ -23,16 +26,23 @@ import { PrivateCallStackItem, PrivateCircuitPublicInputs, PrivateContextInputs, - type PublicCallRequest, + PublicCallRequest, PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, + TxContext, computeContractClassId, deriveKeys, getContractClassFromArtifact, } from '@aztec/circuits.js'; -import { Aes128 } from '@aztec/circuits.js/barretenberg'; +import { Aes128, Schnorr } from '@aztec/circuits.js/barretenberg'; import { computePublicDataTreeLeafSlot, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash'; -import { type ContractArtifact, type FunctionAbi, FunctionSelector, countArgumentsSize } from '@aztec/foundation/abi'; +import { + type ContractArtifact, + type FunctionAbi, + FunctionSelector, + type NoteSelector, + countArgumentsSize, +} from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields'; import { type Logger, applyStringFormatting } from '@aztec/foundation/log'; @@ -40,13 +50,16 @@ import { Timer } from '@aztec/foundation/timer'; import { type KeyStore } from '@aztec/key-store'; import { ContractDataOracle } from '@aztec/pxe'; import { + ContractsDataSourcePublicDB, ExecutionError, type ExecutionNoteCache, type MessageLoadOracleInputs, type NoteData, Oracle, type PackedValuesCache, + PublicExecutor, type TypedOracle, + WorldStateDB, acvm, createSimulationError, extractCallStack, @@ -58,15 +71,21 @@ import { type ContractInstance, type ContractInstanceWithAddress } from '@aztec/ import { MerkleTreeSnapshotOperationsFacade, type MerkleTrees } from '@aztec/world-state'; import { type TXEDatabase } from '../util/txe_database.js'; +import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js'; +import { TXEPublicStateDB } from '../util/txe_public_state_db.js'; export class TXE implements TypedOracle { private blockNumber = 0; private sideEffectsCounter = 0; private contractAddress: AztecAddress; private msgSender: AztecAddress; + private functionSelector = FunctionSelector.fromField(new Fr(0)); private contractDataOracle: ContractDataOracle; + private version: Fr = Fr.ONE; + private chainId: Fr = Fr.ONE; + constructor( private logger: Logger, private trees: MerkleTrees, @@ -82,6 +101,14 @@ export class TXE implements TypedOracle { // Utils + getChainId() { + return Promise.resolve(this.chainId); + } + + getVersion() { + return Promise.resolve(this.version); + } + getMsgSender() { return this.msgSender; } @@ -90,6 +117,10 @@ export class TXE implements TypedOracle { this.msgSender = msgSender; } + setFunctionSelector(functionSelector: FunctionSelector) { + this.functionSelector = functionSelector; + } + getSideEffectsCounter() { return this.sideEffectsCounter; } @@ -110,6 +141,10 @@ export class TXE implements TypedOracle { return this.trees; } + getContractDataOracle() { + return this.contractDataOracle; + } + getTXEDatabase() { return this.txeDatabase; } @@ -127,16 +162,24 @@ export class TXE implements TypedOracle { await this.txeDatabase.addContractArtifact(computeContractClassId(contractClass), artifact); } - async getPrivateContextInputs(blockNumber: number, sideEffectsCounter = this.sideEffectsCounter) { + async getPrivateContextInputs( + blockNumber: number, + sideEffectsCounter = this.sideEffectsCounter, + isStaticCall = false, + isDelegateCall = false, + ) { const trees = this.getTrees(); - const stateReference = await trees.getStateReference(true); + const stateReference = await trees.getStateReference(false); const inputs = PrivateContextInputs.empty(); inputs.historicalHeader.globalVariables.blockNumber = new Fr(blockNumber); inputs.historicalHeader.state = stateReference; inputs.callContext.msgSender = this.msgSender; inputs.callContext.storageContractAddress = this.contractAddress; inputs.callContext.sideEffectCounter = sideEffectsCounter; + inputs.callContext.isStaticCall = isStaticCall; + inputs.callContext.isDelegateCall = isDelegateCall; inputs.startSideEffectCounter = sideEffectsCounter; + inputs.callContext.functionSelector = this.functionSelector; return inputs; } @@ -177,13 +220,35 @@ export class TXE implements TypedOracle { return deriveKeys(secret); } + async addAuthWitness(address: AztecAddress, messageHash: Fr) { + const account = this.txeDatabase.getAccount(address); + const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey); + const schnorr = new Schnorr(); + const signature = schnorr.constructSignature(messageHash.toBuffer(), privateKey).toBuffer(); + const authWitness = new AuthWitness(messageHash, [...signature]); + return this.txeDatabase.addAuthWitness(authWitness.requestHash, authWitness.witness); + } + + async addNullifiers(contractAddress: AztecAddress, nullifiers: Fr[]) { + const db = this.trees.asLatest(); + const siloedNullifiers = nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier).toBuffer()); + + await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers, NULLIFIER_SUBTREE_HEIGHT); + } + + async addNoteHashes(contractAddress: AztecAddress, innerNoteHashes: Fr[]) { + const db = this.trees.asLatest(); + const siloedNoteHashes = innerNoteHashes.map(innerNoteHash => siloNoteHash(contractAddress, innerNoteHash)); + await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, siloedNoteHashes); + } + // TypedOracle - getBlockNumber(): Promise { + getBlockNumber() { return Promise.resolve(this.blockNumber); } - getContractAddress(): Promise { + getContractAddress() { return Promise.resolve(this.contractAddress); } @@ -191,15 +256,15 @@ export class TXE implements TypedOracle { return Fr.random(); } - packArgumentsArray(args: Fr[]): Promise { + packArgumentsArray(args: Fr[]) { return Promise.resolve(this.packedValuesCache.pack(args)); } - packReturns(returns: Fr[]): Promise { + packReturns(returns: Fr[]) { return Promise.resolve(this.packedValuesCache.pack(returns)); } - unpackReturns(returnsHash: Fr): Promise { + unpackReturns(returnsHash: Fr) { return Promise.resolve(this.packedValuesCache.unpack(returnsHash)); } @@ -208,11 +273,11 @@ export class TXE implements TypedOracle { } async getContractInstance(address: AztecAddress): Promise { - const contractInstance = await this.txeDatabase.getContractInstance(address); + const contractInstance = await this.contractDataOracle.getContractInstance(address); if (!contractInstance) { throw new Error(`Contract instance not found for address ${address}`); } - return Promise.resolve(contractInstance); + return contractInstance; } getMembershipWitness(_blockNumber: number, _treeId: MerkleTreeId, _leafValue: Fr): Promise { @@ -279,12 +344,12 @@ export class TXE implements TypedOracle { throw new Error('Method not implemented.'); } - getCompleteAddress(account: AztecAddress): Promise { + getCompleteAddress(account: AztecAddress) { return Promise.resolve(this.txeDatabase.getAccount(account)); } - getAuthWitness(_messageHash: Fr): Promise { - throw new Error('Method not implemented.'); + getAuthWitness(messageHash: Fr) { + return this.txeDatabase.getAuthWitness(messageHash); } popCapsule(): Promise { @@ -333,7 +398,7 @@ export class TXE implements TypedOracle { return Promise.resolve(notes); } - async notifyCreatedNote(storageSlot: Fr, noteTypeId: Fr, noteItems: Fr[], innerNoteHash: Fr, counter: number) { + notifyCreatedNote(storageSlot: Fr, noteTypeId: NoteSelector, noteItems: Fr[], innerNoteHash: Fr, counter: number) { const note = new Note(noteItems); this.noteCache.addNewNote( { @@ -346,16 +411,11 @@ export class TXE implements TypedOracle { }, counter, ); - const db = this.trees.asLatest(); - const noteHash = siloNoteHash(this.contractAddress, innerNoteHash); - await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, [noteHash]); + return Promise.resolve(); } - async notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr, _counter: number) { + notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr, _counter: number) { this.noteCache.nullifyNote(this.contractAddress, innerNullifier, innerNoteHash); - const db = this.trees.asLatest(); - const siloedNullifier = siloNullifier(this.contractAddress, innerNullifier); - await db.batchInsert(MerkleTreeId.NULLIFIER_TREE, [siloedNullifier.toBuffer()], NULLIFIER_SUBTREE_HEIGHT); return Promise.resolve(); } @@ -425,7 +485,7 @@ export class TXE implements TypedOracle { computeEncryptedNoteLog( contractAddress: AztecAddress, storageSlot: Fr, - noteTypeId: Fr, + noteTypeId: NoteSelector, ovKeys: KeyValidationRequest, ivpkM: Point, preimage: Fr[], @@ -442,7 +502,7 @@ export class TXE implements TypedOracle { } emitUnencryptedLog(_log: UnencryptedL2Log, _counter: number): void { - throw new Error('Method not implemented.'); + return; } emitContractClassUnencryptedLog(_log: UnencryptedL2Log, _counter: number): Fr { @@ -454,69 +514,97 @@ export class TXE implements TypedOracle { functionSelector: FunctionSelector, argsHash: Fr, sideEffectCounter: number, - _isStaticCall: boolean, - _isDelegateCall: boolean, + isStaticCall: boolean, + isDelegateCall: boolean, ): Promise { - this.logger.debug( - `Calling private function ${targetContractAddress}:${functionSelector} from ${this.contractAddress}`, + this.logger.verbose( + `Executing external function ${targetContractAddress}:${functionSelector}(${await this.getDebugFunctionName( + targetContractAddress, + functionSelector, + )}) isStaticCall=${isStaticCall} isDelegateCall=${isDelegateCall}`, ); + // Store and modify env const currentContractAddress = AztecAddress.fromField(this.contractAddress); const currentMessageSender = AztecAddress.fromField(this.msgSender); + const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField()); this.setMsgSender(this.contractAddress); this.setContractAddress(targetContractAddress); + this.setFunctionSelector(functionSelector); const artifact = await this.contractDataOracle.getFunctionArtifact(targetContractAddress, functionSelector); const acir = artifact.bytecode; - const initialWitness = await this.getInitialWitness(artifact, argsHash, sideEffectCounter); + const initialWitness = await this.getInitialWitness( + artifact, + argsHash, + sideEffectCounter, + isStaticCall, + isDelegateCall, + ); const acvmCallback = new Oracle(this); const timer = new Timer(); - const acirExecutionResult = await acvm(acir, initialWitness, acvmCallback).catch((err: Error) => { - const execError = new ExecutionError( - err.message, - { - contractAddress: targetContractAddress, - functionSelector, - }, - extractCallStack(err, artifact.debug), - { cause: err }, + try { + const acirExecutionResult = await acvm(acir, initialWitness, acvmCallback).catch((err: Error) => { + const execError = new ExecutionError( + err.message, + { + contractAddress: targetContractAddress, + functionSelector, + }, + extractCallStack(err, artifact.debug), + { cause: err }, + ); + this.logger.debug(`Error executing private function ${targetContractAddress}:${functionSelector}`); + throw createSimulationError(execError); + }); + const duration = timer.ms(); + const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness); + const publicInputs = PrivateCircuitPublicInputs.fromFields(returnWitness); + + const initialWitnessSize = witnessMapToFields(initialWitness).length * Fr.SIZE_IN_BYTES; + this.logger.debug(`Ran external function ${targetContractAddress.toString()}:${functionSelector}`, { + circuitName: 'app-circuit', + duration, + eventName: 'circuit-witness-generation', + inputSize: initialWitnessSize, + outputSize: publicInputs.toBuffer().length, + appCircuitName: 'noname', + } satisfies CircuitWitnessGenerationStats); + + const callStackItem = new PrivateCallStackItem( + targetContractAddress, + new FunctionData(functionSelector, true), + publicInputs, ); - this.logger.debug( - `Error executing private function ${targetContractAddress}:${functionSelector}\n${createSimulationError( - execError, - )}`, + // Apply side effects + this.sideEffectsCounter = publicInputs.endSideEffectCounter.toNumber(); + + await this.addNullifiers( + targetContractAddress, + publicInputs.newNullifiers.filter(nullifier => !nullifier.isEmpty()).map(nullifier => nullifier.value), ); - throw execError; - }); - const duration = timer.ms(); - const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness); - const publicInputs = PrivateCircuitPublicInputs.fromFields(returnWitness); - - const initialWitnessSize = witnessMapToFields(initialWitness).length * Fr.SIZE_IN_BYTES; - this.logger.debug(`Ran external function ${targetContractAddress.toString()}:${functionSelector}`, { - circuitName: 'app-circuit', - duration, - eventName: 'circuit-witness-generation', - inputSize: initialWitnessSize, - outputSize: publicInputs.toBuffer().length, - appCircuitName: 'noname', - } satisfies CircuitWitnessGenerationStats); - - const callStackItem = new PrivateCallStackItem( - targetContractAddress, - new FunctionData(functionSelector, true), - publicInputs, - ); - // Apply side effects - this.sideEffectsCounter += publicInputs.endSideEffectCounter.toNumber(); - this.setContractAddress(currentContractAddress); - this.setMsgSender(currentMessageSender); - return callStackItem; + await this.addNoteHashes( + targetContractAddress, + publicInputs.newNoteHashes.filter(noteHash => !noteHash.isEmpty()).map(noteHash => noteHash.value), + ); + + return callStackItem; + } finally { + this.setContractAddress(currentContractAddress); + this.setMsgSender(currentMessageSender); + this.setFunctionSelector(currentFunctionSelector); + } } - async getInitialWitness(abi: FunctionAbi, argsHash: Fr, sideEffectCounter: number) { + async getInitialWitness( + abi: FunctionAbi, + argsHash: Fr, + sideEffectCounter: number, + isStaticCall: boolean, + isDelegateCall: boolean, + ) { const argumentsSize = countArgumentsSize(abi); const args = this.packedValuesCache.unpack(argsHash); @@ -525,33 +613,220 @@ export class TXE implements TypedOracle { throw new Error('Invalid arguments size'); } - const privateContextInputs = await this.getPrivateContextInputs(this.blockNumber - 1, sideEffectCounter); + const privateContextInputs = await this.getPrivateContextInputs( + this.blockNumber - 1, + sideEffectCounter, + isStaticCall, + isDelegateCall, + ); const fields = [...privateContextInputs.toFields(), ...args]; return toACVMWitness(0, fields); } - callPublicFunction( - _targetContractAddress: AztecAddress, - _functionSelector: FunctionSelector, - _argsHash: Fr, - _sideEffectCounter: number, - _isStaticCall: boolean, - _isDelegateCall: boolean, + public async getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise { + const instance = await this.contractDataOracle.getContractInstance(address); + if (!instance) { + return undefined; + } + const artifact = await this.contractDataOracle.getContractArtifact(instance!.contractClassId); + if (!artifact) { + return undefined; + } + + const f = artifact.functions.find(f => + FunctionSelector.fromNameAndParameters(f.name, f.parameters).equals(selector), + ); + if (!f) { + return undefined; + } + + return `${artifact.name}:${f.name}`; + } + + async executePublicFunction( + targetContractAddress: AztecAddress, + functionSelector: FunctionSelector, + args: Fr[], + callContext: CallContext, + ) { + const header = Header.empty(); + header.state = await this.trees.getStateReference(true); + header.globalVariables.blockNumber = new Fr(await this.getBlockNumber()); + header.state.partial.nullifierTree.root = Fr.fromBuffer( + (await this.trees.getTreeInfo(MerkleTreeId.NULLIFIER_TREE, true)).root, + ); + header.state.partial.noteHashTree.root = Fr.fromBuffer( + (await this.trees.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE, true)).root, + ); + header.state.partial.publicDataTree.root = Fr.fromBuffer( + (await this.trees.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE, true)).root, + ); + header.state.l1ToL2MessageTree.root = Fr.fromBuffer( + (await this.trees.getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, true)).root, + ); + const executor = new PublicExecutor( + new TXEPublicStateDB(this), + new ContractsDataSourcePublicDB(new TXEPublicContractDataSource(this)), + new WorldStateDB(this.trees.asLatest()), + header, + ); + const execution = { + contractAddress: targetContractAddress, + functionSelector, + args, + callContext, + }; + + return executor.simulate( + execution, + GlobalVariables.empty(), + Gas.test(), + TxContext.empty(), + /* pendingNullifiers */ [], + /* transactionFee */ Fr.ZERO, + callContext.sideEffectCounter, + ); + } + + async avmOpcodeCall( + targetContractAddress: AztecAddress, + functionSelector: FunctionSelector, + args: Fr[], + isStaticCall: boolean, + isDelegateCall: boolean, + ) { + // Store and modify env + const currentContractAddress = AztecAddress.fromField(this.contractAddress); + const currentMessageSender = AztecAddress.fromField(this.msgSender); + const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField()); + this.setMsgSender(this.contractAddress); + this.setContractAddress(targetContractAddress); + this.setFunctionSelector(functionSelector); + + const callContext = CallContext.empty(); + callContext.msgSender = this.msgSender; + callContext.functionSelector = this.functionSelector; + callContext.sideEffectCounter = this.sideEffectsCounter; + callContext.storageContractAddress = targetContractAddress; + callContext.isStaticCall = isStaticCall; + callContext.isDelegateCall = isDelegateCall; + + const executionResult = await this.executePublicFunction( + targetContractAddress, + functionSelector, + args, + callContext, + ); + + // Apply side effects + if (!executionResult.reverted) { + this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); + } + this.setContractAddress(currentContractAddress); + this.setMsgSender(currentMessageSender); + this.setFunctionSelector(currentFunctionSelector); + + return executionResult; + } + + async callPublicFunction( + targetContractAddress: AztecAddress, + functionSelector: FunctionSelector, + argsHash: Fr, + sideEffectCounter: number, + isStaticCall: boolean, + isDelegateCall: boolean, ): Promise { - throw new Error('Method not implemented.'); + // Store and modify env + const currentContractAddress = AztecAddress.fromField(this.contractAddress); + const currentMessageSender = AztecAddress.fromField(this.msgSender); + const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField()); + this.setMsgSender(this.contractAddress); + this.setContractAddress(targetContractAddress); + this.setFunctionSelector(functionSelector); + + const callContext = CallContext.empty(); + callContext.msgSender = this.msgSender; + callContext.functionSelector = this.functionSelector; + callContext.sideEffectCounter = sideEffectCounter; + callContext.storageContractAddress = targetContractAddress; + callContext.isStaticCall = isStaticCall; + callContext.isDelegateCall = isDelegateCall; + + const args = this.packedValuesCache.unpack(argsHash); + + const executionResult = await this.executePublicFunction( + targetContractAddress, + functionSelector, + args, + callContext, + ); + + // Apply side effects + this.sideEffectsCounter = executionResult.endSideEffectCounter.toNumber(); + this.setContractAddress(currentContractAddress); + this.setMsgSender(currentMessageSender); + this.setFunctionSelector(currentFunctionSelector); + + return executionResult.returnValues; } - enqueuePublicFunctionCall( - _targetContractAddress: AztecAddress, - _functionSelector: FunctionSelector, - _argsHash: Fr, - _sideEffectCounter: number, - _isStaticCall: boolean, - _isDelegateCall: boolean, + async enqueuePublicFunctionCall( + targetContractAddress: AztecAddress, + functionSelector: FunctionSelector, + argsHash: Fr, + sideEffectCounter: number, + isStaticCall: boolean, + isDelegateCall: boolean, ): Promise { - throw new Error('Method not implemented.'); + // Store and modify env + const currentContractAddress = AztecAddress.fromField(this.contractAddress); + const currentMessageSender = AztecAddress.fromField(this.msgSender); + const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField()); + this.setMsgSender(this.contractAddress); + this.setContractAddress(targetContractAddress); + this.setFunctionSelector(functionSelector); + + const callContext = CallContext.empty(); + callContext.msgSender = this.msgSender; + callContext.functionSelector = this.functionSelector; + callContext.sideEffectCounter = sideEffectCounter; + callContext.storageContractAddress = targetContractAddress; + callContext.isStaticCall = isStaticCall; + callContext.isDelegateCall = isDelegateCall; + + const args = this.packedValuesCache.unpack(argsHash); + + const executionResult = await this.executePublicFunction( + targetContractAddress, + functionSelector, + args, + callContext, + ); + + // Apply side effects + this.sideEffectsCounter += executionResult.endSideEffectCounter.toNumber(); + this.setContractAddress(currentContractAddress); + this.setMsgSender(currentMessageSender); + this.setFunctionSelector(currentFunctionSelector); + + const parentCallContext = CallContext.empty(); + parentCallContext.msgSender = currentMessageSender; + parentCallContext.functionSelector = currentFunctionSelector; + parentCallContext.sideEffectCounter = sideEffectCounter; + parentCallContext.storageContractAddress = currentContractAddress; + parentCallContext.isStaticCall = isStaticCall; + parentCallContext.isDelegateCall = isDelegateCall; + + return PublicCallRequest.from({ + parentCallContext, + contractAddress: targetContractAddress, + functionSelector, + callContext, + args, + }); } setPublicTeardownFunctionCall( diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index 6b53c0de1ebd..de25cc812997 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -10,10 +10,10 @@ import { getContractInstanceFromDeployParams, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; +import { NoteSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { type Logger } from '@aztec/foundation/log'; import { KeyStore } from '@aztec/key-store'; -import { type AztecKVStore } from '@aztec/kv-store'; import { openTmpStore } from '@aztec/kv-store/utils'; import { ExecutionNoteCache, PackedValuesCache, type TypedOracle } from '@aztec/simulator'; import { MerkleTrees } from '@aztec/world-state'; @@ -28,10 +28,11 @@ import { toForeignCallResult, toSingle, } from '../util/encoding.js'; +import { ExpectedFailureError } from '../util/expected_failure_error.js'; import { TXEDatabase } from '../util/txe_database.js'; export class TXEService { - constructor(private logger: Logger, private typedOracle: TypedOracle, private store: AztecKVStore) {} + constructor(private logger: Logger, private typedOracle: TypedOracle) {} static async init(logger: Logger) { const store = openTmpStore(true); @@ -42,8 +43,8 @@ export class TXEService { const txeDatabase = new TXEDatabase(store); logger.info(`TXE service initialized`); const txe = new TXE(logger, trees, packedValuesCache, noteCache, keyStore, txeDatabase); - const service = new TXEService(logger, txe, store); - await service.timeTravel(toSingle(new Fr(1n))); + const service = new TXEService(logger, txe); + await service.advanceBlocksBy(toSingle(new Fr(1n))); return service; } @@ -59,31 +60,20 @@ export class TXEService { return toForeignCallResult(inputs.toFields().map(toSingle)); } - async timeTravel(blocks: ForeignCallSingle) { + async advanceBlocksBy(blocks: ForeignCallSingle) { const nBlocks = fromSingle(blocks).toNumber(); - this.logger.info(`time traveling ${nBlocks} blocks`); + this.logger.debug(`time traveling ${nBlocks} blocks`); const trees = (this.typedOracle as TXE).getTrees(); + const header = Header.empty(); + const l2Block = L2Block.empty(); + header.state = await trees.getStateReference(true); + const blockNumber = await this.typedOracle.getBlockNumber(); + header.globalVariables.blockNumber = new Fr(blockNumber); + l2Block.archive.root = Fr.fromBuffer((await trees.getTreeInfo(MerkleTreeId.ARCHIVE, true)).root); + l2Block.header = header; for (let i = 0; i < nBlocks; i++) { - const header = Header.empty(); - const l2Block = L2Block.empty(); - header.state = await trees.getStateReference(true); const blockNumber = await this.typedOracle.getBlockNumber(); - header.globalVariables.blockNumber = new Fr(blockNumber); - header.state.partial.nullifierTree.root = Fr.fromBuffer( - (await trees.getTreeInfo(MerkleTreeId.NULLIFIER_TREE, true)).root, - ); - header.state.partial.noteHashTree.root = Fr.fromBuffer( - (await trees.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE, true)).root, - ); - header.state.partial.publicDataTree.root = Fr.fromBuffer( - (await trees.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE, true)).root, - ); - header.state.l1ToL2MessageTree.root = Fr.fromBuffer( - (await trees.getTreeInfo(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, true)).root, - ); - l2Block.archive.root = Fr.fromBuffer((await trees.getTreeInfo(MerkleTreeId.ARCHIVE, true)).root); - l2Block.header = header; await trees.handleL2BlockAndMessages(l2Block, []); (this.typedOracle as TXE).setBlockNumber(blockNumber + 1); } @@ -115,7 +105,10 @@ export class TXEService { .map(char => String.fromCharCode(char.toNumber())) .join(''); const decodedArgs = fromArray(args); - this.logger.debug(`Deploy ${pathStr} with ${initializerStr} and ${decodedArgs}`); + const publicKeysHashFr = fromSingle(publicKeysHash); + this.logger.debug( + `Deploy ${pathStr} with initializer ${initializerStr}(${decodedArgs}) and public keys hash ${publicKeysHashFr}`, + ); const contractModule = await import(pathStr); // Hacky way of getting the class, the name of the Artifact is always longer const contractClass = contractModule[Object.keys(contractModule).sort((a, b) => a.length - b.length)[0]]; @@ -123,7 +116,7 @@ export class TXEService { constructorArgs: decodedArgs, skipArgsDecoding: true, salt: Fr.ONE, - publicKeysHash: fromSingle(publicKeysHash), + publicKeysHash: publicKeysHashFr, constructorArtifact: initializerStr ? initializerStr : undefined, deployer: AztecAddress.ZERO, }); @@ -131,7 +124,15 @@ export class TXEService { this.logger.debug(`Deployed ${contractClass.artifact.name} at ${instance.address}`); await (this.typedOracle as TXE).addContractInstance(instance); await (this.typedOracle as TXE).addContractArtifact(contractClass.artifact); - return toForeignCallResult([toSingle(instance.address)]); + return toForeignCallResult([ + toArray([ + instance.salt, + instance.deployer, + instance.contractClassId, + instance.initializationHash, + instance.publicKeysHash, + ]), + ]); } async directStorageWrite( @@ -175,6 +176,7 @@ export class TXEService { const completeAddress = await keyStore.addAccount(fromSingle(secret), fromSingle(partialAddress)); const accountStore = (this.typedOracle as TXE).getTXEDatabase(); await accountStore.setAccount(completeAddress.address, completeAddress); + this.logger.debug(`Created account ${completeAddress.address}`); return toForeignCallResult([ toSingle(completeAddress.address), ...completeAddress.publicKeys.toFields().map(toSingle), @@ -196,6 +198,59 @@ export class TXEService { return toForeignCallResult([toSingle(new Fr(counter))]); } + async addAuthWitness(address: ForeignCallSingle, messageHash: ForeignCallSingle) { + await (this.typedOracle as TXE).addAuthWitness(fromSingle(address), fromSingle(messageHash)); + return toForeignCallResult([]); + } + + async assertPublicCallFails( + address: ForeignCallSingle, + functionSelector: ForeignCallSingle, + _length: ForeignCallSingle, + args: ForeignCallArray, + ) { + const parsedAddress = fromSingle(address); + const parsedSelector = FunctionSelector.fromField(fromSingle(functionSelector)); + const result = await (this.typedOracle as TXE).avmOpcodeCall( + parsedAddress, + parsedSelector, + fromArray(args), + false, + false, + ); + if (!result.reverted) { + throw new ExpectedFailureError('Public call did not revert'); + } + + return toForeignCallResult([]); + } + + async assertPrivateCallFails( + targetContractAddress: ForeignCallSingle, + functionSelector: ForeignCallSingle, + argsHash: ForeignCallSingle, + sideEffectCounter: ForeignCallSingle, + isStaticCall: ForeignCallSingle, + isDelegateCall: ForeignCallSingle, + ) { + try { + await this.typedOracle.callPrivateFunction( + fromSingle(targetContractAddress), + FunctionSelector.fromField(fromSingle(functionSelector)), + fromSingle(argsHash), + fromSingle(sideEffectCounter).toNumber(), + fromSingle(isStaticCall).toBool(), + fromSingle(isDelegateCall).toBool(), + ); + throw new ExpectedFailureError('Private call did not fail'); + } catch (e) { + if (e instanceof ExpectedFailureError) { + throw e; + } + } + return toForeignCallResult([]); + } + // PXE oracles getRandomField() { @@ -356,7 +411,7 @@ export class TXEService { ) { this.typedOracle.notifyCreatedNote( fromSingle(storageSlot), - fromSingle(noteTypeId), + NoteSelector.fromField(fromSingle(noteTypeId)), fromArray(note), fromSingle(innerNoteHash), fromSingle(counter).toNumber(), @@ -433,10 +488,27 @@ export class TXEService { return toForeignCallResult([toSingle(new Fr(exists))]); } + async avmOpcodeCall( + _gas: ForeignCallArray, + address: ForeignCallSingle, + _length: ForeignCallSingle, + args: ForeignCallArray, + functionSelector: ForeignCallSingle, + ) { + const result = await (this.typedOracle as TXE).avmOpcodeCall( + fromSingle(address), + FunctionSelector.fromField(fromSingle(functionSelector)), + fromArray(args), + false, + false, + ); + + return toForeignCallResult([toArray(result.returnValues), toSingle(new Fr(1))]); + } + async getPublicKeysAndPartialAddress(address: ForeignCallSingle) { const parsedAddress = AztecAddress.fromField(fromSingle(address)); const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); - return toForeignCallResult([toArray([...publicKeys.toFields(), partialAddress])]); } @@ -462,7 +534,7 @@ export class TXEService { const encLog = this.typedOracle.computeEncryptedNoteLog( AztecAddress.fromString(fromSingle(contractAddress).toString()), Fr.fromString(fromSingle(storageSlot).toString()), - Fr.fromString(fromSingle(noteTypeId).toString()), + NoteSelector.fromField(Fr.fromString(fromSingle(noteTypeId).toString())), ovKeys, ivpkM, fromArray(preimage), @@ -519,4 +591,56 @@ export class TXEService { } return toForeignCallResult([toArray(witness.toFields())]); } + + async getAuthWitness(messageHash: ForeignCallSingle) { + const parsedMessageHash = fromSingle(messageHash); + const authWitness = await this.typedOracle.getAuthWitness(parsedMessageHash); + if (!authWitness) { + throw new Error(`Auth witness not found for message hash ${parsedMessageHash}.`); + } + return toForeignCallResult([toArray(authWitness)]); + } + + async enqueuePublicFunctionCall( + targetContractAddress: ForeignCallSingle, + functionSelector: ForeignCallSingle, + argsHash: ForeignCallSingle, + sideEffectCounter: ForeignCallSingle, + isStaticCall: ForeignCallSingle, + isDelegateCall: ForeignCallSingle, + ) { + const publicCallRequest = await this.typedOracle.enqueuePublicFunctionCall( + fromSingle(targetContractAddress), + FunctionSelector.fromField(fromSingle(functionSelector)), + fromSingle(argsHash), + fromSingle(sideEffectCounter).toNumber(), + fromSingle(isStaticCall).toBool(), + fromSingle(isDelegateCall).toBool(), + ); + const fields = [ + publicCallRequest.contractAddress.toField(), + publicCallRequest.functionSelector.toField(), + ...publicCallRequest.callContext.toFields(), + publicCallRequest.getArgsHash(), + ]; + return toForeignCallResult([toArray(fields)]); + } + + async getChainId() { + return toForeignCallResult([toSingle(await this.typedOracle.getChainId())]); + } + + async getVersion() { + return toForeignCallResult([toSingle(await this.typedOracle.getVersion())]); + } + + async addNullifiers(contractAddress: ForeignCallSingle, _length: ForeignCallSingle, nullifiers: ForeignCallArray) { + await (this.typedOracle as TXE).addNullifiers(fromSingle(contractAddress), fromArray(nullifiers)); + return toForeignCallResult([]); + } + + async addNoteHashes(contractAddress: ForeignCallSingle, _length: ForeignCallSingle, noteHashes: ForeignCallArray) { + await (this.typedOracle as TXE).addNoteHashes(fromSingle(contractAddress), fromArray(noteHashes)); + return toForeignCallResult([]); + } } diff --git a/yarn-project/txe/src/util/expected_failure_error.ts b/yarn-project/txe/src/util/expected_failure_error.ts new file mode 100644 index 000000000000..8f97a3ae2bf9 --- /dev/null +++ b/yarn-project/txe/src/util/expected_failure_error.ts @@ -0,0 +1,5 @@ +export class ExpectedFailureError extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/yarn-project/txe/src/util/txe_public_contract_data_source.ts b/yarn-project/txe/src/util/txe_public_contract_data_source.ts new file mode 100644 index 000000000000..64f410f95955 --- /dev/null +++ b/yarn-project/txe/src/util/txe_public_contract_data_source.ts @@ -0,0 +1,63 @@ +import { type AztecAddress, Fr, type FunctionSelector, unpackBytecode } from '@aztec/circuits.js'; +import { type ContractArtifact } from '@aztec/foundation/abi'; +import { PrivateFunctionsTree } from '@aztec/pxe'; +import { + type ContractClassPublic, + type ContractDataSource, + type ContractInstanceWithAddress, + type PublicFunction, +} from '@aztec/types/contracts'; + +import { type TXE } from '../oracle/txe_oracle.js'; + +export class TXEPublicContractDataSource implements ContractDataSource { + constructor(private txeOracle: TXE) {} + + async getPublicFunction(address: AztecAddress, selector: FunctionSelector): Promise { + const bytecode = await this.txeOracle.getContractDataOracle().getBytecode(address, selector); + if (!bytecode) { + return undefined; + } + return { bytecode, selector }; + } + + getBlockNumber(): Promise { + return this.txeOracle.getBlockNumber(); + } + + async getContractClass(id: Fr): Promise { + const contractClass = await this.txeOracle.getContractDataOracle().getContractClass(id); + const artifact = await this.txeOracle.getContractDataOracle().getContractArtifact(id); + const tree = new PrivateFunctionsTree(artifact); + const privateFunctionsRoot = tree.getFunctionTreeRoot(); + + return { + id, + artifactHash: contractClass!.artifactHash, + packedBytecode: contractClass!.packedBytecode, + publicFunctions: unpackBytecode(contractClass!.packedBytecode), + privateFunctionsRoot: new Fr(privateFunctionsRoot!.root), + version: contractClass!.version, + privateFunctions: [], + unconstrainedFunctions: [], + }; + } + + async getContract(address: AztecAddress): Promise { + const instance = await this.txeOracle.getContractDataOracle().getContractInstance(address); + return { ...instance, address }; + } + + getContractClassIds(): Promise { + throw new Error('Method not implemented.'); + } + + async getContractArtifact(address: AztecAddress): Promise { + const instance = await this.txeOracle.getContractDataOracle().getContractInstance(address); + return this.txeOracle.getContractDataOracle().getContractArtifact(instance.contractClassId); + } + + addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise { + return this.txeOracle.addContractArtifact(contract); + } +} diff --git a/yarn-project/txe/src/util/txe_public_state_db.ts b/yarn-project/txe/src/util/txe_public_state_db.ts new file mode 100644 index 000000000000..62bdbaf7e5be --- /dev/null +++ b/yarn-project/txe/src/util/txe_public_state_db.ts @@ -0,0 +1,57 @@ +import { MerkleTreeId } from '@aztec/circuit-types'; +import { + type AztecAddress, + Fr, + PUBLIC_DATA_SUBTREE_HEIGHT, + PublicDataTreeLeaf, + type PublicDataTreeLeafPreimage, +} from '@aztec/circuits.js'; +import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; +import { type PublicStateDB } from '@aztec/simulator'; + +import { type TXE } from '../oracle/txe_oracle.js'; + +export class TXEPublicStateDB implements PublicStateDB { + constructor(private txeOracle: TXE) {} + + async storageRead(contract: AztecAddress, slot: Fr): Promise { + const db = this.txeOracle.getTrees().asLatest(); + const leafSlot = computePublicDataTreeLeafSlot(contract, slot).toBigInt(); + + const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); + + let value = Fr.ZERO; + if (lowLeafResult && lowLeafResult.alreadyPresent) { + const preimage = (await db.getLeafPreimage( + MerkleTreeId.PUBLIC_DATA_TREE, + lowLeafResult.index, + )) as PublicDataTreeLeafPreimage; + value = preimage.value; + } + return value; + } + + async storageWrite(contract: AztecAddress, slot: Fr, newValue: Fr): Promise { + const db = this.txeOracle.getTrees().asLatest(); + + await db.batchInsert( + MerkleTreeId.PUBLIC_DATA_TREE, + [new PublicDataTreeLeaf(computePublicDataTreeLeafSlot(contract, slot), newValue).toBuffer()], + PUBLIC_DATA_SUBTREE_HEIGHT, + ); + return newValue.toBigInt(); + } + + checkpoint(): Promise { + return Promise.resolve(); + } + rollbackToCheckpoint(): Promise { + throw new Error('Cannot rollback'); + } + commit(): Promise { + return Promise.resolve(); + } + rollbackToCommit(): Promise { + throw new Error('Cannot rollback'); + } +} diff --git a/yarn-project/types/package.json b/yarn-project/types/package.json index 4abfe1f9a655..b750c105ca8a 100644 --- a/yarn-project/types/package.json +++ b/yarn-project/types/package.json @@ -34,7 +34,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 9fff2b21b6a4..91b0eb30ba88 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -8,6 +8,7 @@ import { type FunctionArtifact, FunctionType, type IntegerValue, + NoteSelector, type StructValue, type TypedStructFieldValue, } from '@aztec/foundation/abi'; @@ -57,6 +58,9 @@ export function contractArtifactFromBuffer(buffer: Buffer): ContractArtifact { if (key === 'bytecode' && typeof value === 'string') { return Buffer.from(value, 'base64'); } + if (typeof value === 'object' && value !== null && value.type === 'NoteSelector') { + return new NoteSelector(Number(value.value)); + } if (typeof value === 'object' && value !== null && value.type === 'Fr') { return new Fr(BigInt(value.value)); } @@ -252,7 +256,8 @@ function getNoteTypes(input: NoirCompiledContract) { return notes.reduce((acc: Record, note) => { const name = note.fields[1].value as string; - const id = new Fr(BigInt(note.fields[0].value)); + // Note id is encoded as a hex string + const id = NoteSelector.fromField(Fr.fromString(note.fields[0].value)); acc[name] = { id, typ: name, diff --git a/yarn-project/world-state/package.json b/yarn-project/world-state/package.json index 5e3dd632a209..2f2b53a1cdfd 100644 --- a/yarn-project/world-state/package.json +++ b/yarn-project/world-state/package.json @@ -29,7 +29,15 @@ "rootDir": "./src", "transform": { "^.+\\.tsx?$": [ - "@swc/jest" + "@swc/jest", + { + "jsc": { + "parser": { + "syntax": "typescript", + "decorators": true + } + } + } ] }, "extensionsToTreatAsEsm": [ diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index cc328c7abd12..1b9ed2231ace 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -57,6 +57,7 @@ __metadata: "@aztec/l1-artifacts": "workspace:^" "@aztec/noir-contracts.js": "workspace:^" "@aztec/protocol-contracts": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" "@jest/globals": ^29.5.0 "@types/debug": ^4.1.7 @@ -119,6 +120,7 @@ __metadata: "@aztec/prover-client": "workspace:^" "@aztec/sequencer-client": "workspace:^" "@aztec/simulator": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.5.0 @@ -158,7 +160,6 @@ __metadata: ts-loader: ^9.4.4 ts-node: ^10.9.1 tslib: ^2.4.0 - tty-browserify: ^0.0.1 typescript: ^5.0.4 util: ^0.12.5 webpack: ^5.88.2 @@ -207,6 +208,7 @@ __metadata: "@aztec/protocol-contracts": "workspace:^" "@aztec/prover-client": "workspace:^" "@aztec/pxe": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@jest/globals": ^29.5.0 "@types/jest": ^29.5.0 "@types/koa": ^2.13.6 @@ -234,6 +236,7 @@ __metadata: "@aztec/foundation": "workspace:^" "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/simulator": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@jest/globals": ^29.5.0 "@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi" "@noir-lang/types": "portal:../../noir/packages/types" @@ -423,6 +426,7 @@ __metadata: "@aztec/pxe": "workspace:^" "@aztec/sequencer-client": "workspace:^" "@aztec/simulator": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.5.0 @@ -464,7 +468,6 @@ __metadata: ts-loader: ^9.4.4 ts-node: ^10.9.1 tslib: ^2.4.0 - tty-browserify: ^0.0.1 typescript: ^5.0.4 util: ^0.12.5 viem: ^2.7.15 @@ -708,6 +711,7 @@ __metadata: "@aztec/circuits.js": "workspace:^" "@aztec/foundation": "workspace:^" "@aztec/kv-store": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@chainsafe/discv5": 9.0.0 "@chainsafe/enr": 3.0.0 "@chainsafe/libp2p-gossipsub": 13.0.0 @@ -776,6 +780,7 @@ __metadata: "@aztec/kv-store": "workspace:^" "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/simulator": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.5.0 "@noir-lang/types": "portal:../../noir/packages/types" @@ -872,6 +877,7 @@ __metadata: "@aztec/p2p": "workspace:^" "@aztec/protocol-contracts": "workspace:^" "@aztec/simulator": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.5.0 @@ -911,6 +917,7 @@ __metadata: "@aztec/noir-contracts.js": "workspace:^" "@aztec/noir-protocol-circuits-types": "workspace:^" "@aztec/protocol-contracts": "workspace:^" + "@aztec/telemetry-client": "workspace:^" "@aztec/types": "workspace:^" "@aztec/world-state": "workspace:^" "@jest/globals": ^29.5.0 @@ -933,6 +940,27 @@ __metadata: languageName: unknown linkType: soft +"@aztec/telemetry-client@workspace:^, @aztec/telemetry-client@workspace:telemetry-client": + version: 0.0.0-use.local + resolution: "@aztec/telemetry-client@workspace:telemetry-client" + dependencies: + "@aztec/foundation": "workspace:^" + "@jest/globals": ^29.5.0 + "@opentelemetry/api": ^1.9.0 + "@opentelemetry/exporter-metrics-otlp-http": ^0.52.0 + "@opentelemetry/exporter-trace-otlp-http": ^0.52.0 + "@opentelemetry/host-metrics": ^0.35.2 + "@opentelemetry/resources": ^1.25.0 + "@opentelemetry/sdk-metrics": ^1.25.0 + "@opentelemetry/sdk-trace-node": ^1.25.0 + "@opentelemetry/semantic-conventions": ^1.25.0 + "@types/jest": ^29.5.0 + jest: ^29.5.0 + ts-node: ^10.9.1 + typescript: ^5.0.4 + languageName: unknown + linkType: soft + "@aztec/txe@workspace:txe": version: 0.0.0-use.local resolution: "@aztec/txe@workspace:txe" @@ -3027,6 +3055,209 @@ __metadata: languageName: node linkType: hard +"@opentelemetry/api-logs@npm:0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/api-logs@npm:0.52.0" + dependencies: + "@opentelemetry/api": ^1.0.0 + checksum: 502f60fd3a4b08fb7e54eaf22d0415e34dcbc9995696945eff8a4a12910e933149900cc470fb476b9411b4bbb98f8b598e3f4d4a37137698fcf0a7ea6ab240d6 + languageName: node + linkType: hard + +"@opentelemetry/api@npm:^1.0.0, @opentelemetry/api@npm:^1.9.0": + version: 1.9.0 + resolution: "@opentelemetry/api@npm:1.9.0" + checksum: 9e88e59d53ced668f3daaecfd721071c5b85a67dd386f1c6f051d1be54375d850016c881f656ffbe9a03bedae85f7e89c2f2b635313f9c9b195ad033cdc31020 + languageName: node + linkType: hard + +"@opentelemetry/context-async-hooks@npm:1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/context-async-hooks@npm:1.25.0" + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: f50f6ef621b6cfaa1d0919e4470b7c8326371beaf6be9a635c6f3221677bf9f5429a81a29b5518a41d3c002e35d4a89cb748ae61f650d61aa2ae3cbe123c0301 + languageName: node + linkType: hard + +"@opentelemetry/core@npm:1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/core@npm:1.25.0" + dependencies: + "@opentelemetry/semantic-conventions": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 46a851081e95ff1b9e3f8b518d064fd25c342522f11f0a082a9692bbfbcd947ed6602372f370fab48f8cbc8ebd7358dfa094e6d31bd26f4696b9bde418296045 + languageName: node + linkType: hard + +"@opentelemetry/exporter-metrics-otlp-http@npm:^0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/exporter-metrics-otlp-http@npm:0.52.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/otlp-exporter-base": 0.52.0 + "@opentelemetry/otlp-transformer": 0.52.0 + "@opentelemetry/resources": 1.25.0 + "@opentelemetry/sdk-metrics": 1.25.0 + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 8438733189879e3162ab4a374d7f22a4f9655257cbcde156f1041954cbc86bfab7299e696df49187684f1c219a76b263e6489c411b7008b81a05d5b0e7dcd92d + languageName: node + linkType: hard + +"@opentelemetry/exporter-trace-otlp-http@npm:^0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/exporter-trace-otlp-http@npm:0.52.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/otlp-exporter-base": 0.52.0 + "@opentelemetry/otlp-transformer": 0.52.0 + "@opentelemetry/resources": 1.25.0 + "@opentelemetry/sdk-trace-base": 1.25.0 + peerDependencies: + "@opentelemetry/api": ^1.0.0 + checksum: bed18523289c579b8108b1c3fcb2b74361bed2d7f3016270feb080a047fa422fc9dfb0678ff1b726cb1e0fa9413cead5824e7f97d1d781467aa983a87fe1ee93 + languageName: node + linkType: hard + +"@opentelemetry/host-metrics@npm:^0.35.2": + version: 0.35.2 + resolution: "@opentelemetry/host-metrics@npm:0.35.2" + dependencies: + "@opentelemetry/sdk-metrics": ^1.8.0 + systeminformation: 5.22.9 + peerDependencies: + "@opentelemetry/api": ^1.3.0 + checksum: 541df2585f9cbf8b6606f6782a2d351383f7a5b0a92b92ad4011ac46adac513474463d0c2474d6902d9d6d3b633be67c60ea0716ea2de277cebc1cb2538fa7a4 + languageName: node + linkType: hard + +"@opentelemetry/otlp-exporter-base@npm:0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/otlp-exporter-base@npm:0.52.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/otlp-transformer": 0.52.0 + peerDependencies: + "@opentelemetry/api": ^1.0.0 + checksum: 5230ba86d274f4d05fa2820a21e8278d796a299299e2af96150085c871427fe5ef4c6fa4954cdc1b8cdd0a87d5d6677ca0e547cc51253968572a6ede51f63ea2 + languageName: node + linkType: hard + +"@opentelemetry/otlp-transformer@npm:0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/otlp-transformer@npm:0.52.0" + dependencies: + "@opentelemetry/api-logs": 0.52.0 + "@opentelemetry/core": 1.25.0 + "@opentelemetry/resources": 1.25.0 + "@opentelemetry/sdk-logs": 0.52.0 + "@opentelemetry/sdk-metrics": 1.25.0 + "@opentelemetry/sdk-trace-base": 1.25.0 + protobufjs: ^7.3.0 + peerDependencies: + "@opentelemetry/api": ">=1.3.0 <1.10.0" + checksum: 5f75f41a710e5e536faecdec7b1687352e450d185d12613bbcbb206570d96ca2833db15e1d7945cb27040a04c017135b07df2f607ccf9ca9a061f86ad87e8c35 + languageName: node + linkType: hard + +"@opentelemetry/propagator-b3@npm:1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/propagator-b3@npm:1.25.0" + dependencies: + "@opentelemetry/core": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 5e8a0feec400ebb20644ee217f904ec8894ccad49b753e80c5e131a4f3390504ca3fd17de58ff546313dedc6498dbd198ff83acc3d8084a205e1d901cfc0bb2d + languageName: node + linkType: hard + +"@opentelemetry/propagator-jaeger@npm:1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/propagator-jaeger@npm:1.25.0" + dependencies: + "@opentelemetry/core": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: c652b4285e254041654a5153649f822b8e2eaa526b67e0a8c56c4eb173d9d0d0efa41ffed3f7dcdd1c2c2b85365cd05e001ee145e8701e4af9d7eef79488ca18 + languageName: node + linkType: hard + +"@opentelemetry/resources@npm:1.25.0, @opentelemetry/resources@npm:^1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/resources@npm:1.25.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/semantic-conventions": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 6b9e59b7fc70944b418a1ae61396ec82d80869b2918bc664e3bd6d302ddc217e2e8fc5e37bcbd04bac46234f2057a005fa2a657caa1288a5c4ab7b697b0665cb + languageName: node + linkType: hard + +"@opentelemetry/sdk-logs@npm:0.52.0": + version: 0.52.0 + resolution: "@opentelemetry/sdk-logs@npm:0.52.0" + dependencies: + "@opentelemetry/api-logs": 0.52.0 + "@opentelemetry/core": 1.25.0 + "@opentelemetry/resources": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.4.0 <1.10.0" + checksum: 7bf7aed40a168866d76e2260237f6cec9c82acaebcc02a3597985b2be644e4aebf69e0f57739e7fd7cc8e75ecd0bdc98b0429ea985d7de6064148477ffd6432e + languageName: node + linkType: hard + +"@opentelemetry/sdk-metrics@npm:1.25.0, @opentelemetry/sdk-metrics@npm:^1.25.0, @opentelemetry/sdk-metrics@npm:^1.8.0": + version: 1.25.0 + resolution: "@opentelemetry/sdk-metrics@npm:1.25.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/resources": 1.25.0 + lodash.merge: ^4.6.2 + peerDependencies: + "@opentelemetry/api": ">=1.3.0 <1.10.0" + checksum: dcb3e80bb41f937db77cb2a91574e2e434875b1740fdcff657d4223ce40002039dac915640a981deada86d53961607150b52fe32497b19c6a17dfd5fb9ed3f05 + languageName: node + linkType: hard + +"@opentelemetry/sdk-trace-base@npm:1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/sdk-trace-base@npm:1.25.0" + dependencies: + "@opentelemetry/core": 1.25.0 + "@opentelemetry/resources": 1.25.0 + "@opentelemetry/semantic-conventions": 1.25.0 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 4c0ce40dbe9dcf5e5f79c60c44ffadb6806f1a8cf45c13d901ea6a2345f6cf26a83a1dad4358859fcf941e01f8bd8654f907f88137d5051e023211f8d645e959 + languageName: node + linkType: hard + +"@opentelemetry/sdk-trace-node@npm:^1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/sdk-trace-node@npm:1.25.0" + dependencies: + "@opentelemetry/context-async-hooks": 1.25.0 + "@opentelemetry/core": 1.25.0 + "@opentelemetry/propagator-b3": 1.25.0 + "@opentelemetry/propagator-jaeger": 1.25.0 + "@opentelemetry/sdk-trace-base": 1.25.0 + semver: ^7.5.2 + peerDependencies: + "@opentelemetry/api": ">=1.0.0 <1.10.0" + checksum: 22a0a61a6c092841ef4438f914edd259d3025078cc9331aaac340c624c2963aa6fdc4970ade5a0e6647c64e92e893ebde0b8ecdd021abac5358ea3c814a5c01c + languageName: node + linkType: hard + +"@opentelemetry/semantic-conventions@npm:1.25.0, @opentelemetry/semantic-conventions@npm:^1.25.0": + version: 1.25.0 + resolution: "@opentelemetry/semantic-conventions@npm:1.25.0" + checksum: 8c9d36f57f0d3d1d4945effe626894ffea860b4be4d5257666ee28b90843ce22694c5b01f9b25ed47a08043958b7e89a65b7ae8e4128f5ed72dcdfe71ac7a19a + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -3034,6 +3265,79 @@ __metadata: languageName: node linkType: hard +"@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/aspromise@npm:1.1.2" + checksum: 011fe7ef0826b0fd1a95935a033a3c0fd08483903e1aa8f8b4e0704e3233406abb9ee25350ec0c20bbecb2aad8da0dcea58b392bbd77d6690736f02c143865d2 + languageName: node + linkType: hard + +"@protobufjs/base64@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/base64@npm:1.1.2" + checksum: 67173ac34de1e242c55da52c2f5bdc65505d82453893f9b51dc74af9fe4c065cf4a657a4538e91b0d4a1a1e0a0642215e31894c31650ff6e3831471061e1ee9e + languageName: node + linkType: hard + +"@protobufjs/codegen@npm:^2.0.4": + version: 2.0.4 + resolution: "@protobufjs/codegen@npm:2.0.4" + checksum: 59240c850b1d3d0b56d8f8098dd04787dcaec5c5bd8de186fa548de86b86076e1c50e80144b90335e705a044edf5bc8b0998548474c2a10a98c7e004a1547e4b + languageName: node + linkType: hard + +"@protobufjs/eventemitter@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/eventemitter@npm:1.1.0" + checksum: 0369163a3d226851682f855f81413cbf166cd98f131edb94a0f67f79e75342d86e89df9d7a1df08ac28be2bc77e0a7f0200526bb6c2a407abbfee1f0262d5fd7 + languageName: node + linkType: hard + +"@protobufjs/fetch@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/fetch@npm:1.1.0" + dependencies: + "@protobufjs/aspromise": ^1.1.1 + "@protobufjs/inquire": ^1.1.0 + checksum: 3fce7e09eb3f1171dd55a192066450f65324fd5f7cc01a431df01bb00d0a895e6bfb5b0c5561ce157ee1d886349c90703d10a4e11a1a256418ff591b969b3477 + languageName: node + linkType: hard + +"@protobufjs/float@npm:^1.0.2": + version: 1.0.2 + resolution: "@protobufjs/float@npm:1.0.2" + checksum: 5781e1241270b8bd1591d324ca9e3a3128d2f768077a446187a049e36505e91bc4156ed5ac3159c3ce3d2ba3743dbc757b051b2d723eea9cd367bfd54ab29b2f + languageName: node + linkType: hard + +"@protobufjs/inquire@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/inquire@npm:1.1.0" + checksum: ca06f02eaf65ca36fb7498fc3492b7fc087bfcc85c702bac5b86fad34b692bdce4990e0ef444c1e2aea8c034227bd1f0484be02810d5d7e931c55445555646f4 + languageName: node + linkType: hard + +"@protobufjs/path@npm:^1.1.2": + version: 1.1.2 + resolution: "@protobufjs/path@npm:1.1.2" + checksum: 856eeb532b16a7aac071cacde5c5620df800db4c80cee6dbc56380524736205aae21e5ae47739114bf669ab5e8ba0e767a282ad894f3b5e124197cb9224445ee + languageName: node + linkType: hard + +"@protobufjs/pool@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/pool@npm:1.1.0" + checksum: d6a34fbbd24f729e2a10ee915b74e1d77d52214de626b921b2d77288bd8f2386808da2315080f2905761527cceffe7ec34c7647bd21a5ae41a25e8212ff79451 + languageName: node + linkType: hard + +"@protobufjs/utf8@npm:^1.1.0": + version: 1.1.0 + resolution: "@protobufjs/utf8@npm:1.1.0" + checksum: f9bf3163d13aaa3b6f5e6fbf37a116e094ea021c0e1f2a7ccd0e12a29e2ce08dafba4e8b36e13f8ed7397e1591610ce880ed1289af4d66cf4ace8a36a9557278 + languageName: node + linkType: hard + "@puppeteer/browsers@npm:2.2.3": version: 2.2.3 resolution: "@puppeteer/browsers@npm:2.2.3" @@ -3922,6 +4226,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:>=13.7.0": + version: 20.14.2 + resolution: "@types/node@npm:20.14.2" + dependencies: + undici-types: ~5.26.4 + checksum: 265362479b8f3b50fcd1e3f9e9af6121feb01a478dff0335ae67cccc3babfe45d0f12209d3d350595eebd7e67471762697b877c380513f8e5d27a238fa50c805 + languageName: node + linkType: hard + "@types/node@npm:^18.14.6, @types/node@npm:^18.15.11, @types/node@npm:^18.15.3, @types/node@npm:^18.7.23": version: 18.19.33 resolution: "@types/node@npm:18.19.33" @@ -10271,6 +10584,13 @@ __metadata: languageName: node linkType: hard +"long@npm:^5.0.0": + version: 5.2.3 + resolution: "long@npm:5.2.3" + checksum: 885ede7c3de4facccbd2cacc6168bae3a02c3e836159ea4252c87b6e34d40af819824b2d4edce330bfb5c4d6e8ce3ec5864bdcf9473fa1f53a4f8225860e5897 + languageName: node + linkType: hard + "lru-cache@npm:^10.0.1, lru-cache@npm:^10.1.0, lru-cache@npm:^10.2.0": version: 10.2.2 resolution: "lru-cache@npm:10.2.2" @@ -11794,6 +12114,26 @@ __metadata: languageName: node linkType: hard +"protobufjs@npm:^7.3.0": + version: 7.3.2 + resolution: "protobufjs@npm:7.3.2" + dependencies: + "@protobufjs/aspromise": ^1.1.2 + "@protobufjs/base64": ^1.1.2 + "@protobufjs/codegen": ^2.0.4 + "@protobufjs/eventemitter": ^1.1.0 + "@protobufjs/fetch": ^1.1.0 + "@protobufjs/float": ^1.0.2 + "@protobufjs/inquire": ^1.1.0 + "@protobufjs/path": ^1.1.2 + "@protobufjs/pool": ^1.1.0 + "@protobufjs/utf8": ^1.1.0 + "@types/node": ">=13.7.0" + long: ^5.0.0 + checksum: cfb2a744787f26ee7c82f3e7c4b72cfc000e9bb4c07828ed78eb414db0ea97a340c0cc3264d0e88606592f847b12c0351411f10e9af255b7ba864eec44d7705f + languageName: node + linkType: hard + "protons-runtime@npm:5.4.0, protons-runtime@npm:^5.0.0, protons-runtime@npm:^5.4.0": version: 5.4.0 resolution: "protons-runtime@npm:5.4.0" @@ -12486,6 +12826,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.5.2": + version: 7.6.2 + resolution: "semver@npm:7.6.2" + bin: + semver: bin/semver.js + checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d + languageName: node + linkType: hard + "serialize-javascript@npm:^6.0.1": version: 6.0.2 resolution: "serialize-javascript@npm:6.0.2" @@ -13200,6 +13549,16 @@ __metadata: languageName: node linkType: hard +"systeminformation@npm:5.22.9": + version: 5.22.9 + resolution: "systeminformation@npm:5.22.9" + bin: + systeminformation: lib/cli.js + checksum: c605e568395041e57483722b38802928bc6122e347f9e1c6a9588b30297e28c19ffb425be0306fcd6e4f14cd443fa0bbbb407e69ef15d891f6776946718b26bb + conditions: (os=darwin | os=linux | os=win32 | os=freebsd | os=openbsd | os=netbsd | os=sunos | os=android) + languageName: node + linkType: hard + "table-layout@npm:^1.0.2": version: 1.0.2 resolution: "table-layout@npm:1.0.2" @@ -13608,13 +13967,6 @@ __metadata: languageName: node linkType: hard -"tty-browserify@npm:^0.0.1": - version: 0.0.1 - resolution: "tty-browserify@npm:0.0.1" - checksum: 93b745d43fa5a7d2b948fa23be8d313576d1d884b48acd957c07710bac1c0d8ac34c0556ad4c57c73d36e11741763ef66b3fb4fb97b06b7e4d525315a3cd45f5 - languageName: node - linkType: hard - "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" From c19aae17635b27aa4fe9abeac6010b2614fe71aa Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 14:07:54 +0000 Subject: [PATCH 14/94] undo formatting --- docs/docs/migration_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index a67a72ab615a..776ee4ac9efa 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -1668,4 +1668,4 @@ Now, just remove the `src` folder,: ```rust easy_private_token_contract = {git = "https://github.com/AztecProtocol/aztec-packages/", tag ="v0.17.0", directory = "noir-projects/noir-contracts/contracts/easy_private_token_contract"} -``` +``` \ No newline at end of file From 38bc061a58e0b6b842b934c9f0359bb1bf491f73 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 14:08:44 +0000 Subject: [PATCH 15/94] undo formatting again --- docs/docs/migration_notes.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index 776ee4ac9efa..e9e1abb4d167 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -7,9 +7,7 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. ## 0.44.0 - ### [Aztec.nr] Autogenerate Serialize methods for events - ```diff #[aztec(event)] struct WithdrawalProcessed { @@ -25,11 +23,10 @@ struct WithdrawalProcessed { ``` ### [Aztec.nr] rename `encode_and_encrypt_with_keys` to `encode_and_encrypt_note_with_keys` - -````diff +```diff contract XYZ { - use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_with_keys; -+ use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys; ++ use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys; .... - numbers.at(owner).initialize(&mut new_number).emit(encode_and_encrypt_with_keys(&mut context, owner_ovpk_m, owner_ivpk_m)); @@ -89,7 +86,7 @@ These changes were done because having the note hash exposed allowed us to not h + (note_hash_for_nullify, nullifier) + } + } -```` +``` ### [Aztec.nr] `note_getter` returns `BoundedVec` @@ -646,7 +643,7 @@ This change was made to communicate that we do not constrain the value in circui Historically it have been possible to "view" `unconstrained` functions to simulate them and get the return values, but not for `public` nor `private` functions. This has lead to a lot of bad code where we have the same function implemented thrice, once in `private`, once in `public` and once in `unconstrained`. It is not possible to call `simulate` on any call to get the return values! -However, beware that it currently always returns a Field array of size 4 for private and public. +However, beware that it currently always returns a Field array of size 4 for private and public. This will change to become similar to the return values of the `unconstrained` functions with proper return types. ```diff From a04678ae3ac126cc6ac9a5bb62907d84510fe42a Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 14:11:08 +0000 Subject: [PATCH 16/94] cancel-in-progress --- .github/workflows/devnet-deploys.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 80fa8aae0c2e..1120fef4628c 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -3,6 +3,10 @@ on: push: branches: [devnet] +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} GIT_COMMIT: ${{ github.sha }} From cf32b29f46ed08f2cae84b445fa8345143523677 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 14:16:48 +0000 Subject: [PATCH 17/94] fix ecs task def name --- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 3595f7a102bc..7a0e55d9c737 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -104,7 +104,7 @@ resource "aws_ecs_task_definition" "p2p-bootstrap" { container_definitions = < Date: Wed, 26 Jun 2024 14:44:47 +0000 Subject: [PATCH 18/94] fix aws_ecs_service name ref --- yarn-project/p2p-bootstrap/terraform/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 7a0e55d9c737..85fa61ad536e 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -167,7 +167,7 @@ DEFINITIONS resource "aws_ecs_service" "p2p-bootstrap" { count = local.bootnode_count - name = "${var.DEPLOY_TAG}-p2p-bootstrap-${count.index + 1}" + name = "${var.DEPLOY_TAG}-p2p-bootstrap-node-${count.index + 1}" cluster = data.terraform_remote_state.setup_iac.outputs.ecs_cluster_id launch_type = "FARGATE" desired_count = 1 From b400d3b360175bd293b36dcafc4800022189c2f3 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 26 Jun 2024 15:03:25 +0000 Subject: [PATCH 19/94] fix container names --- yarn-project/p2p-bootstrap/terraform/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/p2p-bootstrap/terraform/main.tf b/yarn-project/p2p-bootstrap/terraform/main.tf index 85fa61ad536e..31b76cb33cd4 100644 --- a/yarn-project/p2p-bootstrap/terraform/main.tf +++ b/yarn-project/p2p-bootstrap/terraform/main.tf @@ -185,13 +185,13 @@ resource "aws_ecs_service" "p2p-bootstrap" { service_registries { registry_arn = aws_service_discovery_service.p2p-bootstrap[count.index].arn - container_name = "${var.DEPLOY_TAG}-p2p-bootstrap-${count.index + 1}" + container_name = "${var.DEPLOY_TAG}-p2p-bootstrap-node-${count.index + 1}" container_port = 80 } load_balancer { target_group_arn = aws_lb_target_group.p2p-bootstrap-target-group-udp[count.index].id - container_name = "${var.DEPLOY_TAG}-p2p-bootstrap-${count.index + 1}" + container_name = "${var.DEPLOY_TAG}-p2p-bootstrap-node-${count.index + 1}" container_port = var.BOOTNODE_LISTEN_PORT + count.index } From bf8c93967ee44d4f620b462d0318c36c35c287ec Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 28 Jun 2024 11:33:45 +0000 Subject: [PATCH 20/94] PR fixes --- yarn-project/aztec/terraform/node/variables.tf | 5 ----- yarn-project/aztec/terraform/prover/variables.tf | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index f761cfee2e75..36cb280645fe 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -72,8 +72,3 @@ variable "PROVING_ENABLED" { type = bool default = true } - -variable "AGENTS_PER_SEQUENCER" { - type = string - default = 4 -} diff --git a/yarn-project/aztec/terraform/prover/variables.tf b/yarn-project/aztec/terraform/prover/variables.tf index 79ae2219a098..e6c6865d26d3 100644 --- a/yarn-project/aztec/terraform/prover/variables.tf +++ b/yarn-project/aztec/terraform/prover/variables.tf @@ -4,7 +4,7 @@ variable "DEPLOY_TAG" { variable "AGENTS_PER_SEQUENCER" { type = string - default = 4 + default = 1 } variable "PROVING_ENABLED" { From 543f660517b211d77dd560b5563e161224390acc Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 28 Jun 2024 11:45:17 +0000 Subject: [PATCH 21/94] remove ref from main.tf --- yarn-project/aztec/terraform/node/main.tf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index a1a52ffeb410..d446d334c89e 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -57,9 +57,7 @@ locals { publisher_private_keys = [var.SEQ_1_PUBLISHER_PRIVATE_KEY, var.SEQ_2_PUBLISHER_PRIVATE_KEY] node_p2p_private_keys = [var.NODE_1_PRIVATE_KEY, var.NODE_2_PRIVATE_KEY] node_count = length(local.publisher_private_keys) - #node_count = 1 - data_dir = "/usr/src/yarn-project/aztec/data" - agents_per_sequencer = var.AGENTS_PER_SEQUENCER + data_dir = "/usr/src/yarn-project/aztec/data" } output "node_count" { From 898388c84b42ce6ecce016201e4b589fb38e621c Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 28 Jun 2024 14:15:35 +0000 Subject: [PATCH 22/94] use deploy_tag again for fork url --- yarn-project/aztec/terraform/node/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index d446d334c89e..20725c32103d 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -193,7 +193,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "ETHEREUM_HOST", - "value": "https://aztec-dev-mainnet-fork.aztec.network:8545/${var.API_KEY}" + "value": "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" }, { "name": "DATA_DIRECTORY", From ce09a7589f4b3df485e7c6cb1ac92929e6d35d63 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 08:51:09 +0100 Subject: [PATCH 23/94] feat: deploy L1 contracts on GA (#7262) --- .github/scripts/extract_l1_addresses.sh | 47 +++++++++ .github/workflows/devnet-deploys.yml | 30 +++++- iac/mainnet-fork/terraform/main.tf | 2 +- l1-contracts/Earthfile | 2 +- l1-contracts/REDEPLOY | 2 +- l1-contracts/scripts/ci_deploy_contracts.sh | 96 ------------------- yarn-project/Earthfile | 4 +- yarn-project/cli/Earthfile | 20 ++++ .../ethereum/src/deploy_l1_contracts.ts | 2 +- 9 files changed, 102 insertions(+), 103 deletions(-) create mode 100755 .github/scripts/extract_l1_addresses.sh delete mode 100755 l1-contracts/scripts/ci_deploy_contracts.sh create mode 100644 yarn-project/cli/Earthfile diff --git a/.github/scripts/extract_l1_addresses.sh b/.github/scripts/extract_l1_addresses.sh new file mode 100755 index 000000000000..b0946446ffba --- /dev/null +++ b/.github/scripts/extract_l1_addresses.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +FILE_PATH=./script_output + +# Read the file line by line +while IFS= read -r line; do + # Extract the hexadecimal address using awk + address=$(echo "$line" | awk '{print $NF}') + + # Assign the address to the respective variable based on the line content + if [[ $line == *"Rollup Address"* ]]; then + export TF_VAR_ROLLUP_CONTRACT_ADDRESS=$address + echo "TF_VAR_ROLLUP_CONTRACT_ADDRESS=$TF_VAR_ROLLUP_CONTRACT_ADDRESS" + elif [[ $line == *"Registry Address"* ]]; then + export TF_VAR_REGISTRY_CONTRACT_ADDRESS=$address + echo "TF_VAR_REGISTRY_CONTRACT_ADDRESS=$TF_VAR_REGISTRY_CONTRACT_ADDRESS" + elif [[ $line == *"Inbox Address"* ]]; then + export TF_VAR_INBOX_CONTRACT_ADDRESS=$address + echo "TF_VAR_INBOX_CONTRACT_ADDRESS=$TF_VAR_INBOX_CONTRACT_ADDRESS" + elif [[ $line == *"Outbox Address"* ]]; then + export TF_VAR_OUTBOX_CONTRACT_ADDRESS=$address + echo "TF_VAR_OUTBOX_CONTRACT_ADDRESS=$TF_VAR_OUTBOX_CONTRACT_ADDRESS" + elif [[ $line == *"Oracle Address"* ]]; then + export TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$address + echo "TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS" + elif [[ $line == *"Gas Token Address"* ]]; then + export TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS=$address + echo "TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS=$TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS" + elif [[ $line == *"Gas Portal Address"* ]]; then + export TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS=$address + echo "TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS=$TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS" + else + echo "Unknown contract address: $line" + fi +done <"$FILE_PATH" + +# echo all addresses into github env +echo "TF_VAR_ROLLUP_CONTRACT_ADDRESS=$TF_VAR_ROLLUP_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_REGISTRY_CONTRACT_ADDRESS=$TF_VAR_REGISTRY_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_INBOX_CONTRACT_ADDRESS=$TF_VAR_INBOX_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_OUTBOX_CONTRACT_ADDRESS=$TF_VAR_OUTBOX_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS=$TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS" >>$GITHUB_ENV +echo "TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS=$TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS" >>$GITHUB_ENV + +# Set global variable for redeployment of contracts +echo "CONTRACTS_DEPLOYED=1" >>$GITHUB_ENV diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 1120fef4628c..2f006de8e361 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -10,6 +10,8 @@ concurrency: env: DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} GIT_COMMIT: ${{ github.sha }} + DEPLOY_TAG: devnet + FILE_PATH: ./l1-contracts/addresses.txt # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol TF_VAR_CHAIN_ID: 31337 @@ -35,8 +37,8 @@ jobs: with: { ref: "${{ env.GIT_COMMIT }}" } - uses: ./.github/ci-setup-action with: - dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" concurrency_key: build-release-artifacts-${{ github.actor }} + dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - name: "Build & Push images" timeout-minutes: 40 # Run the build steps for each image with version and arch, push to dockerhub @@ -60,6 +62,32 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 + - name: Check if L1 contracts need deployment + id: check_changes + uses: actions/github-script@v6 + with: + script: | + const { execSync } = require('child_process'); + const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); + const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); + return { fileChanged }; + + - name: Deploy L1 Contracts + if: steps.check_changes.outputs.fileChanged == 'true' + run: | + earthly-ci --no-output ./yarn-project/cli+deploy-l1-contracts \ + --PRIVATE_KEY=${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + --RPC_URL=https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ + | tee ${{ env.FILE_PATH }} + ./scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} + + - name: Apply l1-contracts Terraform + if: steps.check_changes.outputs.fileChanged == 'true' + working-directory: ./l1-contracts/terraform + run: | + terraform init -input=false -backend-config="key=devnet/l1-contracts" + terraform apply -input=false -auto-approve + - name: Deploy P2P Bootstrap Nodes working-directory: ./yarn-project/p2p-bootstrap/terraform run: | diff --git a/iac/mainnet-fork/terraform/main.tf b/iac/mainnet-fork/terraform/main.tf index 08198ba5e0b5..026469d3920b 100644 --- a/iac/mainnet-fork/terraform/main.tf +++ b/iac/mainnet-fork/terraform/main.tf @@ -117,7 +117,7 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" { [ { "name": "${var.DEPLOY_TAG}-mainnet-fork", - "image": "${var.DOCKERHUB_ACCOUNT}/mainnet-fork:${var.DEPLOY_TAG}", + "image": "${var.DOCKERHUB_ACCOUNT}/mainnet-fork:aztec-dev", "essential": true, "environment": [ { diff --git a/l1-contracts/Earthfile b/l1-contracts/Earthfile index 2df4d56e48a9..5e1e559be621 100644 --- a/l1-contracts/Earthfile +++ b/l1-contracts/Earthfile @@ -3,7 +3,7 @@ VERSION 0.8 build: FROM ../build-images+build WORKDIR /usr/src/l1-contracts - COPY --dir lib scripts src terraform test *.json *.toml *.sh . + COPY --dir lib src terraform test *.json *.toml *.sh . #RUN git init && git add . && yarn lint && yarn slither && yarn slither-has-diff # "slither": "forge clean && forge build --build-info --skip '*/test/**' --force && slither . --checklist --ignore-compile --show-ignored-findings --config-file ./slither.config.json | tee slither_output.md", # "slither-has-diff": "./slither_has_diff.sh" diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 8d0fb412c885..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -5 \ No newline at end of file +1 \ No newline at end of file diff --git a/l1-contracts/scripts/ci_deploy_contracts.sh b/l1-contracts/scripts/ci_deploy_contracts.sh deleted file mode 100755 index 73dcf50f1a8c..000000000000 --- a/l1-contracts/scripts/ci_deploy_contracts.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -export ETHEREUM_HOST=https://$DEPLOY_TAG-mainnet-fork.aztec.network:8545/$FORK_API_KEY - -REPOSITORY="l1-contracts" - -CONTENT_HASH=$(calculate_content_hash $REPOSITORY) - -echo "Last successfully published commit: $CONTENT_HASH" - -# Check if image hash has already been deployed. -if check_rebuild "cache-$CONTENT_HASH-$DEPLOY_TAG-deployed" $REPOSITORY; then - echo "No changes detected, no contract deploy necessary." - # Set global variable for redeployment of contracts - echo export CONTRACTS_DEPLOYED=0 >>$BASH_ENV - exit 0 -fi - -# Login to pull our ecr images with docker. -retry ecr_login - -# Contract addresses will be saved in the serve directory -mkdir -p serve -FILE_PATH=./serve/contract_addresses.json -CLI_IMAGE=$(calculate_image_uri cli) -retry docker pull $CLI_IMAGE - -# remove 0x prefix from private key -PRIVATE_KEY=${CONTRACT_PUBLISHER_PRIVATE_KEY#0x} - -# Retries up to 3 times with 10 second intervals -ATTEMPTS=3 -for i in $(seq 1 $ATTEMPTS); do - docker run \ - $CLI_IMAGE \ - deploy-l1-contracts -u $ETHEREUM_HOST -p $PRIVATE_KEY | tee $FILE_PATH && break - [ "$i" != "$ATTEMPTS" ] && sleep 10 -done - -## Result format is: -# Rollup Address: 0xe33d37702bb94e83ca09e7dc804c9f4c4ab8ee4a -# Registry Address: 0xf02a70628c4e0d7c41f231f9af24c1678a030438 -# L1 -> L2 Inbox Address: 0xdf34a07c7da15630d3b5d6bb17651d548a6e9d8f -# L2 -> L1 Outbox address: 0xf6b1b3c2c393fe55fe577a1f528bd72a76589ab0 -# Contract Deployment Emitter Address: 0xf3ecc6e9428482a74687ee5f7b96f4dff8781454 -# Availability Oracle Address: 0x610178da211fef7d417bc0e6fed39f05609ad788 -# Gas Token Address: 0x9e4b815648c4a98a9bce6a899cecbaf3758cf23c -# Gas Portal Address: 0xda5dea39534f67f33deb38ec3b1e438fa893bf2c - -# Read the file line by line -while IFS= read -r line; do - # Extract the hexadecimal address using awk - address=$(echo "$line" | awk '{print $NF}') - - # Assign the address to the respective variable based on the line content - if [[ $line == *"Rollup"* ]]; then - export TF_VAR_ROLLUP_CONTRACT_ADDRESS=$address - echo "TF_VAR_ROLLUP_CONTRACT_ADDRESS=$TF_VAR_ROLLUP_CONTRACT_ADDRESS" - elif [[ $line == *"Registry"* ]]; then - export TF_VAR_REGISTRY_CONTRACT_ADDRESS=$address - echo "TF_VAR_REGISTRY_CONTRACT_ADDRESS=$TF_VAR_REGISTRY_CONTRACT_ADDRESS" - elif [[ $line == *"Inbox"* ]]; then - export TF_VAR_INBOX_CONTRACT_ADDRESS=$address - echo "TF_VAR_INBOX_CONTRACT_ADDRESS=$TF_VAR_INBOX_CONTRACT_ADDRESS" - elif [[ $line == *"Outbox"* ]]; then - export TF_VAR_OUTBOX_CONTRACT_ADDRESS=$address - echo "TF_VAR_OUTBOX_CONTRACT_ADDRESS=$TF_VAR_OUTBOX_CONTRACT_ADDRESS" - elif [[ $line == *"Oracle"* ]]; then - export TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$address - echo "TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS=$TF_VAR_AVAILABILITY_ORACLE_CONTRACT_ADDRESS" - elif [[ $line == *"Gas Token"* ]]; then - export TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS=$address - echo "TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS=$TF_VAR_GAS_TOKEN_CONTRACT_ADDRESS" - elif [[ $line == *"Gas Portal"* ]]; then - export TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS=$address - echo "TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS=$TF_VAR_GAS_PORTAL_CONTRACT_ADDRESS" - else - echo "Unknown contract address: $line" - fi -done <"$FILE_PATH" - -if [ "$DRY_DEPLOY" -eq 1 ]; then - echo "DRY_DEPLOY: deploy_terraform l1-contracts ./terraform" - echo "DRY_DEPLOY: tag_remote_image $REPOSITORY cache-$CONTENT_HASH cache-$CONTENT_HASH-$DEPLOY_TAG-deployed" -else - # Write TF state variables - deploy_terraform l1-contracts ./terraform - - # Tag the image as deployed. - retry tag_remote_image $REPOSITORY cache-$CONTENT_HASH cache-$CONTENT_HASH-$DEPLOY_TAG-deployed -fi - -# Set global variable for redeployment of contracts -echo export CONTRACTS_DEPLOYED=1 >>$BASH_ENV diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 1f4e2fdc7906..c94a8019935d 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -115,7 +115,7 @@ rollup-verifier-contract: RUN --entrypoint write-contract -c RootRollupArtifact -n UltraVerifier.sol SAVE ARTIFACT /usr/src/bb /usr/src/bb -txe: +txe: FROM +build RUN yarn workspaces focus @aztec/txe --production && yarn cache clean # Remove a bunch of stuff that we don't need that takes up space. @@ -179,7 +179,7 @@ aztec-faucet-build: aztec-faucet: FROM ubuntu:noble RUN apt update && apt install nodejs curl -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - COPY +aztec-faucet/usr/src /usr/src + COPY +aztec-faucet-build/usr/src /usr/src ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-faucet/dest/bin/index.js"] LET port=8080 diff --git a/yarn-project/cli/Earthfile b/yarn-project/cli/Earthfile new file mode 100644 index 000000000000..18bc82b114d7 --- /dev/null +++ b/yarn-project/cli/Earthfile @@ -0,0 +1,20 @@ +VERSION 0.8 + + +aztec-cli: + FROM ../+build + RUN yarn workspaces focus @aztec/cli --production && yarn cache clean + + RUN mkdir /cache && chmod 777 /cache + ENV XDG_CACHE_HOME /cache + VOLUME "/cache" + ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] + +deploy-l1-contracts: + FROM +aztec-cli + ARG PRIVATE_KEY + ARG RPC_URL + ENV PRIVATE_KEY=$PRIVATE_KEY + ENV ETHEREUM_HOST=$RPC_URL + RUN echo "Deploying L1 contracts with PRIVATE_KEY=$PRIVATE_KEY and RPC_URL=$RPC_URL" + RUN --entrypoint deploy-l1-contracts diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index d8d145b95389..c6feb14af171 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -116,7 +116,7 @@ export function createL1Clients( } /** - * Deploys the aztec L1 contracts; Rollup, Contract Deployment Emitter & (optionally) Decoder Helper. + * Deploys the aztec L1 contracts; Rollup & (optionally) Decoder Helper. * @param rpcUrl - URL of the ETH RPC to use for deployment. * @param account - Private Key or HD Account that will deploy the contracts. * @param chain - The chain instance to deploy to. From e1a9b5d6ff772150f19792dc89ed490ec70c5f28 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 09:06:25 +0100 Subject: [PATCH 24/94] chore: redeploy L1 contracts (#7263) --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From 2bd87c1a75476fb692390b3214a9fb870ca9fbf0 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 09:24:55 +0100 Subject: [PATCH 25/94] fix: fetch-depth 0 (#7264) --- .github/workflows/devnet-deploys.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 2f006de8e361..bf3105416960 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -50,7 +50,9 @@ jobs: needs: build steps: - uses: actions/checkout@v4 - with: { ref: "${{ env.GIT_COMMIT }}" } + with: + ref: "${{ env.GIT_COMMIT }}" + fetch-depth: 0 - uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.7.5 From 7afe0d689b7b904a52b157abeee09bd9adcd289a Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 10:58:57 +0100 Subject: [PATCH 26/94] chore: redeploy devnet (#7265) --- .github/workflows/devnet-deploys.yml | 1 + l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index bf3105416960..2e36309d0bb7 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -31,6 +31,7 @@ jobs: secrets: inherit build: + needs: setup runs-on: ${{ github.actor }}-x86 steps: - uses: actions/checkout@v4 diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..5407c1d3c077 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +3 \ No newline at end of file From 987ba1ab7ce898296270eb10b44ac902a52aa0dc Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 11:06:08 +0100 Subject: [PATCH 27/94] chore: redeploy & log (#7266) --- .github/workflows/devnet-deploys.yml | 11 ++++++----- l1-contracts/REDEPLOY | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 2e36309d0bb7..a0169e546fd1 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -44,7 +44,7 @@ jobs: timeout-minutes: 40 # Run the build steps for each image with version and arch, push to dockerhub run: | - earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=devnet + earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} terraform_deploy: runs-on: ubuntu-latest @@ -73,6 +73,7 @@ jobs: const { execSync } = require('child_process'); const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); + console.log('fileChanged:', fileChanged); return { fileChanged }; - name: Deploy L1 Contracts @@ -88,23 +89,23 @@ jobs: if: steps.check_changes.outputs.fileChanged == 'true' working-directory: ./l1-contracts/terraform run: | - terraform init -input=false -backend-config="key=devnet/l1-contracts" + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" terraform apply -input=false -auto-approve - name: Deploy P2P Bootstrap Nodes working-directory: ./yarn-project/p2p-bootstrap/terraform run: | - terraform init -input=false -backend-config="key=devnet/p2p-bootstrap" + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/p2p-bootstrap" terraform apply -input=false -auto-approve - name: Deploy Aztec Nodes working-directory: ./yarn-project/aztec/terraform/node run: | - terraform init -input=false -backend-config="key=devnet/aztec-node" + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" terraform apply -input=false -auto-approve - name: Deploy Provers working-directory: ./yarn-project/aztec/terraform/prover run: | - terraform init -input=false -backend-config="key=devnet/prover" + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/prover" terraform apply -input=false -auto-approve diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 5407c1d3c077..47cd67fa9a7e 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -3 \ No newline at end of file +4 \ No newline at end of file From 122744708d83e821d6205f51d8212dda51b2b6bc Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 11:17:01 +0100 Subject: [PATCH 28/94] fix: use result key (#7267) --- .github/workflows/devnet-deploys.yml | 9 ++++----- l1-contracts/REDEPLOY | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index a0169e546fd1..c8c735328713 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -67,17 +67,16 @@ jobs: - name: Check if L1 contracts need deployment id: check_changes - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { execSync } = require('child_process'); const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); - console.log('fileChanged:', fileChanged); - return { fileChanged }; + return fileChanged - name: Deploy L1 Contracts - if: steps.check_changes.outputs.fileChanged == 'true' + if: steps.check_changes.outputs.result == 'true' run: | earthly-ci --no-output ./yarn-project/cli+deploy-l1-contracts \ --PRIVATE_KEY=${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ @@ -86,7 +85,7 @@ jobs: ./scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - name: Apply l1-contracts Terraform - if: steps.check_changes.outputs.fileChanged == 'true' + if: steps.check_changes.outputs.result == 'true' working-directory: ./l1-contracts/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 47cd67fa9a7e..8d0fb412c885 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -4 \ No newline at end of file +5 \ No newline at end of file From 49170e46b1897346ca6fbdfc4c6447c6a99a9d09 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 11:30:36 +0100 Subject: [PATCH 29/94] fix: setup-action (#7268) --- .github/workflows/devnet-deploys.yml | 5 +++-- l1-contracts/REDEPLOY | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index c8c735328713..59df8d70e964 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -40,7 +40,7 @@ jobs: with: concurrency_key: build-release-artifacts-${{ github.actor }} dockerhub_password: "${{ secrets.DOCKERHUB_PASSWORD }}" - - name: "Build & Push images" + - name: "Build & Push aztec images" timeout-minutes: 40 # Run the build steps for each image with version and arch, push to dockerhub run: | @@ -50,6 +50,7 @@ jobs: runs-on: ubuntu-latest needs: build steps: + - uses: ./.github/ci-setup-action - uses: actions/checkout@v4 with: ref: "${{ env.GIT_COMMIT }}" @@ -82,7 +83,7 @@ jobs: --PRIVATE_KEY=${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ --RPC_URL=https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ | tee ${{ env.FILE_PATH }} - ./scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} + ./.github/gstscripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - name: Apply l1-contracts Terraform if: steps.check_changes.outputs.result == 'true' diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 8d0fb412c885..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -5 \ No newline at end of file +1 \ No newline at end of file From 8c3fcc6c0c009ef50a3d7664a9133cd73af0ddc9 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 11:41:15 +0100 Subject: [PATCH 30/94] fix: action ordering (#7270) --- .github/workflows/devnet-deploys.yml | 2 +- l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 59df8d70e964..0772563baa7c 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -50,11 +50,11 @@ jobs: runs-on: ubuntu-latest needs: build steps: - - uses: ./.github/ci-setup-action - uses: actions/checkout@v4 with: ref: "${{ env.GIT_COMMIT }}" fetch-depth: 0 + - uses: ./.github/ci-setup-action - uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.7.5 diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From e3c45ec67e5b0387d89e91e557e353d310eb5797 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 13:26:58 +0100 Subject: [PATCH 31/94] fix: publish cli image to dockerhub (#7274) --- .github/workflows/ci.yml | 3 +- .github/workflows/devnet-deploys.yml | 31 +++++++++++++++----- l1-contracts/REDEPLOY | 2 +- yarn-project/Earthfile | 43 ++++++++++++++++++++++++---- yarn-project/cli/Earthfile | 4 ++- 5 files changed, 67 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 196a9efb59a8..247c8b71f574 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,8 @@ name: CI on: push: branches: [master] - pull_request: {} + pull_request: + branches-ignore: [devnet] workflow_dispatch: inputs: {} diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 0772563baa7c..d90153229c7e 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -46,6 +46,23 @@ jobs: run: | earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} + - name: Check if L1 contracts need deployment + id: check_changes_build + uses: actions/github-script@v7 + with: + script: | + const { execSync } = require('child_process'); + const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); + const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); + return fileChanged + + - name: "Build & Push cli image" + if: steps.check_changes_build.outputs.result == 'true' + timeout-minutes: 40 + # Run the build steps for each image with version and arch, push to dockerhub + run: | + earthly-ci --no-output --push ./yarn-project+export-cli --DIST_TAG=${{ env.DEPLOY_TAG }} + terraform_deploy: runs-on: ubuntu-latest needs: build @@ -67,7 +84,7 @@ jobs: aws-region: us-west-2 - name: Check if L1 contracts need deployment - id: check_changes + id: check_changes_release uses: actions/github-script@v7 with: script: | @@ -75,18 +92,18 @@ jobs: const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); return fileChanged - - name: Deploy L1 Contracts - if: steps.check_changes.outputs.result == 'true' + if: steps.check_changes_release.outputs.result == 'true' run: | - earthly-ci --no-output ./yarn-project/cli+deploy-l1-contracts \ - --PRIVATE_KEY=${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ - --RPC_URL=https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ + docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} + docker run -ti --rm aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ + deploy-l1-contracts -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ | tee ${{ env.FILE_PATH }} ./.github/gstscripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - name: Apply l1-contracts Terraform - if: steps.check_changes.outputs.result == 'true' + if: steps.check_changes_release.outputs.result == 'true' working-directory: ./l1-contracts/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index c94a8019935d..0631918b4113 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -183,6 +183,43 @@ aztec-faucet: ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/aztec-faucet/dest/bin/index.js"] LET port=8080 +export-aztec-faucet: + FROM +aztec-faucet + ARG DIST_TAG="latest" + ARG ARCH + SAVE IMAGE --push aztecprotocol/aztec-faucet:${DIST_TAG}${ARCH:+-$ARCH} + +cli-build: + FROM +build + RUN yarn workspaces focus @aztec/cli --production && yarn cache clean + RUN rm -rf \ + ../noir-projects \ + ../l1-contracts \ + ../barretenberg/ts/src \ + ../barretenberg/ts/dest/node-cjs \ + ../barretenberg/ts/dest/browser \ + aztec.js/dest/main.js \ + end-to-end \ + **/src \ + **/artifacts + SAVE ARTIFACT /usr/src /usr/src + +cli: + FROM ubuntu:noble + RUN apt update && apt install nodejs curl -y && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + COPY +cli-build/usr/src /usr/src + + RUN mkdir /cache && chmod 777 /cache + ENV XDG_CACHE_HOME /cache + VOLUME "/cache" + ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] + +export-cli: + FROM +cli + ARG DIST_TAG="latest" + ARG ARCH + SAVE IMAGE --push aztecprotocol/cli:${DIST_TAG}${ARCH:+-$ARCH} + # We care about creating a slimmed down e2e image because we have to serialize it from earthly to docker for running. end-to-end-prod: FROM +build @@ -252,12 +289,6 @@ export-aztec-arch: ARG ARCH SAVE IMAGE --push aztecprotocol/aztec:${DIST_TAG}${ARCH:+-$ARCH} -export-aztec-faucet: - FROM +aztec-faucet - ARG DIST_TAG="latest" - ARG ARCH - SAVE IMAGE --push aztecprotocol/aztec-faucet:${DIST_TAG}${ARCH:+-$ARCH} - export-end-to-end: ARG EARTHLY_GIT_HASH FROM +end-to-end diff --git a/yarn-project/cli/Earthfile b/yarn-project/cli/Earthfile index 18bc82b114d7..ad9f9c3c9876 100644 --- a/yarn-project/cli/Earthfile +++ b/yarn-project/cli/Earthfile @@ -1,14 +1,16 @@ VERSION 0.8 -aztec-cli: +export-aztec-cli: FROM ../+build + ARG DIST_TAG="latest" RUN yarn workspaces focus @aztec/cli --production && yarn cache clean RUN mkdir /cache && chmod 777 /cache ENV XDG_CACHE_HOME /cache VOLUME "/cache" ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] + SAVE IMAGE aztecprotocol/cli:${DIST_TAG} deploy-l1-contracts: FROM +aztec-cli From dbde910dc9b4526a36db45a3e9815c1f7be1b353 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 13:36:01 +0100 Subject: [PATCH 32/94] fix: checkout depth on setup (#7275) --- .github/workflows/devnet-deploys.yml | 4 +++- l1-contracts/REDEPLOY | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index d90153229c7e..787a172f019a 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -35,7 +35,9 @@ jobs: runs-on: ${{ github.actor }}-x86 steps: - uses: actions/checkout@v4 - with: { ref: "${{ env.GIT_COMMIT }}" } + with: + ref: "${{ env.GIT_COMMIT }}" + fetch-depth: 0 - uses: ./.github/ci-setup-action with: concurrency_key: build-release-artifacts-${{ github.actor }} diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..5407c1d3c077 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +3 \ No newline at end of file From 0f7e6ec0fc5f30e5d5aabd852832ac49cfc9eb02 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 13:44:58 +0100 Subject: [PATCH 33/94] fix: typo (#7276) --- .github/workflows/devnet-deploys.yml | 2 +- l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 787a172f019a..4a5fbc1de1d2 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -102,7 +102,7 @@ jobs: deploy-l1-contracts -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ | tee ${{ env.FILE_PATH }} - ./.github/gstscripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} + ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - name: Apply l1-contracts Terraform if: steps.check_changes_release.outputs.result == 'true' diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 5407c1d3c077..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -3 \ No newline at end of file +1 \ No newline at end of file From d5740471cea322135400fb4fa5c75295671d1a54 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 2 Jul 2024 14:03:16 +0100 Subject: [PATCH 34/94] fix: input script's file_path (#7278) Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. --- .github/scripts/extract_l1_addresses.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/extract_l1_addresses.sh b/.github/scripts/extract_l1_addresses.sh index b0946446ffba..b23d5c4bcca8 100755 --- a/.github/scripts/extract_l1_addresses.sh +++ b/.github/scripts/extract_l1_addresses.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -FILE_PATH=./script_output +FILE_PATH=$1 # Read the file line by line while IFS= read -r line; do From 9c512c0b7e8fbc76b976bda024efcb85e586c0d4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 09:58:41 +0100 Subject: [PATCH 35/94] chore: redeploy l1 contracts (#7295) --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From b46079aa754aea0f01b1ee0094e1cc76d52e25a2 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 10:13:14 +0100 Subject: [PATCH 36/94] fix: docker run cmd (#7296) --- .github/workflows/devnet-deploys.yml | 2 +- l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 4a5fbc1de1d2..d7af7d58558d 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -98,7 +98,7 @@ jobs: if: steps.check_changes_release.outputs.result == 'true' run: | docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} - docker run -ti --rm aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ + docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ deploy-l1-contracts -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ | tee ${{ env.FILE_PATH }} diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From ea3102cca6d79e2d47b95a95be7610791148895a Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 11:28:22 +0100 Subject: [PATCH 37/94] fix: taint EFS on l1 redeploy (#7300) --- .github/workflows/devnet-deploys.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index d7af7d58558d..b0d0fb82b294 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -117,10 +117,16 @@ jobs: terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/p2p-bootstrap" terraform apply -input=false -auto-approve - - name: Deploy Aztec Nodes + - name: Taint node filesystem if L1 contracts are redeployed + if: steps.check_changes_release.outputs.result == 'true' working-directory: ./yarn-project/aztec/terraform/node run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" + terraform state list | grep 'aws_efs_file_system.node_data_store' | xargs -n1 terraform taint + + - name: Deploy Aztec Nodes + working-directory: ./yarn-project/aztec/terraform/node + run: | terraform apply -input=false -auto-approve - name: Deploy Provers From dbdb71ecbf1c5053ddd98c780a41c1115b8819a2 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 11:37:57 +0100 Subject: [PATCH 38/94] fix: master conflicts (#7303) --- .github/workflows/ci.yml | 2 +- .github/workflows/devnet-deploys.yml | 6 + .github/workflows/pull-noir.yml | 5 +- .noir-sync-commit | 2 +- .release-please-manifest.json | 8 +- .vscode/settings.json | 1 + CHANGELOG.md | 244 ++++++ CODEOWNERS | 5 +- avm-transpiler/Cargo.lock | 20 +- .../scripts/compile_then_transpile.sh | 2 +- avm-transpiler/src/main.rs | 27 +- avm-transpiler/src/opcodes.rs | 12 +- avm-transpiler/src/transpile.rs | 38 +- barretenberg/.gitrepo | 4 +- barretenberg/CHANGELOG.md | 62 ++ barretenberg/Earthfile | 2 +- .../flows/prove_then_verify_ultra_honk.sh | 2 +- barretenberg/acir_tests/reset_acir_tests.sh | 5 +- barretenberg/cpp/CMakeLists.txt | 2 +- barretenberg/cpp/pil/avm/constants.pil | 44 -- barretenberg/cpp/pil/avm/constants_gen.pil | 39 + barretenberg/cpp/pil/avm/constants_misc.pil | 2 + barretenberg/cpp/pil/avm/kernel.pil | 20 +- barretenberg/cpp/pil/avm/main.pil | 81 +- barretenberg/cpp/src/CMakeLists.txt | 1 + barretenberg/cpp/src/barretenberg/bb/main.cpp | 68 +- .../benchmark/goblin_bench/goblin.bench.cpp | 144 ---- .../commitment_schemes/verification_key.hpp | 4 +- .../zeromorph/zeromorph.hpp | 177 +++-- .../zeromorph/zeromorph.test.cpp | 28 +- .../CMakeLists.txt | 1 + .../zeromorph.test.cpp | 140 ++++ .../cpp/src/barretenberg/constants.hpp | 7 + .../dsl/acir_format/acir_format.cpp | 2 +- .../acir_format/honk_recursion_constraint.cpp | 88 ++- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 10 +- .../src/barretenberg/eccvm/eccvm_prover.cpp | 3 +- .../eccvm/eccvm_transcript.test.cpp | 4 +- .../src/barretenberg/eccvm/eccvm_verifier.cpp | 3 +- .../eccvm_recursive_verifier.cpp | 9 +- .../verifier_commitment_key.hpp | 5 +- .../cpp/src/barretenberg/flavor/flavor.hpp | 45 ++ .../src/barretenberg/goblin/mock_circuits.hpp | 35 - .../goblin/mock_circuits_pinning.test.cpp | 27 - .../library/grand_product_delta.hpp | 22 - .../cpp/src/barretenberg/polynomials/pow.hpp | 32 + .../protogalaxy/decider_verifier.cpp | 4 +- .../relations/generated/avm/alu.hpp | 406 +++++----- .../relations/generated/avm/binary.hpp | 28 +- .../relations/generated/avm/conversion.hpp | 2 +- .../relations/generated/avm/declare_views.hpp | 2 + .../relations/generated/avm/gas.hpp | 6 +- .../relations/generated/avm/keccakf1600.hpp | 2 +- .../relations/generated/avm/kernel.hpp | 62 +- .../relations/generated/avm/main.hpp | 721 +++++++++--------- .../relations/generated/avm/mem.hpp | 84 +- .../relations/generated/avm/pedersen.hpp | 2 +- .../relations/generated/avm/poseidon2.hpp | 2 +- .../relations/generated/avm/powers.hpp | 2 +- .../relations/generated/avm/sha256.hpp | 2 +- .../honk_recursion/transcript/transcript.hpp | 1 + .../verifier/decider_recursive_verifier.cpp | 3 +- .../protogalaxy_recursive_verifier.cpp | 5 +- .../verifier/ultra_recursive_verifier.cpp | 13 +- .../honk_recursion/verifier/verifier.test.cpp | 97 ++- .../stdlib/primitives/biggroup/biggroup.hpp | 4 + .../primitives/biggroup/biggroup.test.cpp | 2 + .../stdlib/primitives/curves/bn254.hpp | 1 + .../stdlib/primitives/curves/grumpkin.hpp | 2 +- .../stdlib/primitives/field/field.cpp | 13 + .../stdlib/primitives/field/field.hpp | 3 + .../stdlib_circuit_builders/mega_flavor.hpp | 38 +- .../stdlib_circuit_builders/ultra_flavor.hpp | 39 +- .../src/barretenberg/sumcheck/sumcheck.hpp | 40 +- .../barretenberg/sumcheck/sumcheck_round.hpp | 58 +- .../translator_vm/translator_prover.cpp | 3 +- .../translator_vm/translator_verifier.cpp | 3 +- .../translator_recursive_verifier.cpp | 5 +- .../ultra_honk/decider_prover.cpp | 3 +- .../ultra_honk/mega_transcript.test.cpp | 4 +- .../barretenberg/ultra_honk/oink_verifier.cpp | 3 - .../ultra_honk/ultra_transcript.test.cpp | 4 +- .../ultra_honk/ultra_verifier.cpp | 5 +- .../barretenberg/vm/avm_trace/avm_common.hpp | 2 + .../vm/avm_trace/avm_deserialization.cpp | 103 +-- .../vm/avm_trace/avm_execution.cpp | 115 +-- .../barretenberg/vm/avm_trace/avm_helper.cpp | 6 +- .../barretenberg/vm/avm_trace/avm_helper.hpp | 3 +- .../vm/avm_trace/avm_kernel_trace.cpp | 25 +- .../vm/avm_trace/avm_kernel_trace.hpp | 65 +- .../barretenberg/vm/avm_trace/avm_opcode.cpp | 12 +- .../barretenberg/vm/avm_trace/avm_opcode.hpp | 6 +- .../barretenberg/vm/avm_trace/avm_trace.cpp | 184 +++-- .../barretenberg/vm/avm_trace/avm_trace.hpp | 146 ++-- .../vm/avm_trace/aztec_constants.hpp | 39 +- .../barretenberg/vm/avm_trace/constants.hpp | 20 +- .../vm/generated/avm_circuit_builder.cpp | 28 +- .../vm/generated/avm_circuit_builder.hpp | 8 +- .../barretenberg/vm/generated/avm_flavor.hpp | 22 +- .../barretenberg/vm/generated/avm_prover.cpp | 8 +- .../vm/generated/avm_verifier.cpp | 20 +- .../vm/tests/avm_arithmetic.test.cpp | 193 +++-- .../vm/tests/avm_bitwise.test.cpp | 16 +- .../barretenberg/vm/tests/avm_cast.test.cpp | 47 +- .../vm/tests/avm_comparison.test.cpp | 31 +- .../vm/tests/avm_control_flow.test.cpp | 28 +- .../vm/tests/avm_execution.test.cpp | 290 +++---- .../barretenberg/vm/tests/avm_gas.test.cpp | 2 +- .../vm/tests/avm_indirect_mem.test.cpp | 8 +- .../vm/tests/avm_inter_table.test.cpp | 6 +- .../barretenberg/vm/tests/avm_kernel.test.cpp | 114 ++- .../vm/tests/avm_mem_opcodes.test.cpp | 30 +- .../barretenberg/vm/tests/avm_memory.test.cpp | 23 +- .../barretenberg/vm/tests/helpers.test.cpp | 12 +- .../barretenberg/vm/tests/helpers.test.hpp | 3 +- barretenberg/ts/CHANGELOG.md | 14 + barretenberg/ts/package.json | 2 +- .../bb-pil-backend/src/prover_builder.rs | 3 +- .../bb-pil-backend/src/relation_builder.rs | 21 +- .../bb-pil-backend/src/verifier_builder.rs | 4 +- boxes/boxes/react/package.json | 2 +- boxes/boxes/vanilla/package.json | 2 +- .../functions/function_types_macros.md | 56 -- .../smart_contracts/functions/index.md | 5 +- .../functions/inner_workings.md | 278 ++++++- .../concepts/smart_contracts/oracles/index.md | 2 +- docs/docs/guides/js_apps/authwit.md | 9 +- .../writing_contracts/authwit.md | 4 +- .../storage/storage_slots.md | 2 +- docs/docs/migration_notes.md | 6 +- .../circuits/private-function.md | 6 +- .../circuits/private-kernel-initial.mdx | 10 +- .../circuits/private-kernel-reset.md | 6 +- .../circuits/private-kernel-tail.md | 4 +- docs/docs/protocol-specs/constants.md | 12 +- .../published-data.md | 18 +- .../gas-and-fees/kernel-tracking.md | 18 +- .../l1-smart-contracts/index.md | 10 +- docs/docs/protocol-specs/logs/index.md | 150 +--- .../public-vm/_nested-context.md | 7 +- .../docs/protocol-specs/public-vm/context.mdx | 12 +- .../protocol-specs/public-vm/execution.md | 8 +- .../public-vm/gen/_instruction-set.mdx | 175 +++-- docs/docs/protocol-specs/public-vm/intro.md | 5 + docs/docs/protocol-specs/public-vm/state.md | 4 +- .../protocol-specs/rollup-circuits/index.md | 10 +- .../rollup-circuits/merge-rollup.md | 7 +- .../rollup-circuits/root-rollup.md | 7 +- .../state/tree-implementations.md | 6 + docs/docs/protocol-specs/state/wonky-tree.md | 422 ++++++++++ .../protocol-specs/transactions/tx-object.md | 6 +- .../history_lib_reference.md | 164 ++-- .../smart_contract_reference/macros.md | 19 + .../token_bridge/4_typescript_glue_code.md | 29 +- docs/sidebars.js | 1 + docs/src/katex-macros.js | 151 ++-- .../InstructionSet/InstructionSet.js | 114 ++- l1-contracts/src/core/Rollup.sol | 9 +- .../core/interfaces/messagebridge/IOutbox.sol | 2 +- .../src/core/libraries/ConstantsGen.sol | 62 +- l1-contracts/src/core/libraries/Errors.sol | 3 +- l1-contracts/src/core/libraries/HeaderLib.sol | 8 +- l1-contracts/src/core/libraries/MerkleLib.sol | 60 ++ .../core/libraries/decoders/TxsDecoder.sol | 50 +- .../src/core/messagebridge/Outbox.sol | 33 +- l1-contracts/test/Rollup.t.sol | 6 +- l1-contracts/test/decoders/Base.sol | 2 +- l1-contracts/test/decoders/Decoders.t.sol | 26 +- .../decoders/helpers/TxsDecoderHelper.sol | 9 + l1-contracts/test/fixtures/empty_block_0.json | 12 +- l1-contracts/test/fixtures/empty_block_1.json | 16 +- l1-contracts/test/fixtures/mixed_block_0.json | 12 +- l1-contracts/test/fixtures/mixed_block_1.json | 16 +- .../test/merkle/UnbalancedMerkle.t.sol | 199 +++++ noir-projects/Dockerfile | 2 +- noir-projects/Dockerfile.test | 12 +- noir-projects/Earthfile | 13 +- noir-projects/aztec-nr/.gitrepo | 4 +- noir-projects/aztec-nr/authwit/src/account.nr | 29 +- noir-projects/aztec-nr/authwit/src/auth.nr | 282 ++++++- .../aztec-nr/authwit/src/auth_witness.nr | 6 + .../aztec-nr/authwit/src/cheatcodes.nr | 6 +- .../src/{entrypoint.nr => entrypoint/mod.nr} | 0 .../context/{globals.nr => globals/mod.nr} | 0 .../src/context/{inputs.nr => inputs/mod.nr} | 0 .../context/inputs/public_context_inputs.nr | 2 - .../aztec/src/{context.nr => context/mod.nr} | 0 .../aztec/src/context/private_context.nr | 104 +-- .../aztec/src/context/public_context.nr | 150 ++-- .../src/context/unconstrained_context.nr | 13 +- .../encrypted_event_emission.nr | 115 ++- .../encrypted_logs/encrypted_note_emission.nr | 66 +- .../aztec/src/encrypted_logs/header.nr | 2 +- .../aztec/src/encrypted_logs/incoming_body.nr | 2 +- .../mod.nr} | 0 .../aztec/src/encrypted_logs/outgoing_body.nr | 3 +- .../aztec/src/encrypted_logs/payload.nr | 2 +- .../aztec/src/{event.nr => event/mod.nr} | 0 .../aztec/src/history/contract_inclusion.nr | 2 + .../aztec/src/{history.nr => history/mod.nr} | 0 .../aztec/src/history/note_inclusion.nr | 2 +- .../aztec/src/history/nullifier_inclusion.nr | 4 +- .../src/history/nullifier_non_inclusion.nr | 4 +- .../aztec/src/history/public_storage.nr | 2 +- .../aztec-nr/aztec/src/initializer.nr | 4 +- .../aztec/src/{keys.nr => keys/mod.nr} | 0 .../aztec/src/keys/point_to_symmetric_key.nr | 2 +- .../aztec-nr/aztec/src/keys/public_keys.nr | 46 +- noir-projects/aztec-nr/aztec/src/lib.nr | 2 +- noir-projects/aztec-nr/aztec/src/messaging.nr | 2 +- .../aztec-nr/aztec/src/note/lifecycle.nr | 6 +- .../aztec/src/{note.nr => note/mod.nr} | 0 .../{note_getter.nr => note_getter/mod.nr} | 8 +- .../aztec/src/note/note_getter/test.nr | 2 - .../aztec/src/note/note_getter_options.nr | 2 +- .../aztec/src/note/note_viewer_options.nr | 2 +- .../oracle/enqueue_public_function_call.nr | 8 +- .../aztec/src/oracle/get_contract_instance.nr | 2 +- .../aztec-nr/aztec/src/oracle/header.nr | 2 +- .../aztec-nr/aztec/src/oracle/logs_traits.nr | 24 + .../aztec/src/{oracle.nr => oracle/mod.nr} | 0 .../aztec-nr/aztec/src/oracle/storage.nr | 60 +- .../aztec-nr/aztec/src/public_storage.nr | 72 -- .../src/{state_vars.nr => state_vars/mod.nr} | 0 .../aztec/src/state_vars/private_immutable.nr | 2 +- .../aztec/src/state_vars/private_mutable.nr | 2 +- .../src/state_vars/private_mutable/test.nr | 8 +- .../aztec/src/state_vars/public_immutable.nr | 28 +- .../aztec/src/state_vars/public_mutable.nr | 15 +- .../aztec/src/state_vars/shared_immutable.nr | 27 +- .../shared_mutable/scheduled_delay_change.nr | 8 +- .../scheduled_delay_change/test.nr | 1 + .../shared_mutable/scheduled_value_change.nr | 8 +- .../scheduled_value_change/test.nr | 1 + .../shared_mutable/shared_mutable.nr | 176 +++-- .../shared_mutable_private_getter.nr | 51 +- .../src/state_vars/shared_mutable/test.nr | 560 +++++++------- .../aztec/src/test/helpers/cheatcodes.nr | 13 + .../src/test/{helpers.nr => helpers/mod.nr} | 0 .../src/test/helpers/test_environment.nr | 12 +- .../aztec-nr/aztec/src/test/helpers/utils.nr | 8 +- .../aztec/src/test/{mocks.nr => mocks/mod.nr} | 0 .../aztec/src/{test.nr => test/mod.nr} | 0 .../aztec/src/unencrypted_logs/mod.nr | 1 + .../unencrypted_event_emission.nr | 58 ++ .../aztec/src/{utils.nr => utils/mod.nr} | 2 +- noir-projects/noir-contracts/Nargo.toml | 2 + noir-projects/noir-contracts/bootstrap.sh | 2 +- .../app_subscription_contract/src/main.nr | 10 +- .../auth_registry_contract/src/main.nr | 4 +- .../contracts/avm_test_contract/src/main.nr | 49 +- .../contracts/card_game_contract/src/cards.nr | 2 - .../contracts/claim_contract/src/main.nr | 2 +- .../src/{events.nr => events/mod.nr} | 0 .../src/main.nr | 31 +- .../src/events.nr | 1 - .../src/events/instance_deployed.nr | 33 - .../src/main.nr | 62 +- .../crowdfunding_contract/src/main.nr | 16 +- .../easy_private_voting_contract/src/main.nr | 4 +- .../inclusion_proofs_contract/src/main.nr | 12 +- .../key_registry_contract/src/main.nr | 26 +- .../pending_note_hashes_contract/src/main.nr | 6 +- .../contracts/private_fpc_contract/Nargo.toml | 10 + .../contracts/private_fpc_contract/src/lib.nr | 16 + .../private_fpc_contract/src/main.nr | 39 + .../private_token_contract/Nargo.toml | 10 + .../private_token_contract/src/main.nr | 239 ++++++ .../private_token_contract/src/test.nr | 2 + .../private_token_contract/src/test/basic.nr | 98 +++ .../private_token_contract/src/test/utils.nr | 70 ++ .../private_token_contract/src/types.nr | 2 + .../src/types/balances_map.nr | 132 ++++ .../src/types/token_note.nr | 251 ++++++ .../schnorr_account_contract/src/main.nr | 4 +- .../src/util.nr | 2 +- .../contracts/test_contract/src/main.nr | 29 +- .../contracts/test_log_contract/src/main.nr | 42 +- .../src/{types.nr => types/mod.nr} | 0 .../src/types/roles.nr | 6 + .../contracts/token_contract/src/main.nr | 23 +- .../token_contract/src/test/utils.nr | 5 +- .../contracts/uniswap_contract/src/main.nr | 6 +- .../noir-contracts/scripts/flamegraph.sh | 14 +- .../noir-protocol-circuits/bootstrap.sh | 2 +- .../parity-lib/src/{base.nr => base/mod.nr} | 0 .../parity-lib/src/{root.nr => root/mod.nr} | 0 .../parity-lib/src/root/root_parity_input.nr | 2 +- .../src/root/root_rollup_parity_input.nr | 2 +- .../parity-lib/src/{utils.nr => utils/mod.nr} | 0 .../kernel_circuit_public_inputs_composer.nr | 255 ------- .../src/{components.nr => components/mod.nr} | 7 +- .../components/previous_kernel_validator.nr | 16 +- .../components/private_call_data_validator.nr | 88 +-- .../find_first_revertible_item_index.nr | 97 +++ .../validate_split_ranges.nr | 184 +++++ ...private_kernel_circuit_output_validator.nr | 52 +- ...e_kernel_circuit_public_inputs_composer.nr | 112 ++- .../src/components/tail_output_composer.nr | 69 ++ ..._validator.nr => tail_output_validator.nr} | 88 +-- .../kernel_circuit_output_hints.nr | 38 +- .../validate_value_transformation.nr | 23 + .../tail_to_public_output_composer.nr | 42 + .../meter_gas_used.nr | 35 + .../split_to_public.nr | 111 +++ .../tail_to_public_output_validator.nr | 194 +++++ .../tail_to_public_output_hints.nr | 123 +++ .../src/private_kernel_empty.nr | 2 +- .../src/private_kernel_init.nr | 24 +- .../src/private_kernel_inner.nr | 18 +- .../src/private_kernel_reset.nr | 151 ++-- .../src/private_kernel_tail.nr | 215 ++---- .../src/private_kernel_tail_to_public.nr | 243 ++---- .../crates/private-kernel-lib/src/tests.nr | 4 - ...kernel_circuit_output_validator_builder.nr | 34 - .../utils.nr | 6 - ...alidate_propagated_sorted_siloed_values.nr | 116 --- .../private-kernel-lib/src/tests/mod.nr | 8 + .../previous_kernel_validator_builder.nr | 21 + .../mod.nr} | 7 +- .../validate_arrays.nr | 12 +- .../validate_as_first_call.nr | 46 +- .../validate_call.nr | 12 +- .../validate_counters.nr | 30 +- .../validate_note_logs.nr | 6 +- .../mod.nr} | 10 +- .../validate_initial_values.nr | 4 +- ...alidate_propagated_from_previous_kernel.nr | 42 +- .../validate_propagated_from_private_call.nr | 72 +- .../mod.nr} | 23 +- ..._from_previous_kernel_with_private_call.nr | 84 +- .../new_from_tx_request.nr | 4 +- .../propagate_from_private_call.nr | 52 +- .../src/tests/tail_output_composer_builder.nr | 28 + .../tail_output_validator_builder/mod.nr | 28 + .../validate_accumulated_values.nr | 21 +- .../validate_empty_values.nr | 8 +- ...alidate_propagated_sorted_siloed_values.nr | 117 +++ .../validate_propagated_values.nr | 14 +- .../tail_to_public_output_composer_builder.nr | 33 + .../meter_gas_used.nr | 79 ++ .../split_to_public.nr | 108 +++ .../tail_to_public_output_composer.nr | 144 ++++ ...tail_to_public_output_validator_builder.nr | 27 + .../crates/public-kernel-lib/src/common.nr | 139 ++-- .../src/public_kernel_app_logic.nr | 48 +- .../src/public_kernel_setup.nr | 5 +- .../src/public_kernel_tail.nr | 28 +- .../src/public_kernel_teardown.nr | 5 +- ...llifier_non_existent_read_request_reset.nr | 6 +- .../private_validation_request_processor.nr | 6 +- .../public_validation_request_processor.nr | 6 +- .../src/{reset.nr => reset/mod.nr} | 0 .../src/{tests.nr => tests/mod.nr} | 0 ...non_existent_read_request_hints_builder.nr | 17 +- .../base_or_merge_rollup_public_inputs.nr | 12 +- .../src/abis/constant_rollup_data.nr | 1 - .../rollup-lib/src/{abis.nr => abis/mod.nr} | 0 .../src/abis/previous_rollup_data.nr | 2 +- .../rollup-lib/src/base/base_rollup_inputs.nr | 136 ++-- .../rollup-lib/src/{base.nr => base/mod.nr} | 0 .../rollup-lib/src/base/state_diff_hints.nr | 13 +- .../crates/rollup-lib/src/components.nr | 81 +- .../src/merge/merge_rollup_inputs.nr | 53 +- .../rollup-lib/src/{merge.nr => merge/mod.nr} | 0 .../rollup-lib/src/{root.nr => root/mod.nr} | 0 .../rollup-lib/src/root/root_rollup_inputs.nr | 21 +- .../rollup-lib/src/{tests.nr => tests/mod.nr} | 0 .../src/tests/previous_rollup_data.nr | 4 +- .../src/tests/root_rollup_inputs.nr | 8 +- .../combined_accumulated_data.nr | 47 +- .../private_accumulated_data.nr | 40 +- .../private_accumulated_data_builder.nr | 447 +---------- .../public_accumulated_data.nr | 38 +- .../public_accumulated_data_builder.nr | 22 +- .../src/abis/append_only_tree_snapshot.nr | 2 - .../crates/types/src/abis/call_request.nr | 13 +- .../crates/types/src/abis/caller_context.nr | 1 - .../contract_class_function_leaf_preimage.nr | 2 +- .../crates/types/src/abis/event_selector.nr | 3 +- .../types/src/abis/function_selector.nr | 3 +- .../crates/types/src/abis/gas.nr | 2 +- .../crates/types/src/abis/global_variables.nr | 1 - .../private_kernel_circuit_public_inputs.nr | 24 +- ...te_kernel_circuit_public_inputs_builder.nr | 50 +- .../crates/types/src/abis/kernel_data.nr | 2 +- .../crates/types/src/abis/log_hash.nr | 8 + .../crates/types/src/{abis.nr => abis/mod.nr} | 0 .../crates/types/src/abis/note_hash.nr | 1 - .../types/src/abis/nullifier_leaf_preimage.nr | 2 +- .../types/src/abis/private_call_request.nr | 1 - .../types/src/abis/private_call_stack_item.nr | 2 +- .../src/abis/private_circuit_public_inputs.nr | 54 +- .../abis/private_kernel/private_call_data.nr | 2 +- .../types/src/abis/private_kernel_data.nr | 2 +- .../types/src/abis/public_call_stack_item.nr | 10 +- .../src/abis/public_circuit_public_inputs.nr | 36 +- .../crates/types/src/abis/public_data_read.nr | 3 +- .../src/abis/public_data_update_request.nr | 3 +- .../types/src/abis/public_kernel_data.nr | 2 +- .../crates/types/src/abis/read_request.nr | 1 - .../crates/types/src/abis/side_effect.nr | 1 - .../key_validation_request.nr | 1 - .../key_validation_request_and_generator.nr | 1 - ...ed_key_validation_request_and_generator.nr | 1 - .../types/src/{address.nr => address/mod.nr} | 0 .../crates/types/src/constants.nr | 82 +- .../crates/types/src/content_commitment.nr | 12 +- .../crates/types/src/contract_class_id.nr | 2 +- .../src/{contrakt.nr => contrakt/mod.nr} | 0 .../src/contrakt/storage_update_request.nr | 1 - .../crates/types/src/data/hash.nr | 2 +- .../crates/types/src/{data.nr => data/mod.nr} | 0 .../crates/types/src/grumpkin_point.nr | 12 +- .../crates/types/src/grumpkin_private_key.nr | 2 +- .../crates/types/src/hash.nr | 24 +- .../types/src/merkle_tree/membership.nr | 2 +- .../types/src/merkle_tree/merkle_tree.nr | 4 +- .../{merkle_tree.nr => merkle_tree/mod.nr} | 0 .../src/{messaging.nr => messaging/mod.nr} | 0 .../crates/types/src/public_data_tree_leaf.nr | 1 - .../src/public_data_tree_leaf_preimage.nr | 2 +- .../src/{recursion.nr => recursion/mod.nr} | 0 .../types/src/{storage.nr => storage/mod.nr} | 0 .../crates/types/src/tests/fixture_builder.nr | 174 +++-- .../types/src/tests/merkle_tree_utils.nr | 24 +- .../types/src/{tests.nr => tests/mod.nr} | 0 .../public_circuit_public_inputs_builder.nr | 20 +- .../crates/types/src/tests/sort.nr | 72 +- .../crates/types/src/tests/utils.nr | 9 +- .../crates/types/src/traits.nr | 1 - .../{transaction.nr => transaction/mod.nr} | 0 .../crates/types/src/utils/arrays.nr | 8 +- .../assert_sorted_transformed_value_array.nr | 3 +- ...t_split_sorted_transformed_value_arrays.nr | 543 +++++++++++++ .../src/utils/arrays/sort_by_counters.nr | 6 +- .../src/utils/arrays/sort_get_order_hints.nr | 4 +- .../src/utils/arrays/sort_get_sorted_hints.nr | 62 ++ .../src/utils/arrays/sort_get_sorted_tuple.nr | 2 +- .../arrays/sort_get_split_order_hints.nr | 279 +++++++ .../types/src/{utils.nr => utils/mod.nr} | 0 .../scripts/flamegraph.sh | 81 ++ noir/bb-version | 2 +- noir/noir-repo/.release-please-manifest.json | 4 +- noir/noir-repo/CHANGELOG.md | 92 +++ noir/noir-repo/Cargo.lock | 120 ++- noir/noir-repo/Cargo.toml | 22 +- noir/noir-repo/acvm-repo/CHANGELOG.md | 148 ++++ noir/noir-repo/acvm-repo/acir/Cargo.toml | 2 +- .../acir/src/circuit/black_box_functions.rs | 45 +- .../opcodes/black_box_function_call.rs | 24 +- .../acir/tests/test_program_serialization.rs | 27 - .../noir-repo/acvm-repo/acir_field/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/acvm/Cargo.toml | 2 +- .../acvm/src/compiler/transformers/csat.rs | 38 +- .../acvm-repo/acvm/src/pwg/blackbox/mod.rs | 4 +- noir/noir-repo/acvm-repo/acvm_js/Cargo.toml | 2 +- noir/noir-repo/acvm-repo/acvm_js/package.json | 2 +- .../test/browser/execute_circuit.test.ts | 10 - .../acvm_js/test/node/execute_circuit.test.ts | 30 - .../acvm-repo/acvm_js/test/shared/pedersen.ts | 13 - .../acvm-repo/blackbox_solver/Cargo.toml | 2 +- .../src/curve_specific_solver.rs | 1 + .../bn254_blackbox_solver/Cargo.toml | 2 +- .../benches/criterion.rs | 18 +- .../src/generator/generators.rs | 2 +- .../bn254_blackbox_solver/src/lib.rs | 13 +- noir/noir-repo/acvm-repo/brillig/Cargo.toml | 2 +- .../acvm-repo/brillig/src/black_box.rs | 4 +- .../noir-repo/acvm-repo/brillig_vm/Cargo.toml | 2 +- .../acvm-repo/brillig_vm/src/black_box.rs | 89 ++- .../noir-repo/acvm-repo/brillig_vm/src/lib.rs | 161 ++-- ...te_note_hash_and_optionally_a_nullifier.rs | 8 +- .../src/transforms/contract_interface.rs | 19 +- .../src/transforms/note_interface.rs | 17 +- .../aztec_macros/src/transforms/storage.rs | 6 +- .../aztec_macros/src/utils/ast_utils.rs | 9 +- noir/noir-repo/compiler/fm/Cargo.toml | 1 - noir/noir-repo/compiler/fm/src/lib.rs | 47 +- .../circuits/assert_lt/src/main.nr | 3 - .../circuits/recursion/src/main.nr | 2 - .../compiler/noirc_driver/src/abi_gen.rs | 106 ++- .../compiler/noirc_driver/src/lib.rs | 31 +- .../noirc_driver/tests/stdlib_warnings.rs | 2 +- .../compiler/noirc_errors/src/reporter.rs | 6 +- .../compiler/noirc_evaluator/Cargo.toml | 1 + .../src/brillig/brillig_gen.rs | 7 +- .../brillig/brillig_gen/brillig_black_box.rs | 54 +- .../src/brillig/brillig_gen/brillig_block.rs | 191 ++++- .../brillig_gen/brillig_block_variables.rs | 13 +- .../brillig/brillig_gen/brillig_directive.rs | 15 +- .../src/brillig/brillig_gen/brillig_fn.rs | 2 +- .../brillig/brillig_gen/brillig_slice_ops.rs | 4 +- .../noirc_evaluator/src/brillig/brillig_ir.rs | 32 +- .../src/brillig/brillig_ir/artifact.rs | 26 +- .../src/brillig/brillig_ir/codegen_binary.rs | 8 +- .../src/brillig/brillig_ir/codegen_calls.rs | 7 +- .../brillig_ir/codegen_control_flow.rs | 55 +- .../brillig/brillig_ir/codegen_intrinsic.rs | 12 +- .../src/brillig/brillig_ir/codegen_memory.rs | 5 +- .../src/brillig/brillig_ir/codegen_stack.rs | 6 +- .../src/brillig/brillig_ir/debug_show.rs | 8 +- .../src/brillig/brillig_ir/entry_point.rs | 46 +- .../src/brillig/brillig_ir/instructions.rs | 38 +- .../src/brillig/brillig_ir/registers.rs | 2 +- .../noirc_evaluator/src/brillig/mod.rs | 11 +- .../compiler/noirc_evaluator/src/errors.rs | 9 + .../compiler/noirc_evaluator/src/ssa.rs | 108 +-- .../src/ssa/acir_gen/acir_ir/acir_variable.rs | 239 +++--- .../src/ssa/acir_gen/acir_ir/big_int.rs | 16 +- .../ssa/acir_gen/acir_ir/generated_acir.rs | 71 +- .../noirc_evaluator/src/ssa/acir_gen/mod.rs | 35 +- .../noirc_evaluator/src/ssa/ir/dfg.rs | 17 +- .../src/ssa/ir/function_inserter.rs | 18 +- .../noirc_evaluator/src/ssa/ir/instruction.rs | 16 +- .../src/ssa/ir/instruction/call.rs | 73 +- .../src/ssa/opt/assert_constant.rs | 39 +- .../src/ssa/opt/flatten_cfg.rs | 106 +-- .../src/ssa/opt/flatten_cfg/value_merger.rs | 2 +- .../src/ssa/opt/remove_enable_side_effects.rs | 4 +- .../src/ssa/opt/remove_if_else.rs | 4 +- .../compiler/noirc_frontend/Cargo.toml | 1 - .../noirc_frontend/src/ast/expression.rs | 152 +++- .../compiler/noirc_frontend/src/ast/mod.rs | 28 +- .../noirc_frontend/src/ast/statement.rs | 7 +- .../noirc_frontend/src/ast/structure.rs | 2 +- .../compiler/noirc_frontend/src/ast/traits.rs | 5 +- .../compiler/noirc_frontend/src/debug/mod.rs | 6 +- .../src/elaborator/expressions.rs | 119 ++- .../noirc_frontend/src/elaborator/lints.rs | 17 +- .../noirc_frontend/src/elaborator/mod.rs | 556 +++++++++++--- .../noirc_frontend/src/elaborator/patterns.rs | 27 +- .../src/elaborator/statements.rs | 8 +- .../noirc_frontend/src/elaborator/traits.rs | 30 +- .../noirc_frontend/src/elaborator/types.rs | 198 +++-- .../noirc_frontend/src/elaborator/unquote.rs | 41 + .../noirc_frontend/src/hir/comptime/errors.rs | 58 +- .../src/hir/comptime/interpreter.rs | 148 ++-- .../src/hir/comptime/interpreter/builtin.rs | 158 ++++ .../src/hir/comptime/interpreter/unquote.rs | 42 + .../noirc_frontend/src/hir/comptime/scan.rs | 4 +- .../noirc_frontend/src/hir/comptime/tests.rs | 50 +- .../noirc_frontend/src/hir/comptime/value.rs | 84 +- .../src/hir/def_collector/dc_crate.rs | 37 +- .../src/hir/def_collector/dc_mod.rs | 447 +++++++---- .../src/hir/def_collector/errors.rs | 31 +- .../noirc_frontend/src/hir/def_map/mod.rs | 4 +- .../compiler/noirc_frontend/src/hir/mod.rs | 40 +- .../src/hir/resolution/errors.rs | 78 +- .../src/hir/resolution/functions.rs | 9 +- .../src/hir/resolution/import.rs | 40 +- .../src/hir/resolution/resolver.rs | 160 ++-- .../src/hir/resolution/traits.rs | 42 +- .../src/hir/type_check/errors.rs | 16 + .../noirc_frontend/src/hir/type_check/expr.rs | 12 +- .../noirc_frontend/src/hir/type_check/mod.rs | 23 +- .../noirc_frontend/src/hir_def/expr.rs | 5 +- .../noirc_frontend/src/hir_def/function.rs | 8 +- .../noirc_frontend/src/hir_def/types.rs | 337 +++++++- .../noirc_frontend/src/lexer/errors.rs | 20 + .../noirc_frontend/src/lexer/lexer.rs | 148 +++- .../noirc_frontend/src/lexer/token.rs | 79 +- .../src/monomorphization/errors.rs | 3 + .../src/monomorphization/mod.rs | 30 +- .../noirc_frontend/src/node_interner.rs | 84 +- .../noirc_frontend/src/noir_parser.lalrpop | 3 +- .../noirc_frontend/src/parser/errors.rs | 2 +- .../compiler/noirc_frontend/src/parser/mod.rs | 8 +- .../noirc_frontend/src/parser/parser.rs | 358 +++------ .../src/parser/parser/function.rs | 34 +- .../src/parser/parser/literals.rs | 12 +- .../noirc_frontend/src/parser/parser/path.rs | 9 +- .../src/parser/parser/primitives.rs | 7 + .../noirc_frontend/src/parser/parser/types.rs | 186 ++++- .../compiler/noirc_frontend/src/tests.rs | 468 +++++++++++- noir/noir-repo/compiler/wasm/Cargo.toml | 1 + noir/noir-repo/compiler/wasm/package.json | 2 +- noir/noir-repo/compiler/wasm/src/compile.rs | 6 +- .../wasm/test/fixtures/deps/lib-a/src/lib.nr | 2 +- .../fixtures/deps/lib-c/src/module/foo.nr | 2 +- .../test/fixtures/noir-contract/src/main.nr | 2 +- .../wasm/test/fixtures/with-deps/src/main.nr | 2 +- noir/noir-repo/cspell.json | 1 + noir/noir-repo/deny.toml | 2 +- .../docs/docs/how_to/how-to-oracles.md | 8 +- .../docs/docs/how_to/merkle-proof.mdx | 1 - .../docs/docs/noir/concepts/assert.md | 39 +- .../docs/noir/concepts/data_types/arrays.md | 6 +- .../docs/noir/concepts/data_types/booleans.md | 4 +- .../docs/noir/concepts/data_types/index.md | 8 + .../docs/noir/concepts/data_types/integers.md | 1 - .../docs/noir/concepts/data_types/slices.mdx | 109 ++- .../docs/noir/concepts/data_types/strings.md | 3 +- .../docs/docs/noir/concepts/generics.md | 4 +- .../docs/docs/noir/concepts/traits.md | 22 +- .../docs/docs/noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 16 +- .../noir/modules_packages_crates/modules.md | 46 ++ .../noir/standard_library/black_box_fns.md | 2 +- .../standard_library/containers/boundedvec.md | 52 +- .../standard_library/containers/hashmap.md | 2 +- .../noir/standard_library/containers/vec.mdx | 19 + .../cryptographic_primitives/ec_primitives.md | 2 +- .../cryptographic_primitives/eddsa.mdx | 2 +- .../docs/noir/standard_library/recursion.md | 9 +- noir/noir-repo/docs/docs/tooling/debugger.md | 2 +- noir/noir-repo/docs/docs/tooling/testing.md | 21 +- noir/noir-repo/docs/docusaurus.config.ts | 1 + .../docs/src/components/Notes/_blackbox.mdx | 4 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.17.0/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.17.0/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 20 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.0/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.0/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.1/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.1/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.2/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.2/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.3/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.3/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../getting_started/01_hello_world.md | 4 +- .../getting_started/02_breakdown.md | 4 +- .../versioned_docs/version-v0.19.4/index.md | 4 +- .../data_types/02_booleans.md | 4 +- .../data_types/03_strings.md | 2 +- .../language_concepts/data_types/04_arrays.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../version-v0.19.4/nargo/01_commands.md | 2 +- .../standard_library/black_box_fns.md | 22 +- .../standard_library/recursion.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 22 +- .../noir/standard_library/recursion.md | 2 +- .../noir/syntax/data_types/arrays.md | 2 +- .../noir/syntax/data_types/booleans.md | 4 +- .../noir/syntax/data_types/strings.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.23.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 20 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.24.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.25.0/noir/concepts/generics.md | 4 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.26.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.27.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.28.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.28.0/tooling/debugger.md | 2 +- .../version-v0.28.0/tutorials/noirjs_app.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.29.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.29.0/tooling/debugger.md | 2 +- .../version-v0.29.0/tutorials/noirjs_app.md | 2 +- .../noir/concepts/data_types/arrays.md | 4 +- .../noir/concepts/data_types/booleans.md | 4 +- .../noir/concepts/data_types/strings.md | 2 +- .../version-v0.30.0/noir/concepts/generics.md | 4 +- .../noir/concepts/unconstrained.md | 2 +- .../modules_packages_crates/dependencies.md | 4 +- .../noir/standard_library/black_box_fns.md | 2 +- .../noir/standard_library/recursion.md | 2 +- .../version-v0.30.0/tooling/debugger.md | 2 +- .../explainers/explainer-oracle.md | 57 ++ .../explainers/explainer-recursion.md | 176 +++++ .../getting_started/_category_.json | 5 + .../barretenberg/_category_.json | 6 + .../getting_started/barretenberg/index.md | 47 ++ .../hello_noir/_category_.json | 5 + .../getting_started/hello_noir/index.md | 145 ++++ .../hello_noir/project_breakdown.md | 159 ++++ .../installation/_category_.json | 6 + .../getting_started/installation/index.md | 48 ++ .../installation/other_install_methods.md | 102 +++ .../getting_started/tooling/noir_codegen.md | 114 +++ .../version-v0.31.0/how_to/_category_.json | 5 + .../how_to/debugger/_category_.json | 6 + .../debugger/debugging_with_the_repl.md | 164 ++++ .../how_to/debugger/debugging_with_vs_code.md | 68 ++ .../version-v0.31.0/how_to/how-to-oracles.md | 273 +++++++ .../how_to/how-to-recursion.md | 180 +++++ .../how_to/how-to-solidity-verifier.md | 251 ++++++ .../version-v0.31.0/how_to/merkle-proof.mdx | 48 ++ .../how_to/using-devcontainers.mdx | 110 +++ .../versioned_docs/version-v0.31.0/index.mdx | 67 ++ .../version-v0.31.0/migration_notes.md | 105 +++ .../noir/concepts/_category_.json | 6 + .../version-v0.31.0/noir/concepts/assert.md | 45 ++ .../version-v0.31.0/noir/concepts/comments.md | 33 + .../noir/concepts/control_flow.md | 77 ++ .../version-v0.31.0/noir/concepts/data_bus.md | 21 + .../noir/concepts/data_types/_category_.json | 5 + .../noir/concepts/data_types/arrays.md | 253 ++++++ .../noir/concepts/data_types/booleans.md | 28 + .../noir/concepts/data_types/fields.md | 192 +++++ .../concepts/data_types/function_types.md | 26 + .../noir/concepts/data_types/index.md | 110 +++ .../noir/concepts/data_types/integers.md | 156 ++++ .../noir/concepts/data_types/references.md | 23 + .../noir/concepts/data_types/slices.mdx | 193 +++++ .../noir/concepts/data_types/strings.md | 79 ++ .../noir/concepts/data_types/structs.md | 70 ++ .../noir/concepts/data_types/tuples.md | 48 ++ .../noir/concepts/functions.md | 226 ++++++ .../version-v0.31.0/noir/concepts/generics.md | 106 +++ .../version-v0.31.0/noir/concepts/globals.md | 72 ++ .../version-v0.31.0/noir/concepts/lambdas.md | 81 ++ .../noir/concepts/mutability.md | 121 +++ .../version-v0.31.0/noir/concepts/ops.md | 98 +++ .../version-v0.31.0/noir/concepts/oracles.md | 31 + .../noir/concepts/shadowing.md | 44 ++ .../version-v0.31.0/noir/concepts/traits.md | 389 ++++++++++ .../noir/concepts/unconstrained.md | 99 +++ .../modules_packages_crates/_category_.json | 6 + .../crates_and_packages.md | 43 ++ .../modules_packages_crates/dependencies.md | 124 +++ .../noir/modules_packages_crates/modules.md | 105 +++ .../modules_packages_crates/workspaces.md | 42 + .../noir/standard_library/_category_.json | 6 + .../noir/standard_library/bigint.md | 122 +++ .../noir/standard_library/black_box_fns.md | 32 + .../noir/standard_library/bn254.md | 46 ++ .../standard_library/containers/boundedvec.md | 419 ++++++++++ .../standard_library/containers/hashmap.md | 570 ++++++++++++++ .../noir/standard_library/containers/index.md | 5 + .../noir/standard_library/containers/vec.mdx | 170 +++++ .../cryptographic_primitives/_category_.json | 5 + .../cryptographic_primitives/ciphers.mdx | 32 + .../cryptographic_primitives/ec_primitives.md | 102 +++ .../ecdsa_sig_verification.mdx | 98 +++ .../cryptographic_primitives/eddsa.mdx | 37 + .../embedded_curve_ops.mdx | 98 +++ .../cryptographic_primitives/hashes.mdx | 246 ++++++ .../cryptographic_primitives/index.md | 14 + .../cryptographic_primitives/schnorr.mdx | 64 ++ .../noir/standard_library/is_unconstrained.md | 59 ++ .../noir/standard_library/logging.md | 78 ++ .../noir/standard_library/merkle_trees.md | 58 ++ .../noir/standard_library/options.md | 101 +++ .../noir/standard_library/recursion.md | 85 +++ .../noir/standard_library/traits.md | 464 +++++++++++ .../noir/standard_library/zeroed.md | 26 + .../NoirJS/backend_barretenberg/.nojekyll | 1 + .../classes/BarretenbergBackend.md | 160 ++++ .../classes/BarretenbergVerifier.md | 58 ++ .../NoirJS/backend_barretenberg/index.md | 40 + .../type-aliases/BackendOptions.md | 21 + .../backend_barretenberg/typedoc-sidebar.cjs | 4 + .../reference/NoirJS/noir_js/.nojekyll | 1 + .../reference/NoirJS/noir_js/classes/Noir.md | 52 ++ .../reference/NoirJS/noir_js/functions/and.md | 22 + .../NoirJS/noir_js/functions/blake2s256.md | 21 + .../functions/ecdsa_secp256k1_verify.md | 28 + .../functions/ecdsa_secp256r1_verify.md | 28 + .../NoirJS/noir_js/functions/keccak256.md | 21 + .../NoirJS/noir_js/functions/sha256.md | 21 + .../reference/NoirJS/noir_js/functions/xor.md | 22 + .../reference/NoirJS/noir_js/index.md | 49 ++ .../noir_js/type-aliases/ErrorWithPayload.md | 15 + .../type-aliases/ForeignCallHandler.md | 24 + .../noir_js/type-aliases/ForeignCallInput.md | 9 + .../noir_js/type-aliases/ForeignCallOutput.md | 9 + .../NoirJS/noir_js/type-aliases/WitnessMap.md | 9 + .../NoirJS/noir_js/typedoc-sidebar.cjs | 4 + .../reference/NoirJS/noir_wasm/.nojekyll | 1 + .../NoirJS/noir_wasm/functions/compile.md | 51 ++ .../noir_wasm/functions/compile_contract.md | 51 ++ .../noir_wasm/functions/createFileManager.md | 21 + .../functions/inflateDebugSymbols.md | 21 + .../reference/NoirJS/noir_wasm/index.md | 49 ++ .../NoirJS/noir_wasm/typedoc-sidebar.cjs | 4 + .../version-v0.31.0/reference/_category_.json | 5 + .../reference/debugger/_category_.json | 6 + .../debugger/debugger_known_limitations.md | 59 ++ .../reference/debugger/debugger_repl.md | 360 +++++++++ .../reference/debugger/debugger_vscode.md | 82 ++ .../reference/nargo_commands.md | 244 ++++++ .../version-v0.31.0/tooling/debugger.md | 26 + .../tooling/language_server.md | 43 ++ .../version-v0.31.0/tooling/testing.md | 62 ++ .../version-v0.31.0/tutorials/noirjs_app.md | 327 ++++++++ .../version-v0.31.0-sidebars.json | 93 +++ noir/noir-repo/examples/.gitignore | 2 + .../examples/codegen_verifier/.gitignore | 1 - .../examples/prove_and_verify/proofs/proof | Bin 2176 -> 0 bytes .../prove_and_verify/prove_and_verify.sh | 2 +- .../recursion/recurse_leaf/src/main.nr | 4 +- .../recursion/recurse_node/src/main.nr | 4 +- noir/noir-repo/noir_stdlib/src/aes128.nr | 2 +- noir/noir-repo/noir_stdlib/src/array.nr | 4 +- noir/noir-repo/noir_stdlib/src/cmp.nr | 6 +- .../src/collections/bounded_vec.nr | 118 ++- .../noir_stdlib/src/collections/map.nr | 8 +- .../noir_stdlib/src/collections/vec.nr | 39 + noir/noir-repo/noir_stdlib/src/compat.nr | 7 +- noir/noir-repo/noir_stdlib/src/default.nr | 2 +- .../noir-repo/noir_stdlib/src/ec/montcurve.nr | 8 +- noir/noir-repo/noir_stdlib/src/ec/swcurve.nr | 8 +- noir/noir-repo/noir_stdlib/src/ec/tecurve.nr | 8 +- .../noir_stdlib/src/ecdsa_secp256k1.nr | 2 +- .../noir_stdlib/src/ecdsa_secp256r1.nr | 2 +- .../noir_stdlib/src/embedded_curve_ops.nr | 10 +- noir/noir-repo/noir_stdlib/src/hash.nr | 74 +- noir/noir-repo/noir_stdlib/src/hash/mimc.nr | 4 +- .../noir_stdlib/src/hash/poseidon.nr | 19 +- .../noir_stdlib/src/hash/poseidon/bn254.nr | 2 +- .../noir_stdlib/src/hash/poseidon2.nr | 5 +- noir/noir-repo/noir_stdlib/src/lib.nr | 6 + noir/noir-repo/noir_stdlib/src/merkle.nr | 2 +- noir/noir-repo/noir_stdlib/src/meta.nr | 1 + .../noir_stdlib/src/meta/type_def.nr | 16 + noir/noir-repo/noir_stdlib/src/option.nr | 2 +- noir/noir-repo/noir_stdlib/src/schnorr.nr | 2 +- noir/noir-repo/noir_stdlib/src/sha256.nr | 8 +- noir/noir-repo/noir_stdlib/src/sha512.nr | 2 +- noir/noir-repo/noir_stdlib/src/slice.nr | 51 +- noir/noir-repo/noir_stdlib/src/string.nr | 2 +- noir/noir-repo/noir_stdlib/src/test.nr | 4 +- noir/noir-repo/noir_stdlib/src/uint128.nr | 20 +- noir/noir-repo/scripts/install_bb.sh | 2 +- noir/noir-repo/scripts/redo-typo-pr.sh | 32 + .../bench_eddsa_poseidon/src/main.nr | 4 +- .../bench_poseidon_hash/src/main.nr | 2 +- .../bench_poseidon_hash_100/src/main.nr | 4 +- .../bench_poseidon_hash_30/src/main.nr | 4 +- .../benchmarks/bench_sha256/Nargo.toml | 7 + .../benchmarks/bench_sha256/src/main.nr | 1 - .../benchmarks/bench_sha256_100/src/main.nr | 4 +- .../benchmarks/bench_sha256_30/src/main.nr | 4 +- .../array_length_defaulting/src/main.nr | 2 +- .../assert_constant_dynamic_array/Nargo.toml | 7 + .../assert_constant_dynamic_array/src/main.nr | 5 + .../assert_constant_dynamic_plus/Nargo.toml | 7 + .../assert_constant_dynamic_plus/src/main.nr | 5 + .../assert_constant_dynamic_slice/Nargo.toml | 7 + .../assert_constant_dynamic_slice/src/main.nr | 5 + .../Nargo.toml | 7 + .../src/main.nr | 12 + .../Nargo.toml | 7 + .../src/main.nr | 12 + .../Nargo.toml | 7 + .../src/main.nr | 12 + .../assert_constant_dynamic_tuple/Nargo.toml | 7 + .../assert_constant_dynamic_tuple/src/main.nr | 5 + .../assert_constant_fail/src/main.nr | 2 +- .../assert_constant_false/Nargo.toml | 7 + .../assert_constant_false/src/main.nr | 3 + .../brillig_nested_slices/src/main.nr | 2 +- .../builtin_function_declaration/Nargo.toml | 4 +- .../builtin_function_declaration/src/main.nr | 2 +- .../dep_impl_primitive/src/main.nr | 2 +- .../dep_submodule_overlap/Nargo.toml | 8 + .../dep_submodule_overlap/src/lib.nr | 3 + .../dep_submodule_overlap/src/main.nr | 9 + .../compile_failure/depend_on_bin/src/main.nr | 2 +- .../integer_too_large/Nargo.toml | 5 + .../integer_too_large/src/main.nr | 4 + .../invalid_main_sub_lib/Nargo.toml | 7 + .../invalid_main_sub_lib/src/main.nr | 5 + .../invalid_main_sub_lib/src/main/lib.nr | 3 + .../invalid_mod_mod_path/Nargo.toml | 7 + .../invalid_mod_mod_path/main/lib.nr | 3 + .../invalid_mod_mod_path/src/main.nr | 4 + .../invalid_mod_mod_path/src/mod.nr | 3 + .../negate_unsigned/src/main.nr | 2 - .../non_comptime_local_fn_call/Nargo.toml | 7 + .../non_comptime_local_fn_call/src/main.nr | 9 + .../orphaned_trait_impl/src/main.nr | 2 +- .../overlapping_dep_and_mod/Nargo.toml | 6 + .../overlapping_dep_and_mod/bin/Nargo.toml | 8 + .../overlapping_dep_and_mod/bin/Prover.toml | 0 .../overlapping_dep_and_mod/bin/src/main.nr | 12 + .../overlapping_dep_and_mod/foo/Nargo.toml | 7 + .../overlapping_dep_and_mod/foo/src/lib.nr | 3 + .../overlapping_mod/Nargo.toml | 7 + .../overlapping_mod/src/foo.nr | 4 + .../overlapping_mod/src/foo/mod.nr | 3 + .../overlapping_mod/src/main.nr | 7 + .../regression_5008/Nargo.toml | 7 + .../regression_5008/src/main.nr | 17 + .../restricted_bit_sizes/src/main.nr | 2 +- .../Nargo.toml | 7 + .../src/main.nr | 5 + .../static_assert_dynamic_slice/Nargo.toml | 7 + .../static_assert_dynamic_slice/src/main.nr | 15 + .../static_assert_plus/Nargo.toml | 7 + .../static_assert_plus/src/main.nr | 7 + .../turbofish_generic_count/src/main.nr | 3 +- .../type_definition_annotation/Nargo.toml | 7 + .../type_definition_annotation/src/main.nr | 8 + .../abi_attribute/Nargo.toml | 6 + .../abi_attribute/src/main.nr | 9 + .../recursive_method/Nargo.toml | 6 + .../recursive_method/src/main.nr | 6 + .../assert_constant/Nargo.toml | 7 + .../assert_constant/src/main.nr | 59 ++ .../Nargo.toml | 2 +- .../comptime_array_len/src/main.nr | 6 + .../comptime_as_slice/Nargo.toml | 7 + .../comptime_as_slice/src/main.nr | 9 + .../comptime_type_definition/Nargo.toml | 7 + .../comptime_type_definition/src/main.nr | 13 + .../src/main.nr | 2 - .../derive_impl/Nargo.toml | 7 + .../derive_impl/src/main.nr | 49 ++ .../ec_baby_jubjub/src/main.nr | 19 +- .../impl_where_clause/Nargo.toml | 7 + .../impl_where_clause/src/main.nr | 34 + .../intrinsic_die/src/main.nr | 2 - .../compile_success_empty/macros/Nargo.toml | 7 + .../compile_success_empty/macros/src/main.nr | 15 + .../method_call_regression/src/main.nr | 2 - .../mod_nr_entrypoint/Nargo.toml | 7 + .../mod_nr_entrypoint/src/baz.nr | 3 + .../mod_nr_entrypoint/src/foo/bar.nr | 3 + .../mod_nr_entrypoint/src/foo/mod.nr | 5 + .../mod_nr_entrypoint/src/main.nr | 11 + .../no_duplicate_methods/Nargo.toml | 6 + .../no_duplicate_methods/Prover.toml | 0 .../no_duplicate_methods/src/main.nr | 26 + .../numeric_generics/src/main.nr | 1 - .../numeric_generics_explicit/Nargo.toml | 6 + .../numeric_generics_explicit/src/main.nr | 111 +++ .../overlapping_dep_and_mod/Nargo.toml | 6 + .../overlapping_dep_and_mod/bin/Nargo.toml | 8 + .../overlapping_dep_and_mod/bin/src/main.nr | 9 + .../overlapping_dep_and_mod/foo/Nargo.toml | 7 + .../overlapping_dep_and_mod/foo/src/lib.nr | 5 + .../reexports/src/main.nr | 2 +- .../regression_2099/src/main.nr | 16 +- .../regression_3635/src/main.nr | 2 - .../regression_4635/src/main.nr | 2 +- .../static_assert/Nargo.toml | 7 + .../static_assert/src/main.nr | 46 ++ .../str_as_bytes/src/main.nr | 1 - .../trait_default_implementation/src/main.nr | 2 - .../trait_generics/src/main.nr | 4 +- .../trait_impl_with_where_clause/Nargo.toml | 6 + .../src/main.nr | 0 .../trait_override_implementation/src/main.nr | 2 - .../compile_success_empty/traits/src/main.nr | 2 - .../compile_success_empty/vectors/src/main.nr | 2 +- .../workspace_reexport_bug/binary/src/main.nr | 2 +- .../workspace_reexport_bug/library/src/lib.nr | 2 +- .../div_by_zero_constants/src/main.nr | 2 - .../div_by_zero_numerator_witness/src/main.nr | 2 - .../div_by_zero_witness/src/main.nr | 1 - .../hashmap_load_factor/src/main.nr | 6 +- .../regression_5202/Nargo.toml | 7 + .../regression_5202/src/main.nr | 41 + .../execution_success/4_sub/src/main.nr | 1 - .../execution_success/5_over/src/main.nr | 1 - .../execution_success/6/src/main.nr | 1 - .../execution_success/6_array/src/main.nr | 1 - .../execution_success/7/src/main.nr | 1 - .../aes128_encrypt/src/main.nr | 2 - .../array_dynamic_blackbox_input/src/main.nr | 2 +- .../src/main.nr | 2 +- .../execution_success/as_witness/Nargo.toml | 6 + .../execution_success/as_witness/Prover.toml | 1 + .../execution_success/as_witness/src/main.nr | 5 + .../execution_success/bigint/src/main.nr | 10 +- .../execution_success/blake3/src/main.nr | 2 - .../brillig_blake2s/src/main.nr | 1 - .../brillig_blake3/src/main.nr | 2 - .../src/main.nr | 4 +- .../brillig_cow_regression/src/main.nr | 32 +- .../brillig_ecdsa_secp256k1/src/main.nr | 1 - .../brillig_ecdsa_secp256r1/src/main.nr | 1 - .../brillig_fns_as_values/src/main.nr | 2 - .../brillig_hash_to_field/src/main.nr | 1 - .../brillig_keccak/src/main.nr | 1 - .../brillig_oracle/src/main.nr | 4 +- .../brillig_pedersen/src/main.nr | 2 - .../brillig_sha256/src/main.nr | 1 - .../brillig_slices/src/main.nr | 2 +- .../conditional_1/src/main.nr | 2 - .../conditional_2/src/main.nr | 2 - .../src/main.nr | 2 - .../execution_success/databus/src/main.nr | 2 - .../diamond_deps_0/src/main.nr | 6 +- .../double_verify_nested_proof/src/main.nr | 1 - .../double_verify_proof/src/main.nr | 1 - .../double_verify_proof_recursive/src/main.nr | 1 - .../ecdsa_secp256k1/src/main.nr | 2 - .../ecdsa_secp256r1/src/main.nr | 2 - .../ecdsa_secp256r1_3x/src/main.nr | 2 - .../execution_success/eddsa/src/main.nr | 12 +- .../embedded_curve_ops/src/main.nr | 2 - .../fold_numeric_generic_poseidon/src/main.nr | 4 +- .../execution_success/generics/src/main.nr | 2 +- .../hash_to_field/src/main.nr | 2 - .../execution_success/hashmap/src/main.nr | 7 +- .../execution_success/import/src/main.nr | 2 +- .../is_unconstrained/src/main.nr | 2 +- .../execution_success/keccak256/src/main.nr | 1 - .../merkle_insert/src/main.nr | 3 +- .../execution_success/modulus/src/main.nr | 13 +- .../src/main.nr | 4 +- .../operator_overloading/src/main.nr | 4 +- .../overlapping_dep_and_mod/Nargo.toml | 6 + .../overlapping_dep_and_mod/bin/Nargo.toml | 8 + .../overlapping_dep_and_mod/bin/Prover.toml | 0 .../overlapping_dep_and_mod/bin/src/main.nr | 14 + .../overlapping_dep_and_mod/foo/Nargo.toml | 7 + .../overlapping_dep_and_mod/foo/src/lib.nr | 5 + .../pedersen_check/src/main.nr | 2 - .../pedersen_commitment/src/main.nr | 1 - .../pedersen_hash/src/main.nr | 1 - .../poseidon_bn254_hash/src/main.nr | 4 +- .../poseidonsponge_x5_254/src/main.nr | 2 +- .../execution_success/prelude/src/main.nr | 4 +- .../regression_3051/src/main.nr | 4 +- .../regression_3394/src/main.nr | 2 - .../regression_4088/src/main.nr | 4 +- .../regression_4124/src/main.nr | 8 +- .../regression_4449/src/main.nr | 1 - .../regression_5045/src/main.nr | 6 +- .../regression_5252/Nargo.toml | 7 + .../regression_5252/Prover.toml | 6 + .../regression_5252/src/main.nr | 23 + .../src/main.nr | 1 - .../execution_success/schnorr/src/main.nr | 15 +- .../execution_success/sha256/src/main.nr | 1 - .../execution_success/sha2_byte/src/main.nr | 1 - .../signed_comparison/src/main.nr | 2 - .../signed_division/src/main.nr | 1 - .../simple_print/src/main.nr | 1 - .../simple_shield/src/main.nr | 2 - .../slice_coercion/src/main.nr | 2 +- .../execution_success/slices/src/main.nr | 11 +- .../execution_success/strings/src/main.nr | 1 - .../execution_success/to_bits/src/main.nr | 2 - .../to_bytes_integration/src/main.nr | 2 - .../trait_method_mut_self/src/main.nr | 4 +- .../traits_in_crates_1/crate1/src/lib.nr | 2 +- .../traits_in_crates_1/src/main.nr | 2 +- .../traits_in_crates_2/crate2/src/lib.nr | 2 +- .../traits_in_crates_2/src/main.nr | 2 +- .../src/main.nr | 6 +- .../execution_success/u128/src/main.nr | 2 - .../execution_success/unit_value/src/main.nr | 2 +- .../verify_honk_proof/Nargo.toml | 3 +- .../verify_honk_proof/Prover.toml | 4 +- .../verify_honk_proof/src/main.nr | 4 +- .../wildcard_type/Nargo.toml | 6 + .../wildcard_type/Prover.toml | 1 + .../wildcard_type/src/main.nr | 23 + .../wrapping_operations/src/main.nr | 2 - noir/noir-repo/test_programs/format.sh | 2 +- .../should_fail_mismatch/src/main.nr | 15 +- .../noir_test_success/bounded_vec/src/main.nr | 27 + .../brillig_overflow_checks/src/main.nr | 2 +- .../comptime_globals/src/main.nr | 2 +- .../embedded_curve_ops/src/main.nr | 2 +- .../field_comparisons/src/main.nr | 2 +- .../fuzzer_checks/Nargo.toml | 5 + .../fuzzer_checks/src/main.nr | 6 + .../noir_test_success/mock_oracle/src/main.nr | 2 +- .../regression_4561/Nargo.toml | 6 + .../regression_4561/src/main.nr | 78 ++ .../should_fail_with_matches/src/main.nr | 28 +- noir/noir-repo/test_programs/rebuild.sh | 26 +- .../test_libraries/diamond_deps_1/src/lib.nr | 2 +- .../test_libraries/exporting_lib/src/lib.nr | 2 +- .../test_libraries/reexporting_lib/src/lib.nr | 4 +- noir/noir-repo/tooling/debugger/Cargo.toml | 1 + .../tooling/debugger/ignored-tests.txt | 3 +- .../noir-repo/tooling/debugger/src/context.rs | 2 +- noir/noir-repo/tooling/debugger/src/dap.rs | 2 +- .../tooling/debugger/src/foreign_calls.rs | 6 +- noir/noir-repo/tooling/debugger/src/lib.rs | 2 +- noir/noir-repo/tooling/debugger/src/repl.rs | 3 +- .../debugger/src/source_code_printer.rs | 8 +- noir/noir-repo/tooling/fuzzer/Cargo.toml | 18 + .../tooling/fuzzer/src/dictionary/mod.rs | 124 +++ noir/noir-repo/tooling/fuzzer/src/lib.rs | 96 +++ .../tooling/fuzzer/src/strategies/int.rs | 83 ++ .../tooling/fuzzer/src/strategies/mod.rs | 99 +++ .../tooling/fuzzer/src/strategies/uint.rs | 98 +++ noir/noir-repo/tooling/fuzzer/src/types.rs | 42 + noir/noir-repo/tooling/lsp/Cargo.toml | 1 + .../tooling/lsp/src/requests/profile_run.rs | 6 +- noir/noir-repo/tooling/lsp/src/solver.rs | 16 +- noir/noir-repo/tooling/nargo/Cargo.toml | 3 +- noir/noir-repo/tooling/nargo/src/lib.rs | 1 - noir/noir-repo/tooling/nargo/src/ops/test.rs | 2 +- noir/noir-repo/tooling/nargo_cli/Cargo.toml | 10 +- .../tooling/nargo_cli/benches/criterion.rs | 8 +- noir/noir-repo/tooling/nargo_cli/build.rs | 574 ++++++-------- .../tooling/nargo_cli/src/cli/check_cmd.rs | 6 +- .../tooling/nargo_cli/src/cli/compile_cmd.rs | 129 ++-- .../tooling/nargo_cli/src/cli/debug_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/execute_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/export_cmd.rs | 2 +- .../tooling/nargo_cli/src/cli/fs/program.rs | 2 +- .../tooling/nargo_cli/src/cli/info_cmd.rs | 6 +- .../tooling/nargo_cli/src/cli/test_cmd.rs | 56 +- .../tooling/nargo_cli/tests/stdlib-tests.rs | 143 +++- noir/noir-repo/tooling/nargo_fmt/src/items.rs | 3 +- .../tooling/nargo_fmt/src/rewrite/expr.rs | 15 +- .../tooling/nargo_fmt/src/rewrite/typ.rs | 6 +- noir/noir-repo/tooling/nargo_fmt/src/utils.rs | 23 +- .../tooling/nargo_fmt/src/visitor/item.rs | 6 +- .../nargo_fmt/tests/expected/contract.nr | 6 +- .../tooling/nargo_fmt/tests/expected/fn.nr | 8 + .../tooling/nargo_fmt/tests/expected/impl.nr | 18 +- .../nargo_fmt/tests/expected/import_braces.nr | 2 +- .../tooling/nargo_fmt/tests/expected/let.nr | 12 +- .../tooling/nargo_fmt/tests/expected/print.nr | 2 - .../nargo_fmt/tests/expected/print2.nr | 2 - .../tests/expected/singleton_import.nr | 2 + .../tooling/nargo_fmt/tests/input/contract.nr | 6 +- .../tooling/nargo_fmt/tests/input/fn.nr | 10 + .../tooling/nargo_fmt/tests/input/impl.nr | 20 +- .../nargo_fmt/tests/input/import_braces.nr | 2 +- .../tooling/nargo_fmt/tests/input/let.nr | 12 +- .../tooling/nargo_fmt/tests/input/print.nr | 2 - .../tooling/nargo_fmt/tests/input/print2.nr | 2 - .../nargo_fmt/tests/input/singleton_import.nr | 2 + .../tooling/noir_codegen/package.json | 2 +- noir/noir-repo/tooling/noir_js/package.json | 2 +- .../assert_lt/src/main.nr | 2 - .../noir_js_backend_barretenberg/package.json | 2 +- .../src/backend.ts | 3 +- .../tooling/noir_js_types/package.json | 2 +- noir/noir-repo/tooling/noirc_abi/Cargo.toml | 13 +- .../tooling/noirc_abi/src/arbitrary.rs | 154 ++++ noir/noir-repo/tooling/noirc_abi/src/lib.rs | 169 +--- .../tooling/noirc_abi_wasm/package.json | 2 +- .../tooling/noirc_artifacts/Cargo.toml | 24 + .../src}/contract.rs | 0 .../src}/debug.rs | 2 +- .../src}/debug_vars.rs | 0 .../mod.rs => noirc_artifacts/src/lib.rs} | 6 + .../src}/program.rs | 0 noir/noir-repo/tooling/profiler/Cargo.toml | 3 +- .../profiler/src/cli/gates_flamegraph_cmd.rs | 439 ++--------- .../noir-repo/tooling/profiler/src/cli/mod.rs | 9 +- .../src/cli/opcodes_flamegraph_cmd.rs | 123 +++ .../tooling/profiler/src/flamegraph.rs | 300 ++++++++ noir/noir-repo/tooling/profiler/src/fs.rs | 15 + .../tooling/profiler/src/gates_provider.rs | 37 + noir/noir-repo/tooling/profiler/src/main.rs | 4 + .../tooling/profiler/src/opcode_formatter.rs | 53 ++ noir/scripts/sync-in-fixup.sh | 3 + noir/scripts/sync-out-fixup.sh | 3 + noir/verify_honk_proof/Nargo.toml | 6 + noir/verify_honk_proof/Prover.toml | 4 + noir/verify_honk_proof/src/main.nr | 21 + yarn-project/.earthlyignore | 7 +- yarn-project/.gitignore | 7 +- yarn-project/Earthfile | 15 +- yarn-project/accounts/.prettierignore | 2 +- yarn-project/accounts/package.json | 5 +- yarn-project/accounts/package.local.json | 12 +- .../accounts/scripts/copy-contracts.sh | 12 +- .../accounts/src/artifacts/EcdsaAccount.json | 1 + .../src/artifacts/SchnorrAccount.json | 1 + .../artifacts/SchnorrSingleKeyAccount.json | 1 + yarn-project/accounts/src/ecdsa/artifact.ts | 2 +- yarn-project/accounts/src/schnorr/artifact.ts | 2 +- .../accounts/src/single_key/artifact.ts | 2 +- yarn-project/accounts/tsconfig.json | 2 +- .../aztec-node/src/aztec-node/server.ts | 33 +- yarn-project/aztec.js/src/index.ts | 1 + .../aztec.js/src/wallet/base_wallet.ts | 13 +- yarn-project/aztec/CHANGELOG.md | 16 + yarn-project/aztec/package.json | 2 +- yarn-project/aztec/terraform/node/main.tf | 2 +- .../bb-prover/src/avm_proving.test.ts | 21 +- yarn-project/bb-prover/src/bb/execute.ts | 15 +- .../src/prover/bb_native_proof_creator.ts | 4 +- .../bb-prover/src/prover/bb_prover.ts | 4 +- .../bb-prover/src/verifier/bb_verifier.ts | 7 +- yarn-project/circuit-types/src/body.ts | 76 +- .../src/interfaces/aztec-node.ts | 3 +- .../circuit-types/src/interfaces/pxe.ts | 23 +- yarn-project/circuit-types/src/mocks.ts | 10 +- .../circuit-types/src/tx/processed_tx.ts | 6 +- yarn-project/circuit-types/src/tx/tx.ts | 5 +- yarn-project/circuit-types/src/tx_effect.ts | 39 +- yarn-project/circuits.js/src/constants.gen.ts | 62 +- ...build_note_hash_read_request_hints.test.ts | 10 +- .../build_note_hash_read_request_hints.ts | 4 +- ...er_non_existent_read_request_hints.test.ts | 14 +- ...llifier_non_existent_read_request_hints.ts | 12 +- ...build_nullifier_read_request_hints.test.ts | 10 +- .../build_nullifier_read_request_hints.ts | 8 +- .../circuits.js/src/scripts/constants.in.ts | 104 ++- .../private_call_stack_item.test.ts.snap | 4 +- ...private_circuit_public_inputs.test.ts.snap | 4 +- .../public_call_stack_item.test.ts.snap | 8 +- .../public_circuit_public_inputs.test.ts.snap | 4 +- .../circuits.js/src/structs/avm/avm.ts | 31 +- .../src/structs/content_commitment.ts | 8 +- .../src/structs/kernel/combine_hints.ts | 18 +- .../kernel/combined_accumulated_data.ts | 42 +- .../kernel/kernel_circuit_public_inputs.ts | 2 +- .../kernel/private_accumulated_data.ts | 30 +- ...vate_kernel_init_circuit_private_inputs.ts | 9 +- ...ate_kernel_inner_circuit_private_inputs.ts | 6 +- ...ate_kernel_reset_circuit_private_inputs.ts | 22 +- ...vate_kernel_tail_circuit_private_inputs.ts | 120 +-- ...ivate_kernel_tail_circuit_public_inputs.ts | 11 +- .../structs/kernel/public_accumulated_data.ts | 54 +- .../kernel/public_accumulated_data_builder.ts | 48 +- .../non_existent_read_request_hints.ts | 14 +- .../structs/private_circuit_public_inputs.ts | 42 +- .../structs/public_call_stack_item.test.ts | 4 +- .../structs/public_circuit_public_inputs.ts | 42 +- .../base_or_merge_rollup_public_inputs.ts | 10 +- .../src/structs/rollup/state_diff_hints.ts | 26 +- .../circuits.js/src/tests/factories.ts | 51 +- .../circuits.js/src/types/public_keys.ts | 31 +- yarn-project/end-to-end/Earthfile | 3 + .../benchmarks/bench_process_history.test.ts | 2 +- .../src/benchmarks/bench_prover.test.ts | 3 + .../benchmarks/bench_publish_rollup.test.ts | 2 +- .../composed/integration_l1_publisher.test.ts | 33 +- .../end-to-end/src/e2e_authwit.test.ts | 8 +- .../end-to-end/src/e2e_block_building.test.ts | 18 - .../end-to-end/src/e2e_card_game.test.ts | 6 + .../end-to-end/src/e2e_event_logs.test.ts | 123 ++- .../end-to-end/src/e2e_fees/fees_test.ts | 116 ++- .../src/e2e_fees/private_refunds.test.ts | 178 +++++ .../end-to-end/src/e2e_key_registry.test.ts | 15 +- .../src/e2e_non_contract_account.test.ts | 25 +- .../e2e_pending_note_hashes_contract.test.ts | 8 +- .../end-to-end/src/e2e_state_vars.test.ts | 4 +- .../transfer_private.test.ts | 12 +- yarn-project/foundation/src/log/logger.ts | 2 +- yarn-project/merkle-tree/src/index.ts | 1 + .../merkle-tree/src/unbalanced_tree.test.ts | 273 +++++++ .../merkle-tree/src/unbalanced_tree.ts | 239 ++++++ yarn-project/noir-contracts.js/package.json | 8 +- .../noir-contracts.js/package.local.json | 4 +- .../scripts/generate-types.sh | 9 + yarn-project/noir-contracts.js/tsconfig.json | 5 +- .../.prettierignore | 2 +- .../noir-protocol-circuits-types/package.json | 7 +- .../package.local.json | 12 +- .../noir-protocol-circuits-types/src/index.ts | 68 +- .../src/scripts/generate_declaration_files.ts | 17 + .../src/scripts/generate_ts_from_abi.ts | 2 +- .../src/type_conversion.ts | 108 +-- .../tsconfig.json | 6 +- .../protocol-contracts/.prettierignore | 2 +- yarn-project/protocol-contracts/package.json | 5 +- .../protocol-contracts/package.local.json | 12 +- .../scripts/copy-contracts.sh | 13 +- .../src/artifacts/AuthRegistry.json | 1 + .../artifacts/ContractClassRegisterer.json | 1 + .../artifacts/ContractInstanceDeployer.json | 1 + .../src/artifacts/GasToken.json | 1 + .../src/artifacts/KeyRegistry.json | 1 + .../src/artifacts/MultiCallEntrypoint.json | 1 + .../src/auth-registry/artifact.ts | 2 +- .../src/class-registerer/artifact.ts | 2 +- .../src/gas-token/artifact.ts | 2 +- .../src/instance-deployer/artifact.ts | 2 +- .../src/key-registry/artifact.ts | 2 +- .../src/multi-call-entrypoint/artifact.ts | 2 +- yarn-project/protocol-contracts/tsconfig.json | 2 +- .../prover-client/src/mocks/fixtures.ts | 24 +- .../prover-client/src/mocks/test_context.ts | 6 +- .../orchestrator/block-building-helpers.ts | 22 +- .../src/orchestrator/orchestrator.ts | 35 +- .../orchestrator/orchestrator_errors.test.ts | 16 +- .../orchestrator_failures.test.ts | 9 +- .../orchestrator_mixed_blocks.test.ts | 3 +- .../orchestrator_mixed_blocks_2.test.ts | 62 +- .../orchestrator_single_blocks.test.ts | 13 +- .../src/orchestrator/proving-state.ts | 26 + .../src/database/deferred_note_dao.test.ts | 4 +- .../pxe/src/database/deferred_note_dao.ts | 4 +- .../src/kernel_prover/kernel_prover.test.ts | 18 +- .../pxe/src/kernel_prover/kernel_prover.ts | 26 +- .../build_private_kernel_init_hints.ts | 22 +- .../build_private_kernel_inner_hints.ts | 9 +- .../build_private_kernel_reset_hints.ts | 26 +- .../build_private_kernel_reset_outputs.ts | 22 +- .../build_private_kernel_tail_hints.ts | 62 -- .../private_inputs_builders/index.ts | 1 - .../kernel_prover/test/test_circuit_prover.ts | 4 +- .../src/note_processor/note_processor.test.ts | 12 +- .../pxe/src/note_processor/note_processor.ts | 23 +- .../src/note_processor/produce_note_dao.ts | 12 +- .../pxe/src/pxe_service/pxe_service.ts | 102 ++- .../src/sequencer/sequencer.test.ts | 2 +- .../src/sequencer/sequencer.ts | 4 +- .../double_spend_validator.test.ts | 8 +- .../tx_validator/double_spend_validator.ts | 12 +- .../simulator/src/acvm/oracle/oracle.ts | 14 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 7 +- yarn-project/simulator/src/avm/avm_context.ts | 4 +- ..._result.ts => avm_contract_call_result.ts} | 2 +- .../src/avm/avm_execution_environment.ts | 37 +- yarn-project/simulator/src/avm/avm_gas.ts | 2 +- .../simulator/src/avm/avm_simulator.test.ts | 140 ++-- .../simulator/src/avm/avm_simulator.ts | 20 +- .../simulator/src/avm/bytecode_utils.ts | 32 + yarn-project/simulator/src/avm/errors.ts | 2 +- .../simulator/src/avm/fixtures/index.ts | 9 +- .../simulator/src/avm/journal/journal.test.ts | 8 +- .../simulator/src/avm/journal/journal.ts | 25 +- .../src/avm/journal/public_storage.ts | 4 +- .../src/avm/opcodes/accrued_substate.test.ts | 26 +- .../src/avm/opcodes/accrued_substate.ts | 25 +- .../avm/opcodes/environment_getters.test.ts | 137 ++-- .../src/avm/opcodes/environment_getters.ts | 37 +- .../src/avm/opcodes/external_calls.test.ts | 2 +- .../src/avm/opcodes/external_calls.ts | 5 +- .../bytecode_serialization.test.ts | 8 +- .../serialization/bytecode_serialization.ts | 7 +- .../instruction_serialization.ts | 6 +- .../src/client/client_execution_context.ts | 21 +- .../src/client/private_execution.test.ts | 112 +-- .../simulator/src/client/view_data_oracle.ts | 15 +- yarn-project/simulator/src/mocks/fixtures.ts | 16 +- .../src/public/abstract_phase_manager.test.ts | 6 +- .../src/public/abstract_phase_manager.ts | 52 +- .../simulator/src/public/execution.ts | 34 +- yarn-project/simulator/src/public/executor.ts | 55 +- .../simulator/src/public/hints_builder.ts | 6 +- yarn-project/simulator/src/public/index.ts | 2 +- .../simulator/src/public/public_kernel.ts | 3 +- .../src/public/public_processor.test.ts | 73 ++ .../src/public/side_effect_trace.test.ts | 18 +- .../simulator/src/public/side_effect_trace.ts | 58 +- .../src/public/side_effect_trace_interface.ts | 6 +- .../src/public/tail_phase_manager.ts | 8 +- .../src/public/transitional_adaptors.ts | 70 -- yarn-project/simulator/src/rollup/rollup.ts | 4 +- yarn-project/tsconfig.json | 5 +- yarn-project/txe/package.json | 2 +- yarn-project/txe/src/oracle/txe_oracle.ts | 72 +- .../txe/src/txe_service/txe_service.ts | 87 ++- .../types/src/abi/contract_artifact.ts | 2 +- yarn-project/types/src/noir/index.ts | 2 + .../src/world-state-db/merkle_tree_db.ts | 4 +- .../src/world-state-db/merkle_trees.ts | 8 +- yarn-project/yarn.lock | 16 +- 1421 files changed, 32993 insertions(+), 11447 deletions(-) delete mode 100644 barretenberg/cpp/pil/avm/constants.pil create mode 100644 barretenberg/cpp/pil/avm/constants_gen.pil create mode 100644 barretenberg/cpp/pil/avm/constants_misc.pil delete mode 100644 barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/constants.hpp delete mode 100644 docs/docs/aztec/concepts/smart_contracts/functions/function_types_macros.md create mode 100644 docs/docs/protocol-specs/state/wonky-tree.md create mode 100644 docs/docs/reference/smart_contract_reference/macros.md create mode 100644 l1-contracts/test/merkle/UnbalancedMerkle.t.sol rename noir-projects/aztec-nr/authwit/src/{entrypoint.nr => entrypoint/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/context/{globals.nr => globals/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/context/{inputs.nr => inputs/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{context.nr => context/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{encrypted_logs.nr => encrypted_logs/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{event.nr => event/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{history.nr => history/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{keys.nr => keys/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{note.nr => note/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/note/{note_getter.nr => note_getter/mod.nr} (97%) rename noir-projects/aztec-nr/aztec/src/{oracle.nr => oracle/mod.nr} (100%) delete mode 100644 noir-projects/aztec-nr/aztec/src/public_storage.nr rename noir-projects/aztec-nr/aztec/src/{state_vars.nr => state_vars/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/test/{helpers.nr => helpers/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/test/{mocks.nr => mocks/mod.nr} (100%) rename noir-projects/aztec-nr/aztec/src/{test.nr => test/mod.nr} (100%) create mode 100644 noir-projects/aztec-nr/aztec/src/unencrypted_logs/mod.nr create mode 100644 noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr rename noir-projects/aztec-nr/aztec/src/{utils.nr => utils/mod.nr} (97%) rename noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/{events.nr => events/mod.nr} (100%) delete mode 100644 noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr delete mode 100644 noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr create mode 100644 noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/private_fpc_contract/src/lib.nr create mode 100644 noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr create mode 100644 noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr rename noir-projects/noir-contracts/contracts/token_blacklist_contract/src/{types.nr => types/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/parity-lib/src/{base.nr => base/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/parity-lib/src/{root.nr => root/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/parity-lib/src/{utils.nr => utils/mod.nr} (100%) delete mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_public_inputs_composer.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/{components.nr => components/mod.nr} (55%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/{kernel_circuit_output_validator.nr => tail_output_validator.nr} (70%) rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/{ => tail_output_validator}/kernel_circuit_output_hints.nr (78%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/validate_value_transformation.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr delete mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests.nr delete mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder.nr delete mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/utils.nr delete mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_sorted_siloed_values.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/mod.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/previous_kernel_validator_builder.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{private_call_data_validator_builder.nr => private_call_data_validator_builder/mod.nr} (89%) rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{private_kernel_circuit_output_validator_builder.nr => private_kernel_circuit_output_validator_builder/mod.nr} (91%) rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{private_kernel_circuit_public_inputs_composer_builder.nr => private_kernel_circuit_public_inputs_composer_builder/mod.nr} (83%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{kernel_circuit_output_validator_builder => tail_output_validator_builder}/validate_accumulated_values.nr (83%) rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{kernel_circuit_output_validator_builder => tail_output_validator_builder}/validate_empty_values.nr (60%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{kernel_circuit_output_validator_builder => tail_output_validator_builder}/validate_propagated_values.nr (76%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr rename noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/{reset.nr => reset/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/{tests.nr => tests/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/rollup-lib/src/{abis.nr => abis/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/rollup-lib/src/{base.nr => base/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/rollup-lib/src/{merge.nr => merge/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/rollup-lib/src/{root.nr => root/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/rollup-lib/src/{tests.nr => tests/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{abis.nr => abis/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{address.nr => address/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{contrakt.nr => contrakt/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{data.nr => data/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{merkle_tree.nr => merkle_tree/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{messaging.nr => messaging/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{recursion.nr => recursion/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{storage.nr => storage/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{tests.nr => tests/mod.nr} (100%) rename noir-projects/noir-protocol-circuits/crates/types/src/{transaction.nr => transaction/mod.nr} (100%) create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_hints.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_split_order_hints.nr rename noir-projects/noir-protocol-circuits/crates/types/src/{utils.nr => utils/mod.nr} (100%) create mode 100755 noir-projects/noir-protocol-circuits/scripts/flamegraph.sh delete mode 100644 noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md create mode 100644 noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md create mode 100644 noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json create mode 100644 noir/noir-repo/examples/.gitignore delete mode 100644 noir/noir-repo/examples/prove_and_verify/proofs/proof create mode 100644 noir/noir-repo/noir_stdlib/src/meta.nr create mode 100644 noir/noir-repo/noir_stdlib/src/meta/type_def.nr create mode 100755 noir/noir-repo/scripts/redo-typo-pr.sh create mode 100644 noir/noir-repo/test_programs/benchmarks/bench_sha256/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/integer_too_large/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/integer_too_large/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Prover.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_mod/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/regression_5008/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/regression_5008/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_failure/type_definition_annotation/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_failure/type_definition_annotation/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_contract/recursive_method/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_contract/recursive_method/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr rename noir/noir-repo/test_programs/compile_success_empty/{impl_with_where_clause => comptime_array_len}/Nargo.toml (62%) create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/derive_impl/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/derive_impl/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr create mode 100644 noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml rename noir/noir-repo/test_programs/compile_success_empty/{impl_with_where_clause => trait_impl_with_where_clause}/src/main.nr (100%) create mode 100644 noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr create mode 100644 noir/noir-repo/test_programs/execution_success/wildcard_type/Nargo.toml create mode 100644 noir/noir-repo/test_programs/execution_success/wildcard_type/Prover.toml create mode 100644 noir/noir-repo/test_programs/execution_success/wildcard_type/src/main.nr create mode 100644 noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/Nargo.toml create mode 100644 noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/src/main.nr create mode 100644 noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml create mode 100644 noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr create mode 100644 noir/noir-repo/tooling/fuzzer/Cargo.toml create mode 100644 noir/noir-repo/tooling/fuzzer/src/dictionary/mod.rs create mode 100644 noir/noir-repo/tooling/fuzzer/src/lib.rs create mode 100644 noir/noir-repo/tooling/fuzzer/src/strategies/int.rs create mode 100644 noir/noir-repo/tooling/fuzzer/src/strategies/mod.rs create mode 100644 noir/noir-repo/tooling/fuzzer/src/strategies/uint.rs create mode 100644 noir/noir-repo/tooling/fuzzer/src/types.rs create mode 100644 noir/noir-repo/tooling/nargo_fmt/tests/expected/singleton_import.nr create mode 100644 noir/noir-repo/tooling/nargo_fmt/tests/input/singleton_import.nr create mode 100644 noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs create mode 100644 noir/noir-repo/tooling/noirc_artifacts/Cargo.toml rename noir/noir-repo/tooling/{nargo/src/artifacts => noirc_artifacts/src}/contract.rs (100%) rename noir/noir-repo/tooling/{nargo/src/artifacts => noirc_artifacts/src}/debug.rs (99%) rename noir/noir-repo/tooling/{nargo/src/artifacts => noirc_artifacts/src}/debug_vars.rs (100%) rename noir/noir-repo/tooling/{nargo/src/artifacts/mod.rs => noirc_artifacts/src/lib.rs} (73%) rename noir/noir-repo/tooling/{nargo/src/artifacts => noirc_artifacts/src}/program.rs (100%) create mode 100644 noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs create mode 100644 noir/noir-repo/tooling/profiler/src/flamegraph.rs create mode 100644 noir/noir-repo/tooling/profiler/src/fs.rs create mode 100644 noir/noir-repo/tooling/profiler/src/gates_provider.rs create mode 100644 noir/noir-repo/tooling/profiler/src/opcode_formatter.rs create mode 100644 noir/verify_honk_proof/Nargo.toml create mode 100644 noir/verify_honk_proof/Prover.toml create mode 100644 noir/verify_honk_proof/src/main.nr create mode 100644 yarn-project/accounts/src/artifacts/EcdsaAccount.json create mode 100644 yarn-project/accounts/src/artifacts/SchnorrAccount.json create mode 100644 yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json create mode 100644 yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts create mode 100644 yarn-project/merkle-tree/src/unbalanced_tree.test.ts create mode 100644 yarn-project/merkle-tree/src/unbalanced_tree.ts create mode 100644 yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts create mode 100644 yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json create mode 100644 yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json create mode 100644 yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json create mode 100644 yarn-project/protocol-contracts/src/artifacts/GasToken.json create mode 100644 yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json create mode 100644 yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json delete mode 100644 yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts rename yarn-project/simulator/src/avm/{avm_message_call_result.ts => avm_contract_call_result.ts} (92%) create mode 100644 yarn-project/simulator/src/avm/bytecode_utils.ts delete mode 100644 yarn-project/simulator/src/public/transitional_adaptors.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 247c8b71f574..3c4c5462ae9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -363,7 +363,7 @@ jobs: noir-format: needs: [setup, changes] runs-on: ${{ github.event.pull_request.user.login || github.actor }}-x86 - if: ${{ needs.changes.outputs.noir == 'true' }} + if: ${{ needs.changes.outputs.noir == 'true' || needs.changes.outputs.noir-projects == 'true' }} steps: - uses: actions/checkout@v4 with: { ref: "${{ env.GIT_COMMIT }}" } diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index b0d0fb82b294..df3af6699911 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -134,3 +134,9 @@ jobs: run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/prover" terraform apply -input=false -auto-approve + + - name: Deploy Provers + working-directory: ./yarn-project/aztec/terraform/prover + run: | + terraform init -input=false -backend-config="key=devnet/prover" + terraform apply -input=false -auto-approve diff --git a/.github/workflows/pull-noir.yml b/.github/workflows/pull-noir.yml index b1ca0cc7bbf7..042ebcb99291 100644 --- a/.github/workflows/pull-noir.yml +++ b/.github/workflows/pull-noir.yml @@ -5,8 +5,11 @@ name: Pull from noir repo concurrency: group: ${{ github.workflow }} cancel-in-progress: false + on: - # o + schedule: + # Run every morning at 8 AM UTC + - cron: "0 8 * * *" workflow_dispatch: {} jobs: diff --git a/.noir-sync-commit b/.noir-sync-commit index 34ef64dcc096..7f0f18023f8f 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -2e543b40eb83ef2080e4d8f870f525fadd631099 +7b77bbfc19c51829814149e623257a3424d8e8c2 diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a2daeb9352c2..dd3cffc8169d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,7 +1,7 @@ { - ".": "0.43.0", + ".": "0.45.0", "yarn-project/cli": "0.35.1", - "yarn-project/aztec": "0.43.0", - "barretenberg": "0.43.0", - "barretenberg/ts": "0.43.0" + "yarn-project/aztec": "0.45.0", + "barretenberg": "0.45.0", + "barretenberg/ts": "0.45.0" } diff --git a/.vscode/settings.json b/.vscode/settings.json index 86a0427f7901..630178ad32ac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -169,4 +169,5 @@ "**/noir/noir-repo/docs/versioned_docs/**": true }, "cmake.sourceDirectory": "${workspaceFolder}/barretenberg/cpp", + "typescript.tsserver.maxTsServerMemory": 4096, } diff --git a/CHANGELOG.md b/CHANGELOG.md index 31100bab7b8a..31bbf771e953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,249 @@ # Changelog +## [0.45.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.44.0...aztec-packages-v0.45.0) (2024-07-02) + + +### ⚠ BREAKING CHANGES + +* error on too large integer value (https://github.com/noir-lang/noir/pull/5371) +* rename struct-specific TypeDefinition -> StructDefinition (https://github.com/noir-lang/noir/pull/5356) +* extend storage read oracle to receive address and block number ([#7243](https://github.com/AztecProtocol/aztec-packages/issues/7243)) +* split storage access oracles ([#7237](https://github.com/AztecProtocol/aztec-packages/issues/7237)) +* remove `dep::` prefix (https://github.com/noir-lang/noir/pull/4946) + +### Features + +* `mod.nr` entrypoint (https://github.com/noir-lang/noir/pull/5039) ([bb5cbab](https://github.com/AztecProtocol/aztec-packages/commit/bb5cbab945cfd61f6a0da79f8874a0fcdc59361a)) +* `static_assert` builtin (https://github.com/noir-lang/noir/pull/5342) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Add `map`, `fold`, `reduce`, `any`, and `all` for slices (https://github.com/noir-lang/noir/pull/5331) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Add `set` and `set_unchecked` methods to `Vec` and `BoundedVec` (https://github.com/noir-lang/noir/pull/5241) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add BoundedVec::map (https://github.com/noir-lang/noir/pull/5250) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add fuzzer for Noir programs (https://github.com/noir-lang/noir/pull/5251) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add new lenses for encryted notes ([#7238](https://github.com/AztecProtocol/aztec-packages/issues/7238)) ([c07cf2c](https://github.com/AztecProtocol/aztec-packages/commit/c07cf2cf2b004dba46a3138a1f64f207b6ee537f)) +* Add opcodes flamegraph and refactor gates flamegraph ([#7282](https://github.com/AztecProtocol/aztec-packages/issues/7282)) ([df3b27b](https://github.com/AztecProtocol/aztec-packages/commit/df3b27b8c603845598bf966100be3a21e8e442db)) +* Add outgoing keys support to getEvents ([#7239](https://github.com/AztecProtocol/aztec-packages/issues/7239)) ([77c304e](https://github.com/AztecProtocol/aztec-packages/commit/77c304ee70de3cf47f68b45c35c776a31d61af46)) +* Add support for wildcard types (https://github.com/noir-lang/noir/pull/5275) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **avm:** Calldata gadget preliminaries ([#7227](https://github.com/AztecProtocol/aztec-packages/issues/7227)) ([79e8588](https://github.com/AztecProtocol/aztec-packages/commit/79e85883c90465cf2ff6e1a2d7af0e5d4d3e111c)) +* Build simple dictionary from inspecting ACIR program (https://github.com/noir-lang/noir/pull/5264) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Constant Honk proof sizes ([#6954](https://github.com/AztecProtocol/aztec-packages/issues/6954)) ([17c8d3a](https://github.com/AztecProtocol/aztec-packages/commit/17c8d3a00f3a2e500d5caa1fb438504bcd357e8a)) +* Disable nargo color output if stderr is tty (https://github.com/noir-lang/noir/pull/5346) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* **docs:** Macros explainer ([#7172](https://github.com/AztecProtocol/aztec-packages/issues/7172)) ([bb2ebfc](https://github.com/AztecProtocol/aztec-packages/commit/bb2ebfce8edae9e851c7c8fb9eb1d50673f4bec6)) +* Error on too large integer value (https://github.com/noir-lang/noir/pull/5371) ([bb5cbab](https://github.com/AztecProtocol/aztec-packages/commit/bb5cbab945cfd61f6a0da79f8874a0fcdc59361a)) +* Example of private token transfer event ([#7242](https://github.com/AztecProtocol/aztec-packages/issues/7242)) ([99ce26f](https://github.com/AztecProtocol/aztec-packages/commit/99ce26f568b5210ac800889b28d396aa9c9d7e3e)) +* **experimental:** Implement macro calls & splicing into `Expr` values (https://github.com/noir-lang/noir/pull/5203) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Extend storage read oracle to receive address and block number ([#7243](https://github.com/AztecProtocol/aztec-packages/issues/7243)) ([153b201](https://github.com/AztecProtocol/aztec-packages/commit/153b2010c5d79f308779370d240dfaa2a086ca3c)) +* **frontend:** Explicit numeric generics and type kinds (https://github.com/noir-lang/noir/pull/5155) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* **frontend:** Where clause on impl (https://github.com/noir-lang/noir/pull/5320) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Function selector opcode in AVM ([#7244](https://github.com/AztecProtocol/aztec-packages/issues/7244)) ([dde47e9](https://github.com/AztecProtocol/aztec-packages/commit/dde47e927ebe5606a272a35dd8c4f4876369b244)) +* Implement comptime support for `array_len` builtin (https://github.com/noir-lang/noir/pull/5272) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Implement comptime support for `as_slice` builtin (https://github.com/noir-lang/noir/pull/5276) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Insert trait impls into the program from type annotations (https://github.com/noir-lang/noir/pull/5327) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Let `should_fail_with` check that the failure reason contains the expected message (https://github.com/noir-lang/noir/pull/5319) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Make macros operate on token streams instead of AST nodes (https://github.com/noir-lang/noir/pull/5301) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Private refunds ([#7226](https://github.com/AztecProtocol/aztec-packages/issues/7226)) ([6fafff6](https://github.com/AztecProtocol/aztec-packages/commit/6fafff6e0ccda9d1e07beb5a5e8638f75b0345c2)) +* Remove `dep::` prefix (https://github.com/noir-lang/noir/pull/4946) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Remove event selector in logs from public context ([#7192](https://github.com/AztecProtocol/aztec-packages/issues/7192)) ([646d45a](https://github.com/AztecProtocol/aztec-packages/commit/646d45a0cb92634909fb38d0478181c8d1d814af)) +* Rename struct-specific TypeDefinition -> StructDefinition (https://github.com/noir-lang/noir/pull/5356) ([bb5cbab](https://github.com/AztecProtocol/aztec-packages/commit/bb5cbab945cfd61f6a0da79f8874a0fcdc59361a)) +* Run `comptime` code from annotations on a type definition (https://github.com/noir-lang/noir/pull/5256) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Split storage access oracles ([#7237](https://github.com/AztecProtocol/aztec-packages/issues/7237)) ([51f7d65](https://github.com/AztecProtocol/aztec-packages/commit/51f7d65d69eede9508f44224db554d5185298509)) +* **stdlib:** Update stdlib to use explicit numeric generics (https://github.com/noir-lang/noir/pull/5306) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Store shared mutable hash ([#7169](https://github.com/AztecProtocol/aztec-packages/issues/7169)) ([868606e](https://github.com/AztecProtocol/aztec-packages/commit/868606e6c2c7b71043eabec7cc7b1eb8240fe4b3)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5242) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5340) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5347) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5377) ([bb5cbab](https://github.com/AztecProtocol/aztec-packages/commit/bb5cbab945cfd61f6a0da79f8874a0fcdc59361a)) +* TXE fixes to avm opcodes and missing oracles, forced ci failure ([#7252](https://github.com/AztecProtocol/aztec-packages/issues/7252)) ([de303e2](https://github.com/AztecProtocol/aztec-packages/commit/de303e22e1a1a1115da444cabbe6155833b207b4)) +* Unconstrained variants for event emission ([#7251](https://github.com/AztecProtocol/aztec-packages/issues/7251)) ([6d093e3](https://github.com/AztecProtocol/aztec-packages/commit/6d093e3cb3ed2b81eebf2a7d923f7487b95749cd)) +* Unify unencrypted log emission and decoding ([#7232](https://github.com/AztecProtocol/aztec-packages/issues/7232)) ([354dba2](https://github.com/AztecProtocol/aztec-packages/commit/354dba2ae23a33419360e0983e325ce76939872d)) +* Update rebuild script ([#7225](https://github.com/AztecProtocol/aztec-packages/issues/7225)) ([af59247](https://github.com/AztecProtocol/aztec-packages/commit/af592474c1d57c9d7886763d04afeb793f98efe3)) +* Use runtime loops for brillig array initialization (https://github.com/noir-lang/noir/pull/5243) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Wonky rollups ([#7189](https://github.com/AztecProtocol/aztec-packages/issues/7189)) ([1de3746](https://github.com/AztecProtocol/aztec-packages/commit/1de3746bb691e2e26e9f5c7a90b4437d4433cd48)) + + +### Bug Fixes + +* Add more thorough check for whether a type is valid when passing it from constrained code to unconstrained code (https://github.com/noir-lang/noir/pull/5009) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add support for nested arrays returned by oracles (https://github.com/noir-lang/noir/pull/5132) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Address compiler warnings coming from stdlib (https://github.com/noir-lang/noir/pull/5351) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Avoid duplicating constant arrays (https://github.com/noir-lang/noir/pull/5287) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Avoid panic in type system (https://github.com/noir-lang/noir/pull/5332) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Avoid unnecessarily splitting expressions with multiplication terms with a shared term (https://github.com/noir-lang/noir/pull/5291) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Benchmark prover e2e test with proving ([#7175](https://github.com/AztecProtocol/aztec-packages/issues/7175)) ([431c14c](https://github.com/AztecProtocol/aztec-packages/commit/431c14ccca8bcbdeba51061cad6f6e01f054dd86)) +* Devnet deployment issues ([#7197](https://github.com/AztecProtocol/aztec-packages/issues/7197)) ([9cf4904](https://github.com/AztecProtocol/aztec-packages/commit/9cf49048eefd1f02d22c6b4a8db100b863f39f84)) +* Disable `if` optimization (https://github.com/noir-lang/noir/pull/5240) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **docs:** Check for already deployed account contracts in token bridge tutorial ([#7234](https://github.com/AztecProtocol/aztec-packages/issues/7234)) ([d9efaf7](https://github.com/AztecProtocol/aztec-packages/commit/d9efaf792b921bdabcfc24bea150130c59b3644c)) +* **docs:** Historical reference library updates ([#7166](https://github.com/AztecProtocol/aztec-packages/issues/7166)) ([b3409c4](https://github.com/AztecProtocol/aztec-packages/commit/b3409c48b5d116698a67b4ceb52bd2fb4ee3c8ad)) +* Don't benchmark the "prove" command as it doesn't exist anymore (https://github.com/noir-lang/noir/pull/5323) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Don't lazily elaborate functions (https://github.com/noir-lang/noir/pull/5282) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **elaborator:** Fix duplicate methods error (https://github.com/noir-lang/noir/pull/5225) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **elaborator:** Fix regression introduced by lazy-global changes (https://github.com/noir-lang/noir/pull/5223) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Error when a local function is called in a comptime context (https://github.com/noir-lang/noir/pull/5334) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Fix authwit package ([#7204](https://github.com/AztecProtocol/aztec-packages/issues/7204)) ([98ccd41](https://github.com/AztecProtocol/aztec-packages/commit/98ccd4152ae8ed3e187f4bd8e18927d70627ff04)) +* Fix incorrect return type being applied to stdlib functions `modulus_be_bytes()`, `modulus_be_bits()`, etc. (https://github.com/noir-lang/noir/pull/5278) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Fix test to accomodate new max read requests ([#7286](https://github.com/AztecProtocol/aztec-packages/issues/7286)) ([a023367](https://github.com/AztecProtocol/aztec-packages/commit/a023367e20a11195e6d2b490f5c09a87997bd2ba)) +* Fix tokenization of unquoted types in macros (https://github.com/noir-lang/noir/pull/5326) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Fix usage of `#[abi(tag)]` attribute with elaborator (https://github.com/noir-lang/noir/pull/5298) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Handle struct with nested arrays in oracle return values (https://github.com/noir-lang/noir/pull/5244) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Ignore calls to `Intrinsic::AsWitness` during brillig codegen (https://github.com/noir-lang/noir/pull/5350) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Implement generic functions in the interpreter (https://github.com/noir-lang/noir/pull/5330) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* **nargo_fmt:** Account for spaces before the generic list of a function (https://github.com/noir-lang/noir/pull/5303) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Replace panic in monomorphization with an error (https://github.com/noir-lang/noir/pull/5305) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Reran pil->cpp codegen & encode_and_encrypt_event_with_randomness fix ([#7247](https://github.com/AztecProtocol/aztec-packages/issues/7247)) ([fa15a45](https://github.com/AztecProtocol/aztec-packages/commit/fa15a450408181ffc50946ee56c4ae0fd8c5a61f)) +* Runtime brillig bigint id assignment (https://github.com/noir-lang/noir/pull/5369) ([bb5cbab](https://github.com/AztecProtocol/aztec-packages/commit/bb5cbab945cfd61f6a0da79f8874a0fcdc59361a)) +* Skip emission of brillig calls which will never be executed (https://github.com/noir-lang/noir/pull/5314) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* TS LSP being slow ([#7181](https://github.com/AztecProtocol/aztec-packages/issues/7181)) ([e934e87](https://github.com/AztecProtocol/aztec-packages/commit/e934e872d5a2fb3ca46646436de25777a33c4737)) +* Update `in_contract` flag before handling function metadata in elaborator (https://github.com/noir-lang/noir/pull/5292) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Use proper serialization in `AbiValue` (https://github.com/noir-lang/noir/pull/5270) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) + + +### Miscellaneous + +* `static_assert` error message fix and split into is-dynamic and is-false (https://github.com/noir-lang/noir/pull/5353) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Add back Pedersen blackbox functions (revert PR 5221) (https://github.com/noir-lang/noir/pull/5318) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add log_hash as input in log emission in private context ([#7249](https://github.com/AztecProtocol/aztec-packages/issues/7249)) ([8b3dfe9](https://github.com/AztecProtocol/aztec-packages/commit/8b3dfe9dabc19e24f759b1a6c8ed14e2d9874149)) +* Add no predicate to poseidon2 (https://github.com/noir-lang/noir/pull/5252) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add no-predicate to hash implementations (https://github.com/noir-lang/noir/pull/5253) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Add property tests for ABI encoding (https://github.com/noir-lang/noir/pull/5216) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Address TODO in `compat.nr` (https://github.com/noir-lang/noir/pull/5339) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* **avm-transpiler:** Better error messages ([#7217](https://github.com/AztecProtocol/aztec-packages/issues/7217)) ([27051ad](https://github.com/AztecProtocol/aztec-packages/commit/27051ad988b98d1b4a60064b2492cd987b1df7ac)) +* **avm:** Remove trailing minus zero in codegen ([#7185](https://github.com/AztecProtocol/aztec-packages/issues/7185)) ([f3c8166](https://github.com/AztecProtocol/aztec-packages/commit/f3c81661688cc04b64a389d8fd72484ca8580a05)) +* Avoid building contracts when producing gates report ([#7136](https://github.com/AztecProtocol/aztec-packages/issues/7136)) ([25507e6](https://github.com/AztecProtocol/aztec-packages/commit/25507e63e6a629a8a16ad47434141a95bbb0e102)) +* Bump `bb` to 0.43.0 (https://github.com/noir-lang/noir/pull/5321) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Bundle SSA Evaluator Options (https://github.com/noir-lang/noir/pull/5317) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **ci:** Trigger a noir sync every morning at 8am ([#7280](https://github.com/AztecProtocol/aztec-packages/issues/7280)) ([412c016](https://github.com/AztecProtocol/aztec-packages/commit/412c0160073d642056855c649d9c59ad1ae100f3)) +* Copy across typo PR script from aztec-packages (https://github.com/noir-lang/noir/pull/5235) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Create separate crate just for noir artifacts (https://github.com/noir-lang/noir/pull/5162) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* **docs:** Fixing trailing slash issue (https://github.com/noir-lang/noir/pull/5233) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Fix examples (https://github.com/noir-lang/noir/pull/5357) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Fix migration notes ([#7279](https://github.com/AztecProtocol/aztec-packages/issues/7279)) ([51d93eb](https://github.com/AztecProtocol/aztec-packages/commit/51d93eb3020ea8f8902c814d0f8dd74640535a90)) +* Fix negative tests in AVM circuit for context input lookups ([#7261](https://github.com/AztecProtocol/aztec-packages/issues/7261)) ([ad2f654](https://github.com/AztecProtocol/aztec-packages/commit/ad2f654eb2589dff118c3e104c4f91825ee7f739)) +* Fixing all relative paths (https://github.com/noir-lang/noir/pull/5220) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Generate PIL constants from via constants gen ([#7258](https://github.com/AztecProtocol/aztec-packages/issues/7258)) ([244ef7e](https://github.com/AztecProtocol/aztec-packages/commit/244ef7e5a6871443444df88c28a1c2a7430d6db1)) +* Gets rid of unencrypted emit in private_context ([#7236](https://github.com/AztecProtocol/aztec-packages/issues/7236)) ([3e6d88e](https://github.com/AztecProtocol/aztec-packages/commit/3e6d88e53c3e4c0777e152393d5310b5607baa0a)) +* Improve authwit comments/docs ([#7180](https://github.com/AztecProtocol/aztec-packages/issues/7180)) ([051ab9e](https://github.com/AztecProtocol/aztec-packages/commit/051ab9e3d4eda170c775f683762c81b6876c61ca)) +* Misc cleanup in simulator ([#7203](https://github.com/AztecProtocol/aztec-packages/issues/7203)) ([eb00830](https://github.com/AztecProtocol/aztec-packages/commit/eb00830fce7afae60447bec5383349d7f490e4d7)) +* Optimize the elaborator (https://github.com/noir-lang/noir/pull/5230) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Parse macros (https://github.com/noir-lang/noir/pull/5229) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Pedersen commitment in Noir (https://github.com/noir-lang/noir/pull/5221) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Pedersen hash in Noir (https://github.com/noir-lang/noir/pull/5217) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Private tail circuits ([#7148](https://github.com/AztecProtocol/aztec-packages/issues/7148)) ([9e67e7d](https://github.com/AztecProtocol/aztec-packages/commit/9e67e7d8c47004763df8fdbee9f278a75db193a0)) +* Pull out change to expression splitting from sync PR ([#7215](https://github.com/AztecProtocol/aztec-packages/issues/7215)) ([b4f50a5](https://github.com/AztecProtocol/aztec-packages/commit/b4f50a5bf03babd83c1f467d2792b50e334bf5a7)) +* Pull out foreign call nested array changes ([#7216](https://github.com/AztecProtocol/aztec-packages/issues/7216)) ([1faaaf5](https://github.com/AztecProtocol/aztec-packages/commit/1faaaf53bb7461d1806a79822ded1ecefe01b59b)) +* Pull out noir-lang/noir[#5120](https://github.com/AztecProtocol/aztec-packages/issues/5120) ([#7205](https://github.com/AztecProtocol/aztec-packages/issues/7205)) ([c5dc094](https://github.com/AztecProtocol/aztec-packages/commit/c5dc0946f4d300df5c6a70026e102de8e69f020b)) +* Pull out pedersen generator builtin from sync PR ([#7210](https://github.com/AztecProtocol/aztec-packages/issues/7210)) ([412f02e](https://github.com/AztecProtocol/aztec-packages/commit/412f02eb05321db1bbc60902e31ab50d743541d6)) +* Pull out SSA changes from sync PR ([#7209](https://github.com/AztecProtocol/aztec-packages/issues/7209)) ([141e137](https://github.com/AztecProtocol/aztec-packages/commit/141e137b06b7f9aa324705e716aac2157312aacb)) +* Push code related to ABI gen into `noirc_driver` (https://github.com/noir-lang/noir/pull/5218) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Redo typo PR by dropbigfish (https://github.com/noir-lang/noir/pull/5234) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Reduce note and nullifier constants ([#7255](https://github.com/AztecProtocol/aztec-packages/issues/7255)) ([4637304](https://github.com/AztecProtocol/aztec-packages/commit/463730458de2397d66ec90fedfeee61700c426a4)) +* Refactor test case generation in build.rs (https://github.com/noir-lang/noir/pull/5280) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Refactor to use `mod.nr` support ([#7259](https://github.com/AztecProtocol/aztec-packages/issues/7259)) ([cda45db](https://github.com/AztecProtocol/aztec-packages/commit/cda45dba624e519ace66fd2e75b85d29a0f6eb9f)) +* Release Noir(0.31.0) (https://github.com/noir-lang/noir/pull/5166) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Remove `is_unconstrained_fn` field from elaborator (https://github.com/noir-lang/noir/pull/5335) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Remove 4738 ref ([#7254](https://github.com/AztecProtocol/aztec-packages/issues/7254)) ([97d997c](https://github.com/AztecProtocol/aztec-packages/commit/97d997c851fe319f864e2826903ffa7d8677d701)) +* Remove a log file ([#7201](https://github.com/AztecProtocol/aztec-packages/issues/7201)) ([83bb218](https://github.com/AztecProtocol/aztec-packages/commit/83bb2180cfacd33298b5b3346140453566f3cf8e)) +* Remove commented code ([#7231](https://github.com/AztecProtocol/aztec-packages/issues/7231)) ([2740d60](https://github.com/AztecProtocol/aztec-packages/commit/2740d600c0d4a18ce90df24e334e572a80233832)) +* Remove panic for unimplemented trait dispatch (https://github.com/noir-lang/noir/pull/5329) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Replace `is_bn254` implementation to not rely on truncation of literals (https://github.com/noir-lang/noir/pull/5247) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Replace `regression_5202` with more manageably sized program (https://github.com/noir-lang/noir/pull/5345) ([eb9e9f6](https://github.com/AztecProtocol/aztec-packages/commit/eb9e9f6f2b3952760822faaacb7e851e936e0800)) +* Replace cached `in_contract` with `in_contract()` method (https://github.com/noir-lang/noir/pull/5324) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Replace logical operators with bitwise in `DebugToString` (https://github.com/noir-lang/noir/pull/5236) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Replace relative paths to noir-protocol-circuits ([e83b07b](https://github.com/AztecProtocol/aztec-packages/commit/e83b07bf813001c144c61c61174c6adf816cc991)) +* Replace relative paths to noir-protocol-circuits ([eca8587](https://github.com/AztecProtocol/aztec-packages/commit/eca858775f8f84455cc0a20d9f9fb828cf342b68)) +* Replace relative paths to noir-protocol-circuits ([b9ddf43](https://github.com/AztecProtocol/aztec-packages/commit/b9ddf43faa0184692917d543e39507192b2ac64b)) +* Replace relative paths to noir-protocol-circuits ([6f817e8](https://github.com/AztecProtocol/aztec-packages/commit/6f817e86b61aea78d9f4132ecf4c3ed2f96b4e5c)) +* Replace relative paths to noir-protocol-circuits ([f9bf0a4](https://github.com/AztecProtocol/aztec-packages/commit/f9bf0a4d8ea7591abbb092f1a44b3ff6bcab7af7)) +* Replicate noir-lang/noir[#4946](https://github.com/AztecProtocol/aztec-packages/issues/4946) ([#7202](https://github.com/AztecProtocol/aztec-packages/issues/7202)) ([b5c07d8](https://github.com/AztecProtocol/aztec-packages/commit/b5c07d8507c783ebb440cb32a897416627b71ec1)) +* Simplify compilation flow to write to file immediately (https://github.com/noir-lang/noir/pull/5265) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Split off fuzzer, abi changes and `noirc_artifacts` from sync ([#7208](https://github.com/AztecProtocol/aztec-packages/issues/7208)) ([255d752](https://github.com/AztecProtocol/aztec-packages/commit/255d752594dd5372c75934a784e995ae4899e431)) +* Thread generics through ACIR/brillig gen (https://github.com/noir-lang/noir/pull/5120) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) +* Use `push_err` more in elaborator (https://github.com/noir-lang/noir/pull/5336) ([f2abb4e](https://github.com/AztecProtocol/aztec-packages/commit/f2abb4e9deb05437666db9c27cd0d49c2ec9ac3d)) +* Use options.limit as upper limit for note-getter loop ([#7253](https://github.com/AztecProtocol/aztec-packages/issues/7253)) ([8ff669b](https://github.com/AztecProtocol/aztec-packages/commit/8ff669b63f302447e099dc52dea248c2ca914043)) +* Use prefix op_ for every instruction in avm_trace.hpp ([#7214](https://github.com/AztecProtocol/aztec-packages/issues/7214)) ([7ed7558](https://github.com/AztecProtocol/aztec-packages/commit/7ed75586cd5deb8aff3730a80cb29c642495bbff)) +* Use the elaborator by default (https://github.com/noir-lang/noir/pull/5246) ([ed815a3](https://github.com/AztecProtocol/aztec-packages/commit/ed815a3713fc311056a8bd0a616945f12d9be2a8)) + +## [0.44.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.43.0...aztec-packages-v0.44.0) (2024-06-26) + + +### ⚠ BREAKING CHANGES + +* make note_getter return BoundedVec instead of an Option array ([#7050](https://github.com/AztecProtocol/aztec-packages/issues/7050)) +* TXE ([#6985](https://github.com/AztecProtocol/aztec-packages/issues/6985)) + +### Features + +* Add macro impls for events ([#7081](https://github.com/AztecProtocol/aztec-packages/issues/7081)) ([c13dd9f](https://github.com/AztecProtocol/aztec-packages/commit/c13dd9fbc9f5390dc4613e5739d3ec3120430087)) +* Add OpenTelemetry to node ([#7102](https://github.com/AztecProtocol/aztec-packages/issues/7102)) ([6bf2b72](https://github.com/AztecProtocol/aztec-packages/commit/6bf2b7269fddb5bd7fe4c567710146b4969d2845)) +* Added prove_output_all flow for honk ([#6869](https://github.com/AztecProtocol/aztec-packages/issues/6869)) ([7bd7c66](https://github.com/AztecProtocol/aztec-packages/commit/7bd7c66de6adb1f703509e9a8e8911ff0ec2025c)) +* **avm:** Add ECC ops to avm_proving_test ([#7058](https://github.com/AztecProtocol/aztec-packages/issues/7058)) ([7f62a90](https://github.com/AztecProtocol/aztec-packages/commit/7f62a901c848020058a58f6e772d495566416e0b)) +* **avm:** Cpp msm changes ([#7056](https://github.com/AztecProtocol/aztec-packages/issues/7056)) ([f9c8f20](https://github.com/AztecProtocol/aztec-packages/commit/f9c8f20f1bd6af0003960b19f61b737e3bad5f1e)) +* **avm:** Include bb-pilcom in monorepo ([#7098](https://github.com/AztecProtocol/aztec-packages/issues/7098)) ([0442158](https://github.com/AztecProtocol/aztec-packages/commit/044215814ac75df37c1d3ce3a6852b4ac49e6065)) +* Constrain event encryption and unify note and event emit api ([#7171](https://github.com/AztecProtocol/aztec-packages/issues/7171)) ([5c3772f](https://github.com/AztecProtocol/aztec-packages/commit/5c3772f09e812a05882039ad888089c238f14001)), closes [#7160](https://github.com/AztecProtocol/aztec-packages/issues/7160) +* Conventional lookups using log-deriv ([#7020](https://github.com/AztecProtocol/aztec-packages/issues/7020)) ([6f1212f](https://github.com/AztecProtocol/aztec-packages/commit/6f1212ff0d6bb7a326e571da2d49cfac75a8e5de)) +* Devnet deployments ([#7024](https://github.com/AztecProtocol/aztec-packages/issues/7024)) ([fa70876](https://github.com/AztecProtocol/aztec-packages/commit/fa70876a17b981e6ffa4bece390186b1231ba4fe)) +* Do not discard logs on revert since the kernel has pruned revertible logs. ([#7076](https://github.com/AztecProtocol/aztec-packages/issues/7076)) ([366fb21](https://github.com/AztecProtocol/aztec-packages/commit/366fb210e4cdb63fb872567506b6c12e57a0508b)), closes [#4712](https://github.com/AztecProtocol/aztec-packages/issues/4712) +* **docs:** Publish PDF of protocol specs + remove links to pages in item lists in protocol specs ([#6684](https://github.com/AztecProtocol/aztec-packages/issues/6684)) ([367e3cf](https://github.com/AztecProtocol/aztec-packages/commit/367e3cf55f0281658c3da3ccd2b6cc87b707cb92)) +* Enable merge recursive verifier in Goblin recursive verifier ([#7182](https://github.com/AztecProtocol/aztec-packages/issues/7182)) ([9b4f56c](https://github.com/AztecProtocol/aztec-packages/commit/9b4f56c89fb17eb3497987e6f9198441a4e89c56)) +* Flamegraph helper script ([#7077](https://github.com/AztecProtocol/aztec-packages/issues/7077)) ([8630c8f](https://github.com/AztecProtocol/aztec-packages/commit/8630c8f2018c711b84997dc4727d5123ad616107)) +* Full test skips public simulation ([#7186](https://github.com/AztecProtocol/aztec-packages/issues/7186)) ([4c1997f](https://github.com/AztecProtocol/aztec-packages/commit/4c1997fdc989fc12c0fb50f690558fccab8e0cd1)) +* Make note_getter return BoundedVec instead of an Option array ([#7050](https://github.com/AztecProtocol/aztec-packages/issues/7050)) ([f9ac0fc](https://github.com/AztecProtocol/aztec-packages/commit/f9ac0fca40a9d7273ec2adddbfbe961f86595f56)) +* **p2p:** More comprehensive peer management, dial retries, persistence fix ([#6953](https://github.com/AztecProtocol/aztec-packages/issues/6953)) ([cdd1cbd](https://github.com/AztecProtocol/aztec-packages/commit/cdd1cbd2ff5a8aceb52bde44c24462fed0808890)) +* Private authwit with static call ([#7073](https://github.com/AztecProtocol/aztec-packages/issues/7073)) ([9c52d47](https://github.com/AztecProtocol/aztec-packages/commit/9c52d474146177b83f78ab9f12d9d41a03678838)) +* Several updates in SMT verification module ([#7105](https://github.com/AztecProtocol/aztec-packages/issues/7105)) ([41b21f1](https://github.com/AztecProtocol/aztec-packages/commit/41b21f179ead617203c6d77b080e4f8b0065e06c)) +* Shplonk revival in ECCVM ([#7164](https://github.com/AztecProtocol/aztec-packages/issues/7164)) ([34eb5a0](https://github.com/AztecProtocol/aztec-packages/commit/34eb5a01d34e5ff5d1414fff53ca0623d83bde5d)) +* Throwing errors in `BufferReader` when out of bounds ([#7149](https://github.com/AztecProtocol/aztec-packages/issues/7149)) ([bf4a986](https://github.com/AztecProtocol/aztec-packages/commit/bf4a986cb07c923b606944ff48960b2df2ea7c6e)) +* Track spans ([#7129](https://github.com/AztecProtocol/aztec-packages/issues/7129)) ([924c3f8](https://github.com/AztecProtocol/aztec-packages/commit/924c3f8809b30d16e81eed5e467aa79ee7074f77)) +* TXE ([#6985](https://github.com/AztecProtocol/aztec-packages/issues/6985)) ([109624f](https://github.com/AztecProtocol/aztec-packages/commit/109624f127dc8da6d9d963b3af9250237be0d4e4)) +* TXE 2: Electric boogaloo ([#7154](https://github.com/AztecProtocol/aztec-packages/issues/7154)) ([bb38246](https://github.com/AztecProtocol/aztec-packages/commit/bb38246d09ee0e5430d31ade32bc28da688b4a84)) + + +### Bug Fixes + +* **avm:** Fix unencryptedlog c++ deser ([#7194](https://github.com/AztecProtocol/aztec-packages/issues/7194)) ([89a99af](https://github.com/AztecProtocol/aztec-packages/commit/89a99af4ff2ea79c276ff379a3cdd1b8cae18d15)) +* **avm:** Re-enable ext call test ([#7147](https://github.com/AztecProtocol/aztec-packages/issues/7147)) ([33ccf1b](https://github.com/AztecProtocol/aztec-packages/commit/33ccf1b61260868e6bb027b7838ef530717bff01)) +* **avm:** Reenable tag error sload ([#7153](https://github.com/AztecProtocol/aztec-packages/issues/7153)) ([fd92d46](https://github.com/AztecProtocol/aztec-packages/commit/fd92d467eee51638b896852b789c8fae17e0689c)) +* **avm:** Update codegen ([#7178](https://github.com/AztecProtocol/aztec-packages/issues/7178)) ([1d29708](https://github.com/AztecProtocol/aztec-packages/commit/1d29708bb6136184c27c1dc4f632b277cf3e4e64)) +* Bug fixing bench prover test ([#7135](https://github.com/AztecProtocol/aztec-packages/issues/7135)) ([13678be](https://github.com/AztecProtocol/aztec-packages/commit/13678be4e1c76d20a804a04b0fa82f68aeca38ae)), closes [#7080](https://github.com/AztecProtocol/aztec-packages/issues/7080) +* **ci:** Don't run npm_deploy l1-contracts ([#7187](https://github.com/AztecProtocol/aztec-packages/issues/7187)) ([80d26d8](https://github.com/AztecProtocol/aztec-packages/commit/80d26d883154b81f0f92664d61c907bcfe46509b)) +* **ci:** Move osxcross from build image ([#7151](https://github.com/AztecProtocol/aztec-packages/issues/7151)) ([7746363](https://github.com/AztecProtocol/aztec-packages/commit/77463638133113de074a6030954a2be9954638e1)) +* Enable log filtering with the DEBUG variable ([#7150](https://github.com/AztecProtocol/aztec-packages/issues/7150)) ([33798b6](https://github.com/AztecProtocol/aztec-packages/commit/33798b6b8d32b88ce2719b4c6dd7ac9024a88c7f)) +* Export event selector and replace function selector with event selector where appropriate ([#7095](https://github.com/AztecProtocol/aztec-packages/issues/7095)) ([fcc15fa](https://github.com/AztecProtocol/aztec-packages/commit/fcc15faffac98ab844dbad51e949c24114a8bcf0)), closes [#7089](https://github.com/AztecProtocol/aztec-packages/issues/7089) +* False decryption fix ([#7066](https://github.com/AztecProtocol/aztec-packages/issues/7066)) ([48d9df4](https://github.com/AztecProtocol/aztec-packages/commit/48d9df4ff227c08a6e66f21c0286bc6349151671)) +* Fix bug for a unit test in full proving mode repated to MSM ([#7104](https://github.com/AztecProtocol/aztec-packages/issues/7104)) ([e37809b](https://github.com/AztecProtocol/aztec-packages/commit/e37809bdcdcf76f89f68403ee75aaf6d32c79a94)) + + +### Miscellaneous + +* `destroy_note(...)` optimization ([#7103](https://github.com/AztecProtocol/aztec-packages/issues/7103)) ([0770011](https://github.com/AztecProtocol/aztec-packages/commit/0770011139d698ffa466605f0c10f0f5fe965da3)) +* Add avm team as codeowners to more repo files ([#7196](https://github.com/AztecProtocol/aztec-packages/issues/7196)) ([9be0ad6](https://github.com/AztecProtocol/aztec-packages/commit/9be0ad6b41a69c35ad9737d60da7a16300b87642)) +* **avm:** Remove avm prefix from pil and executor ([#7099](https://github.com/AztecProtocol/aztec-packages/issues/7099)) ([b502fcd](https://github.com/AztecProtocol/aztec-packages/commit/b502fcd500dcb10945b29d00f86e290bec63cce3)) +* **avm:** Renamings and comments ([#7128](https://github.com/AztecProtocol/aztec-packages/issues/7128)) ([ed2f98e](https://github.com/AztecProtocol/aztec-packages/commit/ed2f98ee9d7f540fbdfae09a0117bf22aaf6ebc7)) +* **avm:** Separate some fixed tables ([#7163](https://github.com/AztecProtocol/aztec-packages/issues/7163)) ([1d4a9a2](https://github.com/AztecProtocol/aztec-packages/commit/1d4a9a29ad37543aa0058bd43fa533f19a91e019)) +* **ci:** Add new e2e base target ([#7179](https://github.com/AztecProtocol/aztec-packages/issues/7179)) ([26fc599](https://github.com/AztecProtocol/aztec-packages/commit/26fc59965b4bd95ba8b06ec3139e3fc44e5c3495)) +* Create workflow for full AVM tests ([#7051](https://github.com/AztecProtocol/aztec-packages/issues/7051)) ([a0b9c4b](https://github.com/AztecProtocol/aztec-packages/commit/a0b9c4b4383f448549c04567cd9c9264ce4240dc)), closes [#6643](https://github.com/AztecProtocol/aztec-packages/issues/6643) +* **docs:** Fix migration notes ([#7195](https://github.com/AztecProtocol/aztec-packages/issues/7195)) ([88efda0](https://github.com/AztecProtocol/aztec-packages/commit/88efda0b40b3a90c4a3b09badaaec8678edd0da7)) +* **docs:** Moving tutorials and quick starts around, spinning off codespaces page ([#6777](https://github.com/AztecProtocol/aztec-packages/issues/6777)) ([1542fa6](https://github.com/AztecProtocol/aztec-packages/commit/1542fa699e32ef88c1a8b9ba3d1f74315a5bb63e)) +* Fix migration notes ([#7133](https://github.com/AztecProtocol/aztec-packages/issues/7133)) ([14917d3](https://github.com/AztecProtocol/aztec-packages/commit/14917d3d8c5da1f6038597d9129c6051a2fd94de)) +* Fix noir-projects dockerfile for CircleCI ([#7093](https://github.com/AztecProtocol/aztec-packages/issues/7093)) ([52ce25d](https://github.com/AztecProtocol/aztec-packages/commit/52ce25d1abcc5a8cff7ec360acf23806cb317b57)) +* Increase the timeout of the runner for full AVM workflow to 70 minutes ([#7183](https://github.com/AztecProtocol/aztec-packages/issues/7183)) ([9aabc32](https://github.com/AztecProtocol/aztec-packages/commit/9aabc324040e84be9d61644d33948c818553f422)) +* Indirects and read/write slices ([#7082](https://github.com/AztecProtocol/aztec-packages/issues/7082)) ([d5e80ee](https://github.com/AztecProtocol/aztec-packages/commit/d5e80ee9b6298f7edf39b99ff51ae7cc26b8cbd8)) +* Minor naming cleanup ([#7144](https://github.com/AztecProtocol/aztec-packages/issues/7144)) ([20e2492](https://github.com/AztecProtocol/aztec-packages/commit/20e249278d3c161e72901d61bb259cb1d297e44c)) +* Note hashes cleanup + optimization ([#7132](https://github.com/AztecProtocol/aztec-packages/issues/7132)) ([edd6d3f](https://github.com/AztecProtocol/aztec-packages/commit/edd6d3ffdddd6aa29c6638e5fab87aadf5d89d09)) +* Note hashing gate optimizations ([#7130](https://github.com/AztecProtocol/aztec-packages/issues/7130)) ([81a2580](https://github.com/AztecProtocol/aztec-packages/commit/81a258003f93335eba2d9d07ffc4f0feca935956)) +* **powdr:** Update to latest and add logging ([#7152](https://github.com/AztecProtocol/aztec-packages/issues/7152)) ([f500f2e](https://github.com/AztecProtocol/aztec-packages/commit/f500f2eeca5abc731ad942e956b8a6b56c6922f5)) +* Reads the return data ([#6669](https://github.com/AztecProtocol/aztec-packages/issues/6669)) ([ef85542](https://github.com/AztecProtocol/aztec-packages/commit/ef8554268c175e6349474883c6072e3979fe45c0)) +* Refactor AVM simulator's side-effect tracing ([#7091](https://github.com/AztecProtocol/aztec-packages/issues/7091)) ([9495413](https://github.com/AztecProtocol/aztec-packages/commit/94954131ea61bb6b58efe4e9f8b4e1f489f53fa9)) +* Remove stray files ([#7158](https://github.com/AztecProtocol/aztec-packages/issues/7158)) ([29398de](https://github.com/AztecProtocol/aztec-packages/commit/29398de7625f70e0efdcc8f9acdda656337c56db)) +* Remove unneeded public input folding ([#7094](https://github.com/AztecProtocol/aztec-packages/issues/7094)) ([c30dc38](https://github.com/AztecProtocol/aztec-packages/commit/c30dc3856cec038d8c53af34cf82e08b0cb456aa)) +* Replace relative paths to noir-protocol-circuits ([f7e4392](https://github.com/AztecProtocol/aztec-packages/commit/f7e439257380b5061e561870addb5be68d753cfc)) +* Replace relative paths to noir-protocol-circuits ([886f7b1](https://github.com/AztecProtocol/aztec-packages/commit/886f7b1cb062c7bf2322122c7881f99b0cd58313)) +* Replace relative paths to noir-protocol-circuits ([b1081f8](https://github.com/AztecProtocol/aztec-packages/commit/b1081f80d1891f70295a850dc1995a2e63d880bf)) +* Replace relative paths to noir-protocol-circuits ([c0989eb](https://github.com/AztecProtocol/aztec-packages/commit/c0989eb159ed9fcb2eaacf57d2c209cc071b5669)) +* Replace relative paths to noir-protocol-circuits ([525bbe7](https://github.com/AztecProtocol/aztec-packages/commit/525bbe750a8154d98355694ad9e1f3e33275ab5b)) +* Replace relative paths to noir-protocol-circuits ([67bcd82](https://github.com/AztecProtocol/aztec-packages/commit/67bcd8279f0d8921437a6f37e6ec3f25a69471a5)) +* Take the PCS out of Zeromorph and refactor tests ([#7078](https://github.com/AztecProtocol/aztec-packages/issues/7078)) ([e192678](https://github.com/AztecProtocol/aztec-packages/commit/e19267872bae6fa2df258a1e363f1ba2f2f47922)) +* Track avm proving time ([#7084](https://github.com/AztecProtocol/aztec-packages/issues/7084)) ([59df722](https://github.com/AztecProtocol/aztec-packages/commit/59df72249a8db2b6d1cf0c7908836041c84a54c1)) +* Ultra flavor cleanup ([#7070](https://github.com/AztecProtocol/aztec-packages/issues/7070)) ([77761c6](https://github.com/AztecProtocol/aztec-packages/commit/77761c670f2d516ab486de0f7bde036ff00ebd99)) + ## [0.43.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-packages-v0.42.0...aztec-packages-v0.43.0) (2024-06-18) diff --git a/CODEOWNERS b/CODEOWNERS index 9d8055da4cd6..48a9dbe1b124 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -12,8 +12,8 @@ /barretenberg/cpp/pil @Maddiaa0 @jeanmon @IlyasRidhuan @fcarreiro # on changes to PIL-generated C++ /barretenberg/cpp/src/barretenberg/**/generated @jeanmon @IlyasRidhuan @fcarreiro -# on changes to AVM trace (C++ witness generator) -/barretenberg/cpp/src/barretenberg/vm/avm_trace @jeanmon @IlyasRidhuan @fcarreiro +# on changes to AVM C++ code +/barretenberg/cpp/src/barretenberg/vm @jeanmon @IlyasRidhuan @fcarreiro # on changes to public context in aztec-nr /noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @fcarreiro @dbanks12 /noir-projects/aztec-nr/aztec/src/context/public_context.nr @fcarreiro @dbanks12 @@ -24,7 +24,6 @@ /yarn-project/simulator/src/public/side_effect_trace.test.ts @fcarreiro @dbanks12 /yarn-project/simulator/src/public/side_effect_trace.ts @fcarreiro @dbanks12 /yarn-project/simulator/src/public/side_effect_trace_interface.ts @fcarreiro @dbanks12 -/yarn-project/simulator/src/public/transitional_adaptors.ts @fcarreiro @dbanks12 # on changes to the AVM transpiler /avm-transpiler/src @fcarreiro @dbanks12 ##################################################### diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index b08fa7d74380..965e79489c1c 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir_field", "base64 0.21.7", @@ -18,7 +18,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.46.0" +version = "0.47.0" dependencies = [ "ark-bn254", "ark-ff", @@ -30,7 +30,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -44,7 +44,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "blake2", @@ -381,7 +381,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir_field", "serde", @@ -389,7 +389,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -691,7 +691,7 @@ dependencies = [ [[package]] name = "fm" -version = "0.30.0" +version = "0.31.0" dependencies = [ "codespan-reporting", "serde", @@ -839,7 +839,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.30.0" +version = "0.31.0" [[package]] name = "itertools" @@ -944,7 +944,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "base64 0.21.7", @@ -962,7 +962,7 @@ dependencies = [ [[package]] name = "noirc_printable_type" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "iter-extended", diff --git a/avm-transpiler/scripts/compile_then_transpile.sh b/avm-transpiler/scripts/compile_then_transpile.sh index 21c4ab486b62..d9008cc101cf 100755 --- a/avm-transpiler/scripts/compile_then_transpile.sh +++ b/avm-transpiler/scripts/compile_then_transpile.sh @@ -18,7 +18,7 @@ fi shift # remove the compile arg so we can inject --show-artifact-paths # Forward all arguments to nargo, tee output to console -artifacts_to_transpile=$($NARGO compile --show-artifact-paths $@ | tee /dev/tty | grep -oP 'Saved contract artifact to: \K.*') +artifacts_to_transpile=$($NARGO compile --use-legacy --show-artifact-paths $@ | tee /dev/tty | grep -oP 'Saved contract artifact to: \K.*') # NOTE: the output that is teed to /dev/tty will normally not be redirectable by the caller. # If the script is run via docker, however, the user will see this output on stdout and will be able to redirect. diff --git a/avm-transpiler/src/main.rs b/avm-transpiler/src/main.rs index 1a858d596011..a6c2c118123f 100644 --- a/avm-transpiler/src/main.rs +++ b/avm-transpiler/src/main.rs @@ -20,12 +20,17 @@ fn main() { let args: Vec = env::args().collect(); let in_contract_artifact_path = &args[1]; let out_transpiled_artifact_path = &args[2]; + let json_parse_error = format!( + "Unable to parse json for: {in_contract_artifact_path} + This is probably a stale json file with a different wire format. + You might need to recompile the contract or delete the json file" + ); // Parse original (pre-transpile) contract. - let contract_json = - fs::read_to_string(Path::new(in_contract_artifact_path)).expect("Unable to read file"); + let contract_json = fs::read_to_string(Path::new(in_contract_artifact_path)) + .expect(&format!("Unable to read file: {in_contract_artifact_path}")); let raw_json_obj: serde_json::Value = - serde_json::from_str(&contract_json).expect("Unable to parse json"); + serde_json::from_str(&contract_json).expect(&json_parse_error); // Skip if contract has "transpiled: true" flag! if let Some(serde_json::Value::Bool(true)) = raw_json_obj.get("transpiled") { @@ -33,16 +38,18 @@ fn main() { return; } - // Backup the original file. - std::fs::copy( - Path::new(in_contract_artifact_path), - Path::new(&(in_contract_artifact_path.clone() + ".bak")), - ) - .expect("Unable to backup file"); + // Backup the output file if it already exists. + if Path::new(out_transpiled_artifact_path).exists() { + std::fs::copy( + Path::new(out_transpiled_artifact_path), + Path::new(&(out_transpiled_artifact_path.clone() + ".bak")), + ) + .expect(&format!("Unable to backup file: {out_transpiled_artifact_path}")); + } // Parse json into contract object let contract: CompiledAcirContractArtifact = - serde_json::from_str(&contract_json).expect("Unable to parse json"); + serde_json::from_str(&contract_json).expect(&json_parse_error); // Transpile contract to AVM bytecode let transpiled_contract = TranspiledContractArtifact::from(contract); diff --git a/avm-transpiler/src/opcodes.rs b/avm-transpiler/src/opcodes.rs index 11cd956237dc..d1e510699e87 100644 --- a/avm-transpiler/src/opcodes.rs +++ b/avm-transpiler/src/opcodes.rs @@ -23,15 +23,15 @@ pub enum AvmOpcode { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, CALLDATACOPY, @@ -106,16 +106,16 @@ impl AvmOpcode { AvmOpcode::ADDRESS => "ADDRESS", AvmOpcode::STORAGEADDRESS => "STORAGEADDRESS", AvmOpcode::SENDER => "SENDER", - AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", - AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", + AvmOpcode::FUNCTIONSELECTOR => "FUNCTIONSELECTOR", AvmOpcode::TRANSACTIONFEE => "TRANSACTIONFEE", - AvmOpcode::CONTRACTCALLDEPTH => "CONTRACTCALLDEPTH", // Execution Environment - Globals AvmOpcode::CHAINID => "CHAINID", AvmOpcode::VERSION => "VERSION", AvmOpcode::BLOCKNUMBER => "BLOCKNUMBER", AvmOpcode::TIMESTAMP => "TIMESTAMP", AvmOpcode::COINBASE => "COINBASE", + AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS", + AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS", AvmOpcode::BLOCKL2GASLIMIT => "BLOCKL2GASLIMIT", AvmOpcode::BLOCKDAGASLIMIT => "BLOCKDAGASLIMIT", // Execution Environment - Calldata diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index f1fdd201b8b7..c50fc327f899 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -247,7 +247,7 @@ fn handle_foreign_call( "avmOpcodeStaticCall" => { handle_external_call(avm_instrs, destinations, inputs, AvmOpcode::STATICCALL); } - "amvOpcodeEmitUnencryptedLog" => { + "avmOpcodeEmitUnencryptedLog" => { handle_emit_unencrypted_log(avm_instrs, destinations, inputs); } "avmOpcodeNoteHashExists" => handle_note_hash_exists(avm_instrs, destinations, inputs), @@ -263,8 +263,8 @@ fn handle_foreign_call( "avmOpcodeGetContractInstance" => { handle_get_contract_instance(avm_instrs, destinations, inputs); } - "storageRead" => handle_storage_read(avm_instrs, destinations, inputs), - "storageWrite" => handle_storage_write(avm_instrs, destinations, inputs), + "avmOpcodeStorageRead" => handle_storage_read(avm_instrs, destinations, inputs), + "avmOpcodeStorageWrite" => handle_storage_write(avm_instrs, destinations, inputs), "debugLog" => handle_debug_log(avm_instrs, destinations, inputs), // Getters. _ if inputs.is_empty() && destinations.len() == 1 => { @@ -314,11 +314,9 @@ fn handle_external_call( ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer.0 as u32, size.0 as u32), _ => panic!("Call instruction's args input should be a HeapVector input"), }; - let temporary_function_selector_offset = match &inputs[4] { + let function_selector_offset = match &inputs[4] { ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, - _ => panic!( - "Call instruction's temporary function selector input should be a basic MemoryAddress", - ), + _ => panic!("Call instruction's function selector input should be a basic MemoryAddress",), }; let ret_offset_maybe = destinations[0]; @@ -351,7 +349,7 @@ fn handle_external_call( AvmOperand::U32 { value: ret_offset }, AvmOperand::U32 { value: ret_size }, AvmOperand::U32 { value: success_offset }, - AvmOperand::U32 { value: temporary_function_selector_offset }, + AvmOperand::U32 { value: function_selector_offset }, ], ..Default::default() }); @@ -435,32 +433,25 @@ fn handle_emit_unencrypted_log( destinations: &Vec, inputs: &Vec, ) { - if !destinations.is_empty() || inputs.len() != 3 { + if !destinations.is_empty() || inputs.len() != 2 { panic!( - "Transpiler expects ForeignCall::EMITUNENCRYPTEDLOG to have 0 destinations and 3 inputs, got {} and {}", + "Transpiler expects ForeignCall::EMITUNENCRYPTEDLOG to have 0 destinations and 2 inputs, got {} and {}", destinations.len(), inputs.len() ); } - let event_offset = match &inputs[0] { - ValueOrArray::MemoryAddress(offset) => offset.to_usize() as u32, - _ => panic!( - "Unexpected inputs[0] (event) for ForeignCall::EMITUNENCRYPTEDLOG: {:?}", - inputs[0] - ), - }; + // The fields are a slice, and this is represented as a (length: Field, slice: HeapVector). // The length field is redundant and we skipt it. - let (message_offset, message_size_offset) = match &inputs[2] { + let (message_offset, message_size_offset) = match &inputs[1] { ValueOrArray::HeapVector(vec) => (vec.pointer.to_usize() as u32, vec.size.0 as u32), _ => panic!("Unexpected inputs for ForeignCall::EMITUNENCRYPTEDLOG: {:?}", inputs), }; avm_instrs.push(AvmInstruction { opcode: AvmOpcode::EMITUNENCRYPTEDLOG, // The message array from Brillig is indirect. - indirect: Some(FIRST_OPERAND_INDIRECT), + indirect: Some(ZEROTH_OPERAND_INDIRECT), operands: vec![ - AvmOperand::U32 { value: event_offset }, AvmOperand::U32 { value: message_offset }, AvmOperand::U32 { value: message_size_offset }, ], @@ -657,6 +648,7 @@ fn handle_getter_instruction( "avmOpcodeTimestamp" => AvmOpcode::TIMESTAMP, "avmOpcodeL2GasLeft" => AvmOpcode::L2GASLEFT, "avmOpcodeDaGasLeft" => AvmOpcode::DAGASLEFT, + "avmOpcodeFunctionSelector" => AvmOpcode::FUNCTIONSELECTOR, // "callStackDepth" => AvmOpcode::CallStackDepth, _ => panic!("Transpiler doesn't know how to process ForeignCall function {:?}", function), }; @@ -933,7 +925,7 @@ fn handle_storage_write( inputs: &Vec, ) { assert!(inputs.len() == 2); - assert!(destinations.len() == 1); + assert!(destinations.len() == 0); let slot_offset_maybe = inputs[0]; let slot_offset = match slot_offset_maybe { @@ -999,8 +991,8 @@ fn handle_storage_read( inputs: &Vec, ) { // For the foreign calls we want to handle, we do not want inputs, as they are getters - assert!(inputs.len() == 2); // output, len - but we dont use this len - its for the oracle - assert!(destinations.len() == 1); + assert!(inputs.len() == 2); // output, len. The latter is not used by the AVM, but required in the oracle call so that TXE knows how many slots to read. + assert!(destinations.len() == 1); // return values let slot_offset_maybe = inputs[0]; let slot_offset = match slot_offset_maybe { diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index b994cf1a68cd..e6ec92110c14 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 947c5552eeb784dad1abb5ecebdb6a80880fec08 - parent = 94954131ea61bb6b58efe4e9f8b4e1f489f53fa9 + commit = 6c5e3b6b9170673a3bedbb82f3e6dc4162f457a2 + parent = d3388d46f0c1c3a4c9f6a15abeae41f764039c10 method = merge cmdver = 0.4.6 diff --git a/barretenberg/CHANGELOG.md b/barretenberg/CHANGELOG.md index 38233698dbcc..e8d8c48a0439 100644 --- a/barretenberg/CHANGELOG.md +++ b/barretenberg/CHANGELOG.md @@ -1,5 +1,67 @@ # Changelog +## [0.45.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.44.0...barretenberg-v0.45.0) (2024-07-02) + + +### Features + +* **avm:** Calldata gadget preliminaries ([#7227](https://github.com/AztecProtocol/aztec-packages/issues/7227)) ([79e8588](https://github.com/AztecProtocol/aztec-packages/commit/79e85883c90465cf2ff6e1a2d7af0e5d4d3e111c)) +* Constant Honk proof sizes ([#6954](https://github.com/AztecProtocol/aztec-packages/issues/6954)) ([17c8d3a](https://github.com/AztecProtocol/aztec-packages/commit/17c8d3a00f3a2e500d5caa1fb438504bcd357e8a)) +* Function selector opcode in AVM ([#7244](https://github.com/AztecProtocol/aztec-packages/issues/7244)) ([dde47e9](https://github.com/AztecProtocol/aztec-packages/commit/dde47e927ebe5606a272a35dd8c4f4876369b244)) +* Update rebuild script ([#7225](https://github.com/AztecProtocol/aztec-packages/issues/7225)) ([af59247](https://github.com/AztecProtocol/aztec-packages/commit/af592474c1d57c9d7886763d04afeb793f98efe3)) + + +### Bug Fixes + +* Benchmark prover e2e test with proving ([#7175](https://github.com/AztecProtocol/aztec-packages/issues/7175)) ([431c14c](https://github.com/AztecProtocol/aztec-packages/commit/431c14ccca8bcbdeba51061cad6f6e01f054dd86)) +* Reran pil->cpp codegen & encode_and_encrypt_event_with_randomness fix ([#7247](https://github.com/AztecProtocol/aztec-packages/issues/7247)) ([fa15a45](https://github.com/AztecProtocol/aztec-packages/commit/fa15a450408181ffc50946ee56c4ae0fd8c5a61f)) + + +### Miscellaneous + +* **avm:** Remove trailing minus zero in codegen ([#7185](https://github.com/AztecProtocol/aztec-packages/issues/7185)) ([f3c8166](https://github.com/AztecProtocol/aztec-packages/commit/f3c81661688cc04b64a389d8fd72484ca8580a05)) +* Fix negative tests in AVM circuit for context input lookups ([#7261](https://github.com/AztecProtocol/aztec-packages/issues/7261)) ([ad2f654](https://github.com/AztecProtocol/aztec-packages/commit/ad2f654eb2589dff118c3e104c4f91825ee7f739)) +* Generate PIL constants from via constants gen ([#7258](https://github.com/AztecProtocol/aztec-packages/issues/7258)) ([244ef7e](https://github.com/AztecProtocol/aztec-packages/commit/244ef7e5a6871443444df88c28a1c2a7430d6db1)) +* Reduce note and nullifier constants ([#7255](https://github.com/AztecProtocol/aztec-packages/issues/7255)) ([4637304](https://github.com/AztecProtocol/aztec-packages/commit/463730458de2397d66ec90fedfeee61700c426a4)) +* Use prefix op_ for every instruction in avm_trace.hpp ([#7214](https://github.com/AztecProtocol/aztec-packages/issues/7214)) ([7ed7558](https://github.com/AztecProtocol/aztec-packages/commit/7ed75586cd5deb8aff3730a80cb29c642495bbff)) + +## [0.44.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.43.0...barretenberg-v0.44.0) (2024-06-26) + + +### Features + +* Added prove_output_all flow for honk ([#6869](https://github.com/AztecProtocol/aztec-packages/issues/6869)) ([7bd7c66](https://github.com/AztecProtocol/aztec-packages/commit/7bd7c66de6adb1f703509e9a8e8911ff0ec2025c)) +* **avm:** Add ECC ops to avm_proving_test ([#7058](https://github.com/AztecProtocol/aztec-packages/issues/7058)) ([7f62a90](https://github.com/AztecProtocol/aztec-packages/commit/7f62a901c848020058a58f6e772d495566416e0b)) +* **avm:** Cpp msm changes ([#7056](https://github.com/AztecProtocol/aztec-packages/issues/7056)) ([f9c8f20](https://github.com/AztecProtocol/aztec-packages/commit/f9c8f20f1bd6af0003960b19f61b737e3bad5f1e)) +* **avm:** Include bb-pilcom in monorepo ([#7098](https://github.com/AztecProtocol/aztec-packages/issues/7098)) ([0442158](https://github.com/AztecProtocol/aztec-packages/commit/044215814ac75df37c1d3ce3a6852b4ac49e6065)) +* Conventional lookups using log-deriv ([#7020](https://github.com/AztecProtocol/aztec-packages/issues/7020)) ([6f1212f](https://github.com/AztecProtocol/aztec-packages/commit/6f1212ff0d6bb7a326e571da2d49cfac75a8e5de)) +* Enable merge recursive verifier in Goblin recursive verifier ([#7182](https://github.com/AztecProtocol/aztec-packages/issues/7182)) ([9b4f56c](https://github.com/AztecProtocol/aztec-packages/commit/9b4f56c89fb17eb3497987e6f9198441a4e89c56)) +* Several updates in SMT verification module ([#7105](https://github.com/AztecProtocol/aztec-packages/issues/7105)) ([41b21f1](https://github.com/AztecProtocol/aztec-packages/commit/41b21f179ead617203c6d77b080e4f8b0065e06c)) +* Shplonk revival in ECCVM ([#7164](https://github.com/AztecProtocol/aztec-packages/issues/7164)) ([34eb5a0](https://github.com/AztecProtocol/aztec-packages/commit/34eb5a01d34e5ff5d1414fff53ca0623d83bde5d)) + + +### Bug Fixes + +* **avm:** Fix unencryptedlog c++ deser ([#7194](https://github.com/AztecProtocol/aztec-packages/issues/7194)) ([89a99af](https://github.com/AztecProtocol/aztec-packages/commit/89a99af4ff2ea79c276ff379a3cdd1b8cae18d15)) +* **avm:** Re-enable ext call test ([#7147](https://github.com/AztecProtocol/aztec-packages/issues/7147)) ([33ccf1b](https://github.com/AztecProtocol/aztec-packages/commit/33ccf1b61260868e6bb027b7838ef530717bff01)) +* **avm:** Reenable tag error sload ([#7153](https://github.com/AztecProtocol/aztec-packages/issues/7153)) ([fd92d46](https://github.com/AztecProtocol/aztec-packages/commit/fd92d467eee51638b896852b789c8fae17e0689c)) +* **avm:** Update codegen ([#7178](https://github.com/AztecProtocol/aztec-packages/issues/7178)) ([1d29708](https://github.com/AztecProtocol/aztec-packages/commit/1d29708bb6136184c27c1dc4f632b277cf3e4e64)) +* Bug fixing bench prover test ([#7135](https://github.com/AztecProtocol/aztec-packages/issues/7135)) ([13678be](https://github.com/AztecProtocol/aztec-packages/commit/13678be4e1c76d20a804a04b0fa82f68aeca38ae)), closes [#7080](https://github.com/AztecProtocol/aztec-packages/issues/7080) +* Fix bug for a unit test in full proving mode repated to MSM ([#7104](https://github.com/AztecProtocol/aztec-packages/issues/7104)) ([e37809b](https://github.com/AztecProtocol/aztec-packages/commit/e37809bdcdcf76f89f68403ee75aaf6d32c79a94)) + + +### Miscellaneous + +* **avm:** Remove avm prefix from pil and executor ([#7099](https://github.com/AztecProtocol/aztec-packages/issues/7099)) ([b502fcd](https://github.com/AztecProtocol/aztec-packages/commit/b502fcd500dcb10945b29d00f86e290bec63cce3)) +* **avm:** Renamings and comments ([#7128](https://github.com/AztecProtocol/aztec-packages/issues/7128)) ([ed2f98e](https://github.com/AztecProtocol/aztec-packages/commit/ed2f98ee9d7f540fbdfae09a0117bf22aaf6ebc7)) +* **avm:** Separate some fixed tables ([#7163](https://github.com/AztecProtocol/aztec-packages/issues/7163)) ([1d4a9a2](https://github.com/AztecProtocol/aztec-packages/commit/1d4a9a29ad37543aa0058bd43fa533f19a91e019)) +* Create workflow for full AVM tests ([#7051](https://github.com/AztecProtocol/aztec-packages/issues/7051)) ([a0b9c4b](https://github.com/AztecProtocol/aztec-packages/commit/a0b9c4b4383f448549c04567cd9c9264ce4240dc)), closes [#6643](https://github.com/AztecProtocol/aztec-packages/issues/6643) +* Indirects and read/write slices ([#7082](https://github.com/AztecProtocol/aztec-packages/issues/7082)) ([d5e80ee](https://github.com/AztecProtocol/aztec-packages/commit/d5e80ee9b6298f7edf39b99ff51ae7cc26b8cbd8)) +* Reads the return data ([#6669](https://github.com/AztecProtocol/aztec-packages/issues/6669)) ([ef85542](https://github.com/AztecProtocol/aztec-packages/commit/ef8554268c175e6349474883c6072e3979fe45c0)) +* Remove unneeded public input folding ([#7094](https://github.com/AztecProtocol/aztec-packages/issues/7094)) ([c30dc38](https://github.com/AztecProtocol/aztec-packages/commit/c30dc3856cec038d8c53af34cf82e08b0cb456aa)) +* Take the PCS out of Zeromorph and refactor tests ([#7078](https://github.com/AztecProtocol/aztec-packages/issues/7078)) ([e192678](https://github.com/AztecProtocol/aztec-packages/commit/e19267872bae6fa2df258a1e363f1ba2f2f47922)) +* Ultra flavor cleanup ([#7070](https://github.com/AztecProtocol/aztec-packages/issues/7070)) ([77761c6](https://github.com/AztecProtocol/aztec-packages/commit/77761c670f2d516ab486de0f7bde036ff00ebd99)) + ## [0.43.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg-v0.42.0...barretenberg-v0.43.0) (2024-06-18) diff --git a/barretenberg/Earthfile b/barretenberg/Earthfile index 73dc1443992c..1eb57ff2507b 100644 --- a/barretenberg/Earthfile +++ b/barretenberg/Earthfile @@ -42,7 +42,7 @@ barretenberg-acir-tests-bb: RUN FLOW=prove_and_verify_mega_honk_program ./run_acir_tests.sh # Fold and verify an ACIR program stack using ClientIvc RUN FLOW=fold_and_verify_program ./run_acir_tests.sh fold_basic - # Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof + # Fold and verify an ACIR program stack using ClientIvc, recursively verify as part of the Tube circuit and produce and verify a Honk proof RUN FLOW=prove_then_verify_tube ./run_acir_tests.sh fold_basic # Construct and separately verify a UltraHonk proof for a single program that recursively verifies a Honk proof RUN FLOW=prove_then_verify_ultra_honk ./run_acir_tests.sh verify_honk_proof diff --git a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh index fd559e256c6d..ac3bb9bc962b 100755 --- a/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh +++ b/barretenberg/acir_tests/flows/prove_then_verify_ultra_honk.sh @@ -1,5 +1,5 @@ #!/bin/sh -set -eu +set -eux VFLAG=${VERBOSE:+-v} BFLAG="-b ./target/program.json" diff --git a/barretenberg/acir_tests/reset_acir_tests.sh b/barretenberg/acir_tests/reset_acir_tests.sh index e83bea9189e9..dffb4d438375 100755 --- a/barretenberg/acir_tests/reset_acir_tests.sh +++ b/barretenberg/acir_tests/reset_acir_tests.sh @@ -1,7 +1,8 @@ -cd ~/aztec-packages/noir/noir-repo +# Run from barretenberg/acir_tests +cd ../../noir/noir-repo cargo clean noirup -p . cd test_programs && ./rebuild.sh -cd ~/aztec-packages/barretenberg/acir_tests +cd ../../../barretenberg/acir_tests rm -rf acir_tests diff --git a/barretenberg/cpp/CMakeLists.txt b/barretenberg/cpp/CMakeLists.txt index 5c76eb77253a..b50fe6e67e16 100644 --- a/barretenberg/cpp/CMakeLists.txt +++ b/barretenberg/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.24 FATAL_ERROR) project( Barretenberg DESCRIPTION "BN254 elliptic curve library, and PLONK SNARK prover" - VERSION 0.43.0 # x-release-please-version + VERSION 0.45.0 # x-release-please-version LANGUAGES CXX C ) # Insert version into `bb` config file diff --git a/barretenberg/cpp/pil/avm/constants.pil b/barretenberg/cpp/pil/avm/constants.pil deleted file mode 100644 index 6de0cfb9e772..000000000000 --- a/barretenberg/cpp/pil/avm/constants.pil +++ /dev/null @@ -1,44 +0,0 @@ - -// NOTE: the constants in this file line up to the indexes of values in the -// `PublicKernelInputs.nr` object -namespace constants(256); - // From Public Context Inputs - pol SENDER_SELECTOR = 0; - pol ADDRESS_SELECTOR = 1; - pol STORAGE_ADDRESS_SELECTOR = 2; - - // NOTE: constant expression evaluation does not seem to be supported yet in pil - // pol START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH = 6 + 23 = 29 - - // Global Variables - pol CHAIN_ID_SELECTOR = 29; - pol VERSION_SELECTOR = 30; - pol BLOCK_NUMBER_SELECTOR = 31; - pol TIMESTAMP_SELECTOR = 32; - pol COINBASE_SELECTOR = 33; - - pol END_GLOBAL_VARIABLES = 29 + 8; // We only use the first 5 of 8 global variables for now - - // Gas - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): This has since moved into the global variables - pol FEE_PER_DA_GAS_SELECTOR = 35; - pol FEE_PER_L2_GAS_SELECTOR = 36; - - pol START_SIDE_EFFECT_COUNTER = 37; - - pol TRANSACTION_FEE_SELECTOR = 40; - - // Other AVM specific constants - pol INTERNAL_CALL_SPACE_ID = 255; - - // Lengths of kernel output vectors - // Read requests - pol MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 32; - pol MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; - pol MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 32; - pol MAX_PUBLIC_DATA_READS_PER_CALL = 32; - - // Emitting Data - pol MAX_NEW_NOTE_HASHES_PER_CALL = 16; - pol MAX_NEW_NULLIIFIERS_PER_CALL = 16; - pol MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; diff --git a/barretenberg/cpp/pil/avm/constants_gen.pil b/barretenberg/cpp/pil/avm/constants_gen.pil new file mode 100644 index 000000000000..a1f4cb2c1a51 --- /dev/null +++ b/barretenberg/cpp/pil/avm/constants_gen.pil @@ -0,0 +1,39 @@ +// GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants in circuits.js +namespace constants(256); + pol MAX_NOTE_HASHES_PER_CALL = 16; + pol MAX_NULLIFIERS_PER_CALL = 16; + pol MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; + pol MAX_L2_TO_L1_MSGS_PER_CALL = 2; + pol MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 32; + pol MAX_PUBLIC_DATA_READS_PER_CALL = 32; + pol MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 16; + pol MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 16; + pol MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 16; + pol MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; + pol MAX_UNENCRYPTED_LOGS_PER_CALL = 4; + pol SENDER_SELECTOR = 0; + pol ADDRESS_SELECTOR = 1; + pol STORAGE_ADDRESS_SELECTOR = 1; + pol FUNCTION_SELECTOR_SELECTOR = 2; + pol START_GLOBAL_VARIABLES = 29; + pol CHAIN_ID_SELECTOR = 29; + pol VERSION_SELECTOR = 30; + pol BLOCK_NUMBER_SELECTOR = 31; + pol TIMESTAMP_SELECTOR = 32; + pol COINBASE_SELECTOR = 33; + pol FEE_PER_DA_GAS_SELECTOR = 35; + pol FEE_PER_L2_GAS_SELECTOR = 36; + pol END_GLOBAL_VARIABLES = 37; + pol START_SIDE_EFFECT_COUNTER = 37; + pol TRANSACTION_FEE_SELECTOR = 40; + pol START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; + pol START_NULLIFIER_EXISTS_OFFSET = 16; + pol START_NULLIFIER_NON_EXISTS_OFFSET = 32; + pol START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET = 48; + pol START_SSTORE_WRITE_OFFSET = 64; + pol START_SLOAD_WRITE_OFFSET = 96; + pol START_EMIT_NOTE_HASH_WRITE_OFFSET = 128; + pol START_EMIT_NULLIFIER_WRITE_OFFSET = 144; + pol START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET = 160; + pol START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = 162; + diff --git a/barretenberg/cpp/pil/avm/constants_misc.pil b/barretenberg/cpp/pil/avm/constants_misc.pil new file mode 100644 index 000000000000..6fd0b7e253a0 --- /dev/null +++ b/barretenberg/cpp/pil/avm/constants_misc.pil @@ -0,0 +1,2 @@ +namespace constants_misc(256); + pol INTERNAL_CALL_SPACE_ID = 255; diff --git a/barretenberg/cpp/pil/avm/kernel.pil b/barretenberg/cpp/pil/avm/kernel.pil index dff09f08d77e..9cc48c6da6c2 100644 --- a/barretenberg/cpp/pil/avm/kernel.pil +++ b/barretenberg/cpp/pil/avm/kernel.pil @@ -1,5 +1,5 @@ include "main.pil"; -include "constants.pil"; +include "constants_gen.pil"; namespace kernel(256); pol public kernel_inputs; @@ -24,24 +24,6 @@ namespace kernel(256); // Global side effect counter; incremented after each side effect is produced. pol commit side_effect_counter; - // FIXED INDEXES - // Exists checks - pol START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; - pol START_NULLIFIER_EXISTS_OFFSET = 32; // START_NOTE_HASH_EXISTS_WRITE_OFFSET + MAX_NOTE_HASH_READ_REQUESTS_PER_CALL - pol START_NULLIFIER_NON_EXISTS_OFFSET = 64; // START_NULLIFIER_EXISTS_OFFSET + MAX_NULLIFIER_READ_REQUESTS_PER_CALL - pol START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET = 96; // START_NULLIFIER_EXISTS_OFFET + (MAX_NULLIFIER_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) - - // Public storage requests - pol START_SSTORE_WRITE_OFFSET = 112; // START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL - pol START_SLOAD_WRITE_OFFSET = 144; // START_SSTORE_WRITE_OFFSET + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL - - // Emit data - pol START_EMIT_NOTE_HASH_WRITE_OFFSET = 176; // START_SLOAD_WRITE_OFFSET + MAX_PUBLIC_DATA_READS_PER_CALL - pol START_EMIT_NULLIFIER_WRITE_OFFSET = 192; // START_EMIT_NOTE_HASH_WRITE_OFFSET + MAX_NEW_NOTE_HASHES_PER_CALL - pol START_EMIT_L2_TO_l1_MSG = 208; // START_EMIT_NULLIFIER_WRITE_OFFSET + MAX_NEW_NULLIFIERS_PER_CALL - pol START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = 210; // START_EMIT_L2_TO_L1_MSG + MAX_NEW_L2_TO_L1_MSGS_PER_CALL - - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6465): Must constrain write_offset counters to be less than side effect MAX // Current write offsets for each opcode pol commit note_hash_exist_write_offset; diff --git a/barretenberg/cpp/pil/avm/main.pil b/barretenberg/cpp/pil/avm/main.pil index 19e445d62907..7858269448b4 100644 --- a/barretenberg/cpp/pil/avm/main.pil +++ b/barretenberg/cpp/pil/avm/main.pil @@ -1,7 +1,8 @@ include "mem.pil"; include "alu.pil"; include "binary.pil"; -include "constants.pil"; +include "constants_gen.pil"; +include "constants_misc.pil"; include "kernel.pil"; include "fixed/gas.pil"; include "fixed/powers.pil"; @@ -17,28 +18,31 @@ namespace main(256); pol constant sel_first = [1] + [0]*; // Used mostly to toggle off the first row consisting // only in first element of shifted polynomials. + //===== PUBLIC COLUMNS========================================================= + pol public calldata; + //===== KERNEL INPUTS ========================================================= // Kernel lookup selector opcodes pol commit sel_q_kernel_lookup; - // CALL CONTEXT - pol commit sel_op_sender; + // CONTEXT - ENVIRONMENT pol commit sel_op_address; pol commit sel_op_storage_address; - - // FEES - pol commit sel_op_fee_per_l2_gas; - pol commit sel_op_fee_per_da_gas; + pol commit sel_op_sender; + pol commit sel_op_function_selector; pol commit sel_op_transaction_fee; - - // GLOBALS + + // CONTEXT - ENVIRONMENT - GLOBALS pol commit sel_op_chain_id; pol commit sel_op_version; pol commit sel_op_block_number; pol commit sel_op_coinbase; pol commit sel_op_timestamp; + // CONTEXT - ENVIRONMENT - GLOBALS - FEES + pol commit sel_op_fee_per_l2_gas; + pol commit sel_op_fee_per_da_gas; - // MACHINE STATE - GAS + // CONTEXT - MACHINE STATE - GAS pol commit sel_op_l2gasleft; pol commit sel_op_dagasleft; @@ -259,9 +263,11 @@ namespace main(256); // Relations on type constraints // TODO: Very likely, we can remove these constraints as the selectors should be derived during // opcode decomposition. - sel_op_sender * (1 - sel_op_sender) = 0; sel_op_address * (1 - sel_op_address) = 0; sel_op_storage_address * (1 - sel_op_storage_address) = 0; + sel_op_sender * (1 - sel_op_sender) = 0; + sel_op_function_selector * (1 - sel_op_function_selector) = 0; + sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; sel_op_chain_id * (1 - sel_op_chain_id) = 0; sel_op_version * (1 - sel_op_version) = 0; sel_op_block_number * (1 - sel_op_block_number) = 0; @@ -269,7 +275,6 @@ namespace main(256); sel_op_timestamp * (1 - sel_op_timestamp) = 0; sel_op_fee_per_l2_gas * (1 - sel_op_fee_per_l2_gas) = 0; sel_op_fee_per_da_gas * (1 - sel_op_fee_per_da_gas) = 0; - sel_op_transaction_fee * (1 - sel_op_transaction_fee) = 0; // MACHINE STATE - GAS sel_op_l2gasleft * (1 - sel_op_l2gasleft) = 0; @@ -407,8 +412,9 @@ namespace main(256); //===== KERNEL LOOKUPS ======================================================= pol KERNEL_INPUT_SELECTORS = ( - sel_op_sender + sel_op_address + sel_op_storage_address + sel_op_chain_id + sel_op_version + sel_op_block_number + sel_op_coinbase + - sel_op_timestamp + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas + sel_op_transaction_fee + sel_op_address + sel_op_storage_address + sel_op_sender + sel_op_function_selector + sel_op_transaction_fee + + sel_op_chain_id + sel_op_version + sel_op_block_number + sel_op_coinbase + sel_op_timestamp + + sel_op_fee_per_l2_gas + sel_op_fee_per_da_gas ); // Ensure that only one kernel lookup is active when the kernel_in_offset is active #[KERNEL_INPUT_ACTIVE_CHECK] @@ -501,7 +507,7 @@ namespace main(256); //====== SPACE ID CONSTRAINTS =============================================== #[SPACE_ID_INTERNAL] - (sel_op_internal_call + sel_op_internal_return) * (space_id - constants.INTERNAL_CALL_SPACE_ID) = 0; + (sel_op_internal_call + sel_op_internal_return) * (space_id - constants_misc.INTERNAL_CALL_SPACE_ID) = 0; #[SPACE_ID_STANDARD_OPCODES] OPCODE_SELECTORS * (call_ptr - space_id) = 0; @@ -565,27 +571,23 @@ namespace main(256); // We can lookup into a fixed index of this polynomial by including constraints that force the value // of kernel_in_offset to the value relevant to the given opcode that is active - // CALL CONTEXT - #[SENDER_KERNEL] - sel_op_sender * (kernel.kernel_in_offset - constants.SENDER_SELECTOR) = 0; - + // CONTEXT - ENVIRONMENT #[ADDRESS_KERNEL] sel_op_address * (kernel.kernel_in_offset - constants.ADDRESS_SELECTOR) = 0; #[STORAGE_ADDRESS_KERNEL] sel_op_storage_address * (kernel.kernel_in_offset - constants.STORAGE_ADDRESS_SELECTOR) = 0; - // FEES - #[FEE_DA_GAS_KERNEL] - sel_op_fee_per_da_gas * (kernel.kernel_in_offset - constants.FEE_PER_DA_GAS_SELECTOR) = 0; + #[SENDER_KERNEL] + sel_op_sender * (kernel.kernel_in_offset - constants.SENDER_SELECTOR) = 0; - #[FEE_L2_GAS_KERNEL] - sel_op_fee_per_l2_gas * (kernel.kernel_in_offset - constants.FEE_PER_L2_GAS_SELECTOR) = 0; + #[FUNCTION_SELECTOR_KERNEL] + sel_op_function_selector * (kernel.kernel_in_offset - constants.FUNCTION_SELECTOR_SELECTOR) = 0; #[FEE_TRANSACTION_FEE_KERNEL] sel_op_transaction_fee * (kernel.kernel_in_offset - constants.TRANSACTION_FEE_SELECTOR) = 0; - // GLOBALS + // CONTEXT - ENVIRONMENT - GLOBALS #[CHAIN_ID_KERNEL] sel_op_chain_id * (kernel.kernel_in_offset - constants.CHAIN_ID_SELECTOR) = 0; @@ -595,52 +597,59 @@ namespace main(256); #[BLOCK_NUMBER_KERNEL] sel_op_block_number * (kernel.kernel_in_offset - constants.BLOCK_NUMBER_SELECTOR) = 0; + #[TIMESTAMP_KERNEL] + sel_op_timestamp * (kernel.kernel_in_offset - constants.TIMESTAMP_SELECTOR) = 0; + #[COINBASE_KERNEL] sel_op_coinbase * (kernel.kernel_in_offset - constants.COINBASE_SELECTOR) = 0; - #[TIMESTAMP_KERNEL] - sel_op_timestamp * (kernel.kernel_in_offset - constants.TIMESTAMP_SELECTOR) = 0; + // CONTEXT - ENVIRONMENT - GLOBALS - FEES + #[FEE_DA_GAS_KERNEL] + sel_op_fee_per_da_gas * (kernel.kernel_in_offset - constants.FEE_PER_DA_GAS_SELECTOR) = 0; + + #[FEE_L2_GAS_KERNEL] + sel_op_fee_per_l2_gas * (kernel.kernel_in_offset - constants.FEE_PER_L2_GAS_SELECTOR) = 0; // OUTPUTS LOOKUPS // Constrain the value of kernel_out_offset to be the correct offset for the operation being performed #[NOTE_HASH_KERNEL_OUTPUT] - sel_op_note_hash_exists * (kernel.kernel_out_offset - (kernel.START_NOTE_HASH_EXISTS_WRITE_OFFSET + kernel.note_hash_exist_write_offset)) = 0; + sel_op_note_hash_exists * (kernel.kernel_out_offset - (constants.START_NOTE_HASH_EXISTS_WRITE_OFFSET + kernel.note_hash_exist_write_offset)) = 0; sel_first * kernel.note_hash_exist_write_offset = 0; #[EMIT_NOTE_HASH_KERNEL_OUTPUT] - sel_op_emit_note_hash * (kernel.kernel_out_offset - (kernel.START_EMIT_NOTE_HASH_WRITE_OFFSET + kernel.emit_note_hash_write_offset)) = 0; + sel_op_emit_note_hash * (kernel.kernel_out_offset - (constants.START_EMIT_NOTE_HASH_WRITE_OFFSET + kernel.emit_note_hash_write_offset)) = 0; sel_first * kernel.emit_note_hash_write_offset = 0; #[NULLIFIER_EXISTS_KERNEL_OUTPUT] - sel_op_nullifier_exists * (kernel.kernel_out_offset - ((ib * (kernel.START_NULLIFIER_EXISTS_OFFSET + kernel.nullifier_exists_write_offset)) + ((1 - ib) * (kernel.START_NULLIFIER_NON_EXISTS_OFFSET + kernel.nullifier_non_exists_write_offset)))) = 0; + sel_op_nullifier_exists * (kernel.kernel_out_offset - ((ib * (constants.START_NULLIFIER_EXISTS_OFFSET + kernel.nullifier_exists_write_offset)) + ((1 - ib) * (constants.START_NULLIFIER_NON_EXISTS_OFFSET + kernel.nullifier_non_exists_write_offset)))) = 0; sel_first * kernel.nullifier_exists_write_offset = 0; sel_first * kernel.nullifier_non_exists_write_offset = 0; #[EMIT_NULLIFIER_KERNEL_OUTPUT] - sel_op_emit_nullifier * (kernel.kernel_out_offset - (kernel.START_EMIT_NULLIFIER_WRITE_OFFSET + kernel.emit_nullifier_write_offset)) = 0; + sel_op_emit_nullifier * (kernel.kernel_out_offset - (constants.START_EMIT_NULLIFIER_WRITE_OFFSET + kernel.emit_nullifier_write_offset)) = 0; sel_first * kernel.emit_nullifier_write_offset = 0; #[L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT] - sel_op_l1_to_l2_msg_exists * (kernel.kernel_out_offset - (kernel.START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + kernel.l1_to_l2_msg_exists_write_offset)) = 0; + sel_op_l1_to_l2_msg_exists * (kernel.kernel_out_offset - (constants.START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + kernel.l1_to_l2_msg_exists_write_offset)) = 0; sel_first * kernel.l1_to_l2_msg_exists_write_offset = 0; #[EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT] - sel_op_emit_unencrypted_log * (kernel.kernel_out_offset - (kernel.START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + kernel.emit_unencrypted_log_write_offset)) = 0; + sel_op_emit_unencrypted_log * (kernel.kernel_out_offset - (constants.START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + kernel.emit_unencrypted_log_write_offset)) = 0; sel_first * kernel.emit_unencrypted_log_write_offset = 0; // TODO: Add the equivalent for GETCONTRACTINSTANCE? #[EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT] - sel_op_emit_l2_to_l1_msg * (kernel.kernel_out_offset - (kernel.START_EMIT_L2_TO_l1_MSG + kernel.emit_l2_to_l1_msg_write_offset)) = 0; + sel_op_emit_l2_to_l1_msg * (kernel.kernel_out_offset - (constants.START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + kernel.emit_l2_to_l1_msg_write_offset)) = 0; sel_first * kernel.emit_l2_to_l1_msg_write_offset = 0; #[SLOAD_KERNEL_OUTPUT] - sel_op_sload * (kernel.kernel_out_offset - (kernel.START_SLOAD_WRITE_OFFSET + kernel.sload_write_offset)) = 0; + sel_op_sload * (kernel.kernel_out_offset - (constants.START_SLOAD_WRITE_OFFSET + kernel.sload_write_offset)) = 0; sel_first * kernel.sload_write_offset = 0; #[SSTORE_KERNEL_OUTPUT] - sel_op_sstore * (kernel.kernel_out_offset - (kernel.START_SSTORE_WRITE_OFFSET + kernel.sstore_write_offset)) = 0; + sel_op_sstore * (kernel.kernel_out_offset - (constants.START_SSTORE_WRITE_OFFSET + kernel.sstore_write_offset)) = 0; sel_first * kernel.sstore_write_offset = 0; // When we encounter a state writing opcode diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index be6d254b7239..077d20a4c3b0 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -56,6 +56,7 @@ add_subdirectory(barretenberg/bb) add_subdirectory(barretenberg/circuit_checker) add_subdirectory(barretenberg/client_ivc) add_subdirectory(barretenberg/commitment_schemes) +add_subdirectory(barretenberg/commitment_schemes_recursion) add_subdirectory(barretenberg/common) add_subdirectory(barretenberg/crypto) add_subdirectory(barretenberg/dsl) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 114e2f0caf2f..1045d543d212 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -741,18 +741,15 @@ bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem:: #endif /** - * @brief Creates a proof for an ACIR circuit - * - * Communication: - * - stdout: The proof is written to stdout as a byte array - * - Filesystem: The proof is written to the path specified by outputPath + * @brief Create a Honk a prover from program bytecode and an optional witness * - * @param bytecodePath Path to the file containing the serialized circuit - * @param witnessPath Path to the file containing the serialized witness - * @param outputPath Path to write the proof to + * @tparam Flavor + * @param bytecodePath + * @param witnessPath + * @return UltraProver_ */ -template -void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath) +template +UltraProver_ compute_valid_prover(const std::string& bytecodePath, const std::string& witnessPath) { using Builder = Flavor::CircuitBuilder; using Prover = UltraProver_; @@ -762,7 +759,10 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, honk_recursion = true; } auto constraint_system = get_constraint_system(bytecodePath, honk_recursion); - auto witness = get_witness(witnessPath); + acir_format::WitnessVector witness = {}; + if (!witnessPath.empty()) { + witness = get_witness(witnessPath); + } auto builder = acir_format::create_circuit(constraint_system, 0, witness, honk_recursion); @@ -770,8 +770,29 @@ void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates); init_bn254_crs(srs_size); - // Construct Honk proof Prover prover{ builder }; + return prover; +} + +/** + * @brief Creates a proof for an ACIR circuit + * + * Communication: + * - stdout: The proof is written to stdout as a byte array + * - Filesystem: The proof is written to the path specified by outputPath + * + * @param bytecodePath Path to the file containing the serialized circuit + * @param witnessPath Path to the file containing the serialized witness + * @param outputPath Path to write the proof to + */ +template +void prove_honk(const std::string& bytecodePath, const std::string& witnessPath, const std::string& outputPath) +{ + // using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; + + // Construct Honk proof + Prover prover = compute_valid_prover(bytecodePath, witnessPath); auto proof = prover.construct_proof(); if (outputPath == "-") { @@ -807,10 +828,9 @@ template bool verify_honk(const std::string& proof_path, auto g2_data = get_bn254_g2_data(CRS_PATH); srs::init_crs_factory({}, g2_data); auto proof = from_buffer>(read_file(proof_path)); - auto verification_key = std::make_shared(from_buffer(read_file(vk_path))); - verification_key->pcs_verification_key = std::make_shared(); - - Verifier verifier{ verification_key }; + auto vk = std::make_shared(from_buffer(read_file(vk_path))); + vk->pcs_verification_key = std::make_shared(); + Verifier verifier{ vk }; bool verified = verifier.verify_proof(proof); @@ -830,22 +850,12 @@ template bool verify_honk(const std::string& proof_path, */ template void write_vk_honk(const std::string& bytecodePath, const std::string& outputPath) { - using Builder = Flavor::CircuitBuilder; + using Prover = UltraProver_; using ProverInstance = ProverInstance_; using VerificationKey = Flavor::VerificationKey; - bool honk_recursion = false; - if constexpr (IsAnyOf) { - honk_recursion = true; - } - auto constraint_system = get_constraint_system(bytecodePath, honk_recursion); - auto builder = acir_format::create_circuit(constraint_system, 0, {}, honk_recursion); - - auto num_extra_gates = builder.get_num_gates_added_to_ensure_nonzero_polynomials(); - size_t srs_size = builder.get_circuit_subgroup_size(builder.get_total_circuit_size() + num_extra_gates); - init_bn254_crs(srs_size); - - ProverInstance prover_inst(builder); + Prover prover = compute_valid_prover(bytecodePath, ""); + ProverInstance& prover_inst = *prover.instance; VerificationKey vk( prover_inst.proving_key); // uses a partial form of the proving key which only has precomputed entities diff --git a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp deleted file mode 100644 index 5ad7944451a6..000000000000 --- a/barretenberg/cpp/src/barretenberg/benchmark/goblin_bench/goblin.bench.cpp +++ /dev/null @@ -1,144 +0,0 @@ - -#include - -#include "barretenberg/common/op_count_google_bench.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" - -using namespace benchmark; -using namespace bb; - -namespace { - -class GoblinBench : public benchmark::Fixture { - public: - GoblinAccumulationOutput kernel_accum; - - // Number of function circuits to accumulate(based on Zacs target numbers) - static constexpr size_t NUM_ITERATIONS_MEDIUM_COMPLEXITY = 6; - - void SetUp([[maybe_unused]] const ::benchmark::State& state) override - { - bb::srs::init_crs_factory("../srs_db/ignition"); - bb::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - - /** - * @brief Perform a specified number of function circuit accumulation rounds - * @details Each round "accumulates" a mock function circuit and a mock kernel circuit. Each round thus consists of - * the generation of two circuits, two MegaHonk proofs and two Merge proofs. To match the sizes called out in the - * spec - * (https://github.com/AztecProtocol/aztec-packages/blob/master/yellow-paper/docs/cryptography/performance-targets.md) - * we set the size of the function circuit to be 2^17 except for the first one which is 2^19. - * - * @param state - */ - void perform_goblin_accumulation_rounds(State& state, GoblinProver& goblin) - { - auto NUM_CIRCUITS = static_cast(state.range(0)); - for (size_t circuit_idx = 0; circuit_idx < NUM_CIRCUITS; ++circuit_idx) { - - // Construct and accumulate a mock function circuit - MegaCircuitBuilder function_circuit{ goblin.op_queue }; - // On the first iteration construct a "large" function circuit (2^19), otherwise medium (2^17) - GoblinMockCircuits::construct_mock_function_circuit(function_circuit, /*large=*/circuit_idx == 0); - auto function_accum = goblin.accumulate(function_circuit); - - // Construct and accumulate the mock kernel circuit - // Note: in first round, kernel_accum is empty since there is no previous kernel to recursively verify - MegaCircuitBuilder circuit_builder{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_recursion_kernel_circuit( - circuit_builder, - { function_accum.proof, function_accum.verification_key }, - { kernel_accum.proof, kernel_accum.verification_key }); - kernel_accum = goblin.accumulate(circuit_builder); - } - } -}; - -/** - * @brief Benchmark the full Goblin IVC protocol - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinFull)(benchmark::State& state) -{ - GoblinProver goblin; - - for (auto _ : state) { - BB_REPORT_OP_COUNT_IN_BENCH(state); - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Construct proofs for ECCVM and Translator - goblin.prove(); - } -} - -/** - * @brief Benchmark only the accumulation rounds - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinAccumulate)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - for (auto _ : state) { - perform_goblin_accumulation_rounds(state, goblin); - } -} - -/** - * @brief Benchmark only the ECCVM component - * - */ -BENCHMARK_DEFINE_F(GoblinBench, GoblinECCVMProve)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Prove ECCVM only - for (auto _ : state) { - goblin.prove_eccvm(); - } -} - -/** - * @brief Benchmark only the Translator component - * - */ -BENCHMARK_DEFINE_F(GoblinBench, TranslatorProve)(benchmark::State& state) -{ - GoblinProver goblin; - - // Perform a specified number of iterations of function/kernel accumulation - perform_goblin_accumulation_rounds(state, goblin); - - // Prove ECCVM (unmeasured) and Translator (measured) - goblin.prove_eccvm(); - for (auto _ : state) { - goblin.prove_translator(); - } -} - -#define ARGS \ - Arg(GoblinBench::NUM_ITERATIONS_MEDIUM_COMPLEXITY) \ - ->Arg(1 << 0) \ - ->Arg(1 << 1) \ - ->Arg(1 << 2) \ - ->Arg(1 << 3) \ - ->Arg(1 << 4) \ - ->Arg(1 << 5) \ - ->Arg(1 << 6) - -BENCHMARK_REGISTER_F(GoblinBench, GoblinFull)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, GoblinAccumulate)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, GoblinECCVMProve)->Unit(benchmark::kMillisecond)->ARGS; -BENCHMARK_REGISTER_F(GoblinBench, TranslatorProve)->Unit(benchmark::kMillisecond)->ARGS; - -} // namespace - -BENCHMARK_MAIN(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp index 23fb76a95029..909a40cd439d 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/verification_key.hpp @@ -29,11 +29,11 @@ template class VerifierCommitmentKey; * @tparam curve::BN254 */ template <> class VerifierCommitmentKey { + public: using Curve = curve::BN254; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; - public: VerifierCommitmentKey() { srs::init_crs_factory("../srs_db/ignition"); @@ -69,11 +69,11 @@ template <> class VerifierCommitmentKey { * @tparam curve::Grumpkin */ template <> class VerifierCommitmentKey { + public: using Curve = curve::Grumpkin; using GroupElement = typename Curve::Element; using Commitment = typename Curve::AffineElement; - public: /** * @brief Construct a new IPA Verification Key object from existing SRS * diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index f6a77ba302c8..2b5075238656 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -6,6 +6,8 @@ #include "barretenberg/common/ref_vector.hpp" #include "barretenberg/common/zip_view.hpp" #include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb { @@ -69,9 +71,6 @@ template class ZeroMorphProver_ { std::span u_challenge) { size_t log_N = numeric::get_msb(polynomial.size()); - // The size of the multilinear challenge must equal the log of the polynomial size - ASSERT(log_N == u_challenge.size()); - // Define the vector of quotients q_k, k = 0, ..., log_N-1 std::vector quotients; for (size_t k = 0; k < log_N; ++k) { @@ -323,7 +322,8 @@ template class ZeroMorphProver_ { * * @todo https://github.com/AztecProtocol/barretenberg/issues/1030: document concatenation trick */ - static OpeningClaim prove(RefSpan f_polynomials, + static OpeningClaim prove(FF circuit_size, + RefSpan f_polynomials, RefSpan g_polynomials, RefSpan f_evaluations, RefSpan g_shift_evaluations, @@ -339,7 +339,7 @@ template class ZeroMorphProver_ { // Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output std::span u_challenge = multilinear_challenge; - size_t log_N = u_challenge.size(); + size_t log_N = numeric::get_msb(static_cast(circuit_size)); size_t N = 1 << log_N; // Compute batching of unshifted polynomials f_i and to-be-shifted polynomials g_i: @@ -392,15 +392,18 @@ template class ZeroMorphProver_ { f_polynomial += concatenated_batched; // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) - auto quotients = compute_multilinear_quotients(f_polynomial, u_challenge); - + std::vector quotients = compute_multilinear_quotients(f_polynomial, u_challenge); // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 - std::vector q_k_commitments; - q_k_commitments.reserve(log_N); for (size_t idx = 0; idx < log_N; ++idx) { - q_k_commitments[idx] = commitment_key->commit(quotients[idx]); + Commitment q_k_commitment = commitment_key->commit(quotients[idx]); std::string label = "ZM:C_q_" + std::to_string(idx); - transcript->send_to_verifier(label, q_k_commitments[idx]); + transcript->send_to_verifier(label, q_k_commitment); + } + // Add buffer elements to remove log_N dependence in proof + for (size_t idx = log_N; idx < CONST_PROOF_SIZE_LOG_N; ++idx) { + auto buffer_element = Commitment::one(); + std::string label = "ZM:C_q_" + std::to_string(idx); + transcript->send_to_verifier(label, buffer_element); } // Get challenge y @@ -462,10 +465,19 @@ template class ZeroMorphVerifier_ { static Commitment compute_C_zeta_x(const Commitment& C_q, std::vector& C_q_k, FF y_challenge, - FF x_challenge) + FF x_challenge, + const FF log_circuit_size, + const FF circuit_size) { - size_t log_N = C_q_k.size(); - size_t N = 1 << log_N; + size_t N{ 0 }; + size_t log_N{ 0 }; + if constexpr (Curve::is_stdlib_type) { + N = static_cast(circuit_size.get_value()); + log_N = static_cast(log_circuit_size.get_value()); + } else { + N = static_cast(circuit_size); + log_N = static_cast(log_circuit_size); + } // Instantiate containers for input to batch mul std::vector scalars; @@ -480,21 +492,40 @@ template class ZeroMorphVerifier_ { } commitments.emplace_back(C_q); - // Contribution from C_q_k, k = 0,...,log_N - for (size_t k = 0; k < log_N; ++k) { + // Contribution from C_q_k, k = 0,...,log_N-1 + for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { + // Utilize dummy rounds in order to make verifier circuit independent of proof size + bool is_dummy_round = k >= log_N; auto deg_k = static_cast((1 << k) - 1); // Compute scalar y^k * x^{N - deg_k - 1} - auto scalar = y_challenge.pow(k); - scalar *= x_challenge.pow(N - deg_k - 1); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints + FF scalar = y_challenge.pow(k); + size_t x_exponent = is_dummy_round ? 0 : N - deg_k - 1; + scalar *= x_challenge.pow(x_exponent); scalar *= FF(-1); - + if constexpr (Curve::is_stdlib_type) { + auto builder = x_challenge.get_context(); + FF zero = FF::from_witness(builder, 0); + stdlib::bool_t dummy_round = stdlib::witness_t(builder, is_dummy_round); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): is it kosher to reassign like this? + scalar = FF::conditional_assign(dummy_round, zero, scalar); + } else { + if (is_dummy_round) { + scalar = 0; + } + } scalars.emplace_back(scalar); commitments.emplace_back(C_q_k[k]); } // Compute batch mul to get the result if constexpr (Curve::is_stdlib_type) { - return Commitment::batch_mul(commitments, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + return Commitment::batch_mul(commitments, scalars); + } } else { return batch_mul_native(commitments, scalars); } @@ -533,15 +564,25 @@ template class ZeroMorphVerifier_ { FF batched_evaluation, FF x_challenge, std::span u_challenge, + const FF log_circuit_size, + const FF circuit_size, const std::vector>& concatenation_groups_commitments = {}) { - size_t log_N = C_q_k.size(); - size_t N = 1 << log_N; + size_t N{ 0 }; + size_t log_N{ 0 }; + if constexpr (Curve::is_stdlib_type) { + N = static_cast(circuit_size.get_value()); + log_N = static_cast(log_circuit_size.get_value()); + } else { + N = static_cast(circuit_size); + log_N = static_cast(log_circuit_size); + } std::vector scalars; std::vector commitments; // Phi_n(x) = (x^N - 1) / (x - 1) + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints auto phi_numerator = x_challenge.pow(N) - 1; // x^N - 1 auto phi_n_x = phi_numerator / (x_challenge - 1); @@ -590,26 +631,57 @@ template class ZeroMorphVerifier_ { // scalar = -x * (x^{2^k} * \Phi_{n-k-1}(x^{2^{k+1}}) - u_k * \Phi_{n-k}(x^{2^k})) auto x_pow_2k = x_challenge; // x^{2^k} auto x_pow_2kp1 = x_challenge * x_challenge; // x^{2^{k + 1}} - for (size_t k = 0; k < log_N; ++k) { - - auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) - auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) - - auto scalar = x_pow_2k * phi_term_1; - scalar -= u_challenge[k] * phi_term_2; - scalar *= x_challenge; - scalar *= FF(-1); - - scalars.emplace_back(scalar); - commitments.emplace_back(C_q_k[k]); - - // Update powers of challenge x - x_pow_2k = x_pow_2kp1; - x_pow_2kp1 *= x_pow_2kp1; + for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { + // Utilize dummy rounds in order to make verifier circuit independent of proof size + bool is_dummy_round = k >= log_N; + if constexpr (Curve::is_stdlib_type) { + auto builder = x_challenge.get_context(); + stdlib::bool_t dummy_scalar = stdlib::witness_t(builder, is_dummy_round); + auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) + auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) + + auto scalar = x_pow_2k * phi_term_1; + scalar -= u_challenge[k] * phi_term_2; + scalar *= x_challenge; + scalar *= -FF(1); + + FF zero = FF::from_witness(builder, 0); + scalar = FF::conditional_assign(dummy_scalar, zero, scalar); + scalars.emplace_back(scalar); + commitments.emplace_back(C_q_k[k]); + + x_pow_2k = FF::conditional_assign(dummy_scalar, x_pow_2k, x_pow_2kp1); + x_pow_2kp1 = FF::conditional_assign(dummy_scalar, x_pow_2kp1, x_pow_2kp1 * x_pow_2kp1); + } else { + if (is_dummy_round) { + scalars.emplace_back(0); + commitments.emplace_back(C_q_k[k]); + } else { + auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) + auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) + + auto scalar = x_pow_2k * phi_term_1; + scalar -= u_challenge[k] * phi_term_2; + scalar *= x_challenge; + scalar *= FF(-1); + + scalars.emplace_back(scalar); + commitments.emplace_back(C_q_k[k]); + + // Update powers of challenge x + x_pow_2k = x_pow_2kp1; + x_pow_2kp1 *= x_pow_2kp1; + } + } } if constexpr (Curve::is_stdlib_type) { - return Commitment::batch_mul(commitments, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + return Commitment::batch_mul(commitments, scalars); + } } else { return batch_mul_native(commitments, scalars); } @@ -638,7 +710,8 @@ template class ZeroMorphVerifier_ { * @param transcript * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated */ - static OpeningClaim verify(RefSpan unshifted_commitments, + static OpeningClaim verify(FF circuit_size, + RefSpan unshifted_commitments, RefSpan to_be_shifted_commitments, RefSpan unshifted_evaluations, RefSpan shifted_evaluations, @@ -648,7 +721,13 @@ template class ZeroMorphVerifier_ { const std::vector>& concatenation_group_commitments = {}, RefSpan concatenated_evaluations = {}) { - size_t log_N = multivariate_challenge.size(); + FF log_N; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): Connect witness log_N to circuit size + if constexpr (Curve::is_stdlib_type) { + log_N = FF(static_cast(numeric::get_msb(static_cast(circuit_size.get_value())))); + } else { + log_N = numeric::get_msb(static_cast(circuit_size)); + } FF rho = transcript->template get_challenge("rho"); // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u) @@ -669,8 +748,8 @@ template class ZeroMorphVerifier_ { // Receive commitments [q_k] std::vector C_q_k; - C_q_k.reserve(log_N); - for (size_t i = 0; i < log_N; ++i) { + C_q_k.reserve(CONST_PROOF_SIZE_LOG_N); + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { C_q_k.emplace_back(transcript->template receive_from_prover("ZM:C_q_" + std::to_string(i))); } @@ -684,7 +763,7 @@ template class ZeroMorphVerifier_ { auto [x_challenge, z_challenge] = transcript->template get_challenges("ZM:x", "ZM:z"); // Compute commitment C_{\zeta_x} - auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); + auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge, log_N, circuit_size); // Compute commitment C_{Z_x} Commitment C_Z_x = compute_C_Z_x(g1_identity, @@ -695,17 +774,23 @@ template class ZeroMorphVerifier_ { batched_evaluation, x_challenge, multivariate_challenge, + log_N, + circuit_size, concatenation_group_commitments); // Compute commitment C_{\zeta,Z} Commitment C_zeta_Z; if constexpr (Curve::is_stdlib_type) { - // Express operation as a batch_mul in order to use Goblinization if available auto builder = z_challenge.get_context(); std::vector scalars = { FF(builder, 1), z_challenge }; std::vector points = { C_zeta_x, C_Z_x }; - C_zeta_Z = Commitment::batch_mul(points, scalars); + // If Ultra and using biggroup, handle edge cases in batch_mul + if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { + C_zeta_Z = Commitment::batch_mul(points, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); + } else { + C_zeta_Z = Commitment::batch_mul(points, scalars); + } } else { C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 122fcb1187fa..146ce53b4614 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -1,9 +1,7 @@ #include "zeromorph.hpp" -#include "../commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/commitment_key.test.hpp" #include "barretenberg/commitment_schemes/ipa/ipa.hpp" #include "barretenberg/commitment_schemes/kzg/kzg.hpp" -#include "barretenberg/transcript/transcript.hpp" - #include namespace bb { @@ -89,10 +87,10 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTest u_challenge) { auto prover_transcript = NativeTranscript::prover_init_empty(); // Execute Prover protocol - auto prover_opening_claim = ZeroMorphProver::prove(RefVector(unshifted.polynomials), // unshifted + auto prover_opening_claim = ZeroMorphProver::prove(N, + RefVector(unshifted.polynomials), // unshifted RefVector(shifted.polynomials), // to-be shifted RefVector(unshifted.evaluations), // unshifted RefVector(shifted.evaluations), // shifted @@ -224,7 +224,8 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTest u_challenge, size_t NUM_CONCATENATED) @@ -261,7 +263,8 @@ template class ZeroMorphTest : public CommitmentTest class ZeroMorphTest : public CommitmentTestexecute_zeromorph_protocol(num_unshifted, num_shifted, num_concatenated); EXPECT_TRUE(verified); } -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt new file mode 100644 index 000000000000..71ce791bd34a --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(commitment_schemes_recursion commitment_schemes stdlib_primitives) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp new file mode 100644 index 000000000000..93cfbc82d89b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp @@ -0,0 +1,140 @@ +#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/commitment_schemes/commitment_key.test.hpp" +#include "barretenberg/commitment_schemes/ipa/ipa.hpp" +#include "barretenberg/commitment_schemes/kzg/kzg.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/stdlib/honk_recursion/transcript/transcript.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include + +#include + +using namespace bb; + +template class ZeroMorphRecursionTest : public CommitmentTest {}; + +numeric::RNG& engine = numeric::get_debug_randomness(); + +/** + * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation + * + */ +TEST(ZeroMorphRecursionTest, ProveAndVerifySingle) +{ + // Define some useful type aliases + using Builder = UltraCircuitBuilder; + using Curve = typename stdlib::bn254; + using NativeCurve = typename Curve::NativeCurve; + using Commitment = typename Curve::AffineElement; + using NativeCommitment = typename Curve::AffineElementNative; + using NativeCurve = typename Curve::NativeCurve; + using NativePCS = std::conditional_t, KZG, IPA>; + using CommitmentKey = typename NativePCS::CK; + using ZeroMorphProver = ZeroMorphProver_; + using Fr = typename Curve::ScalarField; + using NativeFr = typename Curve::NativeCurve::ScalarField; + using Polynomial = bb::Polynomial; + using ZeroMorphVerifier = ZeroMorphVerifier_; + using Transcript = bb::BaseTranscript>; + + constexpr size_t N = 2; + constexpr size_t NUM_UNSHIFTED = 1; + constexpr size_t NUM_SHIFTED = 0; + + srs::init_crs_factory("../srs_db/ignition"); + + std::vector u_challenge = { NativeFr::random_element(&engine) }; + + // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) + std::vector f_polynomials; // unshifted polynomials + std::vector v_evaluations; + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_polynomials.emplace_back(Polynomial::random(N)); + f_polynomials[i][0] = NativeFr(0); // ensure f is "shiftable" + v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); + } + + // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i + std::vector g_polynomials; // to-be-shifted polynomials + std::vector h_polynomials; // shifts of the to-be-shifted polynomials + std::vector w_evaluations; + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_polynomials.emplace_back(f_polynomials[i]); + h_polynomials.emplace_back(g_polynomials[i].shifted()); + w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); + } + + // Compute commitments [f_i] + std::vector f_commitments; + auto commitment_key = std::make_shared(1024); + for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { + f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); + } + + // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) + std::vector g_commitments; + for (size_t i = 0; i < NUM_SHIFTED; ++i) { + g_commitments.emplace_back(f_commitments[i]); + } + + // Initialize an empty NativeTranscript + auto prover_transcript = NativeTranscript::prover_init_empty(); + + // Execute Prover protocol + ZeroMorphProver::prove(N, + RefVector(f_polynomials), + RefVector(g_polynomials), + RefVector(v_evaluations), + RefVector(w_evaluations), + u_challenge, + commitment_key, + prover_transcript); + + Builder builder; + StdlibProof stdlib_proof = bb::convert_proof_to_witness(&builder, prover_transcript->proof_data); + auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); + [[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover("Init"); + + // Execute Verifier protocol without the need for vk prior the final check + const auto commitments_to_witnesses = [&builder](const auto& commitments) { + std::vector commitments_in_biggroup(commitments.size()); + std::transform(commitments.begin(), + commitments.end(), + commitments_in_biggroup.begin(), + [&builder](const auto& native_commitment) { + return Commitment::from_witness(&builder, native_commitment); + }); + return commitments_in_biggroup; + }; + const auto elements_to_witness = [&](const auto& elements) { + std::vector elements_in_circuit(elements.size()); + std::transform(elements.begin(), + elements.end(), + elements_in_circuit.begin(), + [&builder](const auto& native_element) { return Fr::from_witness(&builder, native_element); }); + return elements_in_circuit; + }; + auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); + auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); + auto stdlib_v_evaluations = elements_to_witness(v_evaluations); + auto stdlib_w_evaluations = elements_to_witness(w_evaluations); + + std::vector u_challenge_in_circuit(CONST_PROOF_SIZE_LOG_N); + std::fill_n(u_challenge_in_circuit.begin(), CONST_PROOF_SIZE_LOG_N, Fr::from_witness(&builder, 0)); + u_challenge_in_circuit[0] = Fr::from_witness(&builder, u_challenge[0]); + + [[maybe_unused]] auto opening_claim = ZeroMorphVerifier::verify(Fr::from_witness(&builder, N), + RefVector(stdlib_f_commitments), // unshifted + RefVector(stdlib_g_commitments), // to-be-shifted + RefVector(stdlib_v_evaluations), // unshifted + RefVector(stdlib_w_evaluations), // shifted + u_challenge_in_circuit, + Commitment::one(&builder), + stdlib_verifier_transcript, + {}, + {}); + EXPECT_TRUE(CircuitChecker::check(builder)); +} diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp new file mode 100644 index 000000000000..4adf2c4a6b18 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace bb { +// The log of the max circuit size assumed in order to achieve constant sized proofs +static constexpr uint32_t CONST_PROOF_SIZE_LOG_N = 28; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index bcfcce6776fb..528fd947ed31 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -341,7 +341,7 @@ void build_constraints(Builder& builder, // Add recursion constraints for (size_t i = 0; i < constraint_system.honk_recursion_constraints.size(); ++i) { - auto constraint = constraint_system.honk_recursion_constraints.at(i); + auto& constraint = constraint_system.honk_recursion_constraints.at(i); // A proof passed into the constraint should be stripped of its inner public inputs, but not the // nested aggregation object itself. The verifier circuit requires that the indices to a nested // proof aggregation state are a circuit constant. The user tells us they how they want these diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp index 4b32ec0a14fe..fb7789298458 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/honk_recursion_constraint.cpp @@ -117,8 +117,6 @@ std::array create_ho } } - // Recursively verify the proof - auto vkey = std::make_shared(builder, key_fields); if (!has_valid_witness_assignments) { // Set vkey->circuit_size correctly based on the proof size size_t num_frs_comm = bb::field_conversion::calc_num_bn254_frs(); @@ -128,14 +126,86 @@ std::array create_ho 2 * num_frs_comm) % (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH) == 0); - vkey->log_circuit_size = (input.proof.size() - HonkRecursionConstraint::inner_public_input_offset - - UltraFlavor::NUM_WITNESS_ENTITIES * num_frs_comm - - UltraFlavor::NUM_ALL_ENTITIES * num_frs_fr - 2 * num_frs_comm) / - (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH); - vkey->circuit_size = (1 << vkey->log_circuit_size); - vkey->num_public_inputs = input.public_inputs.size(); - vkey->pub_inputs_offset = UltraFlavor::has_zero_row ? 1 : 0; + // Note: this computation should always result in log_circuit_size = CONST_PROOF_SIZE_LOG_N + auto log_circuit_size = (input.proof.size() - HonkRecursionConstraint::inner_public_input_offset - + UltraFlavor::NUM_WITNESS_ENTITIES * num_frs_comm - + UltraFlavor::NUM_ALL_ENTITIES * num_frs_fr - 2 * num_frs_comm) / + (num_frs_comm + num_frs_fr * UltraFlavor::BATCHED_RELATION_PARTIAL_LENGTH); + builder.assert_equal(builder.add_variable(1 << log_circuit_size), key_fields[0].witness_index); + builder.assert_equal(builder.add_variable(input.public_inputs.size()), key_fields[1].witness_index); + builder.assert_equal(builder.add_variable(UltraFlavor::has_zero_row ? 1 : 0), key_fields[2].witness_index); + uint32_t offset = 3; + + for (size_t i = 0; i < Flavor::NUM_PRECOMPUTED_ENTITIES; ++i) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), key_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), key_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), key_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), key_fields[offset + 3].witness_index); + offset += 4; + } + + offset = HonkRecursionConstraint::inner_public_input_offset; + // first 3 things + builder.assert_equal(builder.add_variable(1 << log_circuit_size), proof_fields[0].witness_index); + builder.assert_equal(builder.add_variable(input.public_inputs.size()), proof_fields[1].witness_index); + builder.assert_equal(builder.add_variable(UltraFlavor::has_zero_row ? 1 : 0), proof_fields[2].witness_index); + + // the public inputs + for (size_t i = 0; i < input.public_inputs.size(); i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // first 7 commitments + for (size_t i = 0; i < Flavor::NUM_WITNESS_ENTITIES; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // now the univariates, which can just be 0s (7*CONST_PROOF_SIZE_LOG_N Frs) + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N * Flavor::BATCHED_RELATION_PARTIAL_LENGTH; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the sumcheck evalutions, which is just 43 0s + for (size_t i = 0; i < Flavor::NUM_ALL_ENTITIES; i++) { + builder.assert_equal(builder.add_variable(fr::random_element()), proof_fields[offset].witness_index); + offset++; + } + + // now the zeromorph commitments, which are CONST_PROOF_SIZE_LOG_N comms + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + + // lastly the 2 commitments + for (size_t i = 0; i < 2; i++) { + auto comm = curve::BN254::AffineElement::one() * fr::random_element(); + auto frs = field_conversion::convert_to_bn254_frs(comm); + builder.assert_equal(builder.add_variable(frs[0]), proof_fields[offset].witness_index); + builder.assert_equal(builder.add_variable(frs[1]), proof_fields[offset + 1].witness_index); + builder.assert_equal(builder.add_variable(frs[2]), proof_fields[offset + 2].witness_index); + builder.assert_equal(builder.add_variable(frs[3]), proof_fields[offset + 3].witness_index); + offset += 4; + } + ASSERT(offset == input.proof.size() + input.public_inputs.size()); } + // Recursively verify the proof + auto vkey = std::make_shared(builder, key_fields); RecursiveVerifier verifier(&builder, vkey); std::array pairing_points = verifier.verify_proof(proof_fields); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index 4a87e300d09c..bdb969415cba 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -936,7 +936,6 @@ class ECCVMFlavor { size_t num_frs_read = 0; circuit_size = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); transcript_add_comm = NativeTranscript::template deserialize_from_buffer( NativeTranscript::proof_data, num_frs_read); transcript_mul_comm = NativeTranscript::template deserialize_from_buffer( @@ -1113,14 +1112,14 @@ class ECCVMFlavor { NativeTranscript::proof_data, num_frs_read); z_perm_comm = NativeTranscript::template deserialize_from_buffer(NativeTranscript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.emplace_back(NativeTranscript::template deserialize_from_buffer< bb::Univariate>( NativeTranscript::proof_data, num_frs_read)); } sumcheck_evaluations = NativeTranscript::template deserialize_from_buffer>( NativeTranscript::proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back( NativeTranscript::template deserialize_from_buffer(proof_data, num_frs_read)); } @@ -1164,7 +1163,6 @@ class ECCVMFlavor { NativeTranscript::proof_data.clear(); NativeTranscript::template serialize_to_buffer(circuit_size, NativeTranscript::proof_data); - size_t log_n = numeric::get_msb(circuit_size); NativeTranscript::template serialize_to_buffer(transcript_add_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(transcript_mul_comm, NativeTranscript::proof_data); @@ -1264,11 +1262,11 @@ class ECCVMFlavor { NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(lookup_inverses_comm, NativeTranscript::proof_data); NativeTranscript::template serialize_to_buffer(z_perm_comm, NativeTranscript::proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(sumcheck_univariates[i], NativeTranscript::proof_data); } NativeTranscript::template serialize_to_buffer(sumcheck_evaluations, NativeTranscript::proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { NativeTranscript::template serialize_to_buffer(zm_cq_comms[i], NativeTranscript::proof_data); } NativeTranscript::template serialize_to_buffer(zm_cq_comm, NativeTranscript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp index 7d049b169707..830eb7606830 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_prover.cpp @@ -121,7 +121,8 @@ void ECCVMProver::execute_pcs_rounds() // Execute the ZeroMorph protocol to produce a univariate opening claim for the multilinear evaluations produced by // Sumcheck auto multivariate_to_univariate_opening_claim = - ZeroMorph::prove(key->polynomials.get_unshifted(), + ZeroMorph::prove(key->circuit_size, + key->polynomials.get_unshifted(), key->polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 9eaedc9df93f..2f8999ada5da 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -140,7 +140,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, label); } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { round++; std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); @@ -153,7 +153,7 @@ class ECCVMTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 2c1e3d6dc571..26bd5ac6ce61 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -61,7 +61,8 @@ bool ECCVMVerifier::verify_proof(const HonkProof& proof) } // Reduce the multivariate evaluation claims produced by sumcheck to a single univariate opening claim - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp index 4ceb64781792..e2821b7789b1 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/eccvm_recursive_verifier.cpp @@ -31,7 +31,11 @@ template void ECCVMRecursiveVerifier_::verify_proof(co VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; - const auto circuit_size = transcript->template receive_from_prover("circuit_size"); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1040): Extract circuit size as BF (field_t) then + // convert to FF (bigfield fq) since this is what's expected by ZM. See issue for more details. + const BF circuit_size_bf = transcript->template receive_from_prover("circuit_size"); + const FF circuit_size{ static_cast(static_cast(circuit_size_bf.get_value())) }; + for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) { comm = transcript->template receive_from_prover(label); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1017): This is a hack to ensure zero commitments @@ -75,7 +79,8 @@ template void ECCVMRecursiveVerifier_::verify_proof(co auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = sumcheck.verify(relation_parameters, alpha, gate_challenges); - auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto multivariate_to_univariate_opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp index 5dcb13ffacb9..b25e5369adb2 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm_recursion/verifier_commitment_key.hpp @@ -7,12 +7,13 @@ namespace bb { * * @tparam Builder */ -template class VerifierCommitmentKey { +template class VerifierCommitmentKey { + public: + using Curve = Curve_; using Builder = Curve::Builder; using Commitment = Curve::AffineElement; using NativeEmbeddedCurve = typename Builder::EmbeddedCurve; - public: /** * @brief Construct a new Verifier Commitment Key object from its native counterpart. instantiated on Grumpkin. * This will be part of the ECCVMRecursiveFlavor once implemented. The Grumpkin SRS points are represented after diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 301597a6299e..0059b7e166ff 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -68,6 +68,9 @@ #include "barretenberg/common/std_array.hpp" #include "barretenberg/common/std_vector.hpp" #include "barretenberg/common/zip_view.hpp" +#include "barretenberg/constants.hpp" +#include "barretenberg/crypto/sha256/sha256.hpp" +#include "barretenberg/ecc/fields/field_conversion.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/polynomials/barycentric.hpp" #include "barretenberg/polynomials/evaluation_domain.hpp" @@ -181,6 +184,8 @@ class ProvingKeyAvm_ : public PrecomputedPolynomials, public WitnessPolynomials template class VerificationKey_ : public PrecomputedCommitments { public: + using FF = typename VerifierCommitmentKey::Curve::ScalarField; + using Commitment = typename VerifierCommitmentKey::Commitment; std::shared_ptr pcs_verification_key; uint64_t pub_inputs_offset = 0; @@ -191,6 +196,46 @@ class VerificationKey_ : public PrecomputedCommitments { this->log_circuit_size = numeric::get_msb(circuit_size); this->num_public_inputs = num_public_inputs; }; + + /** + * @brief Serialize verification key to field elements + * + * @return std::vector + */ + std::vector to_field_elements() + { + std::vector elements; + std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); + elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); + // do the same for the rest of the fields + std::vector num_public_inputs_elements = + bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); + elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); + std::vector pub_inputs_offset_elements = + bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); + elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); + + for (Commitment& comm : this->get_all()) { + std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); + elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); + } + return elements; + } + + uint256_t hash() + { + std::vector field_elements = to_field_elements(); + std::vector to_hash(field_elements.size() * sizeof(FF)); + + const auto convert_and_insert = [&to_hash](auto& vector) { + std::vector buffer = to_buffer(vector); + to_hash.insert(to_hash.end(), buffer.begin(), buffer.end()); + }; + + convert_and_insert(field_elements); + + return from_buffer(crypto::sha256(to_hash)); + } }; // Because of how Gemini is written, is importat to put the polynomials out in this order. diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 0fbdef6204fa..9e696ae35802 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -136,41 +136,6 @@ class GoblinMockCircuits { MockCircuits::construct_arithmetic_circuit(builder); } - /** - * @brief Construct a size 2^17 mock kernel circuit based on vanilla recursion for benchmarking - * @details This circuit contains (1) some arbitrary operations representing general kernel logic, (2) recursive - * verification of a function circuit proof, and optionally (3) recursive verification of a previous kernel circuit - * proof. The arbitrary kernel logic is structured to bring the final dyadic circuit size of the kernel to 2^17. - * - * TODO(https://github.com/AztecProtocol/barretenberg/issues/801): Pairing point aggregation not implemented - * @param builder - * @param function_accum {proof, vkey} for function circuit to be recursively verified - * @param prev_kernel_accum {proof, vkey} for previous kernel circuit to be recursively verified - */ - static void construct_mock_recursion_kernel_circuit(MegaBuilder& builder, - const KernelInput& function_accum, - const KernelInput& prev_kernel_accum) - { - // Add operations representing general kernel logic e.g. state updates. Note: these are structured to make the - // kernel "full" within the dyadic size 2^17 (130914 gates) - const size_t NUM_MERKLE_CHECKS = 40; - const size_t NUM_ECDSA_VERIFICATIONS = 1; - const size_t NUM_SHA_HASHES = 1; - stdlib::generate_merkle_membership_test_circuit(builder, NUM_MERKLE_CHECKS); - stdlib::generate_ecdsa_verification_test_circuit(builder, NUM_ECDSA_VERIFICATIONS); - stdlib::generate_sha256_test_circuit(builder, NUM_SHA_HASHES); - - // Execute recursive aggregation of function proof - RecursiveVerifier verifier1{ &builder, function_accum.verification_key }; - verifier1.verify_proof(function_accum.proof); - - // Execute recursive aggregation of previous kernel proof if one exists - if (!prev_kernel_accum.proof.empty()) { - RecursiveVerifier verifier2{ &builder, prev_kernel_accum.verification_key }; - verifier2.verify_proof(prev_kernel_accum.proof); - } - } - /** * @brief Construct a mock kernel circuit * @details Construct an arbitrary circuit meant to represent the aztec private function execution kernel. Recursive diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp index a31ee0cc09b2..b37cdd162062 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits_pinning.test.cpp @@ -32,31 +32,4 @@ TEST_F(MegaMockCircuitsPinning, FunctionSizes) }; run_test(true); run_test(false); -} - -TEST_F(MegaMockCircuitsPinning, RecursionKernelSizes) -{ - const auto run_test = [](bool large) { - { - GoblinProver goblin; - GoblinAccumulationOutput kernel_accum; - MegaCircuitBuilder app_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_function_circuit(app_circuit, large); - auto function_accum = goblin.accumulate(app_circuit); - MegaCircuitBuilder kernel_circuit{ goblin.op_queue }; - GoblinMockCircuits::construct_mock_recursion_kernel_circuit( - kernel_circuit, - { function_accum.proof, function_accum.verification_key }, - { kernel_accum.proof, kernel_accum.verification_key }); - - auto instance = std::make_shared(kernel_circuit); - if (large) { - EXPECT_EQ(instance->proving_key.log_circuit_size, 17); - } else { - EXPECT_EQ(instance->proving_key.log_circuit_size, 17); - }; - } - }; - run_test(true); - run_test(false); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp index a68b398b118d..b967dc0e93a9 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/library/grand_product_delta.hpp @@ -61,26 +61,4 @@ typename Flavor::FF compute_public_input_delta(std::span -Field compute_lookup_grand_product_delta(const Field& beta, const Field& gamma, const auto domain_size) -{ - Field gamma_by_one_plus_beta = gamma * (Field(1) + beta); // γ(1 + β) - return gamma_by_one_plus_beta.pow(domain_size); // (γ(1 + β))^n -} - } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp index 583a9d3ddf18..7dda9aaa4853 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/pow.hpp @@ -2,6 +2,7 @@ #include "barretenberg/common/compiler_hints.hpp" #include "barretenberg/common/op_count.hpp" #include "barretenberg/common/thread.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" #include #include @@ -63,6 +64,21 @@ template struct PowPolynomial { */ FF univariate_eval(FF challenge) const { return (FF(1) + (challenge * (betas[current_element_idx] - FF(1)))); }; + /** + * @brief Evaluate \f$ ((1−X_{i}) + X_{i}\cdot \beta_{i})\f$ at the challenge point \f$ X_{i}=u_{i} \f$. + */ + template FF univariate_eval(const FF& challenge, const Bool& dummy_round) const + { + FF beta_or_dummy; + if (!dummy_round.get_value()) { + beta_or_dummy = betas[current_element_idx]; + } else { + beta_or_dummy = FF::from_witness(challenge.get_context(), 1); + } + FF beta_val = FF::conditional_assign(dummy_round, FF::from_witness(challenge.get_context(), 1), beta_or_dummy); + return (FF(1) + (challenge * (beta_val - FF(1)))); + } + /** * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$ * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( @@ -77,6 +93,22 @@ template struct PowPolynomial { periodicity *= 2; } + /** + * @brief Partially evaluate the \f$pow_{\beta} \f$-polynomial at the new challenge and update \f$ c_i \f$ + * @details Update the constant \f$c_{i} \to c_{i+1} \f$ multiplying it by \f$pow_{\beta}\f$'s factor \f$\left( + * (1-X_i) + X_i\cdot \beta_i\right)\vert_{X_i = u_i}\f$ computed by \ref univariate_eval. + * @param challenge \f$ i \f$-th verifier challenge \f$ u_{i}\f$ + */ + template void partially_evaluate(const FF& challenge, const stdlib::bool_t& dummy) + { + FF current_univariate_eval = univariate_eval(challenge, dummy); + // If dummy round, make no update to the partial_evaluation_result + partial_evaluation_result = FF::conditional_assign( + dummy, partial_evaluation_result, partial_evaluation_result * current_univariate_eval); + current_element_idx++; + periodicity *= 2; + } + /** * @brief Given \f$ \vec\beta = (\beta_0,...,\beta_{d-1})\f$ compute \f$ pow_{\ell}(\vec \beta) = pow_{\beta}(\vec * \ell)\f$ for \f$ \ell =0,\ldots,2^{d}-1\f$. diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp index 5ae609a0e9a4..080a4f322f0d 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/decider_verifier.cpp @@ -44,12 +44,14 @@ template bool DeciderVerifier_::verify_proof(const Hon // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("Sumcheck verification failed."); return false; } // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(accumulator->verification_key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp index ff4313937703..eda58900a6eb 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/alu.hpp @@ -326,7 +326,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = ((alu_cf * (-alu_cf + FF(1))) - FF(0)); + auto tmp = (alu_cf * (-alu_cf + FF(1))); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -334,7 +334,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((alu_ff_tag * (-alu_ff_tag + FF(1))) - FF(0)); + auto tmp = (alu_ff_tag * (-alu_ff_tag + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -342,7 +342,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = ((alu_u8_tag * (-alu_u8_tag + FF(1))) - FF(0)); + auto tmp = (alu_u8_tag * (-alu_u8_tag + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -350,7 +350,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = ((alu_u16_tag * (-alu_u16_tag + FF(1))) - FF(0)); + auto tmp = (alu_u16_tag * (-alu_u16_tag + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -358,7 +358,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = ((alu_u32_tag * (-alu_u32_tag + FF(1))) - FF(0)); + auto tmp = (alu_u32_tag * (-alu_u32_tag + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -366,7 +366,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = ((alu_u64_tag * (-alu_u64_tag + FF(1))) - FF(0)); + auto tmp = (alu_u64_tag * (-alu_u64_tag + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -374,7 +374,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = ((alu_u128_tag * (-alu_u128_tag + FF(1))) - FF(0)); + auto tmp = (alu_u128_tag * (-alu_u128_tag + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -382,10 +382,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = ((alu_sel_alu * - ((((((alu_ff_tag + alu_u8_tag) + alu_u16_tag) + alu_u32_tag) + alu_u64_tag) + alu_u128_tag) - - FF(1))) - - FF(0)); + auto tmp = + (alu_sel_alu * + ((((((alu_ff_tag + alu_u8_tag) + alu_u16_tag) + alu_u32_tag) + alu_u64_tag) + alu_u128_tag) - FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -404,18 +403,17 @@ template class aluImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = ((((alu_op_add + alu_op_sub) * - ((((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - - alu_ia) + - (alu_ff_tag * alu_ic))) + - ((alu_op_add - alu_op_sub) * ((alu_cf * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })) - alu_ib))) - - FF(0)); + auto tmp = + (((alu_op_add + alu_op_sub) * ((((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - + alu_ia) + + (alu_ff_tag * alu_ic))) + + ((alu_op_add - alu_op_sub) * ((alu_cf * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })) - alu_ib))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -423,23 +421,22 @@ template class aluImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = ((((alu_op_add + alu_op_sub) * - (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) + - (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + - (alu_ff_tag * alu_ia)) - - alu_ic)) + - ((alu_ff_tag * (alu_op_add - alu_op_sub)) * alu_ib)) - - FF(0)); + auto tmp = (((alu_op_add + alu_op_sub) * + (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) + + (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + + (alu_ff_tag * alu_ia)) - + alu_ic)) + + ((alu_ff_tag * (alu_op_add - alu_op_sub)) * alu_ib)); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -447,7 +444,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = (((alu_ff_tag * alu_op_mul) * ((alu_ia * alu_ib) - alu_ic)) - FF(0)); + auto tmp = ((alu_ff_tag * alu_op_mul) * ((alu_ia * alu_ib) - alu_ic)); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -455,16 +452,15 @@ template class aluImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = (((((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_op_mul) * - (((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - - (alu_ia * alu_ib))) - - FF(0)); + auto tmp = ((((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_op_mul) * + (((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))) - + (alu_ia * alu_ib))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -473,13 +469,12 @@ template class aluImpl { Avm_DECLARE_VIEWS(16); auto tmp = - ((alu_op_mul * (((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) - - (((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_ic))) - - FF(0)); + (alu_op_mul * (((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) - + (((-alu_ff_tag + FF(1)) - alu_u128_tag) * alu_ic))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -487,15 +482,14 @@ template class aluImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = (((alu_u128_tag * alu_op_mul) * - ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - ((((alu_u16_r3 + (alu_u16_r4 * FF(65536))) + (alu_u16_r5 * FF(4294967296UL))) + - (alu_u16_r6 * FF(281474976710656UL))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - alu_ia)) - - FF(0)); + auto tmp = ((alu_u128_tag * alu_op_mul) * + ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + ((((alu_u16_r3 + (alu_u16_r4 * FF(65536))) + (alu_u16_r5 * FF(4294967296UL))) + + (alu_u16_r6 * FF(281474976710656UL))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + alu_ia)); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -504,15 +498,14 @@ template class aluImpl { Avm_DECLARE_VIEWS(18); auto tmp = - (((alu_u128_tag * alu_op_mul) * - ((((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + - (alu_u16_r1_shift * FF(4294967296UL))) + - (alu_u16_r2_shift * FF(281474976710656UL))) + - ((((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + - (alu_u16_r6_shift * FF(281474976710656UL))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - alu_ib)) - - FF(0)); + ((alu_u128_tag * alu_op_mul) * + ((((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + + (alu_u16_r1_shift * FF(4294967296UL))) + + (alu_u16_r2_shift * FF(281474976710656UL))) + + ((((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + + (alu_u16_r6_shift * FF(281474976710656UL))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + alu_ib)); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -521,22 +514,21 @@ template class aluImpl { Avm_DECLARE_VIEWS(19); auto tmp = - (((alu_u128_tag * alu_op_mul) * - ((((alu_ia * ((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + - (alu_u16_r1_shift * FF(4294967296UL))) + - (alu_u16_r2_shift * FF(281474976710656UL)))) + - ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) * - (((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + - (alu_u16_r6_shift * FF(281474976710656UL)))) * - FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - - (((alu_cf * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })) + - (((alu_u16_r7 + (alu_u16_r8 * FF(65536))) + (alu_u16_r9 * FF(4294967296UL))) + - (alu_u16_r10 * FF(281474976710656UL)))) * - FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - alu_ic)) - - FF(0)); + ((alu_u128_tag * alu_op_mul) * + ((((alu_ia * ((((alu_u8_r0_shift + (alu_u8_r1_shift * FF(256))) + (alu_u16_r0_shift * FF(65536))) + + (alu_u16_r1_shift * FF(4294967296UL))) + + (alu_u16_r2_shift * FF(281474976710656UL)))) + + ((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) * + (((alu_u16_r3_shift + (alu_u16_r4_shift * FF(65536))) + (alu_u16_r5_shift * FF(4294967296UL))) + + (alu_u16_r6_shift * FF(281474976710656UL)))) * + FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) - + (((alu_cf * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })) + + (((alu_u16_r7 + (alu_u16_r8 * FF(65536))) + (alu_u16_r9 * FF(4294967296UL))) + + (alu_u16_r10 * FF(281474976710656UL)))) * + FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + alu_ic)); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -544,7 +536,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = ((alu_op_not * alu_ff_tag) - FF(0)); + auto tmp = (alu_op_not * alu_ff_tag); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -552,12 +544,12 @@ template class aluImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = ((alu_op_not * ((alu_ia + alu_ic) - ((((((alu_u8_tag * FF(256)) + (alu_u16_tag * FF(65536))) + - (alu_u32_tag * FF(4294967296UL))) + - (alu_u64_tag * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u128_tag * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - FF(1)))) - - FF(0)); + auto tmp = (alu_op_not * + ((alu_ia + alu_ic) - + ((((((alu_u8_tag * FF(256)) + (alu_u16_tag * FF(65536))) + (alu_u32_tag * FF(4294967296UL))) + + (alu_u64_tag * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u128_tag * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + FF(1)))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -565,7 +557,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = (((alu_sel_cmp + alu_op_eq) * (alu_ic * (-alu_ic + FF(1)))) - FF(0)); + auto tmp = ((alu_sel_cmp + alu_op_eq) * (alu_ic * (-alu_ic + FF(1)))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -574,10 +566,9 @@ template class aluImpl { Avm_DECLARE_VIEWS(23); auto tmp = - ((alu_op_eq * - ((((alu_ia - alu_ib) * ((alu_ic * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - FF(1)) + - alu_ic)) - - FF(0)); + (alu_op_eq * + ((((alu_ia - alu_ib) * ((alu_ic * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - FF(1)) + + alu_ic)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -603,7 +594,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = ((alu_p_a_borrow * (-alu_p_a_borrow + FF(1))) - FF(0)); + auto tmp = (alu_p_a_borrow * (-alu_p_a_borrow + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -611,11 +602,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = (((alu_p_sub_a_lo - - ((-alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + - (alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)) - - FF(0)); + auto tmp = ((alu_p_sub_a_lo - + ((-alu_a_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + + (alu_p_a_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * + ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -623,11 +613,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (((alu_p_sub_a_hi - - ((-alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - - alu_p_a_borrow)) * - ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)) - - FF(0)); + auto tmp = ((alu_p_sub_a_hi - + ((-alu_a_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - + alu_p_a_borrow)) * + ((alu_sel_cmp + alu_op_cast) + alu_op_div_std)); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -635,7 +624,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = ((alu_p_b_borrow * (-alu_p_b_borrow + FF(1))) - FF(0)); + auto tmp = (alu_p_b_borrow * (-alu_p_b_borrow + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -643,11 +632,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = (((alu_p_sub_b_lo - - ((-alu_b_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + - (alu_p_b_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * - alu_sel_cmp) - - FF(0)); + auto tmp = ((alu_p_sub_b_lo - + ((-alu_b_lo + FF(uint256_t{ 4891460686036598784UL, 2896914383306846353UL, 0UL, 0UL })) + + (alu_p_b_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL })))) * + alu_sel_cmp); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -655,11 +643,10 @@ template class aluImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = (((alu_p_sub_b_hi - - ((-alu_b_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - - alu_p_b_borrow)) * - alu_sel_cmp) - - FF(0)); + auto tmp = ((alu_p_sub_b_hi - + ((-alu_b_hi + FF(uint256_t{ 13281191951274694749UL, 3486998266802970665UL, 0UL, 0UL })) - + alu_p_b_borrow)) * + alu_sel_cmp); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -667,13 +654,12 @@ template class aluImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = (((alu_res_lo - - (((((alu_a_lo - alu_b_lo) - FF(1)) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * - ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + - (((alu_b_lo - alu_a_lo) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * - (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * - alu_sel_cmp) - - FF(0)); + auto tmp = ((alu_res_lo - + (((((alu_a_lo - alu_b_lo) - FF(1)) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + + (((alu_b_lo - alu_a_lo) + (alu_borrow * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) * + (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * + alu_sel_cmp); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -682,12 +668,11 @@ template class aluImpl { Avm_DECLARE_VIEWS(33); auto tmp = - (((alu_res_hi - - ((((alu_a_hi - alu_b_hi) - alu_borrow) * ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + - (((alu_b_hi - alu_a_hi) - alu_borrow) * - (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * - alu_sel_cmp) - - FF(0)); + ((alu_res_hi - + ((((alu_a_hi - alu_b_hi) - alu_borrow) * ((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte))) + + (((alu_b_hi - alu_a_hi) - alu_borrow) * + (-((alu_op_lt * alu_ic) + ((-alu_ic + FF(1)) * alu_op_lte)) + FF(1))))) * + alu_sel_cmp); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -695,7 +680,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = ((((alu_cmp_rng_ctr_shift - alu_cmp_rng_ctr) + FF(1)) * alu_cmp_rng_ctr) - FF(0)); + auto tmp = (((alu_cmp_rng_ctr_shift - alu_cmp_rng_ctr) + FF(1)) * alu_cmp_rng_ctr); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -703,7 +688,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = (((alu_cmp_rng_ctr_shift - FF(4)) * alu_sel_cmp) - FF(0)); + auto tmp = ((alu_cmp_rng_ctr_shift - FF(4)) * alu_sel_cmp); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -711,7 +696,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = ((alu_sel_rng_chk * (-alu_sel_rng_chk + FF(1))) - FF(0)); + auto tmp = (alu_sel_rng_chk * (-alu_sel_rng_chk + FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -719,7 +704,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = ((alu_sel_rng_chk * alu_sel_cmp) - FF(0)); + auto tmp = (alu_sel_rng_chk * alu_sel_cmp); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -727,10 +712,9 @@ template class aluImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = (((alu_cmp_rng_ctr * - (((-alu_sel_rng_chk + FF(1)) * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - - alu_sel_rng_chk) - - FF(0)); + auto tmp = ((alu_cmp_rng_ctr * + (((-alu_sel_rng_chk + FF(1)) * (-alu_op_eq_diff_inv + FF(1))) + alu_op_eq_diff_inv)) - + alu_sel_rng_chk); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -789,7 +773,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = (((alu_a_lo_shift - alu_b_lo) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_a_lo_shift - alu_b_lo) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -797,7 +781,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = (((alu_a_hi_shift - alu_b_hi) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_a_hi_shift - alu_b_hi) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -805,7 +789,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = (((alu_b_lo_shift - alu_p_sub_a_lo) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_b_lo_shift - alu_p_sub_a_lo) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -813,7 +797,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = (((alu_b_hi_shift - alu_p_sub_a_hi) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_b_hi_shift - alu_p_sub_a_hi) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -821,7 +805,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = (((alu_p_sub_a_lo_shift - alu_p_sub_b_lo) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_p_sub_a_lo_shift - alu_p_sub_b_lo) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -829,7 +813,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = (((alu_p_sub_a_hi_shift - alu_p_sub_b_hi) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_p_sub_a_hi_shift - alu_p_sub_b_hi) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -837,7 +821,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = (((alu_p_sub_b_lo_shift - alu_res_lo) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_p_sub_b_lo_shift - alu_res_lo) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -845,7 +829,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = (((alu_p_sub_b_hi_shift - alu_res_hi) * alu_sel_rng_chk_shift) - FF(0)); + auto tmp = ((alu_p_sub_b_hi_shift - alu_res_hi) * alu_sel_rng_chk_shift); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -861,22 +845,21 @@ template class aluImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = ((alu_op_cast * - (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + - (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + - (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))))) + - (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + - (alu_u16_r1 * FF(4294967296UL))) + - (alu_u16_r2 * FF(281474976710656UL))) + - (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + - (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + - (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + - (alu_ff_tag * alu_ia)) - - alu_ic)) - - FF(0)); + auto tmp = (alu_op_cast * + (((((((alu_u8_tag * alu_u8_r0) + (alu_u16_tag * (alu_u8_r0 + (alu_u8_r1 * FF(256))))) + + (alu_u32_tag * ((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))))) + + (alu_u64_tag * ((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))))) + + (alu_u128_tag * ((((((((alu_u8_r0 + (alu_u8_r1 * FF(256))) + (alu_u16_r0 * FF(65536))) + + (alu_u16_r1 * FF(4294967296UL))) + + (alu_u16_r2 * FF(281474976710656UL))) + + (alu_u16_r3 * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + (alu_u16_r4 * FF(uint256_t{ 0UL, 65536UL, 0UL, 0UL }))) + + (alu_u16_r5 * FF(uint256_t{ 0UL, 4294967296UL, 0UL, 0UL }))) + + (alu_u16_r6 * FF(uint256_t{ 0UL, 281474976710656UL, 0UL, 0UL }))))) + + (alu_ff_tag * alu_ia)) - + alu_ic)); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -884,7 +867,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = ((alu_op_cast * (alu_a_lo_shift - alu_p_sub_a_lo)) - FF(0)); + auto tmp = (alu_op_cast * (alu_a_lo_shift - alu_p_sub_a_lo)); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -892,7 +875,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = ((alu_op_cast * (alu_a_hi_shift - alu_p_sub_a_hi)) - FF(0)); + auto tmp = (alu_op_cast * (alu_a_hi_shift - alu_p_sub_a_hi)); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -900,7 +883,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = ((((alu_op_mul * alu_u128_tag) + alu_op_cast) * alu_sel_alu_shift) - FF(0)); + auto tmp = (((alu_op_mul * alu_u128_tag) + alu_op_cast) * alu_sel_alu_shift); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -908,8 +891,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_lo - ((alu_two_pow_s - alu_b_lo) - FF(1)))) - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_lo - ((alu_two_pow_s - alu_b_lo) - FF(1)))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -917,9 +899,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_hi - ((alu_two_pow_t_sub_s - alu_b_hi) - FF(1)))) - - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (alu_a_hi - ((alu_two_pow_t_sub_s - alu_b_hi) - FF(1)))); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -927,9 +907,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_lo - ((alu_two_pow_t_sub_s - alu_b_lo) - FF(1)))) - - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_lo - ((alu_two_pow_t_sub_s - alu_b_lo) - FF(1)))); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -937,8 +915,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_hi - ((alu_two_pow_s - alu_b_hi) - FF(1)))) - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (alu_a_hi - ((alu_two_pow_s - alu_b_hi) - FF(1)))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -946,7 +923,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = ((alu_shift_lt_bit_len * (-alu_shift_lt_bit_len + FF(1))) - FF(0)); + auto tmp = (alu_shift_lt_bit_len * (-alu_shift_lt_bit_len + FF(1))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -972,8 +949,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shr) * (((alu_b_hi * alu_two_pow_s) + alu_b_lo) - alu_ia)) - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shr) * (((alu_b_hi * alu_two_pow_s) + alu_b_lo) - alu_ia)); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -981,7 +957,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = ((alu_op_shr * (alu_ic - (alu_b_hi * alu_shift_lt_bit_len))) - FF(0)); + auto tmp = (alu_op_shr * (alu_ic - (alu_b_hi * alu_shift_lt_bit_len))); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -989,9 +965,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = - (((alu_shift_lt_bit_len * alu_op_shl) * (((alu_b_hi * alu_two_pow_t_sub_s) + alu_b_lo) - alu_ia)) - - FF(0)); + auto tmp = ((alu_shift_lt_bit_len * alu_op_shl) * (((alu_b_hi * alu_two_pow_t_sub_s) + alu_b_lo) - alu_ia)); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -999,7 +973,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = ((alu_op_shl * (alu_ic - ((alu_b_lo * alu_two_pow_s) * alu_shift_lt_bit_len))) - FF(0)); + auto tmp = (alu_op_shl * (alu_ic - ((alu_b_lo * alu_two_pow_s) * alu_shift_lt_bit_len))); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -1015,7 +989,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = ((alu_op_div_a_lt_b * (-alu_op_div_a_lt_b + FF(1))) - FF(0)); + auto tmp = (alu_op_div_a_lt_b * (-alu_op_div_a_lt_b + FF(1))); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -1023,7 +997,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(67); - auto tmp = ((alu_op_div_a_lt_b * (alu_a_lo - ((alu_ib - alu_ia) - FF(1)))) - FF(0)); + auto tmp = (alu_op_div_a_lt_b * (alu_a_lo - ((alu_ib - alu_ia) - FF(1)))); tmp *= scaling_factor; std::get<67>(evals) += tmp; } @@ -1031,7 +1005,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(68); - auto tmp = ((alu_op_div_a_lt_b * alu_ic) - FF(0)); + auto tmp = (alu_op_div_a_lt_b * alu_ic); tmp *= scaling_factor; std::get<68>(evals) += tmp; } @@ -1039,7 +1013,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(69); - auto tmp = ((alu_op_div_a_lt_b * (alu_ia - alu_remainder)) - FF(0)); + auto tmp = (alu_op_div_a_lt_b * (alu_ia - alu_remainder)); tmp *= scaling_factor; std::get<69>(evals) += tmp; } @@ -1047,7 +1021,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(70); - auto tmp = ((alu_op_div_std * (-alu_op_div_std + FF(1))) - FF(0)); + auto tmp = (alu_op_div_std * (-alu_op_div_std + FF(1))); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -1055,9 +1029,8 @@ template class aluImpl { { Avm_DECLARE_VIEWS(71); - auto tmp = ((alu_op_div_std * - ((alu_ib - alu_divisor_lo) - (alu_divisor_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))) - - FF(0)); + auto tmp = + (alu_op_div_std * ((alu_ib - alu_divisor_lo) - (alu_divisor_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -1065,9 +1038,8 @@ template class aluImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = ((alu_op_div_std * - ((alu_ic - alu_quotient_lo) - (alu_quotient_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))) - - FF(0)); + auto tmp = (alu_op_div_std * + ((alu_ic - alu_quotient_lo) - (alu_quotient_hi * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL })))); tmp *= scaling_factor; std::get<72>(evals) += tmp; } @@ -1085,12 +1057,10 @@ template class aluImpl { Avm_DECLARE_VIEWS(74); auto tmp = - ((alu_op_div_std * - ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * - FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - (alu_a_lo + (alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))))) - - FF(0)); + (alu_op_div_std * + ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + (alu_a_lo + (alu_a_hi * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))))); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -1098,7 +1068,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(75); - auto tmp = ((alu_op_div_std * (alu_b_hi - ((alu_ib - alu_remainder) - FF(1)))) - FF(0)); + auto tmp = (alu_op_div_std * (alu_b_hi - ((alu_ib - alu_remainder) - FF(1)))); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -1106,7 +1076,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(76); - auto tmp = (((alu_cmp_rng_ctr_shift - FF(2)) * alu_op_div_std) - FF(0)); + auto tmp = ((alu_cmp_rng_ctr_shift - FF(2)) * alu_op_div_std); tmp *= scaling_factor; std::get<76>(evals) += tmp; } @@ -1114,7 +1084,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(77); - auto tmp = ((alu_sel_rng_chk * alu_op_div_std) - FF(0)); + auto tmp = (alu_sel_rng_chk * alu_op_div_std); tmp *= scaling_factor; std::get<77>(evals) += tmp; } @@ -1123,12 +1093,10 @@ template class aluImpl { Avm_DECLARE_VIEWS(78); auto tmp = - ((alu_op_div_std * - ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + - ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * - FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - - (alu_ia - alu_remainder))) - - FF(0)); + (alu_op_div_std * + ((((alu_divisor_lo * alu_quotient_lo) + (alu_partial_prod_lo * FF(uint256_t{ 0UL, 1UL, 0UL, 0UL }))) + + ((alu_partial_prod_hi + (alu_divisor_hi * alu_quotient_hi)) * FF(uint256_t{ 0UL, 0UL, 1UL, 0UL }))) - + (alu_ia - alu_remainder))); tmp *= scaling_factor; std::get<78>(evals) += tmp; } @@ -1136,7 +1104,7 @@ template class aluImpl { { Avm_DECLARE_VIEWS(79); - auto tmp = ((alu_sel_div_rng_chk * (-alu_sel_div_rng_chk + FF(1))) - FF(0)); + auto tmp = (alu_sel_div_rng_chk * (-alu_sel_div_rng_chk + FF(1))); tmp *= scaling_factor; std::get<79>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp index 615e12a21c9d..98260f373373 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/binary.hpp @@ -69,7 +69,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((binary_sel_bin * (-binary_sel_bin + FF(1))) - FF(0)); + auto tmp = (binary_sel_bin * (-binary_sel_bin + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -77,7 +77,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = (((binary_op_id_shift - binary_op_id) * binary_mem_tag_ctr) - FF(0)); + auto tmp = ((binary_op_id_shift - binary_op_id) * binary_mem_tag_ctr); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -85,7 +85,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = ((((binary_mem_tag_ctr_shift - binary_mem_tag_ctr) + FF(1)) * binary_mem_tag_ctr) - FF(0)); + auto tmp = (((binary_mem_tag_ctr_shift - binary_mem_tag_ctr) + FF(1)) * binary_mem_tag_ctr); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -93,10 +93,9 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = (((binary_mem_tag_ctr * - (((-binary_sel_bin + FF(1)) * (-binary_mem_tag_ctr_inv + FF(1))) + binary_mem_tag_ctr_inv)) - - binary_sel_bin) - - FF(0)); + auto tmp = ((binary_mem_tag_ctr * + (((-binary_sel_bin + FF(1)) * (-binary_mem_tag_ctr_inv + FF(1))) + binary_mem_tag_ctr_inv)) - + binary_sel_bin); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -104,7 +103,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ia) - FF(0)); + auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ia); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -112,7 +111,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ib) - FF(0)); + auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ib); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -120,7 +119,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (((-binary_sel_bin + FF(1)) * binary_acc_ic) - FF(0)); + auto tmp = ((-binary_sel_bin + FF(1)) * binary_acc_ic); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -128,8 +127,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = - ((((binary_acc_ia - binary_ia_bytes) - (binary_acc_ia_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); + auto tmp = (((binary_acc_ia - binary_ia_bytes) - (binary_acc_ia_shift * FF(256))) * binary_mem_tag_ctr); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -137,8 +135,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = - ((((binary_acc_ib - binary_ib_bytes) - (binary_acc_ib_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); + auto tmp = (((binary_acc_ib - binary_ib_bytes) - (binary_acc_ib_shift * FF(256))) * binary_mem_tag_ctr); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -146,8 +143,7 @@ template class binaryImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = - ((((binary_acc_ic - binary_ic_bytes) - (binary_acc_ic_shift * FF(256))) * binary_mem_tag_ctr) - FF(0)); + auto tmp = (((binary_acc_ic - binary_ic_bytes) - (binary_acc_ic_shift * FF(256))) * binary_mem_tag_ctr); tmp *= scaling_factor; std::get<9>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp index a51605c8f18d..b83fb6bf7ac6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/conversion.hpp @@ -37,7 +37,7 @@ template class conversionImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((conversion_sel_to_radix_le * (-conversion_sel_to_radix_le + FF(1))) - FF(0)); + auto tmp = (conversion_sel_to_radix_le * (-conversion_sel_to_radix_le + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp index 2cdb82e6d1e2..c50b8825f71d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/declare_views.hpp @@ -8,6 +8,7 @@ [[maybe_unused]] auto kernel_kernel_value_out = View(new_term.kernel_kernel_value_out); \ [[maybe_unused]] auto kernel_kernel_side_effect_out = View(new_term.kernel_kernel_side_effect_out); \ [[maybe_unused]] auto kernel_kernel_metadata_out = View(new_term.kernel_kernel_metadata_out); \ + [[maybe_unused]] auto main_calldata = View(new_term.main_calldata); \ [[maybe_unused]] auto alu_a_hi = View(new_term.alu_a_hi); \ [[maybe_unused]] auto alu_a_lo = View(new_term.alu_a_lo); \ [[maybe_unused]] auto alu_b_hi = View(new_term.alu_b_hi); \ @@ -210,6 +211,7 @@ [[maybe_unused]] auto main_sel_op_fdiv = View(new_term.main_sel_op_fdiv); \ [[maybe_unused]] auto main_sel_op_fee_per_da_gas = View(new_term.main_sel_op_fee_per_da_gas); \ [[maybe_unused]] auto main_sel_op_fee_per_l2_gas = View(new_term.main_sel_op_fee_per_l2_gas); \ + [[maybe_unused]] auto main_sel_op_function_selector = View(new_term.main_sel_op_function_selector); \ [[maybe_unused]] auto main_sel_op_get_contract_instance = View(new_term.main_sel_op_get_contract_instance); \ [[maybe_unused]] auto main_sel_op_halt = View(new_term.main_sel_op_halt); \ [[maybe_unused]] auto main_sel_op_internal_call = View(new_term.main_sel_op_internal_call); \ diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp index 7c69045c0014..a5e2adfe5a02 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/gas.hpp @@ -41,7 +41,7 @@ template class gasImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((gas_sel_gas_cost - gas_sel_gas_cost) - FF(0)); + auto tmp = (gas_sel_gas_cost - gas_sel_gas_cost); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -49,7 +49,7 @@ template class gasImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = ((gas_l2_gas_fixed_table - gas_l2_gas_fixed_table) - FF(0)); + auto tmp = (gas_l2_gas_fixed_table - gas_l2_gas_fixed_table); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -57,7 +57,7 @@ template class gasImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = ((gas_da_gas_fixed_table - gas_da_gas_fixed_table) - FF(0)); + auto tmp = (gas_da_gas_fixed_table - gas_da_gas_fixed_table); tmp *= scaling_factor; std::get<2>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp index 18989c0e836b..56e0a9e6a5d3 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/keccakf1600.hpp @@ -37,7 +37,7 @@ template class keccakf1600Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((keccakf1600_sel_keccakf1600 * (-keccakf1600_sel_keccakf1600 + FF(1))) - FF(0)); + auto tmp = (keccakf1600_sel_keccakf1600 * (-keccakf1600_sel_keccakf1600 + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp index e9e0d0e17489..a53770f6481b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/kernel.hpp @@ -98,9 +98,8 @@ template class kernelImpl { Avm_DECLARE_VIEWS(0); auto tmp = - (((-main_sel_last + FF(1)) * (kernel_note_hash_exist_write_offset_shift - - (kernel_note_hash_exist_write_offset + main_sel_op_note_hash_exists))) - - FF(0)); + ((-main_sel_last + FF(1)) * (kernel_note_hash_exist_write_offset_shift - + (kernel_note_hash_exist_write_offset + main_sel_op_note_hash_exists))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -108,10 +107,8 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = - (((-main_sel_last + FF(1)) * (kernel_emit_note_hash_write_offset_shift - - (kernel_emit_note_hash_write_offset + main_sel_op_emit_note_hash))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * (kernel_emit_note_hash_write_offset_shift - + (kernel_emit_note_hash_write_offset + main_sel_op_emit_note_hash))); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -119,10 +116,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_nullifier_exists_write_offset_shift - - (kernel_nullifier_exists_write_offset + (main_sel_op_nullifier_exists * main_ib)))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * + (kernel_nullifier_exists_write_offset_shift - + (kernel_nullifier_exists_write_offset + (main_sel_op_nullifier_exists * main_ib)))); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -131,10 +127,9 @@ template class kernelImpl { Avm_DECLARE_VIEWS(3); auto tmp = - (((-main_sel_last + FF(1)) * - (kernel_nullifier_non_exists_write_offset_shift - - (kernel_nullifier_non_exists_write_offset + (main_sel_op_nullifier_exists * (-main_ib + FF(1)))))) - - FF(0)); + ((-main_sel_last + FF(1)) * + (kernel_nullifier_non_exists_write_offset_shift - + (kernel_nullifier_non_exists_write_offset + (main_sel_op_nullifier_exists * (-main_ib + FF(1)))))); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -142,10 +137,8 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = - (((-main_sel_last + FF(1)) * (kernel_emit_nullifier_write_offset_shift - - (kernel_emit_nullifier_write_offset + main_sel_op_emit_nullifier))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * (kernel_emit_nullifier_write_offset_shift - + (kernel_emit_nullifier_write_offset + main_sel_op_emit_nullifier))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -153,10 +146,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_l1_to_l2_msg_exists_write_offset_shift - - (kernel_l1_to_l2_msg_exists_write_offset + main_sel_op_l1_to_l2_msg_exists))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * + (kernel_l1_to_l2_msg_exists_write_offset_shift - + (kernel_l1_to_l2_msg_exists_write_offset + main_sel_op_l1_to_l2_msg_exists))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -164,10 +156,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_emit_unencrypted_log_write_offset_shift - - (kernel_emit_unencrypted_log_write_offset + main_sel_op_emit_unencrypted_log))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * + (kernel_emit_unencrypted_log_write_offset_shift - + (kernel_emit_unencrypted_log_write_offset + main_sel_op_emit_unencrypted_log))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -175,10 +166,9 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_emit_l2_to_l1_msg_write_offset_shift - - (kernel_emit_l2_to_l1_msg_write_offset + main_sel_op_emit_l2_to_l1_msg))) - - FF(0)); + auto tmp = + ((-main_sel_last + FF(1)) * (kernel_emit_l2_to_l1_msg_write_offset_shift - + (kernel_emit_l2_to_l1_msg_write_offset + main_sel_op_emit_l2_to_l1_msg))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -186,9 +176,8 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_sload_write_offset_shift - (kernel_sload_write_offset + main_sel_op_sload))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * + (kernel_sload_write_offset_shift - (kernel_sload_write_offset + main_sel_op_sload))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -196,9 +185,8 @@ template class kernelImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = (((-main_sel_last + FF(1)) * - (kernel_sstore_write_offset_shift - (kernel_sstore_write_offset + main_sel_op_sstore))) - - FF(0)); + auto tmp = ((-main_sel_last + FF(1)) * + (kernel_sstore_write_offset_shift - (kernel_sstore_write_offset + main_sel_op_sstore))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp index 1517e106ca72..36cdae9545be 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/main.hpp @@ -84,6 +84,7 @@ template struct MainRow { FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; + FF main_sel_op_function_selector{}; FF main_sel_op_get_contract_instance{}; FF main_sel_op_halt{}; FF main_sel_op_internal_call{}; @@ -144,80 +145,77 @@ inline std::string get_relation_label_main(int index) case 5: return "DA_GAS_INACTIVE"; - case 74: + case 75: return "OUTPUT_U8"; - case 75: + case 76: return "SUBOP_FDIV"; - case 76: + case 77: return "SUBOP_FDIV_ZERO_ERR1"; - case 77: + case 78: return "SUBOP_FDIV_ZERO_ERR2"; - case 78: + case 79: return "SUBOP_FDIV_R_IN_TAG_FF"; - case 79: + case 80: return "SUBOP_FDIV_W_IN_TAG_FF"; - case 80: + case 81: return "SUBOP_ERROR_RELEVANT_OP"; - case 81: + case 82: return "KERNEL_INPUT_ACTIVE_CHECK"; - case 82: + case 83: return "KERNEL_OUTPUT_ACTIVE_CHECK"; - case 83: + case 84: return "PC_JUMP"; - case 84: + case 85: return "PC_JUMPI"; - case 85: + case 86: return "RETURN_POINTER_INCREMENT"; - case 91: + case 92: return "RETURN_POINTER_DECREMENT"; - case 97: + case 98: return "PC_INCREMENT"; - case 98: + case 99: return "INTERNAL_RETURN_POINTER_CONSISTENCY"; - case 99: + case 100: return "SPACE_ID_INTERNAL"; - case 100: + case 101: return "SPACE_ID_STANDARD_OPCODES"; - case 101: + case 102: return "CMOV_CONDITION_RES_1"; - case 102: + case 103: return "CMOV_CONDITION_RES_2"; - case 105: + case 106: return "MOV_SAME_VALUE_A"; - case 106: + case 107: return "MOV_SAME_VALUE_B"; - case 107: + case 108: return "MOV_MAIN_SAME_TAG"; - case 111: - return "L2GASLEFT"; - case 112: - return "DAGASLEFT"; + return "L2GASLEFT"; case 113: - return "SENDER_KERNEL"; + return "DAGASLEFT"; case 114: return "ADDRESS_KERNEL"; @@ -226,10 +224,10 @@ inline std::string get_relation_label_main(int index) return "STORAGE_ADDRESS_KERNEL"; case 116: - return "FEE_DA_GAS_KERNEL"; + return "SENDER_KERNEL"; case 117: - return "FEE_L2_GAS_KERNEL"; + return "FUNCTION_SELECTOR_KERNEL"; case 118: return "FEE_TRANSACTION_FEE_KERNEL"; @@ -244,42 +242,48 @@ inline std::string get_relation_label_main(int index) return "BLOCK_NUMBER_KERNEL"; case 122: - return "COINBASE_KERNEL"; + return "TIMESTAMP_KERNEL"; case 123: - return "TIMESTAMP_KERNEL"; + return "COINBASE_KERNEL"; case 124: - return "NOTE_HASH_KERNEL_OUTPUT"; + return "FEE_DA_GAS_KERNEL"; + + case 125: + return "FEE_L2_GAS_KERNEL"; case 126: - return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + return "NOTE_HASH_KERNEL_OUTPUT"; case 128: + return "EMIT_NOTE_HASH_KERNEL_OUTPUT"; + + case 130: return "NULLIFIER_EXISTS_KERNEL_OUTPUT"; - case 131: + case 133: return "EMIT_NULLIFIER_KERNEL_OUTPUT"; - case 133: + case 135: return "L1_TO_L2_MSG_EXISTS_KERNEL_OUTPUT"; - case 135: + case 137: return "EMIT_UNENCRYPTED_LOG_KERNEL_OUTPUT"; - case 137: + case 139: return "EMIT_L2_TO_L1_MSGS_KERNEL_OUTPUT"; - case 139: + case 141: return "SLOAD_KERNEL_OUTPUT"; - case 141: + case 143: return "SSTORE_KERNEL_OUTPUT"; - case 144: + case 146: return "BIN_SEL_1"; - case 145: + case 147: return "BIN_SEL_2"; } return std::to_string(index); @@ -289,11 +293,11 @@ template class mainImpl { public: using FF = FF_; - static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ + static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 3, 3, 3, 3, 3, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 3, 3, 5, 4, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 5, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 4, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, }; template @@ -307,7 +311,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((main_l2_out_of_gas * (-main_l2_out_of_gas + FF(1))) - FF(0)); + auto tmp = (main_l2_out_of_gas * (-main_l2_out_of_gas + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -315,7 +319,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = ((main_da_out_of_gas * (-main_da_out_of_gas + FF(1))) - FF(0)); + auto tmp = (main_da_out_of_gas * (-main_da_out_of_gas + FF(1))); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -323,9 +327,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = ((main_sel_gas_accounting_active * - ((main_l2_gas_remaining_shift - main_l2_gas_remaining) + main_l2_gas_op_cost)) - - FF(0)); + auto tmp = (main_sel_gas_accounting_active * + ((main_l2_gas_remaining_shift - main_l2_gas_remaining) + main_l2_gas_op_cost)); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -333,9 +336,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = ((main_sel_gas_accounting_active * - ((main_da_gas_remaining_shift - main_da_gas_remaining) + main_da_gas_op_cost)) - - FF(0)); + auto tmp = (main_sel_gas_accounting_active * + ((main_da_gas_remaining_shift - main_da_gas_remaining) + main_da_gas_op_cost)); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -343,7 +345,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = (((-main_sel_gas_accounting_active + FF(1)) * main_l2_gas_op_cost) - FF(0)); + auto tmp = ((-main_sel_gas_accounting_active + FF(1)) * main_l2_gas_op_cost); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -351,7 +353,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = (((-main_sel_gas_accounting_active + FF(1)) * main_da_gas_op_cost) - FF(0)); + auto tmp = ((-main_sel_gas_accounting_active + FF(1)) * main_da_gas_op_cost); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -359,11 +361,10 @@ template class mainImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = ((main_sel_gas_accounting_active * - ((((-(main_l2_out_of_gas * FF(2)) + FF(1)) * main_l2_gas_remaining_shift) - - (main_abs_l2_rem_gas_hi * FF(65536))) - - main_abs_l2_rem_gas_lo)) - - FF(0)); + auto tmp = (main_sel_gas_accounting_active * + ((((-(main_l2_out_of_gas * FF(2)) + FF(1)) * main_l2_gas_remaining_shift) - + (main_abs_l2_rem_gas_hi * FF(65536))) - + main_abs_l2_rem_gas_lo)); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -371,11 +372,10 @@ template class mainImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = ((main_sel_gas_accounting_active * - ((((-(main_da_out_of_gas * FF(2)) + FF(1)) * main_da_gas_remaining_shift) - - (main_abs_da_rem_gas_hi * FF(65536))) - - main_abs_da_rem_gas_lo)) - - FF(0)); + auto tmp = (main_sel_gas_accounting_active * + ((((-(main_da_out_of_gas * FF(2)) + FF(1)) * main_da_gas_remaining_shift) - + (main_abs_da_rem_gas_hi * FF(65536))) - + main_abs_da_rem_gas_lo)); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -383,7 +383,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = ((main_sel_op_sender * (-main_sel_op_sender + FF(1))) - FF(0)); + auto tmp = (main_sel_op_address * (-main_sel_op_address + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -391,7 +391,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = ((main_sel_op_address * (-main_sel_op_address + FF(1))) - FF(0)); + auto tmp = (main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -399,7 +399,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = ((main_sel_op_storage_address * (-main_sel_op_storage_address + FF(1))) - FF(0)); + auto tmp = (main_sel_op_sender * (-main_sel_op_sender + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -407,7 +407,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = ((main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))) - FF(0)); + auto tmp = (main_sel_op_function_selector * (-main_sel_op_function_selector + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -415,7 +415,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(12); - auto tmp = ((main_sel_op_version * (-main_sel_op_version + FF(1))) - FF(0)); + auto tmp = (main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))); tmp *= scaling_factor; std::get<12>(evals) += tmp; } @@ -423,7 +423,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = ((main_sel_op_block_number * (-main_sel_op_block_number + FF(1))) - FF(0)); + auto tmp = (main_sel_op_chain_id * (-main_sel_op_chain_id + FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -431,7 +431,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = ((main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))) - FF(0)); + auto tmp = (main_sel_op_version * (-main_sel_op_version + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -439,7 +439,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = ((main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))) - FF(0)); + auto tmp = (main_sel_op_block_number * (-main_sel_op_block_number + FF(1))); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -447,7 +447,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = ((main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))) - FF(0)); + auto tmp = (main_sel_op_coinbase * (-main_sel_op_coinbase + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -455,7 +455,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(17); - auto tmp = ((main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))) - FF(0)); + auto tmp = (main_sel_op_timestamp * (-main_sel_op_timestamp + FF(1))); tmp *= scaling_factor; std::get<17>(evals) += tmp; } @@ -463,7 +463,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(18); - auto tmp = ((main_sel_op_transaction_fee * (-main_sel_op_transaction_fee + FF(1))) - FF(0)); + auto tmp = (main_sel_op_fee_per_l2_gas * (-main_sel_op_fee_per_l2_gas + FF(1))); tmp *= scaling_factor; std::get<18>(evals) += tmp; } @@ -471,7 +471,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(19); - auto tmp = ((main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))) - FF(0)); + auto tmp = (main_sel_op_fee_per_da_gas * (-main_sel_op_fee_per_da_gas + FF(1))); tmp *= scaling_factor; std::get<19>(evals) += tmp; } @@ -479,7 +479,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = ((main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))) - FF(0)); + auto tmp = (main_sel_op_l2gasleft * (-main_sel_op_l2gasleft + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -487,7 +487,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = ((main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))) - FF(0)); + auto tmp = (main_sel_op_dagasleft * (-main_sel_op_dagasleft + FF(1))); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -495,7 +495,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = ((main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))) - FF(0)); + auto tmp = (main_sel_op_note_hash_exists * (-main_sel_op_note_hash_exists + FF(1))); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -503,7 +503,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = ((main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))) - FF(0)); + auto tmp = (main_sel_op_emit_note_hash * (-main_sel_op_emit_note_hash + FF(1))); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -511,7 +511,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = ((main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))) - FF(0)); + auto tmp = (main_sel_op_nullifier_exists * (-main_sel_op_nullifier_exists + FF(1))); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -519,7 +519,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = ((main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))) - FF(0)); + auto tmp = (main_sel_op_emit_nullifier * (-main_sel_op_emit_nullifier + FF(1))); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -527,7 +527,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(26); - auto tmp = ((main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))) - FF(0)); + auto tmp = (main_sel_op_l1_to_l2_msg_exists * (-main_sel_op_l1_to_l2_msg_exists + FF(1))); tmp *= scaling_factor; std::get<26>(evals) += tmp; } @@ -535,7 +535,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = ((main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))) - FF(0)); + auto tmp = (main_sel_op_emit_unencrypted_log * (-main_sel_op_emit_unencrypted_log + FF(1))); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -543,7 +543,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = ((main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))) - FF(0)); + auto tmp = (main_sel_op_emit_l2_to_l1_msg * (-main_sel_op_emit_l2_to_l1_msg + FF(1))); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -551,7 +551,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = ((main_sel_op_sload * (-main_sel_op_sload + FF(1))) - FF(0)); + auto tmp = (main_sel_op_get_contract_instance * (-main_sel_op_get_contract_instance + FF(1))); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -559,7 +559,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = ((main_sel_op_sstore * (-main_sel_op_sstore + FF(1))) - FF(0)); + auto tmp = (main_sel_op_sload * (-main_sel_op_sload + FF(1))); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -567,7 +567,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = ((main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))) - FF(0)); + auto tmp = (main_sel_op_sstore * (-main_sel_op_sstore + FF(1))); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -575,7 +575,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = ((main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))) - FF(0)); + auto tmp = (main_sel_op_radix_le * (-main_sel_op_radix_le + FF(1))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -583,7 +583,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = ((main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))) - FF(0)); + auto tmp = (main_sel_op_sha256 * (-main_sel_op_sha256 + FF(1))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -591,7 +591,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = ((main_sel_op_keccak * (-main_sel_op_keccak + FF(1))) - FF(0)); + auto tmp = (main_sel_op_poseidon2 * (-main_sel_op_poseidon2 + FF(1))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -599,7 +599,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = ((main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))) - FF(0)); + auto tmp = (main_sel_op_keccak * (-main_sel_op_keccak + FF(1))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -607,7 +607,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = ((main_sel_op_add * (-main_sel_op_add + FF(1))) - FF(0)); + auto tmp = (main_sel_op_pedersen * (-main_sel_op_pedersen + FF(1))); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -615,7 +615,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = ((main_sel_op_sub * (-main_sel_op_sub + FF(1))) - FF(0)); + auto tmp = (main_sel_op_add * (-main_sel_op_add + FF(1))); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -623,7 +623,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = ((main_sel_op_mul * (-main_sel_op_mul + FF(1))) - FF(0)); + auto tmp = (main_sel_op_sub * (-main_sel_op_sub + FF(1))); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -631,7 +631,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = ((main_sel_op_div * (-main_sel_op_div + FF(1))) - FF(0)); + auto tmp = (main_sel_op_mul * (-main_sel_op_mul + FF(1))); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -639,7 +639,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = ((main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))) - FF(0)); + auto tmp = (main_sel_op_div * (-main_sel_op_div + FF(1))); tmp *= scaling_factor; std::get<40>(evals) += tmp; } @@ -647,7 +647,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(41); - auto tmp = ((main_sel_op_not * (-main_sel_op_not + FF(1))) - FF(0)); + auto tmp = (main_sel_op_fdiv * (-main_sel_op_fdiv + FF(1))); tmp *= scaling_factor; std::get<41>(evals) += tmp; } @@ -655,7 +655,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(42); - auto tmp = ((main_sel_op_eq * (-main_sel_op_eq + FF(1))) - FF(0)); + auto tmp = (main_sel_op_not * (-main_sel_op_not + FF(1))); tmp *= scaling_factor; std::get<42>(evals) += tmp; } @@ -663,7 +663,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(43); - auto tmp = ((main_sel_op_and * (-main_sel_op_and + FF(1))) - FF(0)); + auto tmp = (main_sel_op_eq * (-main_sel_op_eq + FF(1))); tmp *= scaling_factor; std::get<43>(evals) += tmp; } @@ -671,7 +671,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(44); - auto tmp = ((main_sel_op_or * (-main_sel_op_or + FF(1))) - FF(0)); + auto tmp = (main_sel_op_and * (-main_sel_op_and + FF(1))); tmp *= scaling_factor; std::get<44>(evals) += tmp; } @@ -679,7 +679,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(45); - auto tmp = ((main_sel_op_xor * (-main_sel_op_xor + FF(1))) - FF(0)); + auto tmp = (main_sel_op_or * (-main_sel_op_or + FF(1))); tmp *= scaling_factor; std::get<45>(evals) += tmp; } @@ -687,7 +687,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(46); - auto tmp = ((main_sel_op_cast * (-main_sel_op_cast + FF(1))) - FF(0)); + auto tmp = (main_sel_op_xor * (-main_sel_op_xor + FF(1))); tmp *= scaling_factor; std::get<46>(evals) += tmp; } @@ -695,7 +695,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(47); - auto tmp = ((main_sel_op_lt * (-main_sel_op_lt + FF(1))) - FF(0)); + auto tmp = (main_sel_op_cast * (-main_sel_op_cast + FF(1))); tmp *= scaling_factor; std::get<47>(evals) += tmp; } @@ -703,7 +703,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(48); - auto tmp = ((main_sel_op_lte * (-main_sel_op_lte + FF(1))) - FF(0)); + auto tmp = (main_sel_op_lt * (-main_sel_op_lt + FF(1))); tmp *= scaling_factor; std::get<48>(evals) += tmp; } @@ -711,7 +711,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(49); - auto tmp = ((main_sel_op_shl * (-main_sel_op_shl + FF(1))) - FF(0)); + auto tmp = (main_sel_op_lte * (-main_sel_op_lte + FF(1))); tmp *= scaling_factor; std::get<49>(evals) += tmp; } @@ -719,7 +719,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(50); - auto tmp = ((main_sel_op_shr * (-main_sel_op_shr + FF(1))) - FF(0)); + auto tmp = (main_sel_op_shl * (-main_sel_op_shl + FF(1))); tmp *= scaling_factor; std::get<50>(evals) += tmp; } @@ -727,7 +727,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(51); - auto tmp = ((main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))) - FF(0)); + auto tmp = (main_sel_op_shr * (-main_sel_op_shr + FF(1))); tmp *= scaling_factor; std::get<51>(evals) += tmp; } @@ -735,7 +735,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(52); - auto tmp = ((main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))) - FF(0)); + auto tmp = (main_sel_op_internal_call * (-main_sel_op_internal_call + FF(1))); tmp *= scaling_factor; std::get<52>(evals) += tmp; } @@ -743,7 +743,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(53); - auto tmp = ((main_sel_op_jump * (-main_sel_op_jump + FF(1))) - FF(0)); + auto tmp = (main_sel_op_internal_return * (-main_sel_op_internal_return + FF(1))); tmp *= scaling_factor; std::get<53>(evals) += tmp; } @@ -751,7 +751,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(54); - auto tmp = ((main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))) - FF(0)); + auto tmp = (main_sel_op_jump * (-main_sel_op_jump + FF(1))); tmp *= scaling_factor; std::get<54>(evals) += tmp; } @@ -759,7 +759,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(55); - auto tmp = ((main_sel_op_halt * (-main_sel_op_halt + FF(1))) - FF(0)); + auto tmp = (main_sel_op_jumpi * (-main_sel_op_jumpi + FF(1))); tmp *= scaling_factor; std::get<55>(evals) += tmp; } @@ -767,7 +767,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(56); - auto tmp = ((main_sel_op_external_call * (-main_sel_op_external_call + FF(1))) - FF(0)); + auto tmp = (main_sel_op_halt * (-main_sel_op_halt + FF(1))); tmp *= scaling_factor; std::get<56>(evals) += tmp; } @@ -775,7 +775,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(57); - auto tmp = ((main_sel_op_mov * (-main_sel_op_mov + FF(1))) - FF(0)); + auto tmp = (main_sel_op_external_call * (-main_sel_op_external_call + FF(1))); tmp *= scaling_factor; std::get<57>(evals) += tmp; } @@ -783,7 +783,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(58); - auto tmp = ((main_sel_op_cmov * (-main_sel_op_cmov + FF(1))) - FF(0)); + auto tmp = (main_sel_op_mov * (-main_sel_op_mov + FF(1))); tmp *= scaling_factor; std::get<58>(evals) += tmp; } @@ -791,7 +791,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(59); - auto tmp = ((main_op_err * (-main_op_err + FF(1))) - FF(0)); + auto tmp = (main_sel_op_cmov * (-main_sel_op_cmov + FF(1))); tmp *= scaling_factor; std::get<59>(evals) += tmp; } @@ -799,7 +799,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(60); - auto tmp = ((main_tag_err * (-main_tag_err + FF(1))) - FF(0)); + auto tmp = (main_op_err * (-main_op_err + FF(1))); tmp *= scaling_factor; std::get<60>(evals) += tmp; } @@ -807,7 +807,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(61); - auto tmp = ((main_id_zero * (-main_id_zero + FF(1))) - FF(0)); + auto tmp = (main_tag_err * (-main_tag_err + FF(1))); tmp *= scaling_factor; std::get<61>(evals) += tmp; } @@ -815,7 +815,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(62); - auto tmp = ((main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))) - FF(0)); + auto tmp = (main_id_zero * (-main_id_zero + FF(1))); tmp *= scaling_factor; std::get<62>(evals) += tmp; } @@ -823,7 +823,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(63); - auto tmp = ((main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))) - FF(0)); + auto tmp = (main_sel_mem_op_a * (-main_sel_mem_op_a + FF(1))); tmp *= scaling_factor; std::get<63>(evals) += tmp; } @@ -831,7 +831,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(64); - auto tmp = ((main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))) - FF(0)); + auto tmp = (main_sel_mem_op_b * (-main_sel_mem_op_b + FF(1))); tmp *= scaling_factor; std::get<64>(evals) += tmp; } @@ -839,7 +839,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(65); - auto tmp = ((main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))) - FF(0)); + auto tmp = (main_sel_mem_op_c * (-main_sel_mem_op_c + FF(1))); tmp *= scaling_factor; std::get<65>(evals) += tmp; } @@ -847,7 +847,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(66); - auto tmp = ((main_rwa * (-main_rwa + FF(1))) - FF(0)); + auto tmp = (main_sel_mem_op_d * (-main_sel_mem_op_d + FF(1))); tmp *= scaling_factor; std::get<66>(evals) += tmp; } @@ -855,7 +855,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(67); - auto tmp = ((main_rwb * (-main_rwb + FF(1))) - FF(0)); + auto tmp = (main_rwa * (-main_rwa + FF(1))); tmp *= scaling_factor; std::get<67>(evals) += tmp; } @@ -863,7 +863,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(68); - auto tmp = ((main_rwc * (-main_rwc + FF(1))) - FF(0)); + auto tmp = (main_rwb * (-main_rwb + FF(1))); tmp *= scaling_factor; std::get<68>(evals) += tmp; } @@ -871,7 +871,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(69); - auto tmp = ((main_rwd * (-main_rwd + FF(1))) - FF(0)); + auto tmp = (main_rwc * (-main_rwc + FF(1))); tmp *= scaling_factor; std::get<69>(evals) += tmp; } @@ -879,7 +879,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(70); - auto tmp = ((main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))) - FF(0)); + auto tmp = (main_rwd * (-main_rwd + FF(1))); tmp *= scaling_factor; std::get<70>(evals) += tmp; } @@ -887,7 +887,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(71); - auto tmp = ((main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))) - FF(0)); + auto tmp = (main_sel_resolve_ind_addr_a * (-main_sel_resolve_ind_addr_a + FF(1))); tmp *= scaling_factor; std::get<71>(evals) += tmp; } @@ -895,7 +895,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(72); - auto tmp = ((main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))) - FF(0)); + auto tmp = (main_sel_resolve_ind_addr_b * (-main_sel_resolve_ind_addr_b + FF(1))); tmp *= scaling_factor; std::get<72>(evals) += tmp; } @@ -903,7 +903,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(73); - auto tmp = ((main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))) - FF(0)); + auto tmp = (main_sel_resolve_ind_addr_c * (-main_sel_resolve_ind_addr_c + FF(1))); tmp *= scaling_factor; std::get<73>(evals) += tmp; } @@ -911,7 +911,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(74); - auto tmp = ((((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))) - FF(0)); + auto tmp = (main_sel_resolve_ind_addr_d * (-main_sel_resolve_ind_addr_d + FF(1))); tmp *= scaling_factor; std::get<74>(evals) += tmp; } @@ -919,7 +919,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(75); - auto tmp = (((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)) - FF(0)); + auto tmp = (((main_sel_op_eq + main_sel_op_lte) + main_sel_op_lt) * (main_w_in_tag - FF(1))); tmp *= scaling_factor; std::get<75>(evals) += tmp; } @@ -927,8 +927,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(76); - auto tmp = - (((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)) - FF(0)); + auto tmp = ((main_sel_op_fdiv * (-main_op_err + FF(1))) * ((main_ic * main_ib) - main_ia)); tmp *= scaling_factor; std::get<76>(evals) += tmp; } @@ -936,7 +935,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(77); - auto tmp = ((((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))) - FF(0)); + auto tmp = ((main_sel_op_fdiv + main_sel_op_div) * (((main_ib * main_inv) - FF(1)) + main_op_err)); tmp *= scaling_factor; std::get<77>(evals) += tmp; } @@ -944,7 +943,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(78); - auto tmp = ((main_sel_op_fdiv * (main_r_in_tag - FF(6))) - FF(0)); + auto tmp = (((main_sel_op_fdiv + main_sel_op_div) * main_op_err) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<78>(evals) += tmp; } @@ -952,7 +951,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(79); - auto tmp = ((main_sel_op_fdiv * (main_w_in_tag - FF(6))) - FF(0)); + auto tmp = (main_sel_op_fdiv * (main_r_in_tag - FF(6))); tmp *= scaling_factor; std::get<79>(evals) += tmp; } @@ -960,7 +959,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(80); - auto tmp = ((main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))) - FF(0)); + auto tmp = (main_sel_op_fdiv * (main_w_in_tag - FF(6))); tmp *= scaling_factor; std::get<80>(evals) += tmp; } @@ -968,17 +967,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(81); - auto tmp = ((((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee) * - (-main_sel_q_kernel_lookup + FF(1))) - - FF(0)); + auto tmp = (main_op_err * ((main_sel_op_fdiv + main_sel_op_div) - FF(1))); tmp *= scaling_factor; std::get<81>(evals) += tmp; } @@ -986,14 +975,17 @@ template class mainImpl { { Avm_DECLARE_VIEWS(82); - auto tmp = - ((((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg) * - (-main_sel_q_kernel_output_lookup + FF(1))) - - FF(0)); + auto tmp = ((((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas) * + (-main_sel_q_kernel_lookup + FF(1))); tmp *= scaling_factor; std::get<82>(evals) += tmp; } @@ -1001,7 +993,13 @@ template class mainImpl { { Avm_DECLARE_VIEWS(83); - auto tmp = ((main_sel_op_jump * (main_pc_shift - main_ia)) - FF(0)); + auto tmp = + (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg) * + (-main_sel_q_kernel_output_lookup + FF(1))); tmp *= scaling_factor; std::get<83>(evals) += tmp; } @@ -1009,9 +1007,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(84); - auto tmp = ((main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + - (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))) - - FF(0)); + auto tmp = (main_sel_op_jump * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<84>(evals) += tmp; } @@ -1019,9 +1015,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(85); - auto tmp = - ((main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))) - - FF(0)); + auto tmp = (main_sel_op_jumpi * (((-main_id_zero + FF(1)) * (main_pc_shift - main_ia)) + + (main_id_zero * ((main_pc_shift - main_pc) - FF(1))))); tmp *= scaling_factor; std::get<85>(evals) += tmp; } @@ -1029,7 +1024,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(86); - auto tmp = ((main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)) - FF(0)); + auto tmp = + (main_sel_op_internal_call * (main_internal_return_ptr_shift - (main_internal_return_ptr + FF(1)))); tmp *= scaling_factor; std::get<86>(evals) += tmp; } @@ -1037,7 +1033,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(87); - auto tmp = ((main_sel_op_internal_call * (main_pc_shift - main_ia)) - FF(0)); + auto tmp = (main_sel_op_internal_call * (main_internal_return_ptr - main_mem_addr_b)); tmp *= scaling_factor; std::get<87>(evals) += tmp; } @@ -1045,7 +1041,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(88); - auto tmp = ((main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)) - FF(0)); + auto tmp = (main_sel_op_internal_call * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<88>(evals) += tmp; } @@ -1053,7 +1049,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(89); - auto tmp = ((main_sel_op_internal_call * (main_rwb - FF(1))) - FF(0)); + auto tmp = (main_sel_op_internal_call * ((main_pc + FF(1)) - main_ib)); tmp *= scaling_factor; std::get<89>(evals) += tmp; } @@ -1061,7 +1057,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(90); - auto tmp = ((main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))) - FF(0)); + auto tmp = (main_sel_op_internal_call * (main_rwb - FF(1))); tmp *= scaling_factor; std::get<90>(evals) += tmp; } @@ -1069,9 +1065,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(91); - auto tmp = - ((main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))) - - FF(0)); + auto tmp = (main_sel_op_internal_call * (main_sel_mem_op_b - FF(1))); tmp *= scaling_factor; std::get<91>(evals) += tmp; } @@ -1079,7 +1073,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(92); - auto tmp = ((main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)) - FF(0)); + auto tmp = + (main_sel_op_internal_return * (main_internal_return_ptr_shift - (main_internal_return_ptr - FF(1)))); tmp *= scaling_factor; std::get<92>(evals) += tmp; } @@ -1087,7 +1082,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(93); - auto tmp = ((main_sel_op_internal_return * (main_pc_shift - main_ia)) - FF(0)); + auto tmp = (main_sel_op_internal_return * ((main_internal_return_ptr - FF(1)) - main_mem_addr_a)); tmp *= scaling_factor; std::get<93>(evals) += tmp; } @@ -1095,7 +1090,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(94); - auto tmp = ((main_sel_op_internal_return * main_rwa) - FF(0)); + auto tmp = (main_sel_op_internal_return * (main_pc_shift - main_ia)); tmp *= scaling_factor; std::get<94>(evals) += tmp; } @@ -1103,7 +1098,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(95); - auto tmp = ((main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))) - FF(0)); + auto tmp = (main_sel_op_internal_return * main_rwa); tmp *= scaling_factor; std::get<95>(evals) += tmp; } @@ -1111,43 +1106,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(96); - auto tmp = ((((((main_sel_gas_accounting_active - - (((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + - main_sel_op_keccak) + - main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + - main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) - - (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + - main_sel_op_internal_return)) - - main_sel_op_sload) - - main_sel_op_sstore) - - main_sel_mem_op_activate_gas) - - FF(0)); + auto tmp = (main_sel_op_internal_return * (main_sel_mem_op_a - FF(1))); tmp *= scaling_factor; std::get<96>(evals) += tmp; } @@ -1156,37 +1115,42 @@ template class mainImpl { Avm_DECLARE_VIEWS(97); auto tmp = - (((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * - (((((((main_sel_op_fdiv + - ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + - main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) + - main_sel_op_cast)) + - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + - (main_sel_op_cmov + main_sel_op_mov)) + - ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + - main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + - ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * - (main_pc_shift - (main_pc + FF(1)))) - - FF(0)); + (((((main_sel_gas_accounting_active - + (((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + + main_sel_op_pedersen)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft))) - + (((main_sel_op_jump + main_sel_op_jumpi) + main_sel_op_internal_call) + + main_sel_op_internal_return)) - + main_sel_op_sload) - + main_sel_op_sstore) - + main_sel_mem_op_activate_gas); tmp *= scaling_factor; std::get<97>(evals) += tmp; } @@ -1195,28 +1159,8 @@ template class mainImpl { Avm_DECLARE_VIEWS(98); auto tmp = - (((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + - FF(1)) * - (main_internal_return_ptr_shift - main_internal_return_ptr)) - - FF(0)); - tmp *= scaling_factor; - std::get<98>(evals) += tmp; - } - // Contribution 99 - { - Avm_DECLARE_VIEWS(99); - - auto tmp = - (((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))) - FF(0)); - tmp *= scaling_factor; - std::get<99>(evals) += tmp; - } - // Contribution 100 - { - Avm_DECLARE_VIEWS(100); - - auto tmp = - (((((((((main_sel_op_fdiv + + ((((-main_sel_first + FF(1)) * (-main_sel_op_halt + FF(1))) * + (((((((main_sel_op_fdiv + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + main_sel_op_eq) + @@ -1229,23 +1173,42 @@ template class mainImpl { (main_sel_op_cmov + main_sel_op_mov)) + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + main_sel_op_pedersen)) + - ((((((((((main_sel_op_sender + main_sel_op_address) + main_sel_op_storage_address) + - main_sel_op_chain_id) + - main_sel_op_version) + - main_sel_op_block_number) + - main_sel_op_coinbase) + - main_sel_op_timestamp) + - main_sel_op_fee_per_l2_gas) + - main_sel_op_fee_per_da_gas) + - main_sel_op_transaction_fee)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + main_sel_op_emit_nullifier) + main_sel_op_l1_to_l2_msg_exists) + main_sel_op_emit_unencrypted_log) + main_sel_op_emit_l2_to_l1_msg)) + - (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * - (main_call_ptr - main_space_id)) - - FF(0)); + (main_sel_op_dagasleft + main_sel_op_l2gasleft))) * + (main_pc_shift - (main_pc + FF(1)))); + tmp *= scaling_factor; + std::get<98>(evals) += tmp; + } + // Contribution 99 + { + Avm_DECLARE_VIEWS(99); + + auto tmp = + ((-(((main_sel_first + main_sel_op_internal_call) + main_sel_op_internal_return) + main_sel_op_halt) + + FF(1)) * + (main_internal_return_ptr_shift - main_internal_return_ptr)); + tmp *= scaling_factor; + std::get<99>(evals) += tmp; + } + // Contribution 100 + { + Avm_DECLARE_VIEWS(100); + + auto tmp = ((main_sel_op_internal_call + main_sel_op_internal_return) * (main_space_id - FF(255))); tmp *= scaling_factor; std::get<100>(evals) += tmp; } @@ -1254,7 +1217,36 @@ template class mainImpl { Avm_DECLARE_VIEWS(101); auto tmp = - (((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)) - FF(0)); + ((((((((main_sel_op_fdiv + + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) + + main_sel_op_cast)) + + ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)) + + (main_sel_op_cmov + main_sel_op_mov)) + + ((((main_sel_op_radix_le + main_sel_op_sha256) + main_sel_op_poseidon2) + main_sel_op_keccak) + + main_sel_op_pedersen)) + + (((((((((((main_sel_op_address + main_sel_op_storage_address) + main_sel_op_sender) + + main_sel_op_function_selector) + + main_sel_op_transaction_fee) + + main_sel_op_chain_id) + + main_sel_op_version) + + main_sel_op_block_number) + + main_sel_op_coinbase) + + main_sel_op_timestamp) + + main_sel_op_fee_per_l2_gas) + + main_sel_op_fee_per_da_gas)) + + ((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg)) + + (main_sel_op_dagasleft + main_sel_op_l2gasleft)) * + (main_call_ptr - main_space_id)); tmp *= scaling_factor; std::get<101>(evals) += tmp; } @@ -1262,7 +1254,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(102); - auto tmp = ((((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))) - FF(0)); + auto tmp = ((main_sel_op_cmov + main_sel_op_jumpi) * (((main_id * main_inv) - FF(1)) + main_id_zero)); tmp *= scaling_factor; std::get<102>(evals) += tmp; } @@ -1270,7 +1262,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(103); - auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); + auto tmp = (((main_sel_op_cmov + main_sel_op_jumpi) * main_id_zero) * (-main_inv + FF(1))); tmp *= scaling_factor; std::get<103>(evals) += tmp; } @@ -1278,7 +1270,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(104); - auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); + auto tmp = (main_sel_mov_ia_to_ic - (main_sel_op_mov + (main_sel_op_cmov * (-main_id_zero + FF(1))))); tmp *= scaling_factor; std::get<104>(evals) += tmp; } @@ -1286,7 +1278,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(105); - auto tmp = ((main_sel_mov_ia_to_ic * (main_ia - main_ic)) - FF(0)); + auto tmp = (main_sel_mov_ib_to_ic - (main_sel_op_cmov * main_id_zero)); tmp *= scaling_factor; std::get<105>(evals) += tmp; } @@ -1294,7 +1286,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(106); - auto tmp = ((main_sel_mov_ib_to_ic * (main_ib - main_ic)) - FF(0)); + auto tmp = (main_sel_mov_ia_to_ic * (main_ia - main_ic)); tmp *= scaling_factor; std::get<106>(evals) += tmp; } @@ -1302,7 +1294,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(107); - auto tmp = (((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)) - FF(0)); + auto tmp = (main_sel_mov_ib_to_ic * (main_ib - main_ic)); tmp *= scaling_factor; std::get<107>(evals) += tmp; } @@ -1310,6 +1302,14 @@ template class mainImpl { { Avm_DECLARE_VIEWS(108); + auto tmp = ((main_sel_op_mov + main_sel_op_cmov) * (main_r_in_tag - main_w_in_tag)); + tmp *= scaling_factor; + std::get<108>(evals) += tmp; + } + // Contribution 109 + { + Avm_DECLARE_VIEWS(109); + auto tmp = (main_sel_alu - ((((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + @@ -1322,29 +1322,20 @@ template class mainImpl { (-main_tag_err + FF(1))) * (-main_op_err + FF(1)))); tmp *= scaling_factor; - std::get<108>(evals) += tmp; - } - // Contribution 109 - { - Avm_DECLARE_VIEWS(109); - - auto tmp = - (((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + - main_sel_op_eq) + - main_sel_op_lt) + - main_sel_op_lte) + - main_sel_op_shr) + - main_sel_op_shl) * - (main_alu_in_tag - main_r_in_tag)) - - FF(0)); - tmp *= scaling_factor; std::get<109>(evals) += tmp; } // Contribution 110 { Avm_DECLARE_VIEWS(110); - auto tmp = ((main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)) - FF(0)); + auto tmp = + ((((((((((main_sel_op_add + main_sel_op_sub) + main_sel_op_mul) + main_sel_op_div) + main_sel_op_not) + + main_sel_op_eq) + + main_sel_op_lt) + + main_sel_op_lte) + + main_sel_op_shr) + + main_sel_op_shl) * + (main_alu_in_tag - main_r_in_tag)); tmp *= scaling_factor; std::get<110>(evals) += tmp; } @@ -1352,7 +1343,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(111); - auto tmp = ((main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)) - FF(0)); + auto tmp = (main_sel_op_cast * (main_alu_in_tag - main_w_in_tag)); tmp *= scaling_factor; std::get<111>(evals) += tmp; } @@ -1360,7 +1351,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(112); - auto tmp = ((main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)) - FF(0)); + auto tmp = (main_sel_op_l2gasleft * (main_ia - main_l2_gas_remaining_shift)); tmp *= scaling_factor; std::get<112>(evals) += tmp; } @@ -1368,7 +1359,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(113); - auto tmp = ((main_sel_op_sender * (kernel_kernel_in_offset - FF(0))) - FF(0)); + auto tmp = (main_sel_op_dagasleft * (main_ia - main_da_gas_remaining_shift)); tmp *= scaling_factor; std::get<113>(evals) += tmp; } @@ -1376,7 +1367,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(114); - auto tmp = ((main_sel_op_address * (kernel_kernel_in_offset - FF(1))) - FF(0)); + auto tmp = (main_sel_op_address * (kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<114>(evals) += tmp; } @@ -1384,7 +1375,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(115); - auto tmp = ((main_sel_op_storage_address * (kernel_kernel_in_offset - FF(2))) - FF(0)); + auto tmp = (main_sel_op_storage_address * (kernel_kernel_in_offset - FF(1))); tmp *= scaling_factor; std::get<115>(evals) += tmp; } @@ -1392,7 +1383,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(116); - auto tmp = ((main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))) - FF(0)); + auto tmp = (main_sel_op_sender * kernel_kernel_in_offset); tmp *= scaling_factor; std::get<116>(evals) += tmp; } @@ -1400,7 +1391,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(117); - auto tmp = ((main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))) - FF(0)); + auto tmp = (main_sel_op_function_selector * (kernel_kernel_in_offset - FF(2))); tmp *= scaling_factor; std::get<117>(evals) += tmp; } @@ -1408,7 +1399,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(118); - auto tmp = ((main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(40))) - FF(0)); + auto tmp = (main_sel_op_transaction_fee * (kernel_kernel_in_offset - FF(40))); tmp *= scaling_factor; std::get<118>(evals) += tmp; } @@ -1416,7 +1407,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(119); - auto tmp = ((main_sel_op_chain_id * (kernel_kernel_in_offset - FF(29))) - FF(0)); + auto tmp = (main_sel_op_chain_id * (kernel_kernel_in_offset - FF(29))); tmp *= scaling_factor; std::get<119>(evals) += tmp; } @@ -1424,7 +1415,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(120); - auto tmp = ((main_sel_op_version * (kernel_kernel_in_offset - FF(30))) - FF(0)); + auto tmp = (main_sel_op_version * (kernel_kernel_in_offset - FF(30))); tmp *= scaling_factor; std::get<120>(evals) += tmp; } @@ -1432,7 +1423,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(121); - auto tmp = ((main_sel_op_block_number * (kernel_kernel_in_offset - FF(31))) - FF(0)); + auto tmp = (main_sel_op_block_number * (kernel_kernel_in_offset - FF(31))); tmp *= scaling_factor; std::get<121>(evals) += tmp; } @@ -1440,7 +1431,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(122); - auto tmp = ((main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))) - FF(0)); + auto tmp = (main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))); tmp *= scaling_factor; std::get<122>(evals) += tmp; } @@ -1448,7 +1439,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(123); - auto tmp = ((main_sel_op_timestamp * (kernel_kernel_in_offset - FF(32))) - FF(0)); + auto tmp = (main_sel_op_coinbase * (kernel_kernel_in_offset - FF(33))); tmp *= scaling_factor; std::get<123>(evals) += tmp; } @@ -1456,9 +1447,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(124); - auto tmp = ((main_sel_op_note_hash_exists * - (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))) - - FF(0)); + auto tmp = (main_sel_op_fee_per_da_gas * (kernel_kernel_in_offset - FF(35))); tmp *= scaling_factor; std::get<124>(evals) += tmp; } @@ -1466,7 +1455,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(125); - auto tmp = ((main_sel_first * kernel_note_hash_exist_write_offset) - FF(0)); + auto tmp = (main_sel_op_fee_per_l2_gas * (kernel_kernel_in_offset - FF(36))); tmp *= scaling_factor; std::get<125>(evals) += tmp; } @@ -1474,9 +1463,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(126); - auto tmp = ((main_sel_op_emit_note_hash * - (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(176)))) - - FF(0)); + auto tmp = (main_sel_op_note_hash_exists * + (kernel_kernel_out_offset - (kernel_note_hash_exist_write_offset + FF(0)))); tmp *= scaling_factor; std::get<126>(evals) += tmp; } @@ -1484,7 +1472,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(127); - auto tmp = ((main_sel_first * kernel_emit_note_hash_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_note_hash_exist_write_offset); tmp *= scaling_factor; std::get<127>(evals) += tmp; } @@ -1492,11 +1480,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(128); - auto tmp = ((main_sel_op_nullifier_exists * - (kernel_kernel_out_offset - - ((main_ib * (kernel_nullifier_exists_write_offset + FF(32))) + - ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(64)))))) - - FF(0)); + auto tmp = (main_sel_op_emit_note_hash * + (kernel_kernel_out_offset - (kernel_emit_note_hash_write_offset + FF(128)))); tmp *= scaling_factor; std::get<128>(evals) += tmp; } @@ -1504,7 +1489,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(129); - auto tmp = ((main_sel_first * kernel_nullifier_exists_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_emit_note_hash_write_offset); tmp *= scaling_factor; std::get<129>(evals) += tmp; } @@ -1512,7 +1497,10 @@ template class mainImpl { { Avm_DECLARE_VIEWS(130); - auto tmp = ((main_sel_first * kernel_nullifier_non_exists_write_offset) - FF(0)); + auto tmp = (main_sel_op_nullifier_exists * + (kernel_kernel_out_offset - + ((main_ib * (kernel_nullifier_exists_write_offset + FF(16))) + + ((-main_ib + FF(1)) * (kernel_nullifier_non_exists_write_offset + FF(32)))))); tmp *= scaling_factor; std::get<130>(evals) += tmp; } @@ -1520,9 +1508,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(131); - auto tmp = ((main_sel_op_emit_nullifier * - (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(192)))) - - FF(0)); + auto tmp = (main_sel_first * kernel_nullifier_exists_write_offset); tmp *= scaling_factor; std::get<131>(evals) += tmp; } @@ -1530,7 +1516,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(132); - auto tmp = ((main_sel_first * kernel_emit_nullifier_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_nullifier_non_exists_write_offset); tmp *= scaling_factor; std::get<132>(evals) += tmp; } @@ -1538,9 +1524,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(133); - auto tmp = ((main_sel_op_l1_to_l2_msg_exists * - (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(96)))) - - FF(0)); + auto tmp = (main_sel_op_emit_nullifier * + (kernel_kernel_out_offset - (kernel_emit_nullifier_write_offset + FF(144)))); tmp *= scaling_factor; std::get<133>(evals) += tmp; } @@ -1548,7 +1533,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(134); - auto tmp = ((main_sel_first * kernel_l1_to_l2_msg_exists_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_emit_nullifier_write_offset); tmp *= scaling_factor; std::get<134>(evals) += tmp; } @@ -1556,9 +1541,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(135); - auto tmp = ((main_sel_op_emit_unencrypted_log * - (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(210)))) - - FF(0)); + auto tmp = (main_sel_op_l1_to_l2_msg_exists * + (kernel_kernel_out_offset - (kernel_l1_to_l2_msg_exists_write_offset + FF(48)))); tmp *= scaling_factor; std::get<135>(evals) += tmp; } @@ -1566,7 +1550,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(136); - auto tmp = ((main_sel_first * kernel_emit_unencrypted_log_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_l1_to_l2_msg_exists_write_offset); tmp *= scaling_factor; std::get<136>(evals) += tmp; } @@ -1574,9 +1558,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(137); - auto tmp = ((main_sel_op_emit_l2_to_l1_msg * - (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(208)))) - - FF(0)); + auto tmp = (main_sel_op_emit_unencrypted_log * + (kernel_kernel_out_offset - (kernel_emit_unencrypted_log_write_offset + FF(162)))); tmp *= scaling_factor; std::get<137>(evals) += tmp; } @@ -1584,7 +1567,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(138); - auto tmp = ((main_sel_first * kernel_emit_l2_to_l1_msg_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_emit_unencrypted_log_write_offset); tmp *= scaling_factor; std::get<138>(evals) += tmp; } @@ -1592,8 +1575,8 @@ template class mainImpl { { Avm_DECLARE_VIEWS(139); - auto tmp = - ((main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(144)))) - FF(0)); + auto tmp = (main_sel_op_emit_l2_to_l1_msg * + (kernel_kernel_out_offset - (kernel_emit_l2_to_l1_msg_write_offset + FF(160)))); tmp *= scaling_factor; std::get<139>(evals) += tmp; } @@ -1601,7 +1584,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(140); - auto tmp = ((main_sel_first * kernel_sload_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_emit_l2_to_l1_msg_write_offset); tmp *= scaling_factor; std::get<140>(evals) += tmp; } @@ -1609,8 +1592,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(141); - auto tmp = - ((main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(112)))) - FF(0)); + auto tmp = (main_sel_op_sload * (kernel_kernel_out_offset - (kernel_sload_write_offset + FF(96)))); tmp *= scaling_factor; std::get<141>(evals) += tmp; } @@ -1618,7 +1600,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(142); - auto tmp = ((main_sel_first * kernel_sstore_write_offset) - FF(0)); + auto tmp = (main_sel_first * kernel_sload_write_offset); tmp *= scaling_factor; std::get<142>(evals) += tmp; } @@ -1626,14 +1608,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(143); - auto tmp = - ((((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + - main_sel_op_emit_nullifier) + - main_sel_op_l1_to_l2_msg_exists) + - main_sel_op_emit_unencrypted_log) + - main_sel_op_emit_l2_to_l1_msg) * - (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))) - - FF(0)); + auto tmp = (main_sel_op_sstore * (kernel_kernel_out_offset - (kernel_sstore_write_offset + FF(64)))); tmp *= scaling_factor; std::get<143>(evals) += tmp; } @@ -1641,7 +1616,7 @@ template class mainImpl { { Avm_DECLARE_VIEWS(144); - auto tmp = (main_bin_op_id - (main_sel_op_or + (main_sel_op_xor * FF(2)))); + auto tmp = (main_sel_first * kernel_sstore_write_offset); tmp *= scaling_factor; std::get<144>(evals) += tmp; } @@ -1649,10 +1624,32 @@ template class mainImpl { { Avm_DECLARE_VIEWS(145); - auto tmp = (main_sel_bin - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)); + auto tmp = + (((((((main_sel_op_note_hash_exists + main_sel_op_emit_note_hash) + main_sel_op_nullifier_exists) + + main_sel_op_emit_nullifier) + + main_sel_op_l1_to_l2_msg_exists) + + main_sel_op_emit_unencrypted_log) + + main_sel_op_emit_l2_to_l1_msg) * + (kernel_side_effect_counter_shift - (kernel_side_effect_counter + FF(1)))); tmp *= scaling_factor; std::get<145>(evals) += tmp; } + // Contribution 146 + { + Avm_DECLARE_VIEWS(146); + + auto tmp = (main_bin_op_id - (main_sel_op_or + (main_sel_op_xor * FF(2)))); + tmp *= scaling_factor; + std::get<146>(evals) += tmp; + } + // Contribution 147 + { + Avm_DECLARE_VIEWS(147); + + auto tmp = (main_sel_bin - ((main_sel_op_and + main_sel_op_or) + main_sel_op_xor)); + tmp *= scaling_factor; + std::get<147>(evals) += tmp; + } } }; diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp index 6e4c4fdd982c..da94d705197f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/mem.hpp @@ -126,7 +126,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((mem_lastAccess * (-mem_lastAccess + FF(1))) - FF(0)); + auto tmp = (mem_lastAccess * (-mem_lastAccess + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } @@ -134,7 +134,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(1); - auto tmp = ((mem_last * (-mem_last + FF(1))) - FF(0)); + auto tmp = (mem_last * (-mem_last + FF(1))); tmp *= scaling_factor; std::get<1>(evals) += tmp; } @@ -142,7 +142,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(2); - auto tmp = ((mem_rw * (-mem_rw + FF(1))) - FF(0)); + auto tmp = (mem_rw * (-mem_rw + FF(1))); tmp *= scaling_factor; std::get<2>(evals) += tmp; } @@ -150,7 +150,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(3); - auto tmp = ((mem_tag_err * (-mem_tag_err + FF(1))) - FF(0)); + auto tmp = (mem_tag_err * (-mem_tag_err + FF(1))); tmp *= scaling_factor; std::get<3>(evals) += tmp; } @@ -158,7 +158,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(4); - auto tmp = ((mem_sel_op_a * (-mem_sel_op_a + FF(1))) - FF(0)); + auto tmp = (mem_sel_op_a * (-mem_sel_op_a + FF(1))); tmp *= scaling_factor; std::get<4>(evals) += tmp; } @@ -166,7 +166,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(5); - auto tmp = ((mem_sel_op_b * (-mem_sel_op_b + FF(1))) - FF(0)); + auto tmp = (mem_sel_op_b * (-mem_sel_op_b + FF(1))); tmp *= scaling_factor; std::get<5>(evals) += tmp; } @@ -174,7 +174,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(6); - auto tmp = ((mem_sel_op_c * (-mem_sel_op_c + FF(1))) - FF(0)); + auto tmp = (mem_sel_op_c * (-mem_sel_op_c + FF(1))); tmp *= scaling_factor; std::get<6>(evals) += tmp; } @@ -182,7 +182,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(7); - auto tmp = ((mem_sel_op_d * (-mem_sel_op_d + FF(1))) - FF(0)); + auto tmp = (mem_sel_op_d * (-mem_sel_op_d + FF(1))); tmp *= scaling_factor; std::get<7>(evals) += tmp; } @@ -190,7 +190,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(8); - auto tmp = ((mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_a * (-mem_sel_resolve_ind_addr_a + FF(1))); tmp *= scaling_factor; std::get<8>(evals) += tmp; } @@ -198,7 +198,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(9); - auto tmp = ((mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_b * (-mem_sel_resolve_ind_addr_b + FF(1))); tmp *= scaling_factor; std::get<9>(evals) += tmp; } @@ -206,7 +206,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(10); - auto tmp = ((mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_c * (-mem_sel_resolve_ind_addr_c + FF(1))); tmp *= scaling_factor; std::get<10>(evals) += tmp; } @@ -214,7 +214,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(11); - auto tmp = ((mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_d * (-mem_sel_resolve_ind_addr_d + FF(1))); tmp *= scaling_factor; std::get<11>(evals) += tmp; } @@ -235,7 +235,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(13); - auto tmp = ((mem_sel_mem * (mem_sel_mem - FF(1))) - FF(0)); + auto tmp = (mem_sel_mem * (mem_sel_mem - FF(1))); tmp *= scaling_factor; std::get<13>(evals) += tmp; } @@ -243,7 +243,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(14); - auto tmp = ((((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))) - FF(0)); + auto tmp = (((-main_sel_first + FF(1)) * mem_sel_mem_shift) * (-mem_sel_mem + FF(1))); tmp *= scaling_factor; std::get<14>(evals) += tmp; } @@ -251,7 +251,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(15); - auto tmp = ((main_sel_first * mem_sel_mem) - FF(0)); + auto tmp = (main_sel_first * mem_sel_mem); tmp *= scaling_factor; std::get<15>(evals) += tmp; } @@ -259,7 +259,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(16); - auto tmp = ((((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))) - FF(0)); + auto tmp = (((-mem_last + FF(1)) * mem_sel_mem) * (-mem_sel_mem_shift + FF(1))); tmp *= scaling_factor; std::get<16>(evals) += tmp; } @@ -302,7 +302,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(20); - auto tmp = ((main_sel_first * (-mem_lastAccess + FF(1))) - FF(0)); + auto tmp = (main_sel_first * (-mem_lastAccess + FF(1))); tmp *= scaling_factor; std::get<20>(evals) += tmp; } @@ -310,7 +310,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(21); - auto tmp = (((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)) - FF(0)); + auto tmp = ((-mem_lastAccess + FF(1)) * (mem_glob_addr_shift - mem_glob_addr)); tmp *= scaling_factor; std::get<21>(evals) += tmp; } @@ -318,12 +318,11 @@ template class memImpl { { Avm_DECLARE_VIEWS(22); - auto tmp = ((mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + - ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - - (mem_diff_hi * FF(4294967296UL))) - - (mem_diff_mid * FF(65536))) - - mem_diff_lo)) - - FF(0)); + auto tmp = (mem_sel_rng_chk * (((((mem_lastAccess * (mem_glob_addr_shift - mem_glob_addr)) + + ((-mem_lastAccess + FF(1)) * (mem_tsp_shift - mem_tsp))) - + (mem_diff_hi * FF(4294967296UL))) - + (mem_diff_mid * FF(65536))) - + mem_diff_lo)); tmp *= scaling_factor; std::get<22>(evals) += tmp; } @@ -331,7 +330,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(23); - auto tmp = ((((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)) - FF(0)); + auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_val_shift - mem_val)); tmp *= scaling_factor; std::get<23>(evals) += tmp; } @@ -339,7 +338,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(24); - auto tmp = ((((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)) - FF(0)); + auto tmp = (((-mem_lastAccess + FF(1)) * (-mem_rw_shift + FF(1))) * (mem_tag_shift - mem_tag)); tmp *= scaling_factor; std::get<24>(evals) += tmp; } @@ -347,7 +346,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(25); - auto tmp = (((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift) - FF(0)); + auto tmp = ((mem_lastAccess * (-mem_rw_shift + FF(1))) * mem_val_shift); tmp *= scaling_factor; std::get<25>(evals) += tmp; } @@ -365,9 +364,8 @@ template class memImpl { { Avm_DECLARE_VIEWS(27); - auto tmp = ((((mem_tag * (-mem_skip_check_tag + FF(1))) * (-mem_rw + FF(1))) * - (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)) - - FF(0)); + auto tmp = (((mem_tag * (-mem_skip_check_tag + FF(1))) * (-mem_rw + FF(1))) * + (((mem_r_in_tag - mem_tag) * (-mem_one_min_inv + FF(1))) - mem_tag_err)); tmp *= scaling_factor; std::get<27>(evals) += tmp; } @@ -375,7 +373,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(28); - auto tmp = (((mem_tag * (-mem_tag_err + FF(1))) * mem_one_min_inv) - FF(0)); + auto tmp = ((mem_tag * (-mem_tag_err + FF(1))) * mem_one_min_inv); tmp *= scaling_factor; std::get<28>(evals) += tmp; } @@ -383,7 +381,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(29); - auto tmp = (((mem_skip_check_tag + mem_rw) * mem_tag_err) - FF(0)); + auto tmp = ((mem_skip_check_tag + mem_rw) * mem_tag_err); tmp *= scaling_factor; std::get<29>(evals) += tmp; } @@ -391,7 +389,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(30); - auto tmp = ((mem_rw * (mem_w_in_tag - mem_tag)) - FF(0)); + auto tmp = (mem_rw * (mem_w_in_tag - mem_tag)); tmp *= scaling_factor; std::get<30>(evals) += tmp; } @@ -399,7 +397,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(31); - auto tmp = ((mem_rw * mem_tag_err) - FF(0)); + auto tmp = (mem_rw * mem_tag_err); tmp *= scaling_factor; std::get<31>(evals) += tmp; } @@ -407,7 +405,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(32); - auto tmp = ((mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_a * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<32>(evals) += tmp; } @@ -415,7 +413,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(33); - auto tmp = ((mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_b * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<33>(evals) += tmp; } @@ -423,7 +421,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(34); - auto tmp = ((mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_c * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<34>(evals) += tmp; } @@ -431,7 +429,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(35); - auto tmp = ((mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_d * (mem_r_in_tag - FF(3))); tmp *= scaling_factor; std::get<35>(evals) += tmp; } @@ -439,7 +437,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(36); - auto tmp = ((mem_sel_resolve_ind_addr_a * mem_rw) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_a * mem_rw); tmp *= scaling_factor; std::get<36>(evals) += tmp; } @@ -447,7 +445,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(37); - auto tmp = ((mem_sel_resolve_ind_addr_b * mem_rw) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_b * mem_rw); tmp *= scaling_factor; std::get<37>(evals) += tmp; } @@ -455,7 +453,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(38); - auto tmp = ((mem_sel_resolve_ind_addr_c * mem_rw) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_c * mem_rw); tmp *= scaling_factor; std::get<38>(evals) += tmp; } @@ -463,7 +461,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(39); - auto tmp = ((mem_sel_resolve_ind_addr_d * mem_rw) - FF(0)); + auto tmp = (mem_sel_resolve_ind_addr_d * mem_rw); tmp *= scaling_factor; std::get<39>(evals) += tmp; } @@ -471,7 +469,7 @@ template class memImpl { { Avm_DECLARE_VIEWS(40); - auto tmp = (((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err) - FF(0)); + auto tmp = ((mem_sel_mov_ia_to_ic + mem_sel_mov_ib_to_ic) * mem_tag_err); tmp *= scaling_factor; std::get<40>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp index eb73ea8dfdda..d09722720e9e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/pedersen.hpp @@ -37,7 +37,7 @@ template class pedersenImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((pedersen_sel_pedersen * (-pedersen_sel_pedersen + FF(1))) - FF(0)); + auto tmp = (pedersen_sel_pedersen * (-pedersen_sel_pedersen + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp index 1f6d384a3f72..a758f8333b2b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/poseidon2.hpp @@ -37,7 +37,7 @@ template class poseidon2Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((poseidon2_sel_poseidon_perm * (-poseidon2_sel_poseidon_perm + FF(1))) - FF(0)); + auto tmp = (poseidon2_sel_poseidon_perm * (-poseidon2_sel_poseidon_perm + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp index 7c43cb2db782..dab82e6757ee 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/powers.hpp @@ -37,7 +37,7 @@ template class powersImpl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((powers_power_of_2 - powers_power_of_2) - FF(0)); + auto tmp = (powers_power_of_2 - powers_power_of_2); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp index d77d4d69f672..189cbb7c699c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/generated/avm/sha256.hpp @@ -37,7 +37,7 @@ template class sha256Impl { { Avm_DECLARE_VIEWS(0); - auto tmp = ((sha256_sel_sha256_compression * (-sha256_sel_sha256_compression + FF(1))) - FF(0)); + auto tmp = (sha256_sel_sha256_compression * (-sha256_sel_sha256_compression + FF(1))); tmp *= scaling_factor; std::get<0>(evals) += tmp; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp index 6b09876cd15c..5aeeaf8a6c63 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/transcript/transcript.hpp @@ -17,6 +17,7 @@ template struct StdlibTranscriptParams { Builder* builder = data[0].get_context(); return stdlib::poseidon2::hash(*builder, data); } else { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1035): Add constraints for hashing in Ultra using NativeFr = bb::fr; ASSERT(!data.empty() && data[0].get_context() != nullptr); Builder* builder = data[0].get_context(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp index 44c083a544ca..e3d29e360a51 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/decider_recursive_verifier.cpp @@ -33,7 +33,8 @@ std::array DeciderRecursiveVerifier_:: // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(accumulator->verification_key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index 0a1b48068bd6..bac5ef6dd7bd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -91,10 +91,7 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst gamma, inst->verification_key->circuit_size, static_cast(inst->verification_key->pub_inputs_offset)); - const FF lookup_grand_product_delta = - compute_lookup_grand_product_delta(beta, gamma, inst->verification_key->circuit_size); - inst->relation_parameters = - RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta, lookup_grand_product_delta }; + inst->relation_parameters = RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta }; // Get the relation separation challenges for (size_t idx = 0; idx < NUM_SUBRELATIONS - 1; idx++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp index f609464efec1..38100654bd97 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp @@ -53,7 +53,7 @@ std::array UltraRecursiveVerifier_::ve VerifierCommitments commitments{ key }; CommitmentLabels commitment_labels; - transcript->template receive_from_prover("circuit_size"); + FF circuit_size = transcript->template receive_from_prover("circuit_size"); transcript->template receive_from_prover("public_input_size"); transcript->template receive_from_prover("pub_inputs_offset"); @@ -117,15 +117,12 @@ std::array UltraRecursiveVerifier_::ve commitments.return_data_inverses = transcript->template receive_from_prover(commitment_labels.return_data_inverses); } - const FF public_input_delta = compute_public_input_delta( - public_inputs, beta, gamma, key->circuit_size, static_cast(key->pub_inputs_offset)); - const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, key->circuit_size); + public_inputs, beta, gamma, circuit_size, static_cast(key->pub_inputs_offset)); relation_parameters.beta = beta; relation_parameters.gamma = gamma; relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Get commitment to permutation and lookup grand products commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); @@ -139,6 +136,9 @@ std::array UltraRecursiveVerifier_::ve alpha[idx] = transcript->template get_challenge("alpha_" + std::to_string(idx)); } + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1041): Once hashing produces constraints for Ultra in + // the transcript, a fixed number of gate_challenges must be generated by the prover/verifier in order to achieve a + // verification circuit that is independent of proof size. auto gate_challenges = std::vector(log_circuit_size); for (size_t idx = 0; idx < log_circuit_size; idx++) { gate_challenges[idx] = transcript->template get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); @@ -147,7 +147,8 @@ std::array UltraRecursiveVerifier_::ve sumcheck.verify(relation_parameters, alpha, gate_challenges); // Execute ZeroMorph to produce an opening claim subsequently verified by a univariate PCS - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp index 605b44b702f0..c1d2acecf794 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/verifier.test.cpp @@ -50,19 +50,12 @@ template class RecursiveVerifierTest : public testing */ static InnerBuilder create_inner_circuit(size_t log_num_gates = 10) { - using fr_ct = InnerCurve::ScalarField; - using fq_ct = InnerCurve::BaseField; - using point_ct = InnerCurve::AffineElement; - using public_witness_ct = InnerCurve::public_witness_ct; - using witness_ct = InnerCurve::witness_ct; - using byte_array_ct = InnerCurve::byte_array_ct; using fr = typename InnerCurve::ScalarFieldNative; - using point = typename InnerCurve::GroupNative::affine_element; InnerBuilder builder; // Create 2^log_n many add gates based on input log num gates - const size_t num_gates = 1 << log_num_gates; + const size_t num_gates = (1 << log_num_gates); for (size_t i = 0; i < num_gates; ++i) { fr a = fr::random_element(); uint32_t a_idx = builder.add_variable(a); @@ -77,39 +70,6 @@ template class RecursiveVerifierTest : public testing builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); } - // Perform a batch mul which will add some arbitrary goblin-style ECC op gates if the circuit arithmetic is - // goblinisied otherwise it will add the conventional nonnative gates - size_t num_points = 5; - std::vector circuit_points; - std::vector circuit_scalars; - for (size_t i = 0; i < num_points; ++i) { - circuit_points.push_back(point_ct::from_witness(&builder, point::random_element())); - circuit_scalars.push_back(fr_ct::from_witness(&builder, fr::random_element())); - } - point_ct::batch_mul(circuit_points, circuit_scalars); - - // Define some additional arbitrary convetional circuit logic - fr_ct a(public_witness_ct(&builder, fr::random_element())); - fr_ct b(public_witness_ct(&builder, fr::random_element())); - fr_ct c(public_witness_ct(&builder, fr::random_element())); - - for (size_t i = 0; i < 32; ++i) { - a = (a * b) + b + a; - a = a.madd(b, c); - } - pedersen_hash::hash({ a, b }); - byte_array_ct to_hash(&builder, "nonsense test data"); - blake3s(to_hash); - - fr bigfield_data = fr::random_element(); - fr bigfield_data_a{ bigfield_data.data[0], bigfield_data.data[1], 0, 0 }; - fr bigfield_data_b{ bigfield_data.data[2], bigfield_data.data[3], 0, 0 }; - - fq_ct big_a(fr_ct(witness_ct(&builder, bigfield_data_a.to_montgomery_form())), fr_ct(witness_ct(&builder, 0))); - fq_ct big_b(fr_ct(witness_ct(&builder, bigfield_data_b.to_montgomery_form())), fr_ct(witness_ct(&builder, 0))); - - big_a* big_b; - return builder; }; @@ -156,6 +116,52 @@ template class RecursiveVerifierTest : public testing } } + static void test_independent_vk_hash() + { + auto get_blocks = [](size_t inner_size) { // Create an arbitrary inner circuit + auto inner_circuit = create_inner_circuit(inner_size); + + // Generate a proof over the inner circuit + auto instance = std::make_shared(inner_circuit); + InnerProver inner_prover(instance); + info("test circuit size: ", instance->proving_key.circuit_size); + auto verification_key = std::make_shared(instance->proving_key); + auto inner_proof = inner_prover.construct_proof(); + + // Create a recursive verification circuit for the proof of the inner circuit + OuterBuilder outer_circuit; + RecursiveVerifier verifier{ &outer_circuit, verification_key }; + [[maybe_unused]] auto pairing_points = verifier.verify_proof(inner_proof); + return outer_circuit.blocks; + }; + + bool broke(false); + auto check_eq = [&broke](auto& p1, auto& p2) { + for (size_t idx = 0; idx < p1.size(); idx++) { + if (p1[idx] != p2[idx]) { + broke = true; + info("discrepancy at value index: ", idx); + break; + } + } + }; + + auto blocks_10 = get_blocks(10); + auto blocks_11 = get_blocks(11); + size_t block_idx = 0; + for (auto [b_10, b_11] : zip_view(blocks_10.get(), blocks_11.get())) { + info("block index: ", block_idx); + size_t sel_idx = 0; + for (auto [p_10, p_11] : zip_view(b_10.selectors, b_11.selectors)) { + info("sel index: ", sel_idx); + check_eq(p_10, p_11); + sel_idx++; + } + block_idx++; + } + EXPECT_FALSE(broke); + } + /** * @brief Construct a recursive verification circuit for the proof of an inner circuit then call check_circuit on * it. @@ -269,6 +275,15 @@ HEAVY_TYPED_TEST(RecursiveVerifierTest, SingleRecursiveVerification) TestFixture::test_recursive_verification(); }; +HEAVY_TYPED_TEST(RecursiveVerifierTest, IndependentVKHash) +{ + if constexpr (std::same_as>) { + TestFixture::test_independent_vk_hash(); + } else { + GTEST_SKIP() << "Not built for this parameter"; + } +}; + HEAVY_TYPED_TEST(RecursiveVerifierTest, SingleRecursiveVerificationFailure) { TestFixture::test_recursive_verification_fails(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp index f73d389cab03..83ce2a6c7de5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp @@ -22,6 +22,7 @@ namespace bb::stdlib { template class element { public: using bool_ct = stdlib::bool_t; + using biggroup_tag = element; // Facilitates a constexpr check IsBigGroup struct secp256k1_wnaf { std::vector> wnaf; @@ -937,6 +938,9 @@ template class element { typename std::conditional, batch_lookup_table_plookup<>, batch_lookup_table_base>::type; }; +template +concept IsBigGroup = std::is_same_v; + template inline std::ostream& operator<<(std::ostream& os, element const& v) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index 49c8a471ca5d..84359b972149 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -443,6 +443,8 @@ template class stdlib_biggroup : public testing::Test { static void test_batch_mul() { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1043): this test will fail with num_points is 1 + // (and this case gets hit sometimes when handling points at infinity). const size_t num_points = 5; Builder builder; std::vector points; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp index d437cee50441..83b8f3b70b13 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/bn254.hpp @@ -12,6 +12,7 @@ template struct bn254 { // classes are instantiated with "native" curve types. Eventually, the verifier classes will be instantiated only // with stdlib types, and "native" verification will be acheived via a simulated builder. static constexpr bool is_stdlib_type = true; + using NativeCurve = curve::BN254; // Corresponding native types (used exclusively for testing) using ScalarFieldNative = curve::BN254::ScalarField; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp index 66c704e9d9b4..8f8555886e66 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/curves/grumpkin.hpp @@ -14,8 +14,8 @@ namespace bb::stdlib { */ template struct grumpkin { static constexpr bool is_stdlib_type = true; - using Builder = CircuitBuilder; + using NativeCurve = curve::Grumpkin; // Stdlib types corresponding to those defined in the native description of the curve. // Note: its useful to have these type names match the native analog exactly so that components that digest a diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp index 44da799f729d..5d84e42450fd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.cpp @@ -388,6 +388,19 @@ template field_t field_t::pow(const field_t return accumulator; } +/** + * @brief raise a field_t to a power of an exponent (field_t). Note that the exponent must not exceed 32 bits and is + * implicitly range constrained. + * + * @returns this ** (exponent) + */ +template field_t field_t::pow(const size_t exponent) const +{ + auto* ctx = get_context(); + auto exponent_field_elt = field_t::from_witness(ctx, exponent); + return pow(exponent_field_elt); +} + /** * @returns `this * to_mul + to_add` */ diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp index c3c4a19c1404..2bbfe93989bd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.hpp @@ -129,6 +129,9 @@ template class field_t { // N.B. we implicitly range-constrain 'exponent' to be a 32-bit integer! field_t pow(const field_t& exponent) const; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): Use of this function in ZM verifier is insecure. + field_t pow(size_t exponent) const; + field_t operator+=(const field_t& other) { *this = *this + other; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp index 45467f783253..37680a5c543d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_flavor.hpp @@ -416,9 +416,6 @@ class MegaFlavor { this->circuit_size, this->pub_inputs_offset); relation_parameters.public_input_delta = public_input_delta; - auto lookup_grand_product_delta = compute_lookup_grand_product_delta( - relation_parameters.beta, relation_parameters.gamma, this->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials compute_grand_products(this->polynomials, relation_parameters); @@ -560,31 +557,6 @@ class MegaFlavor { lagrange_last, lagrange_ecc_op, databus_id); - - /** - * @brief Serialize verification key to field elements - * - * @return std::vector - */ - std::vector to_field_elements() - { - std::vector elements; - std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); - elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); - // do the same for the rest of the fields - std::vector num_public_inputs_elements = - bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); - elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); - std::vector pub_inputs_offset_elements = - bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); - elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); - - for (Commitment& comm : this->get_all()) { - std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); - elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); - } - return elements; - } }; /** * @brief A container for storing the partially evaluated multivariates produced by sumcheck. @@ -814,7 +786,6 @@ class MegaFlavor { // take current proof and put them into the struct size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); public_input_size = deserialize_from_buffer(proof_data, num_frs_read); pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); @@ -839,13 +810,13 @@ class MegaFlavor { w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, num_frs_read)); } sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); @@ -856,7 +827,6 @@ class MegaFlavor { { size_t old_proof_length = proof_data.size(); proof_data.clear(); - size_t log_n = numeric::get_msb(circuit_size); serialize_to_buffer(circuit_size, proof_data); serialize_to_buffer(public_input_size, proof_data); serialize_to_buffer(pub_inputs_offset, proof_data); @@ -881,11 +851,11 @@ class MegaFlavor { serialize_to_buffer(w_4_comm, proof_data); serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } serialize_to_buffer(sumcheck_evaluations, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(zm_cq_comms[i], proof_data); } serialize_to_buffer(zm_cq_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 6ca68d7037e7..d9b010c320d8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -344,9 +344,6 @@ class UltraFlavor { this->circuit_size, this->pub_inputs_offset); relation_parameters.public_input_delta = public_input_delta; - auto lookup_grand_product_delta = compute_lookup_grand_product_delta( - relation_parameters.beta, relation_parameters.gamma, this->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials compute_grand_products(this->polynomials, relation_parameters); @@ -361,7 +358,6 @@ class UltraFlavor { * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our * circuits. */ - // using VerificationKey = VerificationKey_, VerifierCommitmentKey>; class VerificationKey : public VerificationKey_, VerifierCommitmentKey> { public: VerificationKey() = default; @@ -472,31 +468,6 @@ class UltraFlavor { table_4, lagrange_first, lagrange_last); - - /** - * @brief Serialize verification key to field elements - * - * @return std::vector - */ - std::vector to_field_elements() - { - std::vector elements; - std::vector circuit_size_elements = bb::field_conversion::convert_to_bn254_frs(this->circuit_size); - elements.insert(elements.end(), circuit_size_elements.begin(), circuit_size_elements.end()); - // do the same for the rest of the fields - std::vector num_public_inputs_elements = - bb::field_conversion::convert_to_bn254_frs(this->num_public_inputs); - elements.insert(elements.end(), num_public_inputs_elements.begin(), num_public_inputs_elements.end()); - std::vector pub_inputs_offset_elements = - bb::field_conversion::convert_to_bn254_frs(this->pub_inputs_offset); - elements.insert(elements.end(), pub_inputs_offset_elements.begin(), pub_inputs_offset_elements.end()); - - for (Commitment& comm : this->get_all()) { - std::vector comm_elements = bb::field_conversion::convert_to_bn254_frs(comm); - elements.insert(elements.end(), comm_elements.begin(), comm_elements.end()); - } - return elements; - } }; /** @@ -696,7 +667,6 @@ class UltraFlavor { // take current proof and put them into the struct size_t num_frs_read = 0; circuit_size = deserialize_from_buffer(proof_data, num_frs_read); - size_t log_n = numeric::get_msb(circuit_size); public_input_size = deserialize_from_buffer(proof_data, num_frs_read); pub_inputs_offset = deserialize_from_buffer(proof_data, num_frs_read); @@ -711,13 +681,13 @@ class UltraFlavor { w_4_comm = deserialize_from_buffer(proof_data, num_frs_read); lookup_inverses_comm = deserialize_from_buffer(proof_data, num_frs_read); z_perm_comm = deserialize_from_buffer(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { sumcheck_univariates.push_back( deserialize_from_buffer>(proof_data, num_frs_read)); } sumcheck_evaluations = deserialize_from_buffer>(proof_data, num_frs_read); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { zm_cq_comms.push_back(deserialize_from_buffer(proof_data, num_frs_read)); } zm_cq_comm = deserialize_from_buffer(proof_data, num_frs_read); @@ -733,7 +703,6 @@ class UltraFlavor { { size_t old_proof_length = proof_data.size(); proof_data.clear(); // clear proof_data so the rest of the function can replace it - size_t log_n = numeric::get_msb(circuit_size); serialize_to_buffer(circuit_size, proof_data); serialize_to_buffer(public_input_size, proof_data); serialize_to_buffer(pub_inputs_offset, proof_data); @@ -748,11 +717,11 @@ class UltraFlavor { serialize_to_buffer(w_4_comm, proof_data); serialize_to_buffer(lookup_inverses_comm, proof_data); serialize_to_buffer(z_perm_comm, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(sumcheck_univariates[i], proof_data); } serialize_to_buffer(sumcheck_evaluations, proof_data); - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { serialize_to_buffer(zm_cq_comms[i], proof_data); } serialize_to_buffer(zm_cq_comm, proof_data); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index 71918f18a98f..d5f71eec3c17 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -213,6 +213,12 @@ template class SumcheckProver { pow_univariate.partially_evaluate(round_challenge); round.round_size = round.round_size >> 1; } + auto zero_univariate = bb::Univariate::zero(); + for (size_t idx = multivariate_d; idx < CONST_PROOF_SIZE_LOG_N; idx++) { + transcript->send_to_verifier("Sumcheck:univariate_" + std::to_string(idx), zero_univariate); + FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(idx)); + multivariate_challenge.emplace_back(round_challenge); + } // Final round: Extract multivariate evaluations from #partially_evaluated_polynomials and add to transcript ClaimedEvaluations multivariate_evaluations; @@ -385,21 +391,39 @@ template class SumcheckVerifier { std::vector multivariate_challenge; multivariate_challenge.reserve(multivariate_d); - - for (size_t round_idx = 0; round_idx < multivariate_d; round_idx++) { + for (size_t round_idx = 0; round_idx < CONST_PROOF_SIZE_LOG_N; round_idx++) { // Obtain the round univariate from the transcript std::string round_univariate_label = "Sumcheck:univariate_" + std::to_string(round_idx); auto round_univariate = transcript->template receive_from_prover>( round_univariate_label); - - bool checked = round.check_sum(round_univariate); - verified = verified && checked; FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(round_idx)); - multivariate_challenge.emplace_back(round_challenge); - round.compute_next_target_sum(round_univariate, round_challenge); - pow_univariate.partially_evaluate(round_challenge); + if constexpr (IsRecursiveFlavor) { + typename Flavor::CircuitBuilder* builder = round_challenge.get_context(); + stdlib::bool_t dummy_round = stdlib::witness_t(builder, round_idx >= multivariate_d); + bool checked = round.check_sum(round_univariate, dummy_round); + // Only utilize the checked value if this is not a constant proof size padding round + if (round_idx < multivariate_d) { + verified = verified && checked; + } + multivariate_challenge.emplace_back(round_challenge); + + round.compute_next_target_sum(round_univariate, round_challenge, dummy_round); + pow_univariate.partially_evaluate(round_challenge, dummy_round); + + } else { + if (round_idx < multivariate_d) { + bool checked = round.check_sum(round_univariate); + verified = verified && checked; + multivariate_challenge.emplace_back(round_challenge); + + round.compute_next_target_sum(round_univariate, round_challenge); + pow_univariate.partially_evaluate(round_challenge); + } else { + multivariate_challenge.emplace_back(round_challenge); + } + } } // Final round diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 41aead2179a3..6b014b663789 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -5,6 +5,7 @@ #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/relation_types.hpp" #include "barretenberg/relations/utils.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" namespace bb { @@ -393,6 +394,42 @@ template class SumcheckVerifierRound { return !sumcheck_round_failed; }; + /** + * @brief Check that the round target sum is correct + * @details The verifier receives the claimed evaluations of the round univariate \f$ \tilde{S}^i \f$ at \f$X_i = + * 0,\ldots, D \f$ and checks \f$\sigma_i = \tilde{S}^{i-1}(u_{i-1}) \stackrel{?}{=} \tilde{S}^i(0) + \tilde{S}^i(1) + * \f$ + * @param univariate Round univariate \f$\tilde{S}^{i}\f$ represented by its evaluations over \f$0,\ldots,D\f$. + * + */ + template + bool check_sum(bb::Univariate& univariate, stdlib::bool_t dummy_round) + { + FF total_sum = + FF::conditional_assign(dummy_round, target_total_sum, univariate.value_at(0) + univariate.value_at(1)); + // TODO(#673): Conditionals like this can go away once native verification is is just recursive verification + // with a simulated builder. + bool sumcheck_round_failed(false); + if constexpr (IsRecursiveFlavor) { + if constexpr (IsECCVMRecursiveFlavor) { + // https://github.com/AztecProtocol/barretenberg/issues/998): Avoids the scenario where the assert_equal + // below fails because we are comparing a constant against a non-constant value and the non-constant + // value is in relaxed form. This happens at the first round when target_total_sum is initially set to + // 0. + total_sum.self_reduce(); + } + target_total_sum.assert_equal(total_sum); + if (!dummy_round.get_value()) { + sumcheck_round_failed = (target_total_sum.get_value() != total_sum.get_value()); + } + } else { + sumcheck_round_failed = (target_total_sum != total_sum); + } + + round_failed = round_failed || sumcheck_round_failed; + return !sumcheck_round_failed; + }; + /** * @brief After checking that the univariate is good for this round, compute the next target sum. * @@ -407,6 +444,23 @@ template class SumcheckVerifierRound { return target_total_sum; } + /** + * @brief After checking that the univariate is good for this round, compute the next target sum. + * + * @param univariate \f$ \tilde{S}^i(X) \f$, given by its evaluations over \f$ \{0,1,2,\ldots, D\}\f$. + * @param round_challenge \f$ u_i\f$ + * @return FF \f$ \sigma_{i+1} = \tilde{S}^i(u_i)\f$ + */ + template + FF compute_next_target_sum(bb::Univariate& univariate, + FF& round_challenge, + stdlib::bool_t dummy_round) + { + // Evaluate \f$\tilde{S}^{i}(u_{i}) \f$ + target_total_sum = FF::conditional_assign(dummy_round, target_total_sum, univariate.evaluate(round_challenge)); + return target_total_sum; + } + /** * @brief Given the evaluations \f$P_1(u_0,\ldots, u_{d-1}), \ldots, P_N(u_0,\ldots, u_{d-1}) \f$ of the * ProverPolynomials at the challenge point \f$(u_0,\ldots, u_{d-1})\f$ stored in \p purported_evaluations, this @@ -425,8 +479,8 @@ template class SumcheckVerifierRound { Utils::template accumulate_relation_evaluations_without_skipping<>( purported_evaluations, relation_evaluations, relation_parameters, pow_polynomial.partial_evaluation_result); - auto running_challenge = FF(1); - auto output = FF(0); + FF running_challenge{ 1 }; + FF output{ 0 }; Utils::scale_and_batch_elements(relation_evaluations, alpha, running_challenge, output); return output; } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp index 0d103c302915..560b208f6053 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_prover.cpp @@ -173,7 +173,8 @@ void TranslatorProver::execute_pcs_rounds() using Curve = typename Flavor::Curve; using ZeroMorph = ZeroMorphProver_; auto prover_opening_claim = - ZeroMorph::prove(key->polynomials.get_unshifted_without_concatenated(), + ZeroMorph::prove(key->circuit_size, + key->polynomials.get_unshifted_without_concatenated(), key->polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted_without_concatenated(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp index cfae12f3a5c1..59429a359275 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_verifier.cpp @@ -113,7 +113,8 @@ bool TranslatorVerifier::verify_proof(const HonkProof& proof) // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description ofthe // unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted_without_concatenated(), + auto opening_claim = ZeroMorph::verify(circuit_size, + commitments.get_unshifted_without_concatenated(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted_without_concatenated(), claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp index bf171d2c4a16..a34af2cf2fa6 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm_recursion/translator_recursive_verifier.cpp @@ -73,7 +73,7 @@ std::array TranslatorRecursiveVerifier_template receive_from_prover("circuit_size"); + const FF circuit_size = transcript->template receive_from_prover("circuit_size"); ASSERT(static_cast(circuit_size.get_value()) == key->circuit_size); evaluation_input_x = transcript->template receive_from_prover("evaluation_input_x"); @@ -113,7 +113,8 @@ std::array TranslatorRecursiveVerifier_ void DeciderProver_::execute_relation_ch template void DeciderProver_::execute_pcs_rounds() { using ZeroMorph = ZeroMorphProver_; - auto prover_opening_claim = ZeroMorph::prove(accumulator->proving_key.polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(accumulator->proving_key.circuit_size, + accumulator->proving_key.polynomials.get_unshifted(), accumulator->proving_key.polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index 8dfc816e01a8..87dcb15cebee 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -88,7 +88,7 @@ class MegaTranscriptTests : public ::testing::Test { round++; } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); std::string label = "Sumcheck:u_" + idx; @@ -100,7 +100,7 @@ class MegaTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 0a5a1810e4c1..c3d89c226dfd 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -136,11 +136,8 @@ template void OinkVerifier::execute_grand_product relation_parameters.gamma, key->circuit_size, static_cast(key->pub_inputs_offset)); - const FF lookup_grand_product_delta = - compute_lookup_grand_product_delta(relation_parameters.beta, relation_parameters.gamma, key->circuit_size); relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Get commitment to permutation and lookup grand products witness_comms.z_perm = transcript->template receive_from_prover(domain_separator + comm_labels.z_perm); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index df541aeb2df5..5124a0f64ebe 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -79,7 +79,7 @@ class UltraTranscriptTests : public ::testing::Test { round++; } - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "Sumcheck:univariate_" + idx, frs_per_uni); std::string label = "Sumcheck:u_" + idx; @@ -91,7 +91,7 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_challenge(round, "rho"); round++; - for (size_t i = 0; i < log_n; ++i) { + for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { std::string idx = std::to_string(i); manifest_expected.add_entry(round, "ZM:C_q_" + idx, frs_per_G); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 942af05365b6..6804be618366 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -70,12 +70,14 @@ template bool UltraVerifier_::verify_proof(const HonkP // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("Sumcheck verification failed."); return false; } // Execute ZeroMorph rounds to produce an opening claim and verify it with a univariate PCS. See // https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the unrolled protocol. - auto opening_claim = ZeroMorph::verify(commitments.get_unshifted(), + auto opening_claim = ZeroMorph::verify(key->circuit_size, + commitments.get_unshifted(), commitments.get_to_be_shifted(), claimed_evaluations.get_unshifted(), claimed_evaluations.get_shifted(), @@ -83,7 +85,6 @@ template bool UltraVerifier_::verify_proof(const HonkP Commitment::one(), transcript); auto pairing_points = PCS::reduce_verify(opening_claim, transcript); - auto pcs_verified = key->pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return sumcheck_verified.value() && pcs_verified; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp index 1ff41a277cd5..5960996ce2c5 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_common.hpp @@ -47,6 +47,7 @@ struct ExternalCallHint { std::vector return_data; uint32_t l2_gas_used; uint32_t da_gas_used; + FF end_side_effect_counter; }; // Add support for deserialization of ExternalCallHint. This is implicitly used by serialize::read @@ -58,6 +59,7 @@ inline void read(uint8_t const*& it, ExternalCallHint& hint) read(it, hint.return_data); read(it, hint.l2_gas_used); read(it, hint.da_gas_used); + read(it, hint.end_side_effect_counter); } struct ContractInstanceHint { diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp index 891d2af56957..1663491d3abd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_deserialization.cpp @@ -57,76 +57,84 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::SHR, three_operand_format }, // Compute - Type Conversions { OpCode::CAST, { OperandType::INDIRECT, OperandType::TAG, OperandType::UINT32, OperandType::UINT32 } }, + // Execution Environment - Globals { OpCode::ADDRESS, getter_format }, { OpCode::STORAGEADDRESS, getter_format }, { OpCode::SENDER, getter_format }, - { OpCode::FEEPERL2GAS, getter_format }, - { OpCode::FEEPERDAGAS, getter_format }, + { OpCode::FUNCTIONSELECTOR, getter_format }, { OpCode::TRANSACTIONFEE, getter_format }, - - { OpCode::GETCONTRACTINSTANCE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, - // TODO: ordering inline with spec - { OpCode::EMITNOTEHASH, getter_format }, // TODO: new format for these - { OpCode::EMITNULLIFIER, getter_format }, // TODO: new format for these - { OpCode::EMITUNENCRYPTEDLOG, getter_format }, - { OpCode::SENDL2TOL1MSG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, - { OpCode::SLOAD, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - { OpCode::SSTORE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - /*TODO: leafIndexOffset is not constrained*/ - { OpCode::NOTEHASHEXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - - { OpCode::NULLIFIEREXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: Address is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - { OpCode::L1TOL2MSGEXISTS, - { OperandType::INDIRECT, - OperandType::UINT32, - /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, - OperandType::UINT32 } }, - // CONTRACTCALLDEPTH, -- not in simulator // Execution Environment - Globals { OpCode::CHAINID, getter_format }, { OpCode::VERSION, getter_format }, { OpCode::BLOCKNUMBER, getter_format }, - { OpCode::TIMESTAMP, getter_format }, // COINBASE, -- not in simulator + { OpCode::TIMESTAMP, getter_format }, + // Execution Environment - Globals - Gas + { OpCode::FEEPERL2GAS, getter_format }, + { OpCode::FEEPERDAGAS, getter_format }, // BLOCKL2GASLIMIT, -- not in simulator // BLOCKDAGASLIMIT, -- not in simulator + // // Execution Environment - Calldata { OpCode::CALLDATACOPY, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Machine State - Gas { OpCode::L2GASLEFT, getter_format }, { OpCode::DAGASLEFT, getter_format }, + // Machine State - Internal Control Flow { OpCode::JUMP, { OperandType::UINT32 } }, { OpCode::JUMPI, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::INTERNALCALL, { OperandType::UINT32 } }, { OpCode::INTERNALRETURN, {} }, + // Machine State - Memory // OpCode::SET is handled differently { OpCode::MOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::CMOV, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, - // World State - // SLOAD, - // SSTORE, - // NOTEHASHEXISTS, - // EMITNOTEHASH, - // NULLIFIEREXISTS, - // EMITNULLIFIER, - // L1TOL2MSGEXISTS, - // HEADERMEMBER, - // GETCONTRACTINSTANCE, - // Accrued Substate - // EMITUNENCRYPTEDLOG, - // SENDL2TOL1MSG, + + // Side Effects - Public Storage + { OpCode::SLOAD, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::SSTORE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Side Effects - Notes, Nullfiers, Logs, Messages + { OpCode::NOTEHASHEXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + + { OpCode::EMITNOTEHASH, + { + OperandType::INDIRECT, + OperandType::UINT32, + } }, // TODO: new format for these + { OpCode::NULLIFIEREXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: Address is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + { OpCode::EMITNULLIFIER, + { + OperandType::INDIRECT, + OperandType::UINT32, + } }, // TODO: new format for these + /*TODO: leafIndexOffset is not constrained*/ + { OpCode::L1TOL2MSGEXISTS, + { OperandType::INDIRECT, + OperandType::UINT32, + /*TODO: leafIndexOffset is not constrained*/ OperandType::UINT32, + OperandType::UINT32 } }, + { OpCode::GETCONTRACTINSTANCE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + { OpCode::EMITUNENCRYPTEDLOG, + { + OperandType::INDIRECT, + OperandType::UINT32, + OperandType::UINT32, + } }, + { OpCode::SENDL2TOL1MSG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + // Control Flow - Contract Calls { OpCode::CALL, external_call_format }, // STATICCALL, @@ -134,15 +142,13 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = { OpCode::RETURN, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, // REVERT, { OpCode::REVERT, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, + // Misc { OpCode::DEBUGLOG, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Gadgets - // KECCAK, - // POSEIDON2, - // SHA256, - // PEDERSEN, - // Gadget - Hashing + // Gadgets - Hashing { OpCode::KECCAK, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::POSEIDON2, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32 } }, { OpCode::SHA256, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, @@ -163,6 +169,7 @@ const std::unordered_map> OPCODE_WIRE_FORMAT = // Gadget - Conversion { OpCode::TORADIXLE, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, + // Gadgets - Unused for now { OpCode::SHA256COMPRESSION, { OperandType::INDIRECT, OperandType::UINT32, OperandType::UINT32, OperandType::UINT32 } }, diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index f3d2dac5f2da..ea7905c12102 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -1,6 +1,7 @@ #include "barretenberg/vm/avm_trace/avm_execution.hpp" #include "barretenberg/bb/log.hpp" #include "barretenberg/common/serialize.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/vm/avm_trace/avm_common.hpp" #include "barretenberg/vm/avm_trace/avm_deserialization.hpp" #include "barretenberg/vm/avm_trace/avm_helper.hpp" @@ -78,10 +79,11 @@ std::tuple Execution::prove(std::vector const& public_in std::array& kernel_inputs = std::get(public_inputs); - // Copy the call context items - kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender - kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address + // Copy items from PublicCircuitPublicInputs vector to public input columns + // PublicCircuitPublicInputs - CallContext + kernel_inputs[SENDER_SELECTOR] = public_inputs_vec[SENDER_SELECTOR]; // Sender + // NOTE: address has same position as storage address (they are the same for now...) + // kernel_inputs[ADDRESS_SELECTOR] = public_inputs_vec[ADDRESS_SELECTOR]; // Address kernel_inputs[STORAGE_ADDRESS_SELECTOR] = public_inputs_vec[STORAGE_ADDRESS_SELECTOR]; // Storage Address + kernel_inputs[FUNCTION_SELECTOR_SELECTOR] = public_inputs_vec[FUNCTION_SELECTOR_SELECTOR]; - // Global variables + // PublicCircuitPublicInputs - GlobalVariables kernel_inputs[CHAIN_ID_SELECTOR] = public_inputs_vec[CHAIN_ID_OFFSET]; // Chain ID kernel_inputs[VERSION_SELECTOR] = public_inputs_vec[VERSION_OFFSET]; // Version kernel_inputs[BLOCK_NUMBER_SELECTOR] = public_inputs_vec[BLOCK_NUMBER_OFFSET]; // Block Number kernel_inputs[TIMESTAMP_SELECTOR] = public_inputs_vec[TIMESTAMP_OFFSET]; // Timestamp kernel_inputs[COINBASE_SELECTOR] = public_inputs_vec[COINBASE_OFFSET]; // Coinbase - - // Fees + // PublicCircuitPublicInputs - GlobalVariables - GasFees kernel_inputs[FEE_PER_DA_GAS_SELECTOR] = public_inputs_vec[FEE_PER_DA_GAS_OFFSET]; kernel_inputs[FEE_PER_L2_GAS_SELECTOR] = public_inputs_vec[FEE_PER_L2_GAS_OFFSET]; @@ -161,7 +165,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in // We copy each type of the kernel outputs into their respective columns, each has differeing lengths / data // For NOTEHASHEXISTS for (size_t i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_NOTE_HASH_EXISTS_WRITE_OFFSET + i; + size_t dest_offset = START_NOTE_HASH_EXISTS_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_NOTE_HASH_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; @@ -169,7 +173,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For NULLIFIEREXISTS for (size_t i = 0; i < MAX_NULLIFIER_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_NULLIFIER_EXISTS_OFFSET + i; + size_t dest_offset = START_NULLIFIER_EXISTS_OFFSET + i; size_t pcpi_offset = PCPI_NULLIFIER_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; @@ -178,7 +182,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For NULLIFIEREXISTS - non existent for (size_t i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_NULLIFIER_NON_EXISTS_OFFSET + i; + size_t dest_offset = START_NULLIFIER_NON_EXISTS_OFFSET + i; size_t pcpi_offset = PCPI_NULLIFIER_NON_EXISTS_OFFSET + (i * READ_REQUEST_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; @@ -187,7 +191,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For L1TOL2MSGEXISTS for (size_t i = 0; i < MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + i; + size_t dest_offset = START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_L1_TO_L2_MSG_READ_REQUESTS_OFFSET + (i * READ_REQUEST_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; @@ -195,7 +199,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For SSTORE for (size_t i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_SSTORE_WRITE_OFFSET + i; + size_t dest_offset = START_SSTORE_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_PUBLIC_DATA_UPDATE_OFFSET + (i * CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH); // slot, value, side effect @@ -205,7 +209,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For SLOAD for (size_t i = 0; i < MAX_PUBLIC_DATA_READS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_SLOAD_WRITE_OFFSET + i; + size_t dest_offset = START_SLOAD_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_PUBLIC_DATA_READ_OFFSET + (i * CONTRACT_STORAGE_READ_LENGTH); // slot, value, side effect @@ -214,24 +218,24 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 2]; } // For EMITNOTEHASH - for (size_t i = 0; i < MAX_NEW_NOTE_HASHES_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_EMIT_NOTE_HASH_WRITE_OFFSET + i; + for (size_t i = 0; i < MAX_NOTE_HASHES_PER_CALL; i++) { + size_t dest_offset = START_EMIT_NOTE_HASH_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_NEW_NOTE_HASHES_OFFSET + (i * NOTE_HASH_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; } // For EMITNULLIFIER - for (size_t i = 0; i < MAX_NEW_NULLIFIERS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_EMIT_NULLIFIER_WRITE_OFFSET + i; + for (size_t i = 0; i < MAX_NULLIFIERS_PER_CALL; i++) { + size_t dest_offset = START_EMIT_NULLIFIER_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_NEW_NULLIFIERS_OFFSET + (i * NULLIFIER_LENGTH); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; ko_side_effect[dest_offset] = public_inputs_vec[pcpi_offset + 1]; } // For EMITL2TOL1MSG - for (size_t i = 0; i < MAX_NEW_L2_TO_L1_MSGS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET + i; + for (size_t i = 0; i < MAX_L2_TO_L1_MSGS_PER_CALL; i++) { + size_t dest_offset = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (i * L2_TO_L1_MESSAGE_LENGTH); // Note: unorthadox order @@ -241,7 +245,7 @@ VmPublicInputs Execution::convert_public_inputs(std::vector const& public_in } // For EMITUNENCRYPTEDLOG for (size_t i = 0; i < MAX_UNENCRYPTED_LOGS_PER_CALL; i++) { - size_t dest_offset = AvmKernelTraceBuilder::START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + i; + size_t dest_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET + i; size_t pcpi_offset = PCPI_NEW_UNENCRYPTED_LOGS_OFFSET + (i * 2); ko_values[dest_offset] = public_inputs_vec[pcpi_offset]; @@ -261,14 +265,23 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) // crs_factory_); // output_state.pcs_verification_key = std::move(pcs_verification_key); + // Proof structure: public_inputs | calldata_size | calldata | raw proof std::vector public_inputs_vec; + std::vector calldata; std::vector raw_proof; - std::copy( - proof.begin(), proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, std::back_inserter(public_inputs_vec)); - std::copy(proof.begin() + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, proof.end(), std::back_inserter(raw_proof)); + + // This can be made nicer using BB's serialize::read, probably. + const auto public_inputs_offset = proof.begin(); + const auto calldata_size_offset = public_inputs_offset + PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH; + const auto calldata_offset = calldata_size_offset + 1; + const auto raw_proof_offset = calldata_offset + static_cast(uint64_t(*calldata_size_offset)); + + std::copy(public_inputs_offset, calldata_size_offset, std::back_inserter(public_inputs_vec)); + std::copy(calldata_offset, raw_proof_offset, std::back_inserter(calldata)); + std::copy(raw_proof_offset, proof.end(), std::back_inserter(raw_proof)); VmPublicInputs public_inputs = convert_public_inputs(public_inputs_vec); - std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_columns = copy_public_inputs_columns(public_inputs, calldata); return verifier.verify_proof(raw_proof, public_inputs_columns); } @@ -309,7 +322,7 @@ std::vector Execution::gen_trace(std::vector const& instructio uint32_t start_side_effect_counter = !public_inputs_vec.empty() ? static_cast(public_inputs_vec[PCPI_START_SIDE_EFFECT_COUNTER_OFFSET]) : 0; - AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter); + AvmTraceBuilder trace_builder(public_inputs, execution_hints, start_side_effect_counter, calldata); // Copied version of pc maintained in trace builder. The value of pc is evolving based // on opcode logic and therefore is not maintained here. However, the next opcode in the execution @@ -433,11 +446,10 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Execution Environment - Calldata case OpCode::CALLDATACOPY: - trace_builder.calldata_copy(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2)), - std::get(inst.operands.at(3)), - calldata); + trace_builder.op_calldata_copy(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2)), + std::get(inst.operands.at(3))); break; // Machine State - Gas case OpCode::L2GASLEFT: @@ -447,9 +459,6 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_dagasleft(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6284): support indirect for below - case OpCode::SENDER: - trace_builder.op_sender(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); - break; case OpCode::ADDRESS: trace_builder.op_address(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; @@ -457,13 +466,12 @@ std::vector Execution::gen_trace(std::vector const& instructio trace_builder.op_storage_address(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; - case OpCode::FEEPERL2GAS: - trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + case OpCode::SENDER: + trace_builder.op_sender(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; - case OpCode::FEEPERDAGAS: - trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + case OpCode::FUNCTIONSELECTOR: + trace_builder.op_function_selector(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); break; case OpCode::TRANSACTIONFEE: trace_builder.op_transaction_fee(std::get(inst.operands.at(0)), @@ -485,6 +493,14 @@ std::vector Execution::gen_trace(std::vector const& instructio case OpCode::TIMESTAMP: trace_builder.op_timestamp(std::get(inst.operands.at(0)), std::get(inst.operands.at(1))); break; + case OpCode::FEEPERL2GAS: + trace_builder.op_fee_per_l2_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); + break; + case OpCode::FEEPERDAGAS: + trace_builder.op_fee_per_da_gas(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1))); + break; case OpCode::NOTEHASHEXISTS: trace_builder.op_note_hash_exists(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), @@ -533,7 +549,8 @@ std::vector Execution::gen_trace(std::vector const& instructio break; case OpCode::EMITUNENCRYPTEDLOG: trace_builder.op_emit_unencrypted_log(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1))); + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::SENDL2TOL1MSG: trace_builder.op_emit_l2_to_l1_msg(std::get(inst.operands.at(0)), @@ -542,18 +559,18 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Machine State - Internal Control Flow case OpCode::JUMP: - trace_builder.jump(std::get(inst.operands.at(0))); + trace_builder.op_jump(std::get(inst.operands.at(0))); break; case OpCode::JUMPI: - trace_builder.jumpi(std::get(inst.operands.at(0)), - std::get(inst.operands.at(1)), - std::get(inst.operands.at(2))); + trace_builder.op_jumpi(std::get(inst.operands.at(0)), + std::get(inst.operands.at(1)), + std::get(inst.operands.at(2))); break; case OpCode::INTERNALCALL: - trace_builder.internal_call(std::get(inst.operands.at(0))); + trace_builder.op_internal_call(std::get(inst.operands.at(0))); break; case OpCode::INTERNALRETURN: - trace_builder.internal_return(); + trace_builder.op_internal_return(); break; // Machine State - Memory case OpCode::SET: { @@ -598,7 +615,7 @@ std::vector Execution::gen_trace(std::vector const& instructio break; // Control Flow - Contract Calls case OpCode::RETURN: { - auto ret = trace_builder.return_op(std::get(inst.operands.at(0)), + auto ret = trace_builder.op_return(std::get(inst.operands.at(0)), std::get(inst.operands.at(1)), std::get(inst.operands.at(2))); returndata.insert(returndata.end(), ret.begin(), ret.end()); @@ -608,7 +625,7 @@ std::vector Execution::gen_trace(std::vector const& instructio case OpCode::DEBUGLOG: // We want a noop, but we need to execute something that both advances the PC, // and adds a valid row to the trace. - trace_builder.jump(pc + 1); + trace_builder.op_jump(pc + 1); break; case OpCode::CALL: trace_builder.op_call(std::get(inst.operands.at(0)), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp index 8a508442aa59..231b62278a9b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.cpp @@ -136,7 +136,8 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx) return static_cast((ind_value & (1 << operand_idx)) >> operand_idx); } -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs) +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata) { // We convert to a vector as the pil generated verifier is generic and unaware of the KERNEL_INPUTS_LENGTH // For each of the public input vectors @@ -158,7 +159,8 @@ std::vector> copy_public_inputs_columns(VmPublicInputs const& pu return { std::move(public_inputs_kernel_inputs), std::move(public_inputs_kernel_value_outputs), std::move(public_inputs_kernel_side_effect_outputs), - std::move(public_inputs_kernel_metadata_outputs) }; + std::move(public_inputs_kernel_metadata_outputs), + calldata }; } } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp index 105e1c529f76..d982ee258a97 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_helper.hpp @@ -16,6 +16,7 @@ bool is_operand_indirect(uint8_t ind_value, uint8_t operand_idx); // There are 4 public input columns, one for inputs, and 3 for the kernel outputs {value, side effect counter, metadata} // The verifier is generic, and so accepts vectors of these values rather than the fixed length arrays that are used // during circuit building. This method copies each array into a vector to be used by the verifier. -std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs); +std::vector> copy_public_inputs_columns(VmPublicInputs const& public_inputs, + std::vector const& calldata); } // namespace bb::avm_trace \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp index 95aa16a17090..2a01d3582b95 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.cpp @@ -49,11 +49,6 @@ void AvmKernelTraceBuilder::perform_kernel_output_lookup(uint32_t write_offset, // We want to be able to get the return value from the public inputs column // Get the return value, this will be places in ia // We read from the public inputs that were provided to the kernel -FF AvmKernelTraceBuilder::op_sender() -{ - return perform_kernel_input_lookup(SENDER_SELECTOR); -} - FF AvmKernelTraceBuilder::op_address() { return perform_kernel_input_lookup(ADDRESS_SELECTOR); @@ -63,14 +58,14 @@ FF AvmKernelTraceBuilder::op_storage_address() return perform_kernel_input_lookup(STORAGE_ADDRESS_SELECTOR); } -FF AvmKernelTraceBuilder::op_fee_per_da_gas() +FF AvmKernelTraceBuilder::op_sender() { - return perform_kernel_input_lookup(FEE_PER_DA_GAS_SELECTOR); + return perform_kernel_input_lookup(SENDER_SELECTOR); } -FF AvmKernelTraceBuilder::op_fee_per_l2_gas() +FF AvmKernelTraceBuilder::op_function_selector() { - return perform_kernel_input_lookup(FEE_PER_L2_GAS_SELECTOR); + return perform_kernel_input_lookup(FUNCTION_SELECTOR_SELECTOR); } FF AvmKernelTraceBuilder::op_transaction_fee() @@ -103,6 +98,16 @@ FF AvmKernelTraceBuilder::op_timestamp() return perform_kernel_input_lookup(TIMESTAMP_SELECTOR); } +FF AvmKernelTraceBuilder::op_fee_per_da_gas() +{ + return perform_kernel_input_lookup(FEE_PER_DA_GAS_SELECTOR); +} + +FF AvmKernelTraceBuilder::op_fee_per_l2_gas() +{ + return perform_kernel_input_lookup(FEE_PER_L2_GAS_SELECTOR); +} + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6481): need to process hint from avm in order to know if // output should be set to true or not void AvmKernelTraceBuilder::op_note_hash_exists(uint32_t clk, @@ -220,7 +225,7 @@ void AvmKernelTraceBuilder::op_emit_l2_to_l1_msg(uint32_t clk, const FF& l2_to_l1_msg, const FF& recipient) { - uint32_t offset = START_L2_TO_L1_MSG_WRITE_OFFSET + emit_l2_to_l1_msg_offset; + uint32_t offset = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + emit_l2_to_l1_msg_offset; perform_kernel_output_lookup(offset, side_effect_counter, l2_to_l1_msg, recipient); emit_l2_to_l1_msg_offset++; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp index a8c43f660463..808b254931e6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_kernel_trace.hpp @@ -9,32 +9,6 @@ #include #include -inline const uint32_t SENDER_SELECTOR = 0; -inline const uint32_t ADDRESS_SELECTOR = 1; -inline const uint32_t STORAGE_ADDRESS_SELECTOR = 2; - -inline const uint32_t START_GLOBAL_VARIABLES = CALL_CONTEXT_LENGTH + HEADER_LENGTH; - -inline const uint32_t CHAIN_ID_SELECTOR = START_GLOBAL_VARIABLES; -inline const uint32_t VERSION_SELECTOR = START_GLOBAL_VARIABLES + 1; -inline const uint32_t BLOCK_NUMBER_SELECTOR = START_GLOBAL_VARIABLES + 2; -inline const uint32_t TIMESTAMP_SELECTOR = START_GLOBAL_VARIABLES + 3; -inline const uint32_t COINBASE_SELECTOR = START_GLOBAL_VARIABLES + 4; - -inline const uint32_t END_GLOBAL_VARIABLES = START_GLOBAL_VARIABLES + GLOBAL_VARIABLES_LENGTH; -inline const uint32_t START_SIDE_EFFECT_COUNTER = END_GLOBAL_VARIABLES; - -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6715): update these to come from the global inputs -inline const uint32_t FEE_PER_DA_GAS_SELECTOR = START_GLOBAL_VARIABLES + 6; -inline const uint32_t FEE_PER_L2_GAS_SELECTOR = START_GLOBAL_VARIABLES + 7; -inline const uint32_t TRANSACTION_FEE_SELECTOR = KERNEL_INPUTS_LENGTH - 1; - -const std::array KERNEL_INPUTS_SELECTORS = { - SENDER_SELECTOR, ADDRESS_SELECTOR, STORAGE_ADDRESS_SELECTOR, FEE_PER_DA_GAS_SELECTOR, - FEE_PER_L2_GAS_SELECTOR, TRANSACTION_FEE_SELECTOR, CHAIN_ID_SELECTOR, VERSION_SELECTOR, - BLOCK_NUMBER_SELECTOR, COINBASE_SELECTOR, TIMESTAMP_SELECTOR -}; - namespace bb::avm_trace { class AvmKernelTraceBuilder { @@ -75,13 +49,10 @@ class AvmKernelTraceBuilder { std::vector finalize(); // Context - FF op_sender(); FF op_address(); FF op_storage_address(); - - // Fees - FF op_fee_per_da_gas(); - FF op_fee_per_l2_gas(); + FF op_sender(); + FF op_function_selector(); FF op_transaction_fee(); // Globals @@ -90,41 +61,21 @@ class AvmKernelTraceBuilder { FF op_block_number(); FF op_coinbase(); FF op_timestamp(); + // Globals - Gas + FF op_fee_per_da_gas(); + FF op_fee_per_l2_gas(); // Outputs // Each returns the selector that was used + void op_sload(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); + void op_sstore(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); void op_note_hash_exists(uint32_t clk, uint32_t side_effect_counter, const FF& note_hash, uint32_t result); void op_emit_note_hash(uint32_t clk, uint32_t side_effect_counter, const FF& note_hash); void op_nullifier_exists(uint32_t clk, uint32_t side_effect_counter, const FF& nullifier, uint32_t result); void op_emit_nullifier(uint32_t clk, uint32_t side_effect_counter, const FF& nullifier); void op_l1_to_l2_msg_exists(uint32_t clk, uint32_t side_effect_counter, const FF& message, uint32_t result); void op_emit_unencrypted_log(uint32_t clk, uint32_t side_effect_counter, const FF& log_hash); - void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& message, const FF& recipient); - - void op_sload(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); - void op_sstore(uint32_t clk, uint32_t side_effect_counter, const FF& slot, const FF& value); - - // TODO: Move into constants.hpp? - static const uint32_t START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; - static const uint32_t START_NULLIFIER_EXISTS_OFFSET = - START_NOTE_HASH_EXISTS_WRITE_OFFSET + MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; - static const uint32_t START_NULLIFIER_NON_EXISTS_OFFSET = - START_NULLIFIER_EXISTS_OFFSET + MAX_NULLIFIER_READ_REQUESTS_PER_CALL; - static const uint32_t START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET = - START_NULLIFIER_NON_EXISTS_OFFSET + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; - - static const uint32_t START_SSTORE_WRITE_OFFSET = - START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; - static const uint32_t START_SLOAD_WRITE_OFFSET = - START_SSTORE_WRITE_OFFSET + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; - - static const uint32_t START_EMIT_NOTE_HASH_WRITE_OFFSET = START_SLOAD_WRITE_OFFSET + MAX_PUBLIC_DATA_READS_PER_CALL; - static const uint32_t START_EMIT_NULLIFIER_WRITE_OFFSET = - START_EMIT_NOTE_HASH_WRITE_OFFSET + MAX_NEW_NOTE_HASHES_PER_CALL; - static const uint32_t START_L2_TO_L1_MSG_WRITE_OFFSET = - START_EMIT_NULLIFIER_WRITE_OFFSET + MAX_NEW_NULLIFIERS_PER_CALL; - static const uint32_t START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = - START_L2_TO_L1_MSG_WRITE_OFFSET + MAX_NEW_L2_TO_L1_MSGS_PER_CALL; + void op_emit_l2_to_l1_msg(uint32_t clk, uint32_t side_effect_counter, const FF& l2_to_l1_msg, const FF& recipient); private: std::vector kernel_trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp index 2439fd4e0a27..f137128d9f0d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.cpp @@ -60,14 +60,10 @@ std::string to_string(OpCode opcode) return "STORAGEADDRESS"; case OpCode::SENDER: return "SENDER"; - case OpCode::FEEPERL2GAS: - return "FEEPERL2GAS"; - case OpCode::FEEPERDAGAS: - return "FEEPERDAGAS"; + case OpCode::FUNCTIONSELECTOR: + return "FUNCTIONSELECTOR"; case OpCode::TRANSACTIONFEE: return "TRANSACTIONFEE"; - case OpCode::CONTRACTCALLDEPTH: - return "CONTRACTCALLDEPTH"; case OpCode::CHAINID: return "CHAINID"; case OpCode::VERSION: @@ -78,6 +74,10 @@ std::string to_string(OpCode opcode) return "TIMESTAMP"; case OpCode::COINBASE: return "COINBASE"; + case OpCode::FEEPERL2GAS: + return "FEEPERL2GAS"; + case OpCode::FEEPERDAGAS: + return "FEEPERDAGAS"; case OpCode::BLOCKL2GASLIMIT: return "BLOCKL2GASLIMIT"; case OpCode::BLOCKDAGASLIMIT: diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp index e3ced1a03e7a..f2beb29d32fc 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_opcode.hpp @@ -45,16 +45,16 @@ enum class OpCode : uint8_t { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, // Execution Environment - Globals CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, // Execution Environment - Calldata diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index ae472b6643d1..55b22de128df 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -32,9 +32,11 @@ namespace bb::avm_trace { */ AvmTraceBuilder::AvmTraceBuilder(VmPublicInputs public_inputs, ExecutionHints execution_hints, - uint32_t side_effect_counter) + uint32_t side_effect_counter, + std::vector calldata) // NOTE: we initialise the environment builder here as it requires public inputs : kernel_trace_builder(std::move(public_inputs)) + , calldata(std::move(calldata)) , side_effect_counter(side_effect_counter) , initial_side_effect_counter(side_effect_counter) , execution_hints(std::move(execution_hints)) @@ -1186,6 +1188,18 @@ Row AvmTraceBuilder::create_kernel_lookup_opcode( }; } +void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_address(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_address = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::ADDRESS); + + main_trace.push_back(row); +} + void AvmTraceBuilder::op_storage_address(uint8_t indirect, uint32_t dst_offset) { FF ia_value = kernel_trace_builder.op_storage_address(); @@ -1210,38 +1224,15 @@ void AvmTraceBuilder::op_sender(uint8_t indirect, uint32_t dst_offset) main_trace.push_back(row); } -void AvmTraceBuilder::op_address(uint8_t indirect, uint32_t dst_offset) -{ - FF ia_value = kernel_trace_builder.op_address(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, ADDRESS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_address = FF(1); - - // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::ADDRESS); - - main_trace.push_back(row); -} - -void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) +void AvmTraceBuilder::op_function_selector(uint8_t indirect, uint32_t dst_offset) { - FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_fee_per_da_gas = FF(1); - - // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERDAGAS); - - main_trace.push_back(row); -} - -void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) -{ - FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); - Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); - row.main_sel_op_fee_per_l2_gas = FF(1); + FF ia_value = kernel_trace_builder.op_function_selector(); + Row row = + create_kernel_lookup_opcode(indirect, dst_offset, FUNCTION_SELECTOR_SELECTOR, ia_value, AvmMemoryTag::U32); + row.main_sel_op_function_selector = FF(1); // Constrain gas cost - gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERL2GAS); + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FUNCTIONSELECTOR); main_trace.push_back(row); } @@ -1318,6 +1309,30 @@ void AvmTraceBuilder::op_timestamp(uint8_t indirect, uint32_t dst_offset) main_trace.push_back(row); } +void AvmTraceBuilder::op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_fee_per_da_gas(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_DA_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_fee_per_da_gas = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERDAGAS); + + main_trace.push_back(row); +} + +void AvmTraceBuilder::op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset) +{ + FF ia_value = kernel_trace_builder.op_fee_per_l2_gas(); + Row row = create_kernel_lookup_opcode(indirect, dst_offset, FEE_PER_L2_GAS_SELECTOR, ia_value, AvmMemoryTag::FF); + row.main_sel_op_fee_per_l2_gas = FF(1); + + // Constrain gas cost + gas_trace_builder.constrain_gas_lookup(static_cast(row.main_clk), OpCode::FEEPERL2GAS); + + main_trace.push_back(row); +} + // Helper function to add kernel lookup operations into the main trace Row AvmTraceBuilder::create_kernel_output_opcode(uint8_t indirect, uint32_t clk, uint32_t data_offset) { @@ -1469,6 +1484,8 @@ void AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash_off gas_trace_builder.constrain_gas_lookup(clk, OpCode::EMITNOTEHASH); main_trace.push_back(row); + + debug("emit_note_hash side-effect cnt: ", side_effect_counter); side_effect_counter++; } @@ -1484,16 +1501,18 @@ void AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier_off gas_trace_builder.constrain_gas_lookup(clk, OpCode::EMITNULLIFIER); main_trace.push_back(row); + + debug("emit_nullifier side-effect cnt: ", side_effect_counter); side_effect_counter++; } -void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t msg_offset) +void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset) { auto const clk = static_cast(main_trace.size()) + 1; // Note: unorthadox order - as seen in L2ToL1Message struct in TS Row row = create_kernel_output_opcode_with_metadata( - indirect, clk, msg_offset, AvmMemoryTag::FF, recipient_offset, AvmMemoryTag::FF); + indirect, clk, content_offset, AvmMemoryTag::FF, recipient_offset, AvmMemoryTag::FF); kernel_trace_builder.op_emit_l2_to_l1_msg(clk, side_effect_counter, row.main_ia, row.main_ib); row.main_sel_op_emit_l2_to_l1_msg = FF(1); @@ -1501,13 +1520,19 @@ void AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_ gas_trace_builder.constrain_gas_lookup(clk, OpCode::SENDL2TOL1MSG); main_trace.push_back(row); + + debug("emit_l2_to_l1_msg side-effect cnt: ", side_effect_counter); side_effect_counter++; } -void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset) +void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, + uint32_t log_offset, + [[maybe_unused]] uint32_t log_size_offset) { auto const clk = static_cast(main_trace.size()) + 1; + // FIXME: read (and constrain) log_size_offset + // FIXME: we need to constrain the log_size_offset mem read (and tag check), not just one field! Row row = create_kernel_output_opcode(indirect, clk, log_offset); kernel_trace_builder.op_emit_unencrypted_log(clk, side_effect_counter, row.main_ia); row.main_sel_op_emit_unencrypted_log = FF(1); @@ -1516,6 +1541,8 @@ void AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log_off gas_trace_builder.constrain_gas_lookup(clk, OpCode::EMITUNENCRYPTEDLOG); main_trace.push_back(row); + + debug("emit_unencrypted_log side-effect cnt: ", side_effect_counter); side_effect_counter++; } @@ -1533,14 +1560,17 @@ void AvmTraceBuilder::op_l1_to_l2_msg_exists(uint8_t indirect, uint32_t log_offs gas_trace_builder.constrain_gas_lookup(clk, OpCode::L1TOL2MSGEXISTS); main_trace.push_back(row); + + debug("l1_to_l2_msg_exists side-effect cnt: ", side_effect_counter); side_effect_counter++; } -void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, uint32_t note_offset, uint32_t dest_offset) +void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, uint32_t note_hash_offset, uint32_t dest_offset) { auto const clk = static_cast(main_trace.size()) + 1; - Row row = create_kernel_output_opcode_with_set_metadata_output_from_hint(indirect, clk, note_offset, dest_offset); + Row row = + create_kernel_output_opcode_with_set_metadata_output_from_hint(indirect, clk, note_hash_offset, dest_offset); kernel_trace_builder.op_note_hash_exists( clk, side_effect_counter, row.main_ia, /*safe*/ static_cast(row.main_ib)); row.main_sel_op_note_hash_exists = FF(1); @@ -1549,6 +1579,8 @@ void AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, uint32_t note_offset gas_trace_builder.constrain_gas_lookup(clk, OpCode::NOTEHASHEXISTS); main_trace.push_back(row); + + debug("note_hash_exists side-effect cnt: ", side_effect_counter); side_effect_counter++; } @@ -1566,6 +1598,8 @@ void AvmTraceBuilder::op_nullifier_exists(uint8_t indirect, uint32_t nullifier_o gas_trace_builder.constrain_gas_lookup(clk, OpCode::NULLIFIEREXISTS); main_trace.push_back(row); + + debug("nullifier_exists side-effect cnt: ", side_effect_counter); side_effect_counter++; } @@ -1625,6 +1659,8 @@ void AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t gas_trace_builder.constrain_gas_lookup(clk, OpCode::SLOAD); main_trace.push_back(row); + + debug("sload side-effect cnt: ", side_effect_counter); side_effect_counter++; clk++; @@ -1687,6 +1723,8 @@ void AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t gas_trace_builder.constrain_gas_lookup(clk, OpCode::SSTORE); main_trace.push_back(row); + + debug("sstore side-effect cnt: ", side_effect_counter); side_effect_counter++; clk++; // All future reads are direct, increment the direct address @@ -1863,10 +1901,8 @@ void AvmTraceBuilder::op_div( * @param cd_offset The starting index of the region in calldata to be copied. * @param copy_size The number of finite field elements to be copied into memory. * @param dst_offset The starting index of memory where calldata will be copied to. - * @param call_data_mem The vector containing calldata. */ -void AvmTraceBuilder::calldata_copy( - uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset, std::vector const& call_data_mem) +void AvmTraceBuilder::op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset) { // We parallelize storing memory operations in chunk of 3, i.e., 1 per intermediate register. // The variable pos is an index pointing to the first storing operation (pertaining to intermediate @@ -1889,7 +1925,7 @@ void AvmTraceBuilder::calldata_copy( uint32_t rwc(0); auto clk = static_cast(main_trace.size()) + 1; - FF ia = call_data_mem.at(cd_offset + pos); + FF ia = calldata.at(cd_offset + pos); uint32_t mem_op_a(1); uint32_t rwa = 1; @@ -1911,7 +1947,7 @@ void AvmTraceBuilder::calldata_copy( call_ptr, clk, IntermRegister::IA, mem_addr_a, ia, AvmMemoryTag::U0, AvmMemoryTag::FF); if (copy_size - pos > 1) { - ib = call_data_mem.at(cd_offset + pos + 1); + ib = calldata.at(cd_offset + pos + 1); mem_op_b = 1; mem_addr_b = direct_dst_offset + pos + 1; rwb = 1; @@ -1922,7 +1958,7 @@ void AvmTraceBuilder::calldata_copy( } if (copy_size - pos > 2) { - ic = call_data_mem.at(cd_offset + pos + 2); + ic = calldata.at(cd_offset + pos + 2); mem_op_c = 1; mem_addr_c = direct_dst_offset + pos + 2; rwc = 1; @@ -1975,7 +2011,7 @@ void AvmTraceBuilder::calldata_copy( // Credit to SEAN for coming up with this revert opcode std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) { - return return_op(indirect, ret_offset, ret_size); + return op_return(indirect, ret_offset, ret_size); } /** @@ -1993,7 +2029,7 @@ std::vector AvmTraceBuilder::op_revert(uint8_t indirect, uint32_t ret_offset * @param ret_size The number of elements to be returned. * @return The returned memory region as a std::vector. */ -std::vector AvmTraceBuilder::return_op(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) +std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) { if (ret_size == 0) { halt(); @@ -2189,7 +2225,7 @@ void AvmTraceBuilder::op_dagasleft(uint8_t indirect, uint32_t dst_offset) * * @param jmp_dest - The destination to jump to */ -void AvmTraceBuilder::jump(uint32_t jmp_dest) +void AvmTraceBuilder::op_jump(uint32_t jmp_dest) { auto clk = static_cast(main_trace.size()) + 1; @@ -2219,7 +2255,7 @@ void AvmTraceBuilder::jump(uint32_t jmp_dest) * @param jmp_dest The destination to jump to * @param cond_offset Offset of the condition */ -void AvmTraceBuilder::jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset) +void AvmTraceBuilder::op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset) { auto clk = static_cast(main_trace.size()) + 1; @@ -2281,7 +2317,7 @@ void AvmTraceBuilder::jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_o * * @param jmp_dest - The destination to jump to */ -void AvmTraceBuilder::internal_call(uint32_t jmp_dest) +void AvmTraceBuilder::op_internal_call(uint32_t jmp_dest) { auto clk = static_cast(main_trace.size()) + 1; @@ -2327,7 +2363,7 @@ void AvmTraceBuilder::internal_call(uint32_t jmp_dest) * TODO(https://github.com/AztecProtocol/aztec-packages/issues/3740): This function MUST come after a call * instruction. */ -void AvmTraceBuilder::internal_return() +void AvmTraceBuilder::op_internal_return() { auto clk = static_cast(main_trace.size()) + 1; @@ -2626,6 +2662,8 @@ void AvmTraceBuilder::op_call(uint8_t indirect, { hint.success }); external_call_counter++; pc++; + // Adjust the side_effect_counter to the the value at the end of the external call. + side_effect_counter = static_cast(hint.end_side_effect_counter); } void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset) @@ -2672,6 +2710,9 @@ void AvmTraceBuilder::op_get_contract_instance(uint8_t indirect, uint32_t addres AvmMemoryTag::FF, internal_return_ptr, contract_instance_vec); + + debug("contract_instance cnt: ", side_effect_counter); + side_effect_counter++; } /** @@ -3734,7 +3775,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c main_trace.at(*trace_size - 1).main_sel_last = FF(1); - // Memory trace inclusion + /********************************************************************************************** + * MEMORY TRACE INCLUSION + **********************************************************************************************/ // We compute in the main loop the timestamp and global address for next row. // Perform initialization for index 0 outside of the loop provided that mem trace exists. @@ -3838,7 +3881,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - // Alu trace inclusion + /********************************************************************************************** + * ALU TRACE INCLUSION + **********************************************************************************************/ + for (size_t i = 0; i < alu_trace_size; i++) { auto const& src = alu_trace.at(i); auto& dest = main_trace.at(i); @@ -3985,6 +4031,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * GADGET TABLES INCLUSION + **********************************************************************************************/ + // Add Conversion Gadget table for (size_t i = 0; i < conv_trace_size; i++) { auto const& src = conv_trace.at(i); @@ -4039,6 +4089,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.pedersen_sel_pedersen = FF(1); } + /********************************************************************************************** + * BINARY TRACE INCLUSION + **********************************************************************************************/ + // Add Binary Trace table for (size_t i = 0; i < bin_trace_size; i++) { auto const& src = bin_trace.at(i); @@ -4104,7 +4158,9 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } - /////////// GAS ACCOUNTING ////////////////////////// + /********************************************************************************************** + * GAS TRACE INCLUSION + **********************************************************************************************/ // Add the gas cost table to the main trace // TODO: do i need a way to produce an interupt that will stop the execution of the trace when the gas left @@ -4194,11 +4250,14 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.main_da_gas_remaining = current_da_gas_remaining; } - /////////// END OF GAS ACCOUNTING ////////////////////////// - // Adding extra row for the shifted values at the top of the execution trace. Row first_row = Row{ .main_sel_first = FF(1), .mem_lastAccess = FF(1) }; main_trace.insert(main_trace.begin(), first_row); + + /********************************************************************************************** + * RANGE CHECKS AND SELECTORS INCLUSION + **********************************************************************************************/ + auto const old_trace_size = main_trace.size(); auto new_trace_size = range_check_required ? old_trace_size @@ -4288,6 +4347,10 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c } } + /********************************************************************************************** + * KERNEL TRACE INCLUSION + **********************************************************************************************/ + // Write the kernel trace into the main trace // 1. The write offsets are constrained to be non changing over the entire trace, so we fill in the values // until we @@ -4303,6 +4366,8 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c // we already prepended the extra row for shifted columns. Therefore, initialization // of side_effect_counter occurs occurs on this row. main_trace.at(1).kernel_side_effect_counter = initial_side_effect_counter; + // This index is required to retrieve the right side effect counter after an external call. + size_t external_call_cnt = 0; // External loop iterates over the kernel entries which are sorted by increasing clk. // Internal loop iterates to fill the gap in main trace between each kernel entries. @@ -4327,7 +4392,15 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c dest.kernel_l1_to_l2_msg_exists_write_offset = prev.kernel_l1_to_l2_msg_exists_write_offset; dest.kernel_sload_write_offset = prev.kernel_sload_write_offset; dest.kernel_sstore_write_offset = prev.kernel_sstore_write_offset; - dest.kernel_side_effect_counter = prev.kernel_side_effect_counter; + + // Adjust side effect counter after an external call + if (prev.main_sel_op_external_call == 1) { + dest.kernel_side_effect_counter = + execution_hints.externalcall_hints.at(external_call_cnt).end_side_effect_counter; + external_call_cnt++; + } else { + dest.kernel_side_effect_counter = prev.kernel_side_effect_counter; + } } Row& curr = main_trace.at(clk); @@ -4456,6 +4529,11 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c std::get(kernel_trace_builder.public_inputs).at(i); } + // calldata column inclusion + for (size_t i = 0; i < calldata.size(); i++) { + main_trace.at(i).main_calldata = calldata.at(i); + } + // Get tag_err counts from the mem_trace_builder if (range_check_required) { finalise_mem_trace_lookup_counts(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp index 3a6e13dbc06b..307943c8940a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.hpp @@ -39,7 +39,8 @@ class AvmTraceBuilder { public: AvmTraceBuilder(VmPublicInputs public_inputs = {}, ExecutionHints execution_hints = {}, - uint32_t side_effect_counter = 0); + uint32_t side_effect_counter = 0, + std::vector calldata = {}); std::vector finalize(uint32_t min_trace_size = 0, bool range_check_required = ENABLE_PROVING); void reset(); @@ -48,128 +49,99 @@ class AvmTraceBuilder { // Addition with direct or indirect memory access. void op_add(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Subtraction with direct or indirect memory access. void op_sub(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Multiplication with direct or indirect memory access. void op_mul(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - + // Integer Division with direct or indirect memory access. + void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Finite field division with direct or indirect memory access. void op_fdiv(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset); - // Bitwise not with direct or indirect memory access. - void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Equality with direct or indirect memory access. void op_eq(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Less Than with direct or indirect memory access. + void op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Less Than or Equal to with direct or indirect memory access. + void op_lte(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Bitwise and with direct or indirect memory access. void op_and(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Bitwise or with direct or indirect memory access. void op_or(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Bitwise xor with direct or indirect memory access. void op_xor(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Less Than with direct or indirect memory access. - void op_lt(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Less Than or Equal to with direct or indirect memory access. - void op_lte(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Shift Right with direct or indirect memory access. - void op_shr(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - + // Bitwise not with direct or indirect memory access. + void op_not(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag in_tag); // Shift Left with direct or indirect memory access. void op_shl(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Shift Right with direct or indirect memory access. + void op_shr(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); - // Set a constant from bytecode with direct or indirect memory access. - void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); - - // Move (copy) the value and tag of a memory cell to another one. - void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset); - - // Move (copy) the value and tag of a memory cell to another one whereby the source - // is determined conditionally based on a conditional value determined by cond_offset. - void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); + // Cast an element pointed by the address a_offset into type specified by dst_tag and + // store the result in address given by dst_offset. + void op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag); - // Call Context - void op_storage_address(uint8_t indirect, uint32_t dst_offset); + // Context - Environment void op_sender(uint8_t indirect, uint32_t dst_offset); void op_address(uint8_t indirect, uint32_t dst_offset); - - // Fees - void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); - void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); + void op_storage_address(uint8_t indirect, uint32_t dst_offset); void op_transaction_fee(uint8_t indirect, uint32_t dst_offset); + void op_function_selector(uint8_t indirect, uint32_t dst_offset); - // Globals + // Context - Environment - Globals void op_chain_id(uint8_t indirect, uint32_t dst_offset); void op_version(uint8_t indirect, uint32_t dst_offset); void op_block_number(uint8_t indirect, uint32_t dst_offset); void op_coinbase(uint8_t indirect, uint32_t dst_offset); void op_timestamp(uint8_t indirect, uint32_t dst_offset); + // Context - Environment - Globals - Gas + void op_fee_per_da_gas(uint8_t indirect, uint32_t dst_offset); + void op_fee_per_l2_gas(uint8_t indirect, uint32_t dst_offset); - // Outputs - // With single output values - void op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); - void op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); - void op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset); - void op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t msg_offset, uint32_t recipient_offset); - void op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset); - - // With additional metadata output - void op_l1_to_l2_msg_exists(uint8_t indirect, uint32_t msg_offset, uint32_t dest_offset); - void op_note_hash_exists(uint8_t indirect, uint32_t note_hash_offset, uint32_t dest_offset); - void op_nullifier_exists(uint8_t indirect, uint32_t nullifier_offset, uint32_t dest_offset); - - void op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); - void op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); - - // Cast an element pointed by the address a_offset into type specified by dst_tag and - // store the result in address given by dst_offset. - void op_cast(uint8_t indirect, uint32_t a_offset, uint32_t dst_offset, AvmMemoryTag dst_tag); - - // Integer Division with direct or indirect memory access. - void op_div(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t dst_offset, AvmMemoryTag in_tag); + // Context - Environment - Calldata + // CALLDATACOPY opcode with direct/indirect memory access, i.e., + // direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] + // indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size] + void op_calldata_copy(uint8_t indirect, uint32_t cd_offset, uint32_t copy_size, uint32_t dst_offset); - // Machine State - Gas + // Context - Machine State - Gas void op_l2gasleft(uint8_t indirect, uint32_t dst_offset); void op_dagasleft(uint8_t indirect, uint32_t dst_offset); // Jump to a given program counter. - void jump(uint32_t jmp_dest); - + void op_jump(uint32_t jmp_dest); // Jump conditionally to a given program counter. - void jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset); - + void op_jumpi(uint8_t indirect, uint32_t jmp_dest, uint32_t cond_offset); // Jump to a given program counter; storing the return location on a call stack. // TODO(md): this program counter MUST be an operand to the OPCODE. - void internal_call(uint32_t jmp_dest); + void op_internal_call(uint32_t jmp_dest); + // Return from an internal call. + void op_internal_return(); - // Return from a jump. - void internal_return(); + // Set a constant from bytecode with direct or indirect memory access. + void op_set(uint8_t indirect, uint128_t val, uint32_t dst_offset, AvmMemoryTag in_tag); + // Move (copy) the value and tag of a memory cell to another one. + void op_mov(uint8_t indirect, uint32_t src_offset, uint32_t dst_offset); + // Move (copy) the value and tag of a memory cell to another one whereby the source + // is determined conditionally based on a conditional value determined by cond_offset. + void op_cmov(uint8_t indirect, uint32_t a_offset, uint32_t b_offset, uint32_t cond_offset, uint32_t dst_offset); - // Halt -> stop program execution. - void halt(); + // Side Effects - Public Storage + void op_sload(uint8_t indirect, uint32_t slot_offset, uint32_t size, uint32_t dest_offset); + void op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t size, uint32_t slot_offset); - // CALLDATACOPY opcode with direct/indirect memory access, i.e., - // direct: M[dst_offset:dst_offset+copy_size] = calldata[cd_offset:cd_offset+copy_size] - // indirect: M[M[dst_offset]:M[dst_offset]+copy_size] = calldata[cd_offset:cd_offset+copy_size] - void calldata_copy(uint8_t indirect, - uint32_t cd_offset, - uint32_t copy_size, - uint32_t dst_offset, - std::vector const& call_data_mem); + // With single output values + void op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset); + void op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset); + void op_emit_unencrypted_log(uint8_t indirect, uint32_t log_offset, uint32_t log_size_offset); + void op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset); + void op_get_contract_instance(uint8_t indirect, uint32_t address_offset, uint32_t dst_offset); - // REVERT Opcode (that just call return under the hood for now) - std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); - // RETURN opcode with direct and indirect memory access, i.e., - // direct: return(M[ret_offset:ret_offset+ret_size]) - // indirect: return(M[M[ret_offset]:M[ret_offset]+ret_size]) - std::vector return_op(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + // With additional metadata output + void op_l1_to_l2_msg_exists(uint8_t indirect, uint32_t log_offset, uint32_t dest_offset); + void op_note_hash_exists(uint8_t indirect, uint32_t note_hash_offset, uint32_t dest_offset); + void op_nullifier_exists(uint8_t indirect, uint32_t nullifier_offset, uint32_t dest_offset); // Calls void op_call(uint8_t indirect, @@ -182,6 +154,16 @@ class AvmTraceBuilder { uint32_t success_offset, uint32_t function_selector_offset); + // RETURN opcode with direct and indirect memory access, i.e., + // direct: return(M[ret_offset:ret_offset+ret_size]) + // indirect: return(M[M[ret_offset]:M[ret_offset]+ret_size]) + std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + // REVERT Opcode (that just call return under the hood for now) + std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + + // (not an opcode) Halt -> stop program execution. + void halt(); + // Gadgets // --- Conversions // To Radix LE conversion operation. @@ -241,6 +223,8 @@ class AvmTraceBuilder { AvmPedersenTraceBuilder pedersen_trace_builder; AvmEccTraceBuilder ecc_trace_builder; + std::vector calldata{}; + /** * @brief Create a kernel lookup opcode object * diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp index 2f6cc507365f..8ad866f7f54b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp @@ -1,15 +1,15 @@ // GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants in circuits.js #pragma once -#define MAX_NEW_NOTE_HASHES_PER_CALL 16 -#define MAX_NEW_NULLIFIERS_PER_CALL 16 +#define MAX_NOTE_HASHES_PER_CALL 16 +#define MAX_NULLIFIERS_PER_CALL 16 #define MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL 16 -#define MAX_NEW_L2_TO_L1_MSGS_PER_CALL 2 +#define MAX_L2_TO_L1_MSGS_PER_CALL 2 #define MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL 32 #define MAX_PUBLIC_DATA_READS_PER_CALL 32 -#define MAX_NOTE_HASH_READ_REQUESTS_PER_CALL 32 -#define MAX_NULLIFIER_READ_REQUESTS_PER_CALL 32 -#define MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL 32 +#define MAX_NOTE_HASH_READ_REQUESTS_PER_CALL 16 +#define MAX_NULLIFIER_READ_REQUESTS_PER_CALL 16 +#define MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL 16 #define MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL 16 #define MAX_UNENCRYPTED_LOGS_PER_CALL 4 #define AZTEC_ADDRESS_LENGTH 1 @@ -30,5 +30,30 @@ #define STATE_REFERENCE_LENGTH 8 #define TOTAL_FEES_LENGTH 1 #define HEADER_LENGTH 23 -#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 578 +#define PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH 482 #define PUBLIC_CONTEXT_INPUTS_LENGTH 41 +#define SENDER_SELECTOR 0 +#define ADDRESS_SELECTOR 1 +#define STORAGE_ADDRESS_SELECTOR 1 +#define FUNCTION_SELECTOR_SELECTOR 2 +#define START_GLOBAL_VARIABLES 29 +#define CHAIN_ID_SELECTOR 29 +#define VERSION_SELECTOR 30 +#define BLOCK_NUMBER_SELECTOR 31 +#define TIMESTAMP_SELECTOR 32 +#define COINBASE_SELECTOR 33 +#define FEE_PER_DA_GAS_SELECTOR 35 +#define FEE_PER_L2_GAS_SELECTOR 36 +#define END_GLOBAL_VARIABLES 37 +#define START_SIDE_EFFECT_COUNTER 37 +#define TRANSACTION_FEE_SELECTOR 40 +#define START_NOTE_HASH_EXISTS_WRITE_OFFSET 0 +#define START_NULLIFIER_EXISTS_OFFSET 16 +#define START_NULLIFIER_NON_EXISTS_OFFSET 32 +#define START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET 48 +#define START_SSTORE_WRITE_OFFSET 64 +#define START_SLOAD_WRITE_OFFSET 96 +#define START_EMIT_NOTE_HASH_WRITE_OFFSET 128 +#define START_EMIT_NULLIFIER_WRITE_OFFSET 144 +#define START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET 160 +#define START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET 162 diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp index 4d60a7b0ad90..62d2cbc49459 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/constants.hpp @@ -7,36 +7,38 @@ // NOTE(MD): for now we will only include the public inputs that are included in call_context // With more being added in subsequent prs -// KERNEL_INPUTS_LENGTH = CALL_CONTEXT_LENGTH + +// KERNEL_INPUTS_LENGTH = CALL_CONTEXT_LENGTH inline const std::size_t KERNEL_INPUTS_LENGTH = PUBLIC_CONTEXT_INPUTS_LENGTH; inline const std::size_t KERNEL_OUTPUTS_LENGTH = MAX_NOTE_HASH_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL + - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_NEW_NOTE_HASHES_PER_CALL + - MAX_NEW_NULLIFIERS_PER_CALL + MAX_NEW_L2_TO_L1_MSGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL; + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL + MAX_NOTE_HASHES_PER_CALL + + MAX_NULLIFIERS_PER_CALL + MAX_L2_TO_L1_MSGS_PER_CALL + MAX_UNENCRYPTED_LOGS_PER_CALL; // START INDEXES in the PUBLIC_CIRCUIT_PUBLIC_INPUTS // These line up with indexes found in // https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts inline const uint32_t PCPI_GLOBALS_START = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 7 - GLOBAL_VARIABLES_LENGTH; +// Global Variables inline const uint32_t CHAIN_ID_OFFSET = PCPI_GLOBALS_START; inline const uint32_t VERSION_OFFSET = PCPI_GLOBALS_START + 1; inline const uint32_t BLOCK_NUMBER_OFFSET = PCPI_GLOBALS_START + 2; inline const uint32_t TIMESTAMP_OFFSET = PCPI_GLOBALS_START + 3; inline const uint32_t COINBASE_OFFSET = PCPI_GLOBALS_START + 4; - +// Global Variables - fees inline const uint32_t FEE_PER_DA_GAS_OFFSET = PCPI_GLOBALS_START + 6; inline const uint32_t FEE_PER_L2_GAS_OFFSET = PCPI_GLOBALS_START + 7; -inline const uint32_t TRANSACTION_FEE_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 1; +// Top-level PublicCircuitPublicInputs members inline const uint32_t DA_START_GAS_LEFT_PCPI_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 3 - GAS_LENGTH; inline const uint32_t L2_START_GAS_LEFT_PCPI_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 2 - GAS_LENGTH; +inline const uint32_t TRANSACTION_FEE_OFFSET = PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH - 1; // Kernel output pil offset (Where update objects are inlined) -// Kernel outputs public inputs offsets +// Side Effects (offsets to vectors in PublicCircuitPublicInputs) inline const uint32_t PCPI_NOTE_HASH_EXISTS_OFFSET = CALL_CONTEXT_LENGTH + 2; inline const uint32_t PCPI_NULLIFIER_EXISTS_OFFSET = PCPI_NOTE_HASH_EXISTS_OFFSET + (MAX_NOTE_HASH_READ_REQUESTS_PER_CALL * READ_REQUEST_LENGTH); @@ -61,14 +63,14 @@ inline const uint32_t PCPI_NEW_NOTE_HASHES_OFFSET = PCPI_PUBLIC_CALLSTACK_OFFSET + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL; inline const uint32_t PCPI_NEW_NULLIFIERS_OFFSET = - PCPI_NEW_NOTE_HASHES_OFFSET + (MAX_NEW_NOTE_HASHES_PER_CALL * NOTE_HASH_LENGTH); + PCPI_NEW_NOTE_HASHES_OFFSET + (MAX_NOTE_HASHES_PER_CALL * NOTE_HASH_LENGTH); // TODO(md): Note legnth of nullifier is 3? - it includes the note it is nullifying too inline const uint32_t PCPI_NEW_L2_TO_L1_MSGS_OFFSET = - PCPI_NEW_NULLIFIERS_OFFSET + (MAX_NEW_NULLIFIERS_PER_CALL * NULLIFIER_LENGTH); + PCPI_NEW_NULLIFIERS_OFFSET + (MAX_NULLIFIERS_PER_CALL * NULLIFIER_LENGTH); inline const uint32_t PCPI_START_SIDE_EFFECT_COUNTER_OFFSET = - PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (MAX_NEW_L2_TO_L1_MSGS_PER_CALL * L2_TO_L1_MESSAGE_LENGTH); + PCPI_NEW_L2_TO_L1_MSGS_OFFSET + (MAX_L2_TO_L1_MSGS_PER_CALL * L2_TO_L1_MESSAGE_LENGTH); inline const uint32_t PCPI_NEW_UNENCRYPTED_LOGS_OFFSET = PCPI_START_SIDE_EFFECT_COUNTER_OFFSET + /*1 item gap*/ 1; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp index 448bf350a0e9..a1194d51e98f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.cpp @@ -24,6 +24,7 @@ template std::vector AvmFullRow::names() "kernel_kernel_value_out", "kernel_kernel_side_effect_out", "kernel_kernel_metadata_out", + "main_calldata", "alu_a_hi", "alu_a_lo", "alu_b_hi", @@ -220,6 +221,7 @@ template std::vector AvmFullRow::names() "main_sel_op_fdiv", "main_sel_op_fee_per_da_gas", "main_sel_op_fee_per_l2_gas", + "main_sel_op_function_selector", "main_sel_op_get_contract_instance", "main_sel_op_halt", "main_sel_op_internal_call", @@ -412,18 +414,19 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << field_to_string(row.main_clk) << "," << field_to_string(row.main_sel_first) << "," << field_to_string(row.kernel_kernel_inputs) << "," << field_to_string(row.kernel_kernel_value_out) << "," << field_to_string(row.kernel_kernel_side_effect_out) << "," - << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.alu_a_hi) << "," - << field_to_string(row.alu_a_lo) << "," << field_to_string(row.alu_b_hi) << "," - << field_to_string(row.alu_b_lo) << "," << field_to_string(row.alu_borrow) << "," - << field_to_string(row.alu_cf) << "," << field_to_string(row.alu_clk) << "," - << field_to_string(row.alu_cmp_rng_ctr) << "," << field_to_string(row.alu_div_u16_r0) << "," - << field_to_string(row.alu_div_u16_r1) << "," << field_to_string(row.alu_div_u16_r2) << "," - << field_to_string(row.alu_div_u16_r3) << "," << field_to_string(row.alu_div_u16_r4) << "," - << field_to_string(row.alu_div_u16_r5) << "," << field_to_string(row.alu_div_u16_r6) << "," - << field_to_string(row.alu_div_u16_r7) << "," << field_to_string(row.alu_divisor_hi) << "," - << field_to_string(row.alu_divisor_lo) << "," << field_to_string(row.alu_ff_tag) << "," - << field_to_string(row.alu_ia) << "," << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) - << "," << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," + << field_to_string(row.kernel_kernel_metadata_out) << "," << field_to_string(row.main_calldata) << "," + << field_to_string(row.alu_a_hi) << "," << field_to_string(row.alu_a_lo) << "," + << field_to_string(row.alu_b_hi) << "," << field_to_string(row.alu_b_lo) << "," + << field_to_string(row.alu_borrow) << "," << field_to_string(row.alu_cf) << "," + << field_to_string(row.alu_clk) << "," << field_to_string(row.alu_cmp_rng_ctr) << "," + << field_to_string(row.alu_div_u16_r0) << "," << field_to_string(row.alu_div_u16_r1) << "," + << field_to_string(row.alu_div_u16_r2) << "," << field_to_string(row.alu_div_u16_r3) << "," + << field_to_string(row.alu_div_u16_r4) << "," << field_to_string(row.alu_div_u16_r5) << "," + << field_to_string(row.alu_div_u16_r6) << "," << field_to_string(row.alu_div_u16_r7) << "," + << field_to_string(row.alu_divisor_hi) << "," << field_to_string(row.alu_divisor_lo) << "," + << field_to_string(row.alu_ff_tag) << "," << field_to_string(row.alu_ia) << "," + << field_to_string(row.alu_ib) << "," << field_to_string(row.alu_ic) << "," + << field_to_string(row.alu_in_tag) << "," << field_to_string(row.alu_op_add) << "," << field_to_string(row.alu_op_cast) << "," << field_to_string(row.alu_op_cast_prev) << "," << field_to_string(row.alu_op_div) << "," << field_to_string(row.alu_op_div_a_lt_b) << "," << field_to_string(row.alu_op_div_std) << "," << field_to_string(row.alu_op_eq) << "," @@ -518,6 +521,7 @@ template std::ostream& operator<<(std::ostream& os, AvmFullRow << "," << field_to_string(row.main_sel_op_external_call) << "," << field_to_string(row.main_sel_op_fdiv) << "," << field_to_string(row.main_sel_op_fee_per_da_gas) << "," << field_to_string(row.main_sel_op_fee_per_l2_gas) << "," + << field_to_string(row.main_sel_op_function_selector) << "," << field_to_string(row.main_sel_op_get_contract_instance) << "," << field_to_string(row.main_sel_op_halt) << "," << field_to_string(row.main_sel_op_internal_call) << "," << field_to_string(row.main_sel_op_internal_return) << "," << field_to_string(row.main_sel_op_jump) << "," diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp index 9bbe9334c855..6508ba7d465b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_circuit_builder.hpp @@ -93,6 +93,7 @@ template struct AvmFullRow { FF kernel_kernel_value_out{}; FF kernel_kernel_side_effect_out{}; FF kernel_kernel_metadata_out{}; + FF main_calldata{}; FF alu_a_hi{}; FF alu_a_lo{}; FF alu_b_hi{}; @@ -289,6 +290,7 @@ template struct AvmFullRow { FF main_sel_op_fdiv{}; FF main_sel_op_fee_per_da_gas{}; FF main_sel_op_fee_per_l2_gas{}; + FF main_sel_op_function_selector{}; FF main_sel_op_get_contract_instance{}; FF main_sel_op_halt{}; FF main_sel_op_internal_call{}; @@ -553,8 +555,8 @@ class AvmCircuitBuilder { using Polynomial = Flavor::Polynomial; using ProverPolynomials = Flavor::ProverPolynomials; - static constexpr size_t num_fixed_columns = 450; - static constexpr size_t num_polys = 385; + static constexpr size_t num_fixed_columns = 452; + static constexpr size_t num_polys = 387; std::vector rows; void set_trace(std::vector&& trace) { rows = std::move(trace); } @@ -576,6 +578,7 @@ class AvmCircuitBuilder { polys.kernel_kernel_value_out[i] = rows[i].kernel_kernel_value_out; polys.kernel_kernel_side_effect_out[i] = rows[i].kernel_kernel_side_effect_out; polys.kernel_kernel_metadata_out[i] = rows[i].kernel_kernel_metadata_out; + polys.main_calldata[i] = rows[i].main_calldata; polys.alu_a_hi[i] = rows[i].alu_a_hi; polys.alu_a_lo[i] = rows[i].alu_a_lo; polys.alu_b_hi[i] = rows[i].alu_b_hi; @@ -773,6 +776,7 @@ class AvmCircuitBuilder { polys.main_sel_op_fdiv[i] = rows[i].main_sel_op_fdiv; polys.main_sel_op_fee_per_da_gas[i] = rows[i].main_sel_op_fee_per_da_gas; polys.main_sel_op_fee_per_l2_gas[i] = rows[i].main_sel_op_fee_per_l2_gas; + polys.main_sel_op_function_selector[i] = rows[i].main_sel_op_function_selector; polys.main_sel_op_get_contract_instance[i] = rows[i].main_sel_op_get_contract_instance; polys.main_sel_op_halt[i] = rows[i].main_sel_op_halt; polys.main_sel_op_internal_call[i] = rows[i].main_sel_op_internal_call; diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index e5729066c00e..c29a3b0212a6 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -100,11 +100,11 @@ class AvmFlavor { using RelationSeparator = FF; static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 2; - static constexpr size_t NUM_WITNESS_ENTITIES = 383; + static constexpr size_t NUM_WITNESS_ENTITIES = 385; static constexpr size_t NUM_WIRES = NUM_WITNESS_ENTITIES + NUM_PRECOMPUTED_ENTITIES; // We have two copies of the witness entities, so we subtract the number of fixed ones (they have no shift), one for // the unshifted and one for the shifted - static constexpr size_t NUM_ALL_ENTITIES = 450; + static constexpr size_t NUM_ALL_ENTITIES = 452; using GrandProductRelations = std::tuple, perm_main_bin_relation, @@ -264,6 +264,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -460,6 +461,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -650,6 +652,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -846,6 +849,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1041,6 +1045,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1237,6 +1242,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1494,6 +1500,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -1690,6 +1697,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -1947,6 +1955,7 @@ class AvmFlavor { kernel_kernel_value_out, kernel_kernel_side_effect_out, kernel_kernel_metadata_out, + main_calldata, alu_a_hi, alu_a_lo, alu_b_hi, @@ -2143,6 +2152,7 @@ class AvmFlavor { main_sel_op_fdiv, main_sel_op_fee_per_da_gas, main_sel_op_fee_per_l2_gas, + main_sel_op_function_selector, main_sel_op_get_contract_instance, main_sel_op_halt, main_sel_op_internal_call, @@ -2756,6 +2766,7 @@ class AvmFlavor { Base::kernel_kernel_value_out = "KERNEL_KERNEL_VALUE_OUT"; Base::kernel_kernel_side_effect_out = "KERNEL_KERNEL_SIDE_EFFECT_OUT"; Base::kernel_kernel_metadata_out = "KERNEL_KERNEL_METADATA_OUT"; + Base::main_calldata = "MAIN_CALLDATA"; Base::alu_a_hi = "ALU_A_HI"; Base::alu_a_lo = "ALU_A_LO"; Base::alu_b_hi = "ALU_B_HI"; @@ -2952,6 +2963,7 @@ class AvmFlavor { Base::main_sel_op_fdiv = "MAIN_SEL_OP_FDIV"; Base::main_sel_op_fee_per_da_gas = "MAIN_SEL_OP_FEE_PER_DA_GAS"; Base::main_sel_op_fee_per_l2_gas = "MAIN_SEL_OP_FEE_PER_L2_GAS"; + Base::main_sel_op_function_selector = "MAIN_SEL_OP_FUNCTION_SELECTOR"; Base::main_sel_op_get_contract_instance = "MAIN_SEL_OP_GET_CONTRACT_INSTANCE"; Base::main_sel_op_halt = "MAIN_SEL_OP_HALT"; Base::main_sel_op_internal_call = "MAIN_SEL_OP_INTERNAL_CALL"; @@ -3158,6 +3170,7 @@ class AvmFlavor { Commitment kernel_kernel_value_out; Commitment kernel_kernel_side_effect_out; Commitment kernel_kernel_metadata_out; + Commitment main_calldata; Commitment alu_a_hi; Commitment alu_a_lo; Commitment alu_b_hi; @@ -3354,6 +3367,7 @@ class AvmFlavor { Commitment main_sel_op_fdiv; Commitment main_sel_op_fee_per_da_gas; Commitment main_sel_op_fee_per_l2_gas; + Commitment main_sel_op_function_selector; Commitment main_sel_op_get_contract_instance; Commitment main_sel_op_halt; Commitment main_sel_op_internal_call; @@ -3560,6 +3574,7 @@ class AvmFlavor { kernel_kernel_value_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_side_effect_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); kernel_kernel_metadata_out = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + main_calldata = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_a_lo = deserialize_from_buffer(Transcript::proof_data, num_frs_read); alu_b_hi = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3767,6 +3782,7 @@ class AvmFlavor { main_sel_op_fdiv = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_fee_per_da_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_fee_per_l2_gas = deserialize_from_buffer(Transcript::proof_data, num_frs_read); + main_sel_op_function_selector = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_get_contract_instance = deserialize_from_buffer(Transcript::proof_data, num_frs_read); main_sel_op_halt = deserialize_from_buffer(Transcript::proof_data, num_frs_read); @@ -3978,6 +3994,7 @@ class AvmFlavor { serialize_to_buffer(kernel_kernel_value_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_side_effect_out, Transcript::proof_data); serialize_to_buffer(kernel_kernel_metadata_out, Transcript::proof_data); + serialize_to_buffer(main_calldata, Transcript::proof_data); serialize_to_buffer(alu_a_hi, Transcript::proof_data); serialize_to_buffer(alu_a_lo, Transcript::proof_data); serialize_to_buffer(alu_b_hi, Transcript::proof_data); @@ -4174,6 +4191,7 @@ class AvmFlavor { serialize_to_buffer(main_sel_op_fdiv, Transcript::proof_data); serialize_to_buffer(main_sel_op_fee_per_da_gas, Transcript::proof_data); serialize_to_buffer(main_sel_op_fee_per_l2_gas, Transcript::proof_data); + serialize_to_buffer(main_sel_op_function_selector, Transcript::proof_data); serialize_to_buffer(main_sel_op_get_contract_instance, Transcript::proof_data); serialize_to_buffer(main_sel_op_halt, Transcript::proof_data); serialize_to_buffer(main_sel_op_internal_call, Transcript::proof_data); diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index a10bc668d027..93ff4ac5989f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -62,6 +62,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); + witness_commitments.main_calldata = commitment_key->commit(key->main_calldata); witness_commitments.alu_a_hi = commitment_key->commit(key->alu_a_hi); witness_commitments.alu_a_lo = commitment_key->commit(key->alu_a_lo); witness_commitments.alu_b_hi = commitment_key->commit(key->alu_b_hi); @@ -269,6 +270,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.main_sel_op_fdiv = commitment_key->commit(key->main_sel_op_fdiv); witness_commitments.main_sel_op_fee_per_da_gas = commitment_key->commit(key->main_sel_op_fee_per_da_gas); witness_commitments.main_sel_op_fee_per_l2_gas = commitment_key->commit(key->main_sel_op_fee_per_l2_gas); + witness_commitments.main_sel_op_function_selector = commitment_key->commit(key->main_sel_op_function_selector); witness_commitments.main_sel_op_get_contract_instance = commitment_key->commit(key->main_sel_op_get_contract_instance); witness_commitments.main_sel_op_halt = commitment_key->commit(key->main_sel_op_halt); @@ -408,6 +410,7 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.kernel_kernel_side_effect_out); transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, witness_commitments.kernel_kernel_metadata_out); + transcript->send_to_verifier(commitment_labels.main_calldata, witness_commitments.main_calldata); transcript->send_to_verifier(commitment_labels.alu_a_hi, witness_commitments.alu_a_hi); transcript->send_to_verifier(commitment_labels.alu_a_lo, witness_commitments.alu_a_lo); transcript->send_to_verifier(commitment_labels.alu_b_hi, witness_commitments.alu_b_hi); @@ -638,6 +641,8 @@ void AvmProver::execute_wire_commitments_round() witness_commitments.main_sel_op_fee_per_da_gas); transcript->send_to_verifier(commitment_labels.main_sel_op_fee_per_l2_gas, witness_commitments.main_sel_op_fee_per_l2_gas); + transcript->send_to_verifier(commitment_labels.main_sel_op_function_selector, + witness_commitments.main_sel_op_function_selector); transcript->send_to_verifier(commitment_labels.main_sel_op_get_contract_instance, witness_commitments.main_sel_op_get_contract_instance); transcript->send_to_verifier(commitment_labels.main_sel_op_halt, witness_commitments.main_sel_op_halt); @@ -963,7 +968,8 @@ void AvmProver::execute_relation_check_rounds() * */ void AvmProver::execute_pcs_rounds() { - auto prover_opening_claim = ZeroMorph::prove(prover_polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(key->circuit_size, + prover_polynomials.get_unshifted(), prover_polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index 0a863144aadb..d15ad4f2fcaf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -79,6 +79,7 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); commitments.kernel_kernel_metadata_out = transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); + commitments.main_calldata = transcript->template receive_from_prover(commitment_labels.main_calldata); commitments.alu_a_hi = transcript->template receive_from_prover(commitment_labels.alu_a_hi); commitments.alu_a_lo = transcript->template receive_from_prover(commitment_labels.alu_a_lo); commitments.alu_b_hi = transcript->template receive_from_prover(commitment_labels.alu_b_hi); @@ -375,6 +376,8 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.main_sel_op_fee_per_da_gas); commitments.main_sel_op_fee_per_l2_gas = transcript->template receive_from_prover(commitment_labels.main_sel_op_fee_per_l2_gas); + commitments.main_sel_op_function_selector = + transcript->template receive_from_prover(commitment_labels.main_sel_op_function_selector); commitments.main_sel_op_get_contract_instance = transcript->template receive_from_prover(commitment_labels.main_sel_op_get_contract_instance); commitments.main_sel_op_halt = @@ -712,31 +715,36 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector mle_challenge(multivariate_challenge.begin(), + multivariate_challenge.begin() + static_cast(log_circuit_size)); - FF kernel_kernel_inputs_evaluation = - evaluate_public_input_column(public_inputs[0], circuit_size, multivariate_challenge); + FF kernel_kernel_inputs_evaluation = evaluate_public_input_column(public_inputs[0], circuit_size, mle_challenge); if (kernel_kernel_inputs_evaluation != claimed_evaluations.kernel_kernel_inputs) { return false; } - FF kernel_kernel_value_out_evaluation = - evaluate_public_input_column(public_inputs[1], circuit_size, multivariate_challenge); + FF kernel_kernel_value_out_evaluation = evaluate_public_input_column(public_inputs[1], circuit_size, mle_challenge); if (kernel_kernel_value_out_evaluation != claimed_evaluations.kernel_kernel_value_out) { return false; } FF kernel_kernel_side_effect_out_evaluation = - evaluate_public_input_column(public_inputs[2], circuit_size, multivariate_challenge); + evaluate_public_input_column(public_inputs[2], circuit_size, mle_challenge); if (kernel_kernel_side_effect_out_evaluation != claimed_evaluations.kernel_kernel_side_effect_out) { return false; } FF kernel_kernel_metadata_out_evaluation = - evaluate_public_input_column(public_inputs[3], circuit_size, multivariate_challenge); + evaluate_public_input_column(public_inputs[3], circuit_size, mle_challenge); if (kernel_kernel_metadata_out_evaluation != claimed_evaluations.kernel_kernel_metadata_out) { return false; } + FF main_calldata_evaluation = evaluate_public_input_column(public_inputs[4], circuit_size, mle_challenge); + if (main_calldata_evaluation != claimed_evaluations.main_calldata) { + return false; + } + // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. // NOTE: temporarily disabled - facing integration issues diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp index fa7c78ab02f4..a320b2d7245d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_arithmetic.test.cpp @@ -215,6 +215,11 @@ class AvmArithmeticTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + void gen_trace_builder(std::vector const& calldata) + { + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + } + // Generate a trace with an EQ opcode operation. std::vector gen_trace_eq(uint128_t const& a, uint128_t const& b, @@ -226,7 +231,7 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, addr_a, tag); trace_builder.op_set(0, b, addr_b, tag); trace_builder.op_eq(0, addr_a, addr_b, addr_c, tag); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); return trace_builder.finalize(); } @@ -368,11 +373,13 @@ std::vector> positive_op_div_test_values = { { // Test on basic addition over finite field type. TEST_F(AvmArithmeticTestsFF, addition) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); - // Memory layout: [37,4,11,0,0,0,....] + // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] - trace_builder.return_op(0, 0, 5); + trace_builder.op_return(0, 0, 5); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(37), FF(4), FF(41), FF(0), FF(1), FF(4), AvmMemoryTag::FF); @@ -381,17 +388,19 @@ TEST_F(AvmArithmeticTestsFF, addition) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test on basic subtraction over finite field type. TEST_F(AvmArithmeticTestsFF, subtraction) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(17), FF(8), FF(9), FF(2), FF(0), FF(1), AvmMemoryTag::FF); @@ -400,17 +409,19 @@ TEST_F(AvmArithmeticTestsFF, subtraction) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic multiplication over finite field type. TEST_F(AvmArithmeticTestsFF, multiplication) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(20), FF(5), FF(100), FF(2), FF(0), FF(1), AvmMemoryTag::FF); @@ -420,17 +431,19 @@ TEST_F(AvmArithmeticTestsFF, multiplication) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on multiplication by zero over finite field type. TEST_F(AvmArithmeticTestsFF, multiplicationByZero) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 127 }); + std::vector const calldata = { 127 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [127,0,0,0,0,0,....] trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::FF); // [127,0,0,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(127), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -440,17 +453,19 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) EXPECT_EQ(alu_row.alu_cf, FF(0)); EXPECT_EQ(alu_row.alu_u8_r0, FF(0)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on basic division over finite field type. TEST_F(AvmArithmeticTestsFF, fDivision) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -463,17 +478,19 @@ TEST_F(AvmArithmeticTestsFF, fDivision) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division with zero numerator over finite field type. TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -486,14 +503,16 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); EXPECT_EQ(row->main_rwc, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division by zero over finite field type. // We check that the operator error flag is raised. TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -511,7 +530,7 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) EXPECT_EQ(row->main_rwc, FF(1)); EXPECT_EQ(row->main_op_err, FF(1)); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test on division of zero by zero over finite field type. @@ -543,7 +562,9 @@ TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) // No check on the evaluation is performed here. TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) { - trace_builder.calldata_copy(0, 0, 3, 2, std::vector{ 45, 23, 12 }); + std::vector const calldata = { 45, 23, 12 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 2); // Memory layout: [0,0,45,23,12,0,0,0,....] trace_builder.op_add(0, 2, 3, 4, AvmMemoryTag::FF); // [0,0,45,23,68,0,0,0,....] @@ -558,7 +579,7 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.halt(); auto trace = trace_builder.finalize(); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Test of equality on FF elements @@ -566,9 +587,11 @@ TEST_F(AvmArithmeticTestsFF, equality) { // Pick a field-sized number FF elem = FF::modulus - FF(1); - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ elem, elem, 1 }); + std::vector const calldata = { elem, elem, 1 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q -1, 1,0..] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, elem, FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -576,16 +599,18 @@ TEST_F(AvmArithmeticTestsFF, equality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(0)); // Expect 0 as inv of (q-1) - (q-1) - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Test correct non-equality of FF elements TEST_F(AvmArithmeticTestsFF, nonEquality) { FF elem = FF::modulus - FF(1); - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ elem, elem + FF(1), 0 }); + std::vector const calldata = { elem, elem + FF(1), 0 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [q - 1, q, 1,0..] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -593,7 +618,7 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) EXPECT_EQ(alu_row.alu_ff_tag, FF(1)); EXPECT_EQ(alu_row.alu_op_eq_diff_inv, FF(-1).invert()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_P(AvmArithmeticTestsDiv, division) @@ -603,7 +628,7 @@ TEST_P(AvmArithmeticTestsDiv, division) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_div(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); common_validate_div(trace, a, b, output, 0, 1, 2, mem_tag); @@ -652,7 +677,7 @@ TEST_F(AvmArithmeticTestsU8, addition) // Memory layout: [62,29,0,0,0,....] trace_builder.op_add(0, 0, 1, 2, AvmMemoryTag::U8); // [62,29,91,0,0,....] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(62), FF(29), FF(91), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -673,7 +698,7 @@ TEST_F(AvmArithmeticTestsU8, additionCarry) // Memory layout: [159,100,0,0,0,....] trace_builder.op_add(0, 0, 1, 2, AvmMemoryTag::U8); // [159,100,3,0,0,....] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(159), FF(100), FF(3), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -695,7 +720,7 @@ TEST_F(AvmArithmeticTestsU8, subtraction) // Memory layout: [162,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2, AvmMemoryTag::U8); // [162,29,133,0,0,....] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(162), FF(29), FF(133), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -717,7 +742,7 @@ TEST_F(AvmArithmeticTestsU8, subtractionCarry) // Memory layout: [5,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2, AvmMemoryTag::U8); // [5,29,232,0,0,....] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(5), FF(29), FF(232), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -745,7 +770,7 @@ TEST_F(AvmArithmeticTestsU8, multiplication) trace_builder.op_set(0, 15, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U8); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(13), FF(15), FF(195), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -768,7 +793,7 @@ TEST_F(AvmArithmeticTestsU8, multiplicationOverflow) trace_builder.op_set(0, 170, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U8); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(200), FF(170), FF(208), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -822,7 +847,7 @@ TEST_F(AvmArithmeticTestsU16, addition) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_add(0, 546, 119, 5, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = @@ -844,7 +869,7 @@ TEST_F(AvmArithmeticTestsU16, additionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_add(0, 1, 0, 0, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = @@ -866,7 +891,7 @@ TEST_F(AvmArithmeticTestsU16, subtraction) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_sub(0, 546, 119, 5, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = @@ -890,7 +915,7 @@ TEST_F(AvmArithmeticTestsU16, subtractionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_sub(0, 1, 0, 0, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = @@ -919,7 +944,7 @@ TEST_F(AvmArithmeticTestsU16, multiplication) trace_builder.op_set(0, 245, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -944,7 +969,7 @@ TEST_F(AvmArithmeticTestsU16, multiplicationOverflow) trace_builder.op_set(0, 1024, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(512), FF(1024), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U16); @@ -1000,7 +1025,7 @@ TEST_F(AvmArithmeticTestsU32, addition) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add( @@ -1023,7 +1048,7 @@ TEST_F(AvmArithmeticTestsU32, additionCarry) trace_builder.op_set(0, 2293, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = @@ -1045,7 +1070,7 @@ TEST_F(AvmArithmeticTestsU32, subtraction) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 8, 9, 0, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1072,7 +1097,7 @@ TEST_F(AvmArithmeticTestsU32, subtractionCarry) trace_builder.op_set(0, 3210987654, 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 9, 8, 0, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1103,7 +1128,7 @@ TEST_F(AvmArithmeticTestsU32, multiplication) trace_builder.op_set(0, 11111, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1132,7 +1157,7 @@ TEST_F(AvmArithmeticTestsU32, multiplicationOverflow) trace_builder.op_set(0, 13 << 22, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U32); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1197,7 +1222,7 @@ TEST_F(AvmArithmeticTestsU64, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_add(0, 8, 9, 9, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1227,7 +1252,7 @@ TEST_F(AvmArithmeticTestsU64, additionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_add(0, 0, 1, 0, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1255,7 +1280,7 @@ TEST_F(AvmArithmeticTestsU64, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_sub(0, 8, 9, 9, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1287,7 +1312,7 @@ TEST_F(AvmArithmeticTestsU64, subtractionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_sub(0, 0, 1, 0, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1315,7 +1340,7 @@ TEST_F(AvmArithmeticTestsU64, multiplication) trace_builder.op_set(0, 555444333, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1348,7 +1373,7 @@ TEST_F(AvmArithmeticTestsU64, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(a), FF(b), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U64); @@ -1414,7 +1439,7 @@ TEST_F(AvmArithmeticTestsU128, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, @@ -1454,7 +1479,7 @@ TEST_F(AvmArithmeticTestsU128, additionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, @@ -1493,7 +1518,7 @@ TEST_F(AvmArithmeticTestsU128, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, @@ -1535,7 +1560,7 @@ TEST_F(AvmArithmeticTestsU128, subtractionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, @@ -1573,7 +1598,7 @@ TEST_F(AvmArithmeticTestsU128, multiplication) FF c{ uint256_t{ 0xA7DDA0BAE60CA3A5, 0x70289AEB0, 0, 0 } }; trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1612,7 +1637,7 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, @@ -1758,7 +1783,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, multiplication) // Test on basic incorrect division over finite field type. TEST_F(AvmArithmeticNegativeTestsFF, fDivision) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1775,7 +1802,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // in the trace. TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 15, 315 }); + std::vector const calldata = { 15, 315 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] @@ -1801,7 +1830,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Test with finite field division by zero occurs and no error is raised (remove error flag) TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 15 }); + std::vector const calldata = { 15 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] @@ -1837,7 +1868,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) // Test with finite field division using a wrong read instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1855,7 +1888,9 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) // Test with finite field division using a wrong write instruction tag TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) { - trace_builder.calldata_copy(0, 0, 1, 0, std::vector{ 18, 6 }); + std::vector const calldata = { 18, 6 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] trace_builder.halt(); @@ -1874,11 +1909,13 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) // the addition, subtraction, multiplication. TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 37, 4, 11 }); + std::vector const calldata = { 37, 4, 11 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::FF); // [37,4,11,0,41,0,....] - trace_builder.return_op(0, 0, 5); + trace_builder.op_return(0, 0, 5); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -1893,11 +1930,13 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 8, 4, 17 }); + std::vector const calldata = { 8, 4, 17 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1, AvmMemoryTag::FF); // [8,9,17,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -1911,11 +1950,13 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) { - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ 5, 0, 20 }); + std::vector const calldata = { 5, 0, 20 }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 3, 0); // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1, AvmMemoryTag::FF); // [5,100,20,0,0,0....] - trace_builder.return_op(0, 0, 3); + trace_builder.op_return(0, 0, 3); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector @@ -1954,9 +1995,11 @@ TEST_F(AvmArithmeticNegativeTestsFF, nonBooleanEq) TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) { FF elem = FF::modulus - FF(15); - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ elem, elem }); + std::vector const calldata = { elem, elem }; + gen_trace_builder(calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2, AvmMemoryTag::FF); // Memory Layout [elem, elem, 1, 0..] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); // Find the first row enabling the eq selector @@ -2306,7 +2349,7 @@ TEST_F(AvmArithmeticNegativeTestsU128, multiplicationSecondRowNoOp) trace_builder.op_set(0, 4, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(3), FF(4), FF(12), FF(0), FF(1), FF(2), AvmMemoryTag::U128); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp index 482d397cbcc1..e70b50106af9 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_bitwise.test.cpp @@ -469,7 +469,7 @@ TEST_P(AvmBitwiseTestsNot, ParamTest) const auto [a, output] = operands; trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_not(0, 0, 1, mem_tag); // [1,254,0,0,....] - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); FF ff_a = FF(uint256_t::from_uint128(a)); FF ff_output = FF(uint256_t::from_uint128(output)); @@ -488,11 +488,11 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_and(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 2, 1); + trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } INSTANTIATE_TEST_SUITE_P(AvmBitwiseTests, AvmBitwiseTestsAnd, @@ -505,7 +505,7 @@ TEST_P(AvmBitwiseTestsOr, AllOrTest) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_or(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 2, 1); + trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 1, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -522,7 +522,7 @@ TEST_P(AvmBitwiseTestsXor, AllXorTest) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 2, 1); + trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 2, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -540,7 +540,7 @@ TEST_P(AvmBitwiseTestsShr, AllShrTest) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 2, 1); + trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, true); validate_trace(std::move(trace), public_inputs); @@ -557,7 +557,7 @@ TEST_P(AvmBitwiseTestsShl, AllShlTest) trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 2, 1); + trace_builder.op_return(0, 2, 1); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, false); @@ -719,7 +719,7 @@ TEST_F(AvmBitwiseNegativeTestsFF, UndefinedOverFF) trace_builder.op_not(0, 0, 1, AvmMemoryTag::U8); // Finally, we will have a write in row 3 of the mem_trace to copy the result // from the op_not operation. - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); // Manually update the memory tags in the relevant trace; auto trace = trace_builder.finalize(); // TODO(ilyas): When the SET opcodes applies relational constraints, this will fail diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp index 446215b1ec00..11d9768300df 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_cast.test.cpp @@ -23,6 +23,7 @@ class AvmCastTests : public ::testing::Test { VmPublicInputs public_inputs; AvmTraceBuilder trace_builder; + std::vector calldata; std::vector trace; size_t main_addr; @@ -34,7 +35,7 @@ class AvmCastTests : public ::testing::Test { { trace_builder.op_set(0, a, src_address, src_tag); trace_builder.op_cast(0, src_address, dst_address, dst_tag); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); } @@ -113,9 +114,9 @@ class AvmCastTests : public ::testing::Test { // We still want the ability to enable proving through the environment variable and therefore we do not pass // the boolean variable force_proof to validate_trace second argument. if (force_proof) { - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } else { - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } } }; @@ -171,9 +172,11 @@ TEST_F(AvmCastTests, noTruncationFFToU32) TEST_F(AvmCastTests, truncationFFToU16ModMinus1) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus - 1) }); + calldata = { FF::modulus - 1 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -182,9 +185,11 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) TEST_F(AvmCastTests, truncationFFToU16ModMinus2) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -208,7 +213,7 @@ TEST_F(AvmCastTests, indirectAddrTruncationU64ToU8) trace_builder.op_set(0, 11, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 256'000'000'203UL, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 0, 1, AvmMemoryTag::U8); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -223,7 +228,7 @@ TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) trace_builder.op_set(0, 11, 6, AvmMemoryTag::U32); trace_builder.op_set(0, 4234, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 5, 6, AvmMemoryTag::U8); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_cast == FF(1); }); @@ -291,9 +296,11 @@ TEST_F(AvmCastNegativeTests, wrongOutputAluIc) TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two) }); + calldata = { FF::modulus_minus_two }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -314,9 +321,11 @@ TEST_F(AvmCastNegativeTests, wrongPSubALo) TEST_F(AvmCastNegativeTests, wrongPSubAHi) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -352,9 +361,11 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionLo) TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 987) }); + calldata = { FF::modulus_minus_two - 987 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); @@ -396,9 +407,11 @@ TEST_F(AvmCastNegativeTests, wrongCopySubLoForRangeCheck) TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) { - trace_builder.calldata_copy(0, 0, 1, 0, { FF(FF::modulus_minus_two - 972836) }); + std::vector const calldata = { FF::modulus_minus_two - 972836 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); gen_indices(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp index 0f0f4ebac527..c3e65de12425 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_comparison.test.cpp @@ -106,14 +106,18 @@ TEST_P(AvmCmpTestsLT, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); } trace_builder.op_lt(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); // Get the row in the avm with the LT selector set @@ -128,7 +132,7 @@ TEST_P(AvmCmpTestsLT, ParamTest) ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLT, @@ -138,14 +142,18 @@ TEST_P(AvmCmpTestsLTE, ParamTest) { const auto [params, mem_tag] = GetParam(); const auto [a, b, c] = params; + std::vector calldata{}; + if (mem_tag == AvmMemoryTag::FF) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ a, b }); + calldata = { a, b }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); } else { trace_builder.op_set(0, uint128_t(a), 0, mem_tag); trace_builder.op_set(0, uint128_t(b), 1, mem_tag); } trace_builder.op_lte(0, 0, 1, 2, mem_tag); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_lte == FF(1); }); @@ -157,7 +165,7 @@ TEST_P(AvmCmpTestsLTE, ParamTest) ASSERT_TRUE(row != trace.end()); ASSERT_TRUE(alu_row != trace.end()); common_validate_cmp(*row, *alu_row, a, b, c, FF(0), FF(1), FF(2), mem_tag); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } INSTANTIATE_TEST_SUITE_P(AvmCmpTests, AvmCmpTestsLTE, @@ -309,9 +317,11 @@ TEST_P(AvmCmpNegativeTestsLT, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lt(0, 0, 1, 2, AvmMemoryTag::FF); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lt == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, false); @@ -327,9 +337,10 @@ TEST_P(AvmCmpNegativeTestsLTE, ParamTest) const auto [failure, params] = GetParam(); const auto [failure_string, failure_mode] = failure; const auto [a, b, output] = params; - trace_builder.calldata_copy(0, 0, 3, 0, std::vector{ a, b, output }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ a, b, output }); + trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lte(0, 0, 1, 2, AvmMemoryTag::FF); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lte == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp index 616bdd5f1267..f961e542cb47 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_control_flow.test.cpp @@ -63,7 +63,7 @@ TEST_F(AvmControlFlowTests, simpleCall) // pc opcode // 0 INTERNAL_CALL(pc=4) // 4 HALT - trace_builder.internal_call(CALL_PC); + trace_builder.op_internal_call(CALL_PC); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -87,7 +87,7 @@ TEST_F(AvmControlFlowTests, simpleCall) EXPECT_EQ(halt_row->main_pc, FF(CALL_PC)); EXPECT_EQ(halt_row->main_internal_return_ptr, FF(1)); } - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } TEST_F(AvmControlFlowTests, simpleJump) @@ -98,7 +98,7 @@ TEST_F(AvmControlFlowTests, simpleJump) // pc opcode // 0 JUMP(pc=4) // 4 HALT - trace_builder.jump(JUMP_PC); + trace_builder.op_jump(JUMP_PC); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -132,8 +132,8 @@ TEST_F(AvmControlFlowTests, simpleCallAndReturn) // 0 INTERNAL_CALL(pc=20) // 20 INTERNAL_RETURN // 1 HALT - trace_builder.internal_call(CALL_PC); - trace_builder.internal_return(); + trace_builder.op_internal_call(CALL_PC); + trace_builder.op_internal_return(); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -191,15 +191,15 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) // 22 INTERNAL_RETURN // 421 INTERNAL_RETURN // 1 HALT - trace_builder.internal_call(CALL_PC_1); - trace_builder.internal_call(CALL_PC_2); - trace_builder.internal_call(CALL_PC_3); - trace_builder.internal_return(); - trace_builder.internal_call(CALL_PC_4); - trace_builder.internal_return(); - trace_builder.jump(JUMP_PC_1); - trace_builder.internal_return(); - trace_builder.internal_return(); + trace_builder.op_internal_call(CALL_PC_1); + trace_builder.op_internal_call(CALL_PC_2); + trace_builder.op_internal_call(CALL_PC_3); + trace_builder.op_internal_return(); + trace_builder.op_internal_call(CALL_PC_4); + trace_builder.op_internal_return(); + trace_builder.op_jump(JUMP_PC_1); + trace_builder.op_internal_return(); + trace_builder.op_internal_return(); trace_builder.halt(); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp index 10f971f1f701..24829d562f4c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_execution.test.cpp @@ -100,7 +100,7 @@ TEST_F(AvmExecutionTests, basicAddReturn) ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); auto trace = gen_trace_from_instr(instructions); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for SET and SUB opcodes @@ -165,7 +165,7 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) // Find the first row enabling the subtraction selector auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sub == 1; }); EXPECT_EQ(row->main_ic, 10000); // 47123 - 37123 = 10000 - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Positive test for multiple MUL opcodes @@ -467,7 +467,7 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // It must have failed as subtraction was "jumped over". EXPECT_EQ(row, trace.end()); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { 13, 156 }); } // Positive test for JUMPI. @@ -561,8 +561,8 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) EXPECT_EQ(row->main_ic, 1600); // 800 = (20 + 20) * (20 + 20) // traces validation - validate_trace(std::move(trace_jump), public_inputs); - validate_trace(std::move(trace_no_jump), public_inputs); + validate_trace(std::move(trace_jump), public_inputs, { 9873123 }); + validate_trace(std::move(trace_no_jump), public_inputs, { 0 }); } // Positive test with MOV. @@ -805,7 +805,7 @@ TEST_F(AvmExecutionTests, toRadixLeOpcode) } EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, { FF::modulus - FF(1) }); } // // Positive test with SHA256COMPRESSION. @@ -873,7 +873,7 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with SHA256 @@ -992,7 +992,7 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with Keccakf1600. @@ -1177,7 +1177,7 @@ TEST_F(AvmExecutionTests, pedersenHashOpCode) EXPECT_EQ(returndata[0], expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // // Positive test with EmbeddedCurveAdd @@ -1239,7 +1239,7 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test with MSM @@ -1316,139 +1316,154 @@ TEST_F(AvmExecutionTests, msmOpCode) EXPECT_EQ(returndata, expected_output); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Positive test for Kernel Input opcodes TEST_F(AvmExecutionTests, kernelInputOpcodes) { - std::string bytecode_hex = to_hex(OpCode::SENDER) + // opcode SENDER - "00" // Indirect flag - "00000001" // dst_offset 1 - + to_hex(OpCode::ADDRESS) + // opcode ADDRESS - "00" // Indirect flag - "00000002" // dst_offset 2 - + to_hex(OpCode::STORAGEADDRESS) + // opcode STORAGEADDRESS - "00" // Indirect flag - "00000003" // dst_offset 3 - + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS - "00" // Indirect flag - "00000004" // dst_offset 4 - + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS - "00" // Indirect flag - "00000005" // dst_offset 5 - + to_hex(OpCode::TRANSACTIONFEE) + // opcode TRANSACTIONFEE - "00" // Indirect flag - "00000006" // dst_offset 6 - + to_hex(OpCode::CHAINID) + // opcode CHAINID - "00" // Indirect flag - "00000007" // dst_offset 7 - + to_hex(OpCode::VERSION) + // opcode VERSION - "00" // Indirect flag - "00000008" // dst_offset 8 - + to_hex(OpCode::BLOCKNUMBER) + // opcode BLOCKNUMBER - "00" // Indirect flag - "00000009" // dst_offset 9 - + to_hex(OpCode::TIMESTAMP) + // opcode TIMESTAMP - "00" // Indirect flag - "0000000a" // dst_offset 10 - // Not in simulator + std::string bytecode_hex = to_hex(OpCode::ADDRESS) + // opcode ADDRESS + "00" // Indirect flag + "00000001" // dst_offset + + to_hex(OpCode::STORAGEADDRESS) + // opcode STORAGEADDRESS + "00" // Indirect flag + "00000002" // dst_offset + + to_hex(OpCode::SENDER) + // opcode SENDER + "00" // Indirect flag + "00000003" // dst_offset + + to_hex(OpCode::FUNCTIONSELECTOR) + // opcode TRANSACTIONFEE + "00" // Indirect flag + "00000004" // dst_offset + + to_hex(OpCode::TRANSACTIONFEE) + // opcode TRANSACTIONFEE + "00" // Indirect flag + "00000005" // dst_offset + + to_hex(OpCode::CHAINID) + // opcode CHAINID + "00" // Indirect flag + "00000006" // dst_offset + + to_hex(OpCode::VERSION) + // opcode VERSION + "00" // Indirect flag + "00000007" // dst_offset + + to_hex(OpCode::BLOCKNUMBER) + // opcode BLOCKNUMBER + "00" // Indirect flag + "00000008" // dst_offset + + to_hex(OpCode::TIMESTAMP) + // opcode TIMESTAMP + "00" // Indirect flag + "00000009" // dst_offset + // Not in simulator // + to_hex(OpCode::COINBASE) + // opcode COINBASE // "00" // Indirect flag - // "0000000a" // dst_offset 10 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "00000001" // ret offset 1 - "0000000a"; // ret size 10 + // "00000009" // dst_offset + + to_hex(OpCode::FEEPERL2GAS) + // opcode FEEPERL2GAS + "00" // Indirect flag + "0000000a" // dst_offset + + to_hex(OpCode::FEEPERDAGAS) + // opcode FEEPERDAGAS + "00" // Indirect flag + "0000000b" // dst_offset + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "00000001" // ret offset 1 + "0000000b"; // ret size 11 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse(bytecode); - ASSERT_THAT(instructions, SizeIs(11)); + ASSERT_THAT(instructions, SizeIs(12)); - // SENDER + // ADDRESS EXPECT_THAT(instructions.at(0), - AllOf(Field(&Instruction::op_code, OpCode::SENDER), + AllOf(Field(&Instruction::op_code, OpCode::ADDRESS), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(1))))); - // ADDRESS + // STORAGEADDRESS EXPECT_THAT(instructions.at(1), - AllOf(Field(&Instruction::op_code, OpCode::ADDRESS), + AllOf(Field(&Instruction::op_code, OpCode::STORAGEADDRESS), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(2))))); - // STORAGEADDRESS + // SENDER EXPECT_THAT(instructions.at(2), - AllOf(Field(&Instruction::op_code, OpCode::STORAGEADDRESS), + AllOf(Field(&Instruction::op_code, OpCode::SENDER), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(3))))); - // FEEPERL2GAS + + // FUNCTIONSELECTOR EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::FEEPERL2GAS), + AllOf(Field(&Instruction::op_code, OpCode::FUNCTIONSELECTOR), Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(4))))); - // FEEPERDAGAS - EXPECT_THAT(instructions.at(4), - AllOf(Field(&Instruction::op_code, OpCode::FEEPERDAGAS), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(5))))); - // TRANSACTIONFEE - EXPECT_THAT(instructions.at(5), + EXPECT_THAT(instructions.at(4), AllOf(Field(&Instruction::op_code, OpCode::TRANSACTIONFEE), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(6))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(5))))); // CHAINID - EXPECT_THAT(instructions.at(6), + EXPECT_THAT(instructions.at(5), AllOf(Field(&Instruction::op_code, OpCode::CHAINID), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(7))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(6))))); // VERSION - EXPECT_THAT(instructions.at(7), + EXPECT_THAT(instructions.at(6), AllOf(Field(&Instruction::op_code, OpCode::VERSION), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(8))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(7))))); // BLOCKNUMBER - EXPECT_THAT(instructions.at(8), + EXPECT_THAT(instructions.at(7), AllOf(Field(&Instruction::op_code, OpCode::BLOCKNUMBER), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(9))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(8))))); // TIMESTAMP - EXPECT_THAT(instructions.at(9), + EXPECT_THAT(instructions.at(8), AllOf(Field(&Instruction::op_code, OpCode::TIMESTAMP), - Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(10))))); + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(9))))); // COINBASE // Not in simulator - // EXPECT_THAT(instructions.at(9), + // EXPECT_THAT(instructions.at(8), // AllOf(Field(&Instruction::op_code, OpCode::COINBASE), // Field(&Instruction::operands, ElementsAre(VariantWith(0), // VariantWith(10))))); + // FEEPERL2GAS + EXPECT_THAT(instructions.at(9), + AllOf(Field(&Instruction::op_code, OpCode::FEEPERL2GAS), + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(10))))); + + // FEEPERDAGAS + EXPECT_THAT(instructions.at(10), + AllOf(Field(&Instruction::op_code, OpCode::FEEPERDAGAS), + Field(&Instruction::operands, ElementsAre(VariantWith(0), VariantWith(11))))); + // Public inputs for the circuit std::vector calldata = {}; FF sender = 1; FF address = 2; - FF storage_address = 3; - FF feeperl2gas = 4; - FF feeperdagas = 5; - FF transactionfee = 6; - FF chainid = 7; - FF version = 8; - FF blocknumber = 9; - FF timestamp = 10; - // Not in simulator - // FF coinbase = 10; + // NOTE: address doesn't actually exist in public circuit public inputs, + // so storage address is just an alias of address for now + FF storage_address = address; + FF function_selector = 4; + FF transaction_fee = 5; + FF chainid = 6; + FF version = 7; + FF blocknumber = 8; + FF timestamp = 9; + // FF coinbase = 10; // Not in simulator + FF feeperl2gas = 10; + FF feeperdagas = 11; // The return data for this test should be a the opcodes in sequence, as the opcodes dst address lines up with // this array The returndata call above will then return this array - std::vector returndata = { sender, address, storage_address, feeperl2gas, feeperdagas, - transactionfee, chainid, version, blocknumber, /*coinbase,*/ timestamp }; + std::vector returndata = { sender, address, storage_address, function_selector, transaction_fee, + chainid, version, blocknumber, /*coinbase,*/ timestamp, feeperl2gas, + feeperdagas }; // Set up public inputs to contain the above values // TODO: maybe have a javascript like object construction so that this is readable // Reduce the amount of times we have similar code to this - public_inputs_vec[SENDER_SELECTOR] = sender; + // public_inputs_vec[ADDRESS_SELECTOR] = address; public_inputs_vec[STORAGE_ADDRESS_SELECTOR] = storage_address; + public_inputs_vec[SENDER_SELECTOR] = sender; + public_inputs_vec[FUNCTION_SELECTOR_SELECTOR] = function_selector; + public_inputs_vec[TRANSACTION_FEE_OFFSET] = transaction_fee; // Global variables public_inputs_vec[CHAIN_ID_OFFSET] = chainid; @@ -1457,21 +1472,13 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) public_inputs_vec[TIMESTAMP_OFFSET] = timestamp; // Not in the simulator yet // public_inputs_vec[COINBASE_OFFSET] = coinbase; - - // Fees + // Global variables - Gas public_inputs_vec[FEE_PER_DA_GAS_OFFSET] = feeperdagas; public_inputs_vec[FEE_PER_L2_GAS_OFFSET] = feeperl2gas; - // Transaction fee - public_inputs_vec[TRANSACTION_FEE_OFFSET] = transactionfee; - auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec); // Validate that the opcode read the correct value into ia - // Check sender - auto sender_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sender == 1; }); - EXPECT_EQ(sender_row->main_ia, sender); - // Check address auto address_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_address == 1; }); @@ -1482,6 +1489,20 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_storage_address == 1; }); EXPECT_EQ(storage_addr_row->main_ia, storage_address); + // Check sender + auto sender_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_sender == 1; }); + EXPECT_EQ(sender_row->main_ia, sender); + + // Check function selector + auto function_selector_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == 1; }); + EXPECT_EQ(function_selector_row->main_ia, function_selector); + + // Check transactionfee + auto transaction_fee_row = + std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_transaction_fee == 1; }); + EXPECT_EQ(transaction_fee_row->main_ia, transaction_fee); + // Check chain id auto chainid_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_chain_id == 1; }); @@ -1502,6 +1523,12 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_timestamp == 1; }); EXPECT_EQ(timestamp_row->main_ia, timestamp); + // // Check coinbase + // Not in simulator + // auto coinbase_row = + // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == 1; }); + // EXPECT_EQ(coinbase_row->main_ia, coinbase); + // Check feeperdagas auto feeperdagas_row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_da_gas == 1; }); @@ -1512,17 +1539,6 @@ TEST_F(AvmExecutionTests, kernelInputOpcodes) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_fee_per_l2_gas == 1; }); EXPECT_EQ(feeperl2gas_row->main_ia, feeperl2gas); - // Check transactionfee - auto transactionfee_row = - std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_transaction_fee == 1; }); - EXPECT_EQ(transactionfee_row->main_ia, transactionfee); - - // // Check coinbase - // Not in simulator - // auto coinbase_row = - // std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_coinbase == 1; }); - // EXPECT_EQ(coinbase_row->main_ia, coinbase); - validate_trace(std::move(trace), Execution::convert_public_inputs(public_inputs_vec)); } @@ -1650,6 +1666,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) + to_hex(OpCode::EMITUNENCRYPTEDLOG) + // opcode EMITUNENCRYPTEDLOG "00" // Indirect flag "00000001" // src offset 1 + "00000002" // src size offset + to_hex(OpCode::SENDL2TOL1MSG) + // opcode SENDL2TOL1MSG "00" // Indirect flag "00000001" // src offset 1 @@ -1676,7 +1693,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) EXPECT_EQ(emit_note_hash_row->kernel_side_effect_counter, 0); // Get the row of the first note hash out - uint32_t emit_note_hash_out_offset = AvmKernelTraceBuilder::START_EMIT_NOTE_HASH_WRITE_OFFSET; + uint32_t emit_note_hash_out_offset = START_EMIT_NOTE_HASH_WRITE_OFFSET; auto emit_note_hash_kernel_out_row = std::ranges::find_if( trace.begin(), trace.end(), [&](Row r) { return r.main_clk == emit_note_hash_out_offset; }); EXPECT_EQ(emit_note_hash_kernel_out_row->kernel_kernel_value_out, 1); @@ -1689,7 +1706,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) EXPECT_EQ(emit_nullifier_row->main_ia, 1); EXPECT_EQ(emit_nullifier_row->kernel_side_effect_counter, 1); - uint32_t emit_nullifier_out_offset = AvmKernelTraceBuilder::START_EMIT_NULLIFIER_WRITE_OFFSET; + uint32_t emit_nullifier_out_offset = START_EMIT_NULLIFIER_WRITE_OFFSET; auto emit_nullifier_kernel_out_row = std::ranges::find_if( trace.begin(), trace.end(), [&](Row r) { return r.main_clk == emit_nullifier_out_offset; }); EXPECT_EQ(emit_nullifier_kernel_out_row->kernel_kernel_value_out, 1); @@ -1702,7 +1719,7 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) EXPECT_EQ(emit_log_row->main_ia, 1); EXPECT_EQ(emit_log_row->kernel_side_effect_counter, 2); - uint32_t emit_log_out_offset = AvmKernelTraceBuilder::START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; + uint32_t emit_log_out_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; auto emit_log_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == emit_log_out_offset; }); EXPECT_EQ(emit_log_kernel_out_row->kernel_kernel_value_out, 1); @@ -1716,13 +1733,12 @@ TEST_F(AvmExecutionTests, kernelOutputEmitOpcodes) EXPECT_EQ(send_row->main_ib, 1); EXPECT_EQ(send_row->kernel_side_effect_counter, 3); - auto msg_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { - return r.main_clk == AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET; - }); + auto msg_out_row = std::ranges::find_if( + trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET; }); EXPECT_EQ(msg_out_row->kernel_kernel_value_out, 1); EXPECT_EQ(msg_out_row->kernel_kernel_side_effect_out, 3); EXPECT_EQ(msg_out_row->kernel_kernel_metadata_out, 1); - feed_output(AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET, 1, 3, 1); + feed_output(START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET, 1, 3, 1); validate_trace(std::move(trace), public_inputs); } @@ -1773,7 +1789,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) EXPECT_EQ(sload_row->kernel_side_effect_counter, 0); // Get the row of the first read storage read out - uint32_t sload_out_offset = AvmKernelTraceBuilder::START_SLOAD_WRITE_OFFSET; + uint32_t sload_out_offset = START_SLOAD_WRITE_OFFSET; auto sload_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sload_out_offset; }); EXPECT_EQ(sload_kernel_out_row->kernel_kernel_value_out, 42); // value @@ -1834,7 +1850,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeComplex) EXPECT_EQ(sload_row->kernel_side_effect_counter, 1); // Get the row of the first read storage read out - uint32_t sload_out_offset = AvmKernelTraceBuilder::START_SLOAD_WRITE_OFFSET; + uint32_t sload_out_offset = START_SLOAD_WRITE_OFFSET; auto sload_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sload_out_offset; }); EXPECT_EQ(sload_kernel_out_row->kernel_kernel_value_out, 42); // value @@ -1886,7 +1902,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) EXPECT_EQ(sstore_row->kernel_side_effect_counter, 0); // Get the row of the first storage write out - uint32_t sstore_out_offset = AvmKernelTraceBuilder::START_SSTORE_WRITE_OFFSET; + uint32_t sstore_out_offset = START_SSTORE_WRITE_OFFSET; auto sstore_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sstore_out_offset; }); @@ -1898,7 +1914,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) EXPECT_EQ(metadata_out, 9); // slot feed_output(sstore_out_offset, value_out, side_effect_out, metadata_out); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SSTORE @@ -1946,7 +1962,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeComplex) EXPECT_EQ(sstore_row->kernel_side_effect_counter, 1); // Get the row of the first storage write out - uint32_t sstore_out_offset = AvmKernelTraceBuilder::START_SSTORE_WRITE_OFFSET; + uint32_t sstore_out_offset = START_SSTORE_WRITE_OFFSET; auto sstore_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sstore_out_offset; }); EXPECT_EQ(sstore_kernel_out_row->kernel_kernel_value_out, 42); // value @@ -1960,7 +1976,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeComplex) feed_output(sstore_out_offset, 42, 0, 9); feed_output(sstore_out_offset + 1, 123, 1, 10); - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // SLOAD and SSTORE @@ -2015,7 +2031,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) EXPECT_EQ(sload_row->kernel_side_effect_counter, 0); // Get the row of the first storage read out - uint32_t sload_out_offset = AvmKernelTraceBuilder::START_SLOAD_WRITE_OFFSET; + uint32_t sload_out_offset = START_SLOAD_WRITE_OFFSET; auto sload_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sload_out_offset; }); EXPECT_EQ(sload_kernel_out_row->kernel_kernel_value_out, 42); // value @@ -2030,7 +2046,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) EXPECT_EQ(sstore_row->kernel_side_effect_counter, 1); // Get the row of the first storage write out - uint32_t sstore_out_offset = AvmKernelTraceBuilder::START_SSTORE_WRITE_OFFSET; + uint32_t sstore_out_offset = START_SSTORE_WRITE_OFFSET; auto sstore_kernel_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { return r.main_clk == sstore_out_offset; }); EXPECT_EQ(sstore_kernel_out_row->kernel_kernel_value_out, 42); // value @@ -2095,13 +2111,12 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) EXPECT_EQ(note_hash_row->main_ib, 1); // Storage slot EXPECT_EQ(note_hash_row->kernel_side_effect_counter, 0); - auto note_hash_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { - return r.main_clk == AvmKernelTraceBuilder::START_NOTE_HASH_EXISTS_WRITE_OFFSET; - }); + auto note_hash_out_row = std::ranges::find_if( + trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_NOTE_HASH_EXISTS_WRITE_OFFSET; }); EXPECT_EQ(note_hash_out_row->kernel_kernel_value_out, 1); // value EXPECT_EQ(note_hash_out_row->kernel_kernel_side_effect_out, 0); EXPECT_EQ(note_hash_out_row->kernel_kernel_metadata_out, 1); // exists - feed_output(AvmKernelTraceBuilder::START_NOTE_HASH_EXISTS_WRITE_OFFSET, 1, 0, 1); + feed_output(START_NOTE_HASH_EXISTS_WRITE_OFFSET, 1, 0, 1); // CHECK NULLIFIEREXISTS auto nullifier_row = @@ -2110,13 +2125,12 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) EXPECT_EQ(nullifier_row->main_ib, 1); // Storage slot EXPECT_EQ(nullifier_row->kernel_side_effect_counter, 1); - auto nullifier_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { - return r.main_clk == AvmKernelTraceBuilder::START_NULLIFIER_EXISTS_OFFSET; - }); + auto nullifier_out_row = std::ranges::find_if( + trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_NULLIFIER_EXISTS_OFFSET; }); EXPECT_EQ(nullifier_out_row->kernel_kernel_value_out, 1); // value EXPECT_EQ(nullifier_out_row->kernel_kernel_side_effect_out, 1); EXPECT_EQ(nullifier_out_row->kernel_kernel_metadata_out, 1); // exists - feed_output(AvmKernelTraceBuilder::START_NULLIFIER_EXISTS_OFFSET, 1, 1, 1); + feed_output(START_NULLIFIER_EXISTS_OFFSET, 1, 1, 1); // CHECK L1TOL2MSGEXISTS auto l1_to_l2_row = @@ -2125,13 +2139,12 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) EXPECT_EQ(l1_to_l2_row->main_ib, 1); // Storage slot EXPECT_EQ(l1_to_l2_row->kernel_side_effect_counter, 2); - auto msg_out_row = std::ranges::find_if(trace.begin(), trace.end(), [&](Row r) { - return r.main_clk == AvmKernelTraceBuilder::START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET; - }); + auto msg_out_row = std::ranges::find_if( + trace.begin(), trace.end(), [&](Row r) { return r.main_clk == START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET; }); EXPECT_EQ(msg_out_row->kernel_kernel_value_out, 1); // value EXPECT_EQ(msg_out_row->kernel_kernel_side_effect_out, 2); EXPECT_EQ(msg_out_row->kernel_kernel_metadata_out, 1); // exists - feed_output(AvmKernelTraceBuilder::START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET, 1, 2, 1); + feed_output(START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET, 1, 2, 1); validate_trace(std::move(trace), public_inputs); } @@ -2205,13 +2218,18 @@ TEST_F(AvmExecutionTests, opCallOpcodes) std::vector returndata = {}; // Generate Hint for call operation - auto execution_hints = ExecutionHints().with_externalcall_hints( - { { .success = 1, .return_data = { 9, 8 }, .l2_gas_used = 0, .da_gas_used = 0 } }); + auto execution_hints = ExecutionHints().with_externalcall_hints({ { + .success = 1, + .return_data = { 9, 8 }, + .l2_gas_used = 0, + .da_gas_used = 0, + .end_side_effect_counter = 0, + } }); auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 9, 8, 1 })); // The 1 represents the success - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) @@ -2250,7 +2268,7 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcodes) auto trace = Execution::gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); EXPECT_EQ(returndata, std::vector({ 1, 2, 3, 4, 5, 6 })); // The first one represents true - validate_trace(std::move(trace), public_inputs); + validate_trace(std::move(trace), public_inputs, calldata); } // Negative test detecting an invalid opcode byte. TEST_F(AvmExecutionTests, invalidOpcode) diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp index 2666bb40e018..8cd841fa0713 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_gas.test.cpp @@ -61,7 +61,7 @@ TEST_F(AvmGasPositiveTests, gasAdd) auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { // trace_builder.set() trace_builder.op_add(0, 1, 2, 3, AvmMemoryTag::FF); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); }; auto checks = [=](const std::vector& trace) { diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp index f45924769244..47e82b751023 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_indirect_mem.test.cpp @@ -41,7 +41,7 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) // All indirect flags are encoded as 7 = 1 + 2 + 4 trace_builder.op_add(7, 0, 1, 2, AvmMemoryTag::U16); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -68,7 +68,7 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) EXPECT_EQ(row->main_sel_mem_op_b, FF(1)); EXPECT_EQ(row->main_sel_mem_op_c, FF(1)); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } // Testing a subtraction operation with direct input operands a, b, and an indirect @@ -87,7 +87,7 @@ TEST_F(AvmIndirectMemTests, indirectOutputSub) // The indirect flag is encoded as 4 trace_builder.op_sub(4, 50, 51, 5, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -133,7 +133,7 @@ TEST_F(AvmIndirectMemTests, indirectInputAMul) // The indirect flag is encoded as 1 trace_builder.op_mul(1, 1000, 101, 102, AvmMemoryTag::U64); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp index 098dbb0c181c..400d0a480b4c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_inter_table.test.cpp @@ -57,7 +57,7 @@ class AvmPermMainAluNegativeTests : public AvmInterTableTests { trace_builder.op_add(0, 0, 1, 1, AvmMemoryTag::U64); // 19 + 15 = 34 trace_builder.op_add(0, 0, 1, 1, AvmMemoryTag::U64); // 19 + 34 = 53 trace_builder.op_mul(0, 0, 1, 2, AvmMemoryTag::U64); // 19 * 53 = 1007 - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); @@ -152,7 +152,7 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2, tag); // 7 + 8 = 15 - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(min_trace_size); // Find the row with addition operation and retrieve clk. @@ -401,7 +401,7 @@ class AvmPermMainMemNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 52, AvmMemoryTag::U8); trace_builder.op_set(0, b, 11, AvmMemoryTag::U8); trace_builder.op_sub(0, 52, 11, 55, AvmMemoryTag::U8); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp index 786902dc1105..3800b76da221 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_kernel.test.cpp @@ -11,6 +11,8 @@ namespace tests_avm { using namespace bb; using namespace bb::avm_trace; +auto const BAD_LOOKUP = "LOOKUP_INTO_KERNEL"; + class AvmKernelTests : public ::testing::Test { protected: // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. @@ -280,6 +282,42 @@ TEST_F(AvmKernelPositiveTests, kernelStorageAddress) test_kernel_lookup(true, indirect_apply_opcodes, checks); } +TEST_F(AvmKernelPositiveTests, kernelFunctionSelector) +{ + // Direct + uint32_t dst_offset = 42; + uint32_t indirect_dst_offset = 69; + // We test that the function selector opcode is included at index 0 in the public inputs + auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_function_selector(/*indirect*/ false, dst_offset); + }; + auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_set( + /*indirect*/ false, + /*value*/ dst_offset, + /*dst_offset*/ indirect_dst_offset, + AvmMemoryTag::U32); + trace_builder.op_function_selector(/*indirect*/ true, indirect_dst_offset); + }; + + auto checks = [=](bool indirect, const std::vector& trace) { + auto row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == FF(1); }); + EXPECT_TRUE(row != trace.end()); + + expect_row(row, + /*kernel_in_offset=*/FUNCTION_SELECTOR_SELECTOR, + /*ia=*/FUNCTION_SELECTOR_SELECTOR + + 1, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect ? indirect_dst_offset : 0, + /*mem_addr_a=*/dst_offset, + /*w_in_tag=*/AvmMemoryTag::U32); + }; + + test_kernel_lookup(false, direct_apply_opcodes, checks); + test_kernel_lookup(true, indirect_apply_opcodes, checks); +} + TEST_F(AvmKernelPositiveTests, kernelFeePerDa) { uint32_t dst_offset = 42; @@ -578,10 +616,12 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, auto& ta = trace.at(1); ta.main_ia = incorrect_ia; + // memory trace should only have one row for these tests as well, so first row has looked-up val + ta.mem_val = incorrect_ia; check_trace(/*indirect*/ false, trace); - EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace), public_inputs), expected_message); + EXPECT_THROW_WITH_MESSAGE(validate_trace_check_circuit(std::move(trace)), expected_message); } TEST_F(AvmKernelNegativeTests, incorrectIaSender) @@ -607,7 +647,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaSender) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaAddress) @@ -633,7 +673,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaAddress) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaStorageAddress) @@ -659,7 +699,33 @@ TEST_F(AvmKernelNegativeTests, incorrectIaStorageAddress) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); +} + +TEST_F(AvmKernelNegativeTests, incorrectIaFunctionSelector) +{ + uint32_t dst_offset = 42; + FF incorrect_ia = FF(69); + + // We test that the sender opcode is inlcuded at index x in the public inputs + auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { + trace_builder.op_function_selector(/*indirect*/ false, dst_offset); + }; + auto checks = [=](bool indirect, const std::vector& trace) { + auto row = std::ranges::find_if( + trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_function_selector == FF(1); }); + EXPECT_TRUE(row != trace.end()); + + expect_row( + row, + /*kernel_in_offset=*/FUNCTION_SELECTOR_SELECTOR, + /*ia=*/incorrect_ia, // Note the value generated above for public inputs is the same as the index read + 1 + /*ind_a*/ indirect, + /*mem_addr_a=*/dst_offset, + /*w_in_tag=*/AvmMemoryTag::U32); + }; + + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaDaGas) @@ -685,7 +751,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaDaGas) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIal2Gas) @@ -711,7 +777,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIal2Gas) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaTransactionFee) @@ -737,7 +803,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTransactionFee) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaChainId) @@ -763,7 +829,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaChainId) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaVersion) @@ -789,7 +855,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaVersion) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaBlockNumber) @@ -815,7 +881,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaBlockNumber) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaTimestamp) @@ -841,7 +907,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaTimestamp) /*w_in_tag=*/AvmMemoryTag::U64); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } TEST_F(AvmKernelNegativeTests, incorrectIaCoinbase) @@ -867,7 +933,7 @@ TEST_F(AvmKernelNegativeTests, incorrectIaCoinbase) /*w_in_tag=*/AvmMemoryTag::FF); }; - negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, "PERM_MAIN_MEM_A"); + negative_test_incorrect_ia_kernel_lookup(apply_opcodes, checks, incorrect_ia, BAD_LOOKUP); } // KERNEL OUTPUTS @@ -880,7 +946,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNoteHash) uint32_t indirect_offset = 69; uint32_t value = 1234; - uint32_t output_offset = AvmKernelTraceBuilder::START_EMIT_NOTE_HASH_WRITE_OFFSET; + uint32_t output_offset = START_EMIT_NOTE_HASH_WRITE_OFFSET; // We write the note hash into memory auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { @@ -922,7 +988,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitNullifier) uint32_t indirect_offset = 69; uint32_t value = 1234; - uint32_t output_offset = AvmKernelTraceBuilder::START_EMIT_NULLIFIER_WRITE_OFFSET; + uint32_t output_offset = START_EMIT_NULLIFIER_WRITE_OFFSET; // We write the note hash into memory auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { @@ -970,7 +1036,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitL2ToL1Msg) uint32_t value = 1234; uint32_t recipient = 420; - uint32_t output_offset = AvmKernelTraceBuilder::START_L2_TO_L1_MSG_WRITE_OFFSET; + uint32_t output_offset = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET; // auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { // trace_builder.op_set(0, 1234, msg_offset, AvmMemoryTag::FF); @@ -1017,17 +1083,17 @@ TEST_F(AvmKernelOutputPositiveTests, kernelEmitUnencryptedLog) uint32_t indirect_offset = 69; uint32_t value = 1234; uint32_t slot = 0; - uint32_t output_offset = AvmKernelTraceBuilder::START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; + uint32_t output_offset = START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET; // We write the note hash into memory auto direct_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, 1234, direct_offset, AvmMemoryTag::FF); - trace_builder.op_emit_unencrypted_log(/*indirect=*/false, direct_offset); + trace_builder.op_emit_unencrypted_log(/*indirect=*/false, direct_offset, /*log_size_offset=*/0); }; auto indirect_apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, 1234, direct_offset, AvmMemoryTag::FF); trace_builder.op_set(0, direct_offset, indirect_offset, AvmMemoryTag::U32); - trace_builder.op_emit_unencrypted_log(/*indirect=*/true, indirect_offset); + trace_builder.op_emit_unencrypted_log(/*indirect=*/true, indirect_offset, /*log_size_offset=*/0); }; auto checks = [=](bool indirect, const std::vector& trace) { @@ -1060,7 +1126,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSload) uint32_t size = 1; uint32_t slot_offset = 420; auto slot = 12345; - uint32_t output_offset = AvmKernelTraceBuilder::START_SLOAD_WRITE_OFFSET; + uint32_t output_offset = START_SLOAD_WRITE_OFFSET; // Provide a hint for sload value slot auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, value } }); @@ -1103,7 +1169,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelSstore) auto slot = 12345; uint8_t indirect = 0; uint32_t size = 1; - uint32_t output_offset = AvmKernelTraceBuilder::START_SSTORE_WRITE_OFFSET; + uint32_t output_offset = START_SSTORE_WRITE_OFFSET; auto apply_opcodes = [=](AvmTraceBuilder& trace_builder) { trace_builder.op_set(0, static_cast(value), value_offset, AvmMemoryTag::FF); @@ -1145,7 +1211,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNoteHashExists) uint32_t metadata_offset = 420; uint32_t indirect_metadata_offset = 690; auto exists = 1; - uint32_t output_offset = AvmKernelTraceBuilder::START_NOTE_HASH_EXISTS_WRITE_OFFSET; + uint32_t output_offset = START_NOTE_HASH_EXISTS_WRITE_OFFSET; auto execution_hints = ExecutionHints().with_note_hash_exists_hints({ { 0, exists } }); @@ -1192,7 +1258,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierExists) auto value = 1234; uint32_t metadata_offset = 420; auto exists = 1; - uint32_t output_offset = AvmKernelTraceBuilder::START_NULLIFIER_EXISTS_OFFSET; + uint32_t output_offset = START_NULLIFIER_EXISTS_OFFSET; auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); @@ -1231,7 +1297,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelNullifierNonExists) auto value = 1234; uint32_t metadata_offset = 420; auto exists = 0; - uint32_t output_offset = AvmKernelTraceBuilder::START_NULLIFIER_NON_EXISTS_OFFSET; + uint32_t output_offset = START_NULLIFIER_NON_EXISTS_OFFSET; auto execution_hints = ExecutionHints().with_nullifier_exists_hints({ { 0, exists } }); @@ -1270,7 +1336,7 @@ TEST_F(AvmKernelOutputPositiveTests, kernelL1ToL2MsgExists) auto value = 1234; uint32_t metadata_offset = 420; auto exists = 1; - uint32_t output_offset = AvmKernelTraceBuilder::START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET; + uint32_t output_offset = START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET; // Create an execution hints object with the result of the operation auto execution_hints = ExecutionHints().with_l1_to_l2_message_exists_hints({ { 0, exists } }); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp index 71bfcbbe39e7..94157443a75f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_mem_opcodes.test.cpp @@ -56,7 +56,7 @@ class AvmMemOpcodeTests : public ::testing::Test { } trace_builder.op_mov(indirect ? 3 : 0, src_offset, dst_offset); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); } @@ -67,7 +67,7 @@ class AvmMemOpcodeTests : public ::testing::Test { trace_builder.op_set(0, mov_a ? 9871 : 0, 20, AvmMemoryTag::U64); // Non-zero/zero condition value (we move a/b) trace_builder.op_cmov(0, 10, 11, 20, 12); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(0); @@ -361,7 +361,7 @@ TEST_F(AvmMemOpcodeTests, uninitializedValueMov) { trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(0, 0, 1); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); validate_mov_trace(false, 0, 0, 1, AvmMemoryTag::U0); @@ -372,7 +372,7 @@ TEST_F(AvmMemOpcodeTests, indUninitializedValueMov) trace_builder.op_set(0, 1, 3, AvmMemoryTag::U32); trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(3, 2, 3); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::U0, 0, 1, true); @@ -390,7 +390,7 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) trace_builder.op_set(0, 16, 101, AvmMemoryTag::U128); // This will make the indirect load failing. trace_builder.op_set(0, 5, 15, AvmMemoryTag::FF); trace_builder.op_mov(3, 100, 101); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_mov_indices(true); @@ -402,7 +402,7 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) MEM_ROW_FIELD_EQ(r_in_tag, static_cast(AvmMemoryTag::U32)), MEM_ROW_FIELD_EQ(sel_resolve_ind_addr_c, 1))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, {}, true); } /****************************************************************************** @@ -417,7 +417,7 @@ TEST_F(AvmMemOpcodeTests, allDirectCMovA) trace_builder.op_set(0, 8, 12, AvmMemoryTag::U32); // Target, should be overwritten trace_builder.op_cmov(0, 10, 11, 20, 12); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(0); @@ -434,7 +434,7 @@ TEST_F(AvmMemOpcodeTests, allDirectCMovB) trace_builder.op_set(0, 8, 12, AvmMemoryTag::U32); // Target, should be overwritten trace_builder.op_cmov(0, 10, 11, 20, 12); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(0); @@ -451,7 +451,7 @@ TEST_F(AvmMemOpcodeTests, allDirectCMovConditionUninitialized) // value. It will be therefore zero. (we move b) trace_builder.op_cmov(0, 10, 11, 20, 12); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(0); @@ -467,7 +467,7 @@ TEST_F(AvmMemOpcodeTests, allDirectCMovOverwriteA) trace_builder.op_set(0, 0, 20, AvmMemoryTag::U64); // Zero condition value (we move b) trace_builder.op_cmov(0, 10, 11, 20, 10); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(0); @@ -494,7 +494,7 @@ TEST_F(AvmMemOpcodeTests, allIndirectCMovA) trace_builder.op_set(0, 8, 12, AvmMemoryTag::U32); // Target, should be overwritten trace_builder.op_cmov(15, 110, 111, 120, 112); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(15); @@ -506,7 +506,7 @@ TEST_F(AvmMemOpcodeTests, allIndirectCMovA) TEST_F(AvmMemOpcodeTests, allIndirectCMovAllUnitialized) { trace_builder.op_cmov(15, 10, 11, 20, 10); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_cmov_indices(15); @@ -521,7 +521,7 @@ TEST_F(AvmMemOpcodeTests, allIndirectCMovAllUnitialized) TEST_F(AvmMemOpcodeTests, directSet) { trace_builder.op_set(0, 5683, 99, AvmMemoryTag::U128); - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_index_c(1, false); @@ -549,7 +549,7 @@ TEST_F(AvmMemOpcodeTests, indirectSet) { trace_builder.op_set(0, 100, 10, AvmMemoryTag::U32); trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_index_c(2, true); @@ -589,7 +589,7 @@ TEST_F(AvmMemOpcodeTests, indirectSetWrongTag) { trace_builder.op_set(0, 100, 10, AvmMemoryTag::U8); // The address 100 has incorrect tag U8. trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.return_op(0, 0, 0); + trace_builder.op_return(0, 0, 0); trace = trace_builder.finalize(); compute_index_c(2, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp index 5dcfe52e0dfa..05a02bb3862f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/avm_memory.test.cpp @@ -36,7 +36,9 @@ class AvmMemoryTests : public ::testing::Test { // The proof must pass and we check that the AVM error is raised. TEST_F(AvmMemoryTests, mismatchedTagAddOperation) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + std::vector const calldata = { 98, 12 }; + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, calldata); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_add(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -75,7 +77,7 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) EXPECT_EQ(row->mem_r_in_tag, FF(static_cast(AvmMemoryTag::U8))); EXPECT_EQ(row->mem_tag, FF(static_cast(AvmMemoryTag::FF))); - validate_trace(std::move(trace), public_inputs, true); + validate_trace(std::move(trace), public_inputs, calldata, true); } // Testing an equality operation with a mismatched memory tag. @@ -161,7 +163,7 @@ TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] - trace_builder.return_op(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation @@ -191,7 +193,7 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2, AvmMemoryTag::U8); // [4,9,36,0,0,0.....] - trace_builder.return_op(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation @@ -216,7 +218,7 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Testing violation that a memory read at uninitialized location must have value 0. TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) { - trace_builder.return_op(0, 1, 1); // Return single memory word at position 1 + trace_builder.op_return(0, 1, 1); // Return single memory word at position 1 auto trace = trace_builder.finalize(); trace[1].mem_val = 9; @@ -228,7 +230,8 @@ TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) // must raise a VM error. TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 98, 12 }); + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 98, 12 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_sub(0, 0, 1, 4, AvmMemoryTag::U8); trace_builder.halt(); @@ -262,8 +265,8 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) // must not set a VM error. TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, std::vector{ 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); @@ -288,8 +291,8 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) // Testing violation that a write operation must not set a VM error. TEST_F(AvmMemoryTests, noErrorTagWriteViolation) { - trace_builder.calldata_copy(0, 0, 2, 0, std::vector{ 84, 7 }); - + trace_builder = AvmTraceBuilder(public_inputs, {}, 0, { 84, 7 }); + trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_fdiv(0, 0, 1, 4); trace_builder.halt(); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp index 1657ba8ce0db..d84f11226dec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.cpp @@ -23,9 +23,9 @@ std::vector gen_three_op_params(std::vector opera * * @param trace The execution trace */ -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs) +void validate_trace_check_circuit(std::vector&& trace) { - validate_trace(std::move(trace), public_inputs, false); + validate_trace(std::move(trace), {}, {}, false); }; /** @@ -34,7 +34,10 @@ void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs publi * * @param trace The execution trace */ -void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs, bool with_proof) +void validate_trace(std::vector&& trace, + VmPublicInputs const& public_inputs, + std::vector const& calldata, + bool with_proof) { auto circuit_builder = AvmCircuitBuilder(); circuit_builder.set_trace(std::move(trace)); @@ -47,7 +50,8 @@ void validate_trace(std::vector&& trace, VmPublicInputs const& public_input AvmVerifier verifier = composer.create_verifier(circuit_builder); - std::vector> public_inputs_as_vec = bb::avm_trace::copy_public_inputs_columns(public_inputs); + std::vector> public_inputs_as_vec = + bb::avm_trace::copy_public_inputs_columns(public_inputs, calldata); bool verified = verifier.verify_proof(proof, { public_inputs_as_vec }); diff --git a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp index 0dcf63815024..0640121b319d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/tests/helpers.test.hpp @@ -28,9 +28,10 @@ using VmPublicInputs = bb::avm_trace::VmPublicInputs; // If the test is expecting a relation to fail, then use validate_trace_check_circuit. // Otherwise, use validate_trace with a single argument. If the proving needs to be // enabled all the time in a given test, use validate_trace with setting with_proof = true. -void validate_trace_check_circuit(std::vector&& trace, VmPublicInputs public_inputs = {}); +void validate_trace_check_circuit(std::vector&& trace); void validate_trace(std::vector&& trace, VmPublicInputs const& public_inputs = {}, + std::vector const& calldata = {}, bool with_proof = bb::avm_trace::ENABLE_PROVING); void mutate_ic_in_trace(std::vector& trace, std::function&& selectRow, diff --git a/barretenberg/ts/CHANGELOG.md b/barretenberg/ts/CHANGELOG.md index b546c5f69fe1..ad1af151b023 100644 --- a/barretenberg/ts/CHANGELOG.md +++ b/barretenberg/ts/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [0.45.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.44.0...barretenberg.js-v0.45.0) (2024-07-02) + + +### Miscellaneous + +* **barretenberg.js:** Synchronize aztec-packages versions + +## [0.44.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.43.0...barretenberg.js-v0.44.0) (2024-06-26) + + +### Bug Fixes + +* False decryption fix ([#7066](https://github.com/AztecProtocol/aztec-packages/issues/7066)) ([48d9df4](https://github.com/AztecProtocol/aztec-packages/commit/48d9df4ff227c08a6e66f21c0286bc6349151671)) + ## [0.43.0](https://github.com/AztecProtocol/aztec-packages/compare/barretenberg.js-v0.42.0...barretenberg.js-v0.43.0) (2024-06-18) diff --git a/barretenberg/ts/package.json b/barretenberg/ts/package.json index 77f78d446a82..5bec49f0d074 100644 --- a/barretenberg/ts/package.json +++ b/barretenberg/ts/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/bb.js", - "version": "0.43.0", + "version": "0.45.0", "homepage": "https://github.com/AztecProtocol/aztec-packages/tree/master/barretenberg/ts", "license": "MIT", "type": "module", diff --git a/bb-pilcom/bb-pil-backend/src/prover_builder.rs b/bb-pilcom/bb-pil-backend/src/prover_builder.rs index ee129d6ca837..c0ea19709a52 100644 --- a/bb-pilcom/bb-pil-backend/src/prover_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/prover_builder.rs @@ -192,7 +192,8 @@ impl ProverBuilder for BBFiles { * */ void {name}Prover::execute_pcs_rounds() {{ - auto prover_opening_claim = ZeroMorph::prove(prover_polynomials.get_unshifted(), + auto prover_opening_claim = ZeroMorph::prove(key->circuit_size, + prover_polynomials.get_unshifted(), prover_polynomials.get_to_be_shifted(), sumcheck_output.claimed_evaluations.get_unshifted(), sumcheck_output.claimed_evaluations.get_shifted(), diff --git a/bb-pilcom/bb-pil-backend/src/relation_builder.rs b/bb-pilcom/bb-pil-backend/src/relation_builder.rs index cfae7c85092a..dcb15e54f4e2 100644 --- a/bb-pilcom/bb-pil-backend/src/relation_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/relation_builder.rs @@ -399,11 +399,22 @@ fn craft_expression( Expression::Number(_) => (degree, format!("({} + {})", rhs, lhs)), _ => (degree, format!("({} + {})", lhs, rhs)), }, - AlgebraicBinaryOperator::Sub => match lhe.as_ref() { - // BBerg hack, we do not want a field on the lhs of an expression - Expression::Number(_) => (degree, format!("(-{} + {})", rhs, lhs)), - _ => (degree, format!("({} - {})", lhs, rhs)), - }, + AlgebraicBinaryOperator::Sub => { + // BBerg hack here, to make sure we dont have a trivial (- FF(0)) + if let Expression::Number(rhe) = rhe.as_ref() { + // If the binary operation is a sub and the rhs expression is 0, we can just + // return the lhs + if rhe.to_arbitrary_integer() == 0u64.into() { + return (degree, lhs); + } + } + // Otherwise continue with the match + match lhe.as_ref() { + // BBerg hack, we do not want a field on the lhs of an expression + Expression::Number(_) => (degree, format!("(-{} + {})", rhs, lhs)), + _ => (degree, format!("({} - {})", lhs, rhs)), + } + } AlgebraicBinaryOperator::Mul => match lhe.as_ref() { // BBerg hack, we do not want a field on the lhs of an expression Expression::Number(_) => (ld + rd, format!("({} * {})", rhs, lhs)), diff --git a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs index ed93731b67fa..a10a7bea021f 100644 --- a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs @@ -56,7 +56,7 @@ impl VerifierBuilder for BBFiles { |public_inputs_column_name: &String, idx: usize| { format!( " - FF {public_inputs_column_name}_evaluation = evaluate_public_input_column(public_inputs[{idx}], circuit_size, multivariate_challenge); + FF {public_inputs_column_name}_evaluation = evaluate_public_input_column(public_inputs[{idx}], circuit_size, mle_challenge); if ({public_inputs_column_name}_evaluation != claimed_evaluations.{public_inputs_column_name}) {{ return false; }} @@ -178,6 +178,8 @@ impl VerifierBuilder for BBFiles { }} // Public columns evaluation checks + std::vector mle_challenge(multivariate_challenge.begin(), + multivariate_challenge.begin() + static_cast(log_circuit_size)); {public_inputs_check} // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index 8e574163eb54..ddf98a6fef89 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -6,7 +6,7 @@ "type": "module", "main": "./dist/index.js", "scripts": { - "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile --silence-warnings", + "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile --use-legacy --silence-warnings", "codegen": "${AZTEC_BUILDER:-aztec-builder} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dist .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen", diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index 045d0e976fa6..f590df2b6d39 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -5,7 +5,7 @@ "version": "0.1.0", "type": "module", "scripts": { - "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile --silence-warnings", + "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile --use-legacy --silence-warnings", "codegen": "${AZTEC_BUILDER:-aztec-builder} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", diff --git a/docs/docs/aztec/concepts/smart_contracts/functions/function_types_macros.md b/docs/docs/aztec/concepts/smart_contracts/functions/function_types_macros.md deleted file mode 100644 index 144abb2be2d5..000000000000 --- a/docs/docs/aztec/concepts/smart_contracts/functions/function_types_macros.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Function Macros -sidebar_position: 2 -tags: [functions, macros] ---- - -This page explains three types of functions that exist on Aztec - public, private, and unconstrained; as well as all macros. - -## All Aztec macros - -In addition to the function macros in Noir, Aztec also has its own macros for specific functions. An Aztec contract function can be annotated with more than 1 macro. -It is also worth mentioning Noir's `unconstrained` function type [here](https://noir-lang.org/docs/noir/concepts/unconstrained/). - -- `#[aztec(public)]` or `#[aztec(private)]` - Whether the function is public or private (more in next section) -- `#[aztec(initializer)]` - If one or more functions are marked as an initializer, then one of them must be called before any non-initilizer functions -- `#[aztec(noinitcheck)]` - The function is able to be called before an initializer (if one exists) -- `#[aztec(view)]` - Makes calls to the function static (see also [Static calls](../../../../protocol-specs/calls/static-calls)) -- `#[aztec(internal)]` - Function can only be called from within the contract - -## Example - -See [Private token contract](./../../../../tutorials/contract_tutorials/token_contract.md). - -# Public, Private, and unconstrained types - -For a deeper dive into how some of these functions work under the hood, check out the [Inner Workings](./inner_workings.md) page. - -## `Public` Functions - -A public function is executed by the sequencer and has access to a state model that is very similar to that of the EVM and Ethereum. Even though they work in an EVM-like model for public transactions, they are able to write data into private storage that can be consumed later by a private function. - -:::note -All data inserted into private storage from a public function will be publicly viewable (not private). -::: - -To create a public function you can annotate it with the `#[aztec(public)]` attribute. This will make the [public context](./context.md) available within the function's execution scope. - -#include_code set_minter /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -## `Private` Functions - -A private function operates on private information, and is executed by the user. Annotate the function with the `#[aztec(private)]` attribute to tell the compiler it's a private function. This will make the [private context](./context.md#the-private-context) available within the function's execution scope. - -#include_code redeem_shield /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -## `unconstrained` functions - -Unconstrained functions are an underlying part of Noir. In short, they are functions which are not directly constrained and therefore should be seen as un-trusted. That they are un-trusted means that the developer must make sure to constrain their return values when used. Note: Calling an unconstrained function from a private function means that you are injecting unconstrained values. - -Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. - -#include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - -:::info -Note, that unconstrained functions can have access to both public and private data when executed on the user's device. This is possible since it is not actually part of the circuits that are executed in contract execution. -::: diff --git a/docs/docs/aztec/concepts/smart_contracts/functions/index.md b/docs/docs/aztec/concepts/smart_contracts/functions/index.md index 4c181e199b40..edc475c13d03 100644 --- a/docs/docs/aztec/concepts/smart_contracts/functions/index.md +++ b/docs/docs/aztec/concepts/smart_contracts/functions/index.md @@ -18,11 +18,12 @@ Initializers are regular functions that set an "initialized" flag (a nullifier) There are also special oracle functions, which can get data from outside of the smart contract. In the context of Aztec, oracles are often used to get user-provided inputs. -Explore this section to learn: +## Learn more about functions - [How function visibility works in Aztec](./visibility.md) -- [Function types and Macros](./function_types_macros.md), and how to write them - How to write an [initializer function](../../../../guides/smart_contracts/writing_contracts/initializers.md) - [Calling functions from within the same smart contract and from different contracts](../../../../guides/smart_contracts/writing_contracts/call_functions.md), including calling private functions from private functions, public from public, and even private from public - [Oracles](../oracles/index.md) and how Aztec smart contracts might use them - [How functions work under the hood](./inner_workings.md) + +Find a function macros reference [here](../../../../reference/smart_contract_reference/macros.md). \ No newline at end of file diff --git a/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md b/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md index 4a46590ad2a5..8b01fa450622 100644 --- a/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md +++ b/docs/docs/aztec/concepts/smart_contracts/functions/inner_workings.md @@ -1,14 +1,16 @@ --- -title: Inner Workings of Functions +title: Inner Workings of Functions and Macros sidebar_position: 3 tags: [functions] --- Below, we go more into depth of what is happening under the hood when you create a function in an Aztec contract and what the attributes are really doing. -## Private functions +If you are looking for a reference of function macros, go [here](../../../../reference/smart_contract_reference/macros.md). -Aztec.nr uses an attribute system to annotate a function's type. Annotating a function with the `#[aztec(private)]` attribute tells the framework that this is a private function that will be executed on a users device. The compiler will create a circuit to define this function. +## Private functions #[aztec(private)] + +A private function operates on private information, and is executed by the user on their device. Annotate the function with the `#[aztec(private)]` attribute to tell the compiler it's a private function. This will make the [private context](./context.md#the-private-context) available within the function's execution scope. The compiler will create a circuit to define this function. `#aztec(private)` is just syntactic sugar. At compile time, the Aztec.nr framework inserts code that allows the function to interact with the [kernel](../../circuits/kernels/private_kernel.md). @@ -22,7 +24,7 @@ To help illustrate how this interacts with the internals of Aztec and its kernel #include_code simple_macro_example_expanded /noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr rust -#### The expansion broken down? +#### The expansion broken down Viewing the expanded Aztec contract uncovers a lot about how Aztec contracts interact with the [kernel](../../circuits/kernels/private_kernel.md). To aid with developing intuition, we will break down each inserted line. @@ -75,6 +77,8 @@ This function takes the application context, and converts it into the `PrivateCi ## Unconstrained functions +Unconstrained functions are an underlying part of Noir. In short, they are functions which are not directly constrained and therefore should be seen as un-trusted. That they are un-trusted means that the developer must make sure to constrain their return values when used. Note: Calling an unconstrained function from a private function means that you are injecting unconstrained values. + Defining a function as `unconstrained` tells Aztec to simulate it completely client-side in the [ACIR simulator](../../pxe/acir_simulator.md) without generating proofs. They are useful for extracting information from a user through an [oracle](../oracles). When an unconstrained function is called, it prompts the ACIR simulator to @@ -94,3 +98,269 @@ This: 2. Converts `args` into a format suitable for the ACVM (Abstract Circuit Virtual Machine), creating an initial witness (witness = set of inputs required to compute the function). `args` might be an oracle to request a user's balance 3. Executes the function in the ACVM, which involves running the ACIR with the initial witness and the context. If requesting a user's balance, this would query the balance from the PXE database 4. Extracts the return values from the `partialWitness` and decodes them based on the artifact to get the final function output. The [artifact](../../../../reference/smart_contract_reference/contract_artifact.md) is the compiled output of the contract, and has information like the function signature, parameter types, and return types + +Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. + +#include_code balance_of_private /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust + +:::info +Note, that unconstrained functions can have access to both public and private data when executed on the user's device. This is possible since it is not actually part of the circuits that are executed in contract execution. +::: + +## `Public` Functions #[aztec(public)] + +A public function is executed by the sequencer and has access to a state model that is very similar to that of the EVM and Ethereum. Even though they work in an EVM-like model for public transactions, they are able to write data into private storage that can be consumed later by a private function. + +:::note +All data inserted into private storage from a public function will be publicly viewable (not private). +::: + +To create a public function you can annotate it with the `#[aztec(public)]` attribute. This will make the [public context](./context.md) available within the function's execution scope. + +#include_code set_minter /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust + +Under the hood: + +- Context Creation: The macro inserts code at the beginning of the function to create a`PublicContext` object: +```rust +let mut context = PublicContext::new(inputs); +``` +This context provides access to public state and transaction information +- Function Signature Modification: The macro modifies the function signature to include a `PublicContextInputs` parameter: +```rust +fn function_name(inputs: PublicContextInputs, ...other_params) -> ReturnType +``` +- Return Type Transformation: For functions that return a value, the macro wraps the return type in a `PublicCircuitPublicInputs` struct: +```rust +-> protocol_types::abis::public_circuit_public_inputs::PublicCircuitPublicInputs +``` +- Storage Access: If the contract has a storage struct defined, the macro inserts code to initialize the storage: +```rust +let storage = Storage::init(&mut context); +``` +- Function Body Wrapping: The original function body is wrapped in a new scope that handles the context and return value +- Visibility Control: The function is marked as pub, making it accessible from outside the contract. +- Unconstrained Execution: Public functions are marked as unconstrained, meaning they don't generate proofs and are executed directly by the sequencer. + +## Constrained `view` Functions #[aztec(view)] + +The `#[aztec(view)]` attribute is used to define constrained view functions in Aztec contracts. These functions are similar to view functions in Solidity, in that they are read-only and do not modify the contract's state. They are similar to the [`unconstrained`](#unconstrained-functions-aztecunconstrained) keyword but are executed in a constrained environment. It is not possible to update state within an `#[aztec(view)]` function. + +This means the results of these functions are verifiable and can be trusted, as they are part of the proof generation and verification process. This is unlike unconstrained functions, where results are provided by the PXE and are not verified. + +This makes `#[aztec(view)]` functions suitable for critical read-only operations where the integrity of the result is crucial. Unconstrained functions, on the other hand, are executed entirely client-side without generating any proofs. It is better to use `#[aztec(view)]` if the result of the function will be used in another function that will affect state, and they can be used for cross-contract calls. + +`#[aztec(view)]` functions can be combined with other Aztec attributes like `#[aztec(private)]` or `#[aztec(public)]`. + +## `Initializer` Functions #[aztec(initializer)] + +This is used to designate functions as initializers (or constructors) for an Aztec contract. These functions are responsible for setting up the initial state of the contract when it is first deployed. The macro does two important things: + +- `assert_initialization_matches_address_preimage(context)`: This checks that the arguments and sender to the initializer match the commitments from the address preimage +- `mark_as_initialized(&mut context)`: This is called at the end of the function to emit the initialization nullifier, marking the contract as fully initialized and ensuring this function cannot be called again + +Key things to keep in mind: + +- A contract can have multiple initializer functions defined, but only one initializer function should be called for the lifetime of a contract instance +- Other functions in the contract will have an initialization check inserted, ie they cannot be called until the contract is initialized, unless they are marked with [`#[aztec(noinitcheck)])`](#aztecnoinitcheck) + +## #[aztec(noinitcheck)] + +In normal circumstances, all functions in an Aztec contract (except initializers) have an initialization check inserted at the beginning of the function body. This check ensures that the contract has been initialized before any other function can be called. However, there may be scenarios where you want a function to be callable regardless of the contract's initialization state. This is when you would use `#[aztec(noinitcheck)]`. + +When a function is annotated with `#[aztec(noinitcheck)]`: + +- The Aztec macro processor skips the [insertion of the initialization check](#initializer-functions-aztecinitializer) for this specific function +- The function can be called at any time, even if the contract hasn't been initialized yet + +## `Internal` functions #[aztec(internal)] + +This macro inserts a check at the beginning of the function to ensure that the caller is the contract itself. This is done by adding the following assertion: + +```rust +assert(context.msg_sender() == context.this_address(), "Function can only be called internally"); +``` + +## Custom notes #[aztec(note)] + +The `#[aztec(note)]` attribute is used to define custom note types in Aztec contracts. Learn more about notes [here](../../../concepts/storage/index.md). + +When a struct is annotated with `#[aztec(note)]`, the Aztec macro applies a series of transformations and generates implementations to turn it into a note that can be used in contracts to store private data. + +1. **NoteInterface Implementation**: The macro automatically implements most methods of the `NoteInterface` trait for the annotated struct. This includes: + + - `serialize_content` and `deserialize_content` + - `get_header` and `set_header` + - `get_note_type_id` + - `compute_note_content_hash` + - `to_be_bytes` + - A `properties` method in the note's implementation + +2. **Automatic Header Field**: If the struct doesn't already have a `header` field of type `NoteHeader`, one is automatically created + +3. **Note Type ID Generation**: A unique `note_type_id` is automatically computed for the note type using a Keccak hash of the struct name + +4. **Serialization and Deserialization**: Methods for converting the note to and from a series of `Field` elements are generated, assuming each field can be converted to/from a `Field` + +5. **Property Metadata**: A separate struct is generated to describe the note's fields, which is used for efficient retrieval of note data + +6. **Export Information**: The note type and its ID are automatically exported + + +### Before expansion + +Here is how you could define a custom note: + +```rust +#[aztec(note)] +struct CustomNote { + data: Field, + owner: Address, +} +``` + +### After expansaion + +```rust +impl CustomNote { + fn serialize_content(self: CustomNote) -> [Field; NOTE_SERIALIZED_LEN] { + [self.data, self.owner.to_field()] + } + + fn deserialize_content(serialized_note: [Field; NOTE_SERIALIZED_LEN]) -> Self { + CustomNote { + data: serialized_note[0] as Field, + owner: Address::from_field(serialized_note[1]), + header: NoteHeader::empty() + } + } + + fn get_note_type_id() -> Field { + // Automatically generated unique ID based on Keccak hash of the struct name + 0xd2de93eaab1d59abddf06134e737665f076f556feb7b6d3d72ca557b430b14d2 + } + + fn get_header(note: CustomNote) -> aztec::note::note_header::NoteHeader { + note.header + } + + fn set_header(self: &mut CustomNote, header: aztec::note::note_header::NoteHeader) { + self.header = header; + } + + fn compute_note_content_hash(self: CustomNote) -> Field { + aztec::hash::pedersen_hash( + self.serialize_content(), + aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH + ) + } + + fn to_be_bytes(self, storage_slot: Field) -> [u8; 128] { + assert(128 == 2 * 32 + 64, "Note byte length must be equal to (serialized_length * 32) + 64 bytes"); + let serialized_note = self.serialize_content(); + + let mut buffer: [u8; 128] = [0; 128]; + + let storage_slot_bytes = storage_slot.to_be_bytes(32); + let note_type_id_bytes = CustomNote::get_note_type_id().to_be_bytes(32); + + for i in 0..32 { + buffer[i] = storage_slot_bytes[i]; + buffer[32 + i] = note_type_id_bytes[i]; + } + + for i in 0..serialized_note.len() { + let bytes = serialized_note[i].to_be_bytes(32); + for j in 0..32 { + buffer[64 + i * 32 + j] = bytes[j]; + } + } + buffer + } + + pub fn properties() -> CustomNoteProperties { + CustomNoteProperties { + data: aztec::note::note_getter_options::PropertySelector { index: 0, offset: 0, length: 32 }, + owner: aztec::note::note_getter_options::PropertySelector { index: 1, offset: 0, length: 32 } + } + } +} + +struct CustomNoteProperties { + data: aztec::note::note_getter_options::PropertySelector, + owner: aztec::note::note_getter_options::PropertySelector, +} +``` +Key things to keep in mind: + +- Developers can override any of the auto-generated methods by specifying a note interface +- The note's fields are automatically serialized and deserialized in the order they are defined in the struct + +## Storage struct #[aztec(storage)] + +The `#[aztec(storage)]` attribute is used to define the storage structure for an Aztec contract. + +When a struct is annotated with `#[aztec(storage)]`, the macro does this under the hood: + +1. **Context Injection**: injects a `Context` generic parameter into the storage struct and all its fields. This allows the storage to interact with the Aztec context, eg when using `context.msg_sender()` + +2. **Storage Implementation Generation**: generates an `impl` block for the storage struct with an `init` function. The developer can override this by implementing a `impl` block themselves + +3. **Storage Slot Assignment**: automatically assigns storage slots to each field in the struct based on their serialized length + +4. **Storage Layout Generation**: a `StorageLayout` struct and a global variable are generated to export the storage layout information for use in the contract artifact + +### Before expansion + +```rust +#[aztec(storage)] +struct Storage { + balance: PublicMutable, + owner: PublicMutable
, + token_map: Map, +} +``` + +### After expansion + +```rust +struct Storage { + balance: PublicMutable, + owner: PublicMutable, + token_map: Map, +} + +impl Storage { + fn init(context: Context) -> Self { + Storage { + balance: PublicMutable::new(context, 1), + owner: PublicMutable::new(context, 2), + token_map: Map::new(context, 3, |context, slot| Field::new(context, slot)), + } + } +} + +struct StorageLayout { + balance: dep::aztec::prelude::Storable, + owner: dep::aztec::prelude::Storable, + token_map: dep::aztec::prelude::Storable, +} + +#[abi(storage)] +global CONTRACT_NAME_STORAGE_LAYOUT = StorageLayout { + balance: dep::aztec::prelude::Storable { slot: 1 }, + owner: dep::aztec::prelude::Storable { slot: 2 }, + token_map: dep::aztec::prelude::Storable { slot: 3 }, +}; +``` + +Key things to keep in mind: + +- Only one storage struct can be defined per contract +- `Map` types and private `Note` types always occupy a single storage slot + +## Further reading +- [How do macros work](./inner_workings.md) +- [Macros reference](../../../../reference/smart_contract_reference/macros.md) + + diff --git a/docs/docs/aztec/concepts/smart_contracts/oracles/index.md b/docs/docs/aztec/concepts/smart_contracts/oracles/index.md index f21cacc1a73e..fd36f37b7066 100644 --- a/docs/docs/aztec/concepts/smart_contracts/oracles/index.md +++ b/docs/docs/aztec/concepts/smart_contracts/oracles/index.md @@ -18,7 +18,7 @@ If we fetch the notes using an oracle call, we can keep the function signature i Oracles introduce **non-determinism** into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise, the circuit will be **under-constrained** and potentially insecure! `Aztec.nr` has a module dedicated to its oracles. If you are interested, you can view them by following the link below: -#include_code oracles-module /noir-projects/aztec-nr/aztec/src/oracle.nr rust +#include_code oracles-module /noir-projects/aztec-nr/aztec/src/oracle/mod.nr rust ## Inbuilt oracles diff --git a/docs/docs/guides/js_apps/authwit.md b/docs/docs/guides/js_apps/authwit.md index 76a3f404dee6..702a8a29bb4e 100644 --- a/docs/docs/guides/js_apps/authwit.md +++ b/docs/docs/guides/js_apps/authwit.md @@ -15,7 +15,6 @@ These are all the libraries you might need for using authwits in Aztec.js: import { computeAuthWitMessageHash, computeInnerAuthWitHash, - computeOuterAuthWitHash, } from "@aztec/aztec.js"; ``` @@ -63,9 +62,9 @@ You can hash your own authwit message by creating an inner hash with the data, l #include_code compute_inner_authwit_hash yarn-project/end-to-end/src/e2e_authwit.test.ts typescript -Then create the outer hash by hashing the inner hash with the authwit receiver address, chainId, and version: +Then create the message hash by hashing the inner hash with the authwit receiver address, chainId, and version: -#include_code compute_outer_authwit_hash yarn-project/end-to-end/src/e2e_authwit.test.ts typescript +#include_code compute_arbitrary_authwit_hash yarn-project/end-to-end/src/e2e_authwit.test.ts typescript ## Create the authwit @@ -89,9 +88,9 @@ In this example, - `wallets[1]` is the authwit reciever and caller of the function - `action` was [defined previously](#define-the-action) -If you created an artbitrary message, you can create the authwit by replacing these params with the outer hash: +If you created an arbitrary message, you can create the authwit by replacing these params with the outer hash: -#include_code compute_outer_authwit_hash yarn-project/end-to-end/src/e2e_authwit.test.ts typescript +#include_code compute_arbitrary_authwit_hash yarn-project/end-to-end/src/e2e_authwit.test.ts typescript Then add it to the wallet of the authwit receiver (the caller of the function): diff --git a/docs/docs/guides/smart_contracts/writing_contracts/authwit.md b/docs/docs/guides/smart_contracts/writing_contracts/authwit.md index 8f74c3bf3409..b3a1e9689230 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/authwit.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/authwit.md @@ -91,7 +91,7 @@ For our purposes here (not building a wallet), the most important part of the li ### General utilities -The primary general utility is the `compute_call_authwit_hash` function which computes the action hash from its components. This is useful for when you need to generate a hash that is not for the current call, such as when you want to update a public approval state value that is later used for [authentication in public](#updating-approval-state-in-noir). You can view the implementation of this function [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/authwit/src/auth.nr). +The primary general utility is the `compute_authwit_message_hash_from_call` function which computes the action hash from its components. This is useful for when you need to generate a hash that is not for the current call, such as when you want to update a public approval state value that is later used for [authentication in public](#updating-approval-state-in-noir). You can view the implementation of this function [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/authwit/src/auth.nr). #### TypeScript utilities @@ -174,7 +174,7 @@ In the snippet below, this is done as a separate contract call, but can also be We have cases where we need a non-wallet contract to approve an action to be executed by another contract. One of the cases could be when making more complex defi where funds are passed along. When doing so, we need the intermediate contracts to support approving of actions on their behalf. -This is fairly straight forward to do using the `auth` library which include logic for updating values in the public auth registry. Namely, you can prepare the `message_hash` using `compute_call_authwit_hash` and then simply feed it into the `set_authorized` function (both are in `auth` library) to update the value. +This is fairly straight forward to do using the `auth` library which includes logic for updating values in the public auth registry. Namely, you can prepare the `message_hash` using `compute_authwit_message_hash_from_call` and then simply feed it into the `set_authorized` function (both are in `auth` library) to update the value. When another contract later is consuming the authwit using `assert_current_call_valid_authwit_public` it will be calling the registry, and spend that authwit. diff --git a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md index a21af4811c89..6c40b6a681b9 100644 --- a/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md +++ b/docs/docs/guides/smart_contracts/writing_contracts/storage/storage_slots.md @@ -35,7 +35,7 @@ sequenceDiagram TokenNote->>Utils: note_hash = H(amount, to, randomness) Utils->>NoteHash: compute_inner_hash(derived_slot, note_hash) NoteHash->>LifeCycle: inner_note_hash = H(derived_slot, note_hash) - LifeCycle->>Context: push_new_note_hash(inner_note_hash) + LifeCycle->>Context: push_note_hash(inner_note_hash) end Context->>Kernel: siloed_note_hash = H(contract_address, inner_note_hash) ``` diff --git a/docs/docs/migration_notes.md b/docs/docs/migration_notes.md index e9e1abb4d167..af8d0bfcb2c3 100644 --- a/docs/docs/migration_notes.md +++ b/docs/docs/migration_notes.md @@ -6,6 +6,10 @@ keywords: [sandbox, aztec, notes, migration, updating, upgrading] Aztec is in full-speed development. Literally every version breaks compatibility with the previous ones. This page attempts to target errors and difficulties you might encounter when upgrading, and how to resolve them. +## 0.45.0 +### [Aztec.nr] Remove unencrypted logs from private +They leak privacy so is a footgun! + ## 0.44.0 ### [Aztec.nr] Autogenerate Serialize methods for events ```diff @@ -136,7 +140,7 @@ const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionSelector.toField(), - new Fr(this.version), - innerHash, -); -+const outerHash = computeAuthWitMessageHash( ++const messageHash = computeAuthWitMessageHash( + { consumer: this.dappEntrypointAddress, innerHash }, + { chainId: new Fr(this.chainId), version: new Fr(this.version) }, +); diff --git a/docs/docs/protocol-specs/circuits/private-function.md b/docs/docs/protocol-specs/circuits/private-function.md index d137504d2271..3beae7c57b43 100644 --- a/docs/docs/protocol-specs/circuits/private-function.md +++ b/docs/docs/protocol-specs/circuits/private-function.md @@ -43,9 +43,9 @@ The public inputs of _every_ private function _must_ adhere to the following ABI | `call_context` | [`CallContext`](#callcontext) | Context of the call corresponding to this function execution. | | `args_hash` | `field` | Hash of the function arguments. | | `return_values` | [`field`; [`RETURN_VALUES_LENGTH`](../constants.md#circuit-constants)] | Return values of this function call. | -| `note_hashes` | [[`NoteHash`](#notehash); [`MAX_NEW_NOTE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | New note hashes created in this function call. | -| `nullifiers` | [[`Nullifier`](#nullifier); [`MAX_NEW_NULLIFIERS_PER_CALL`](../constants.md#circuit-constants)] | New nullifiers created in this function call. | -| `l2_to_l1_messages` | [[`L2toL1Message`](#l2tol1message); [`MAX_NEW_L2_TO_L1_MSGS_PER_CALL`](../constants.md#circuit-constants)] | New L2 to L1 messages created in this function call. | +| `note_hashes` | [[`NoteHash`](#notehash); [`MAX_NOTE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | New note hashes created in this function call. | +| `nullifiers` | [[`Nullifier`](#nullifier); [`MAX_NULLIFIERS_PER_CALL`](../constants.md#circuit-constants)] | New nullifiers created in this function call. | +| `l2_to_l1_messages` | [[`L2toL1Message`](#l2tol1message); [`MAX_L2_TO_L1_MSGS_PER_CALL`](../constants.md#circuit-constants)] | New L2 to L1 messages created in this function call. | | `unencrypted_log_hashes` | [[`UnencryptedLogHash`](#unencryptedloghash); [`MAX_UNENCRYPTED_LOG_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Hashes of the unencrypted logs emitted in this function call. | | `encrypted_log_hashes` | [[`EncryptedLogHash`](#encryptedloghash); [`MAX_ENCRYPTED_LOG_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Hashes of the encrypted logs emitted in this function call. | | `encrypted_note_preimage_hashes` | [[`EncryptedNotePreimageHash`](#encryptednotepreimagehash); [`MAX_ENCRYPTED_NOTE_PREIMAGE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Hashes of the encrypted note preimages emitted in this function call. | diff --git a/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx b/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx index a7e2fde94a53..74919b877b32 100644 --- a/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx +++ b/docs/docs/protocol-specs/circuits/private-kernel-initial.mdx @@ -737,8 +737,8 @@ Data that holds details about the current private function call. | Field | Type | Description | | ----------------------------- | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | -| `note_hash_range_hints` | [`field`, [`MAX_NEW_NOTE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for note hashes. | -| `nullifier_range_hints` | [`field`, [`MAX_NEW_NULLIFIERS_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for nullifiers. | +| `note_hash_range_hints` | [`field`, [`MAX_NOTE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for note hashes. | +| `nullifier_range_hints` | [`field`, [`MAX_NULLIFIERS_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for nullifiers. | | `unencrypted_log_range_hints` | [`field`, [`MAX_UNENCRYPTED_LOG_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for unencrypted logs. | | `encrypted_log_range_hints` | [`field`, [`MAX_ENCRYPTED_LOG_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for encrypted logs. | | `encrypted_note_range_hints` | [`field`, [`MAX_ENCRYPTED_NOTE_PREIMAGE_HASHES_PER_CALL`](../constants.md#circuit-constants)] | Indices of the next emitted private call requests for encrypted notes. | @@ -768,9 +768,9 @@ Would it be accurate to describe this as `AccumulatedTransientSideEffects`, perh | Field | Type | Description | | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -| `note_hash_contexts` | [[`NoteHashContext`](#notehashcontext); [`MAX_NEW_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Note hashes with extra data aiding verification. | -| `nullifier_contexts` | [[`NullifierContext`](#nullifiercontext); [`MAX_NEW_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Nullifiers with extra data aiding verification. | -| `l2_to_l1_message_contexts` | [[`L2toL1MessageContext`](#l2tol1messagecontext); [`MAX_NEW_L2_TO_L1_MSGS_PER_TX`](../constants.md#circuit-constants)] | L2-to-l1 messages with extra data aiding verification. | +| `note_hash_contexts` | [[`NoteHashContext`](#notehashcontext); [`MAX_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Note hashes with extra data aiding verification. | +| `nullifier_contexts` | [[`NullifierContext`](#nullifiercontext); [`MAX_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Nullifiers with extra data aiding verification. | +| `l2_to_l1_message_contexts` | [[`L2toL1MessageContext`](#l2tol1messagecontext); [`MAX_L2_TO_L1_MSGS_PER_TX`](../constants.md#circuit-constants)] | L2-to-l1 messages with extra data aiding verification. | | `unencrypted_log_hash_contexts` | [[`UnencryptedLogHashContext`](#unencryptedloghashcontext); [`MAX_UNENCRYPTED_LOG_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hashes of the unencrypted logs with extra data aiding verification. | | `encrypted_log_hash_contexts` | [[`EncryptedLogHashContext`](#encryptedloghashcontext); [`MAX_ENCRYPTED_LOG_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hashes of the encrypted logs with extra data aiding verification. | | `encrypted_note_preimage_hash_contexts` | [[`EncryptedNotePreimageHashContext`](#encryptednotepreimagehash); [`MAX_ENCRYPTED_NOTE_PREIMAGE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hashes of the encrypted note preimages with extra data aiding verification. | diff --git a/docs/docs/protocol-specs/circuits/private-kernel-reset.md b/docs/docs/protocol-specs/circuits/private-kernel-reset.md index 01b374e88b99..0b06176d7d90 100644 --- a/docs/docs/protocol-specs/circuits/private-kernel-reset.md +++ b/docs/docs/protocol-specs/circuits/private-kernel-reset.md @@ -243,10 +243,10 @@ The format aligns with the [`PreviousKernel`](./private-kernel-inner#previousker | Field | Type | Description | | ------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -| `transient_nullifier_indices` | [`field`; [`MAX_NEW_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Indices of the nullifiers for transient notes. | -| `nullifier_index_hints` | [`field`; [`MAX_NEW_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Indices of the `transient_nullifier_indices` for transient nullifiers. | +| `transient_nullifier_indices` | [`field`; [`MAX_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Indices of the nullifiers for transient notes. | +| `nullifier_index_hints` | [`field`; [`MAX_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Indices of the `transient_nullifier_indices` for transient nullifiers. | | `encrypted_note_preimage_hash_index_hints` | [`field`; [`MAX_ENCRYPTED_NOTE_PREIMAGE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Indices of the `encrypted_note_preimage_hash_contexts` for transient preimage hashes. | -| `log_note_hash_hints` | [`field`; [`MAX_NEW_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Indices of the `note_hash_contexts` for transient preimage hashes. | +| `log_note_hash_hints` | [`field`; [`MAX_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Indices of the `note_hash_contexts` for transient preimage hashes. | ## `PublicInputs` diff --git a/docs/docs/protocol-specs/circuits/private-kernel-tail.md b/docs/docs/protocol-specs/circuits/private-kernel-tail.md index dc842b8994a7..67450a5b2815 100644 --- a/docs/docs/protocol-specs/circuits/private-kernel-tail.md +++ b/docs/docs/protocol-specs/circuits/private-kernel-tail.md @@ -227,8 +227,8 @@ Data that aids in the verifications carried out in this circuit: | Field | Type | Description | | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -| `note_hash_hints` | [[`OrderHint`](#orderhint); [`MAX_NEW_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hints for ordering `note_hash_contexts`. | -| `nullifier_hints` | [[`OrderHint`](#orderhint); [`MAX_NEW_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Hints for ordering `nullifier_contexts`. | +| `note_hash_hints` | [[`OrderHint`](#orderhint); [`MAX_NOTE_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hints for ordering `note_hash_contexts`. | +| `nullifier_hints` | [[`OrderHint`](#orderhint); [`MAX_NULLIFIERS_PER_TX`](../constants.md#circuit-constants)] | Hints for ordering `nullifier_contexts`. | | `public_call_request_hints` | [`field`; [`MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX`](../constants.md#circuit-constants)] | Indices of ordered `public_call_request_contexts`. | | `unencrypted_log_hash_hints` | [[`OrderHint`](#orderhint); [`MAX_UNENCRYPTED_LOG_HASHES_PER_TX`](../constants.md#circuit-constants)] | Hints for ordering `unencrypted_log_hash_contexts`. | | `ordered_unencrypted_log_hashes_revertible` | [`field`; [`MAX_UNENCRYPTED_LOG_HASHES_PER_TX`](../constants.md#circuit-constants)] | Ordered revertible `unencrypted_log_hashes`. | diff --git a/docs/docs/protocol-specs/constants.md b/docs/docs/protocol-specs/constants.md index cc41abb0048d..1ca57a885157 100644 --- a/docs/docs/protocol-specs/constants.md +++ b/docs/docs/protocol-specs/constants.md @@ -42,9 +42,9 @@ The statically-sized nature the kernel & rollup circuits will restrict the quant | Name | Value | Description | |---|---|---| | `RETURN_VALUES_LENGTH` | 4 | -| `MAX_NEW_NOTE_HASHES_PER_CALL` | 128 | -| `MAX_NEW_NULLIFIERS_PER_CALL` | 128 | -| `MAX_NEW_L2_TO_L1_MSGS_PER_CALL` | 4 | +| `MAX_NOTE_HASHES_PER_CALL` | 128 | +| `MAX_NULLIFIERS_PER_CALL` | 128 | +| `MAX_L2_TO_L1_MSGS_PER_CALL` | 4 | | `MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL` | 128 | | `MAX_PUBLIC_DATA_READS_PER_CALL` | 128 | | `MAX_UNENCRYPTED_LOG_HASHES_PER_CALL` | 128 | @@ -61,9 +61,9 @@ The statically-sized nature the kernel & rollup circuits will restrict the quant | Name | Value | Description | |---|---|---| -| `MAX_NEW_NOTE_HASHES_PER_TX` | 128 | -| `MAX_NEW_NULLIFIERS_PER_TX` | 128 | -| `MAX_NEW_L2_TO_L1_MSGS_PER_TX` | 16 | +| `MAX_NOTE_HASHES_PER_TX` | 128 | +| `MAX_NULLIFIERS_PER_TX` | 128 | +| `MAX_L2_TO_L1_MSGS_PER_TX` | 16 | | `MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX` | 31 | | `MAX_PUBLIC_DATA_READS_PER_TX` | 16 | | `MAX_UNENCRYPTED_LOG_HASHES_PER_TX` | 128 | diff --git a/docs/docs/protocol-specs/data-publication-and-availability/published-data.md b/docs/docs/protocol-specs/data-publication-and-availability/published-data.md index c50f8adba292..9a72572e1b0f 100644 --- a/docs/docs/protocol-specs/data-publication-and-availability/published-data.md +++ b/docs/docs/protocol-specs/data-publication-and-availability/published-data.md @@ -7,9 +7,9 @@ The "Effects" of a transaction are the collection of state changes and metadata | Field | Type | Description | | -------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `revertCode` | `RevertCode` | Indicates the reason for reverting in public application logic. 0 indicates success. | -| `note_hashes` | `Tuple` | The note hashes to be inserted into the note hash tree. | -| `nullifiers` | `Tuple` | The nullifiers to be inserted into the nullifier tree. | -| `l2_to_l2_msgs` | `Tuple` | The L2 to L1 messages to be inserted into the messagebox on L1. | +| `note_hashes` | `Tuple` | The note hashes to be inserted into the note hash tree. | +| `nullifiers` | `Tuple` | The nullifiers to be inserted into the nullifier tree. | +| `l2_to_l2_msgs` | `Tuple` | The L2 to L1 messages to be inserted into the messagebox on L1. | | `public_data_writes` | `Tuple` | Public data writes to be inserted into the public data tree | | `encrypted_logs` | `TxL2Logs` | Buffers containing the emitted encrypted logs. | | `unencrypted_logs` | `TxL2Logs` | Buffers containing the emitted unencrypted logs. | @@ -23,12 +23,12 @@ Each can have several transactions. Thus, an block is presently encoded as: | 0x4 + a \* 0x20 = tx0Start | 0x4 | len(numTxs) (denoted t) | | | | TxEffect 0 | | tx0Start | 0x20 | revertCode | -| tx0Start + 0x20 | 0x1 | len(newNoteHashes) (denoted b) | -| tx0Start + 0x20 + 0x1 | b \* 0x20 | newNoteHashes | -| tx0Start + 0x20 + 0x1 + b \* 0x20 | 0x1 | len(newNullifiers) (denoted c) | -| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 | c \* 0x20 | newNullifiers | -| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 | 0x1 | len(newL2ToL1Msgs) (denoted d) | -| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 + 0x1 | d \* 0x20 | newL2ToL1Msgs | +| tx0Start + 0x20 | 0x1 | len(noteHashes) (denoted b) | +| tx0Start + 0x20 + 0x1 | b \* 0x20 | noteHashes | +| tx0Start + 0x20 + 0x1 + b \* 0x20 | 0x1 | len(nullifiers) (denoted c) | +| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 | c \* 0x20 | nullifiers | +| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 | 0x1 | len(l2ToL1Msgs) (denoted d) | +| tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 + 0x1 | d \* 0x20 | l2ToL1Msgs | | tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 + 0x1 + d \* 0x20 | 0x1 | len(newPublicDataWrites) (denoted e) | | tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 + 0x1 + d \* 0x20 + 0x01 | e \* 0x40 | newPublicDataWrites | | tx0Start + 0x20 + 0x1 + b \* 0x20 + 0x1 + c \* 0x20 + 0x1 + d \* 0x20 + 0x01 + e \* 0x40 | 0x04 | byteLen(newEncryptedLogs) (denoted f) | diff --git a/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md b/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md index 39c17faab895..3aaa83f7d8d7 100644 --- a/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md +++ b/docs/docs/protocol-specs/gas-and-fees/kernel-tracking.md @@ -59,11 +59,11 @@ PrivateKernelCircuitPublicInputs --> CombinedConstantData class PrivateAccumulatedData { +Field encrypted_log_preimages_length +Field unencrypted_log_preimages_length - +Field[MAX_NEW_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs + +Field[MAX_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs +SideEffect[MAX_ENCRYPTED_LOGS_PER_TX] encrypted_logs_hashes +SideEffect[MAX_UNENCRYPTED_LOGS_PER_TX] unencrypted_logs_hashes - +SideEffect[MAX_NEW_NOTE_HASHES_PER_TX] new_note_hashes - +SideEffectLinkedToNoteHash[MAX_NEW_NULLIFIERS_PER_TX] new_nullifiers + +SideEffect[MAX_NOTE_HASHES_PER_TX] new_note_hashes + +SideEffectLinkedToNoteHash[MAX_NULLIFIERS_PER_TX] new_nullifiers +CallRequest[MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX] private_call_stack +CallRequest[MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX] public_call_stack } @@ -312,11 +312,11 @@ class CombinedConstantData { class PublicAccumulatedData { +Field encrypted_log_preimages_length +Field unencrypted_log_preimages_length - +Field[MAX_NEW_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs + +Field[MAX_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs +SideEffect[MAX_ENCRYPTED_LOGS_PER_TX] encrypted_logs_hashes +SideEffect[MAX_UNENCRYPTED_LOGS_PER_TX] unencrypted_logs_hashes - +SideEffect[MAX_NEW_NOTE_HASHES_PER_TX] new_note_hashes - +SideEffectLinkedToNoteHash[MAX_NEW_NULLIFIERS_PER_TX] new_nullifiers + +SideEffect[MAX_NOTE_HASHES_PER_TX] new_note_hashes + +SideEffectLinkedToNoteHash[MAX_NULLIFIERS_PER_TX] new_nullifiers +CallRequest[MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX] public_call_stack +PublicDataUpdateRequest[MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] public_data_update_requests +Gas gas_used @@ -378,9 +378,9 @@ class CombinedAccumulatedData { +Field unencrypted_log_preimages_length +Field encrypted_logs_hash +Field unencrypted_logs_hash - +Field[MAX_NEW_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs - +Field[MAX_NEW_NOTE_HASHES_PER_TX] new_note_hashes - +Field[MAX_NEW_NULLIFIERS_PER_TX] new_nullifiers + +Field[MAX_L2_TO_L1_MSGS_PER_TX] new_l2_to_l1_msgs + +Field[MAX_NOTE_HASHES_PER_TX] new_note_hashes + +Field[MAX_NULLIFIERS_PER_TX] new_nullifiers +PublicDataUpdateRequest[MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] public_data_update_requests +Gas gas_used } diff --git a/docs/docs/protocol-specs/l1-smart-contracts/index.md b/docs/docs/protocol-specs/l1-smart-contracts/index.md index c3b2c9e99f58..de32098a4eb7 100644 --- a/docs/docs/protocol-specs/l1-smart-contracts/index.md +++ b/docs/docs/protocol-specs/l1-smart-contracts/index.md @@ -34,19 +34,19 @@ def process(block: ProvenBlock, proof: Proof): assert self.outbox.insert( block_number, header.content_commitment.out_hash, - header.content_commitment.tx_tree_height + math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX)) + header.content_commitment.tx_tree_height + math.ceil(log2(MAX_L2_TO_L1_MSGS_PER_TX)) ) self.archive = block.archive emit BlockProcessed(block_number) ``` -:::info Why `math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX))`? +:::info Why `math.ceil(log2(MAX_L2_TO_L1_MSGS_PER_TX))`? The argument to the `insert` function is the `outbox` is the heigh of the message tree. Since every transaction can hold more than 1 message, it might add multiple layers to the tree. -For a binary tree, the number of extra layers to add is computed as `math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX))`. -Currently, `MAX_NEW_L2_TO_L1_MSGS_PER_TX = 2` which means that we are simply adding 1 extra layer. +For a binary tree, the number of extra layers to add is computed as `math.ceil(log2(MAX_L2_TO_L1_MSGS_PER_TX))`. +Currently, `MAX_L2_TO_L1_MSGS_PER_TX = 2` which means that we are simply adding 1 extra layer. ::: @@ -129,7 +129,7 @@ class StateTransitioner: assert self.OUTBOX.insert( block_number, header.content_commitment.out_hash, - header.content_commitment.tx_tree_height + math.ceil(log2(MAX_NEW_L2_TO_L1_MSGS_PER_TX)) + header.content_commitment.tx_tree_height + math.ceil(log2(MAX_L2_TO_L1_MSGS_PER_TX)) ) self.archive = archive emit BlockProcessed(block_number) diff --git a/docs/docs/protocol-specs/logs/index.md b/docs/docs/protocol-specs/logs/index.md index 1d442184e4f5..1f98711bd1e8 100644 --- a/docs/docs/protocol-specs/logs/index.md +++ b/docs/docs/protocol-specs/logs/index.md @@ -53,161 +53,27 @@ A function can emit an arbitrary number of logs, provided they don't exceed the -To minimize the on-chain verification data size, protocol circuits aggregate log hashes. The end result is a single hash within the root rollup proof, encompassing all logs of the same type. +To minimize the on-chain verification data size, protocol circuits aggregate log hashes. The end result is a single hash within the base rollup proof, encompassing all logs of the same type. Each protocol circuit outputs two values for each log type: - _`accumulated_logs_hash`_: A hash representing all logs. - _`accumulated_logs_length`_: The total length of all log preimages. +Both the `accumulated_logs_hash` and `accumulated_logs_length` for each type are included in the base rollup's `txs_effect_hash`. When rolling up to merge and root circuits, the two input proof's `txs_effect_hash`es are hashed together to form the new value of `txs_effect_hash`. + +When publishing a block on L1, the raw logs of each type and their lengths are provided (**Availability**), hashed and accumulated into each respective `accumulated_logs_hash` and `accumulated_logs_length`, then included in the on-chain recalculation of `txs_effect_hash`. If this value doesn't match the one from the rollup circuits, the block will not be valid (**Immutability**). + + For private and public kernel circuits, beyond aggregating logs from a function call, they ensure that the contract's address emitting the logs is linked to the _logs_hash_. For more details, refer to the "Hashing" sections in [Unencrypted Log](#hashing-1), [Encrypted Log](#hashing-2), and [Encrypted Note Preimage](#hashing-3). -### Encoding - -1. The encoded logs data of a transaction is a flattened array of all logs data within the transaction: - - _`tx_logs_data = [number_of_logs, ...log_data_0, ...log_data_1, ...]`_ - - The format of _log_data_ varies based on the log type. For specifics, see the "Encoding" sections in [Unencrypted Log](#encoding-1), [Encrypted Log](#encoding-2), and [Encrypted Note Preimage](#encoding-3). - -2. The encoded logs data of a block is a flatten array of a collection of the above _tx_logs_data_, with hints facilitating hashing replay in a binary tree structure: - - _`block_logs_data = [number_of_branches, number_of_transactions, ...tx_logs_data_0, ...tx_logs_data_1, ...]`_ - - - _number_of_transactions_ is the number of leaves in the left-most branch, restricted to either _1_ or _2_. - - _number_of_branches_ is the depth of the parent node of the left-most leaf. - -Here is a step-by-step example to construct the _`block_logs_data`_: - -1. A rollup, _R01_, merges two transactions: _tx0_ containing _tx_logs_data_0_, and _tx1_ containing _tx_logs_data_1_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - ``` - - _block_logs_data_: _`[0, 2, ...tx_logs_data_0, ...tx_logs_data_1]`_ - - Where _0_ is the depth of the node _R01_, and _2_ is the number of aggregated _tx_logs_data_ of _R01_. - -2. Another rollup, _R23_, merges two transactions: _tx3_ containing _tx_logs_data_3_, and _tx2_ without any logs: - - ```mermaid - flowchart BT - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -. no logs .- R23 - tx3 --- R23 - ``` - - _block_logs_data_: _`[0, 1, ...tx_logs_data_3]`_ - - Here, the number of aggregated _tx_logs_data_ is _1_. - -3. A rollup, _RA_, merges the two rollups _R01_ and _R23_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -.- R23 - tx3 --- R23 - RA((RA)) - R01 --- RA - R23 --- RA - ``` - - _block_logs_data_: _`[1, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3]`_ - - The result is the _block_logs_data_ of _R01_ concatenated with the _block_logs_data_ of _R23_, with the _number_of_branches_ of _R01_ incremented by _1_. The updated value of _number_of_branches_ (_0 + 1_) is also the depth of the node _R01_. - -4. A rollup, _RB_, merges the above rollup _RA_ and another rollup _R45_: - - ```mermaid - flowchart BT - tx0((tx0)) - tx1((tx1)) - R01((R01)) - tx0 --- R01 - tx1 --- R01 - tx2((tx2)) - tx3((tx3)) - R23((R23)) - tx2 -.- R23 - tx3 --- R23 - RA((RA)) - R01 --- RA - R23 --- RA - tx4((tx4)) - tx5((tx5)) - R45((R45)) - tx4 --- R45 - tx5 --- R45 - RB((RB)) - RA --- RB - R45 --- RB - ``` - - _block_logs_data_: _`[2, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3, 0, 2, ...tx_logs_data_4, ...tx_logs_data_5]`_ - - The result is the concatenation of the _block_logs_data_ from both rollups, with the _number_of_branches_ of the left-side rollup, _RA_, incremented by _1_. - -### Verification - -Upon receiving a proof and its encoded logs data, the entity can ensure the correctness of the provided _block_logs_data_ by verifying that the _accumulated_logs_hash_ in the proof can be derived from it: - -```js -const accumulated_logs_hash = compute_accumulated_logs_hash(block_logs_data); -assert(accumulated_logs_hash == proof.accumulated_logs_hash); -assert(block_logs_data.accumulated_logs_length == proof.accumulated_logs_length); - -function compute_accumulated_logs_hash(logs_data) { - const number_of_branches = logs_data.read_u32(); - - const number_of_transactions = logs_data.read_u32(); - let res = hash_tx_logs_data(logs_data); - if number_of_transactions == 2 { - res = hash(res, hash_tx_logs_data(logs_data)); - } - - for (let i = 0; i < number_of_branches; ++i) { - const res_right = compute_accumulated_logs_hash(logs_data); - res = hash(res, res_right); - } - - return res; -} - -function hash_tx_logs_data(logs_data) { - const number_of_logs = logs_data.read_u32(); - let res = hash_log_data(logs_data); - for (let i = 1; i < number_of_logs; ++i) { - const log_hash = hash_log_data(logs_data); - res = hash(res, log_hash); - } - return res; -} -``` - -The _accumulated_logs_length_ in _block_logs_data_ is computed during the processing of each _logs_data_ within _hash_log_data()_. The implementation of _hash_log_data_ varies depending on the type of the logs being processed. Refer to the "Verification" sections in [Unencrypted Log](#verification-1), [Encrypted Log](#verification-2), and [Encrypted Note Preimage](#verification-3) for details. - ## Unencrypted Log Unencrypted logs are used to communicate public information out of smart contracts. They can be emitted from both public and private functions. diff --git a/docs/docs/protocol-specs/public-vm/_nested-context.md b/docs/docs/protocol-specs/public-vm/_nested-context.md index 2b24cff09f22..c6fbd1824ab8 100644 --- a/docs/docs/protocol-specs/public-vm/_nested-context.md +++ b/docs/docs/protocol-specs/public-vm/_nested-context.md @@ -14,11 +14,10 @@ nestedContext = deriveContext(context, instr.args, isStaticCall, isDelegateCall) Nested context derivation is defined as follows: ```jsx nestedExecutionEnvironment = ExecutionEnvironment { - sender: isDelegateCall ? context.sender : context.address, address: M[addrOffset], storageAddress: isDelegateCall ? context.storageAddress : M[addrOffset], - feePerL2Gas: context.environment.feePerL2Gas, - feePerDaGas: context.environment.feePerDaGas, + sender: isDelegateCall ? context.sender : context.address, + functionSelector: context.environment.functionSelector, transactionFee: context.environment.transactionFee, contractCallDepth: context.contractCallDepth + 1, contractCallPointer: context.worldStateAccessTrace.contractCalls.length + 1, @@ -49,4 +48,4 @@ nestedContext = AvmContext { } ``` -> `M[offset]` notation is shorthand for `context.machineState.memory[offset]` \ No newline at end of file +> `M[offset]` notation is shorthand for `context.machineState.memory[offset]` diff --git a/docs/docs/protocol-specs/public-vm/context.mdx b/docs/docs/protocol-specs/public-vm/context.mdx index d770462befe2..6bb784ef6064 100644 --- a/docs/docs/protocol-specs/public-vm/context.mdx +++ b/docs/docs/protocol-specs/public-vm/context.mdx @@ -28,9 +28,7 @@ A context's **execution environment** remains constant throughout a contract cal | address | `AztecAddress` | | | storageAddress | `AztecAddress` | | | sender | `AztecAddress` | | -| portal | `EthAddress` | | -| feePerL2Gas | `field` | | -| feePerDaGas | `field` | | +| functionSelector | `u32` | | | transactionFee | `field` | Computed transaction fee based on gas fees, inclusion fee, and gas usage. Zero in all phases but teardown. | | contractCallDepth | `field` | Depth of the current call (how many nested calls deep is it). | | contractCallPointer | `field` | Uniquely identifies each contract call processed by an AVM session. An initial call is assigned pointer value of 1 (expanded on in the AVM circuit section's ["Call Pointer"](./avm-circuit#call-pointer) subsection). | @@ -76,9 +74,7 @@ INITIAL_EXECUTION_ENVIRONMENT = ExecutionEnvironment { address: PublicCallRequest.contractAddress, storageAddress: PublicCallRequest.CallContext.storageContractAddress, sender: PublicCallRequest.CallContext.msgSender, - portal: PublicCallRequest.CallContext.portalContractAddress, - feePerL2Gas: TxRequest.feePerL2Gas, - feePerDaGas: TxRequest.feePerDaGas, + functionelector: PublicCallRequest.functionSelector, contractCallDepth: 0, contractCallPointer: 1, globals: @@ -88,8 +84,8 @@ INITIAL_EXECUTION_ENVIRONMENT = ExecutionEnvironment { } INITIAL_MACHINE_STATE = MachineState { - l2GasLeft: TxRequest.l2GasLimit, - daGasLeft: TxRequest.daGasLimit, + l2GasLeft: , + daGasLeft: , pc: 0, internalCallStack: [], // initialized as empty memory: [0, ..., 0], // all 2^32 entries are initialized to zero diff --git a/docs/docs/protocol-specs/public-vm/execution.md b/docs/docs/protocol-specs/public-vm/execution.md index 901929e94feb..ea2fa9e301a9 100644 --- a/docs/docs/protocol-specs/public-vm/execution.md +++ b/docs/docs/protocol-specs/public-vm/execution.md @@ -208,9 +208,9 @@ The AVM's exceptional halting conditions area listed below: assert worldStateAccessTrace.publicStorageReads.length <= 1024 AND worldStateAccessTrace.publicStorageWrites.length <= 1024 AND worldStateAccessTrace.noteHashChecks.length <= 1024 - AND worldStateAccessTrace.newNoteHashes.length <= 1024 + AND worldStateAccessTrace.noteHashes.length <= 1024 AND worldStateAccessTrace.nullifierChecks.length <= 1024 - AND worldStateAccessTrace.newNullifiers.length <= 1024 + AND worldStateAccessTrace.nullifiers.length <= 1024 AND worldStateAccessTrace.l1ToL2MessageChecks.length <= 1024 AND worldStateAccessTrace.archiveChecks.length <= 1024 @@ -224,13 +224,13 @@ The AVM's exceptional halting conditions area listed below: assert instructions[machineState.pc].opcode != NOTEHASHEXISTS OR noteHashChecks.length < 1024 assert instructions[machineState.pc].opcode != EMITNOTEHASH - OR newNoteHashes.length < 1024 + OR noteHashes.length < 1024 // Nullifiers assert instructions[machineState.pc].opcode != NULLIFIEREXISTS OR nullifierChecks.length < 1024 assert instructions[machineState.pc].opcode != EMITNULLIFIER - OR newNullifiers.length < 1024 + OR nullifiers.length < 1024 // Read L1 to L2 messages assert instructions[machineState.pc].opcode != L1TOL2MSGEXISTS diff --git a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx index 0431d007a937..76a1afddf456 100644 --- a/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx +++ b/docs/docs/protocol-specs/public-vm/gen/_instruction-set.mdx @@ -159,22 +159,14 @@ Click on an instruction name to jump to its section. 0x12 - \[\`FEEPERL2GAS\`\](#isa-section-feeperl2gas) - Get the fee to be paid per "L2 gas" - constant for entire transaction + \[\`FUNCTIONSELECTOR\`\](#isa-section-functionselector) + Get the function selector of the contract function being executed { - `M[dstOffset] = context.environment.feePerL2Gas` + `M[dstOffset] = context.environment.functionSelector` } 0x13 - \[\`FEEPERDAGAS\`\](#isa-section-feeperdagas) - Get the fee to be paid per "DA gas" - constant for entire transaction - { - `M[dstOffset] = context.environment.feePerDaGas` - } - - - 0x14 \[\`TRANSACTIONFEE\`\](#isa-section-transactionfee) Get the computed transaction fee during teardown phase, zero otherwise { @@ -182,15 +174,7 @@ Click on an instruction name to jump to its section. } - 0x15 - \[\`CONTRACTCALLDEPTH\`\](#isa-section-contractcalldepth) - Get how many contract calls deep the current call context is - { - `M[dstOffset] = context.environment.contractCallDepth` - } - - - 0x16 + 0x14 \[\`CHAINID\`\](#isa-section-chainid) Get this rollup's L1 chain ID { @@ -198,7 +182,7 @@ Click on an instruction name to jump to its section. } - 0x17 + 0x15 \[\`VERSION\`\](#isa-section-version) Get this rollup's L2 version ID { @@ -206,7 +190,7 @@ Click on an instruction name to jump to its section. } - 0x18 + 0x16 \[\`BLOCKNUMBER\`\](#isa-section-blocknumber) Get this L2 block's number { @@ -214,7 +198,7 @@ Click on an instruction name to jump to its section. } - 0x19 + 0x17 \[\`TIMESTAMP\`\](#isa-section-timestamp) Get this L2 block's timestamp { @@ -222,17 +206,33 @@ Click on an instruction name to jump to its section. } - 0x1a + 0x18 \[\`COINBASE\`\](#isa-section-coinbase) - Get the block's beneficiary address + (UNIMPLEMENTED) Get the block's beneficiary address { `M[dstOffset] = context.environment.globals.coinbase` } + + 0x19 + \[\`FEEPERL2GAS\`\](#isa-section-feeperl2gas) + Get the fee to be paid per "L2 gas" - constant for entire transaction + { + `M[dstOffset] = context.environment.globals.feePerL2Gas` + } + + + 0x1a + \[\`FEEPERDAGAS\`\](#isa-section-feeperdagas) + Get the fee to be paid per "DA gas" - constant for entire transaction + { + `M[dstOffset] = context.environment.globals.feePerDaGas` + } + 0x1b \[\`BLOCKL2GASLIMIT\`\](#isa-section-blockl2gaslimit) - Total amount of "L2 gas" that a block can consume + (UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume { `M[dstOffset] = context.environment.globals.l2GasLimit` } @@ -240,7 +240,7 @@ Click on an instruction name to jump to its section. 0x1c \[\`BLOCKDAGASLIMIT\`\](#isa-section-blockdagaslimit) - Total amount of "DA gas" that a block can consume + (UNIMPLEMENTED) Total amount of "DA gas" that a block can consume { `M[dstOffset] = context.environment.globals.daGasLimit` } @@ -399,7 +399,7 @@ M[existsOffset] = exists`} 0x2e \[\`HEADERMEMBER\`\](#isa-section-headermember) - Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so + (UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so {`exists = context.worldState.header.has({ leafIndex: M[blockIndexOffset], leaf: M[msgKeyOffset] @@ -434,8 +434,7 @@ if exists: {`context.accruedSubstate.unencryptedLogs.append( UnencryptedLog { address: context.environment.address, - eventSelector: M[eventSelectorOffset], - log: M[logOffset:logOffset+logSize], + log: M[logOffset:logOffset+M[logSizeOffset]], } )`} @@ -487,7 +486,7 @@ updateContextAfterNestedCall(context, instr.args, nestedContext)`} 0x34 \[\`DELEGATECALL\`\](#isa-section-delegatecall) - Call into another contract, but keep the caller's `sender` and `storageAddress` + (UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress` {`// instr.args are { gasOffset, addrOffset, argsOffset, retOffset, retSize } chargeGas(context, @@ -896,10 +895,10 @@ Get the address of the sender (caller of the current context) [![](/img/protocol-specs/public-vm/bit-formats/SENDER.png)](/img/protocol-specs/public-vm/bit-formats/SENDER.png) -### `FEEPERL2GAS` -Get the fee to be paid per "L2 gas" - constant for entire transaction +### `FUNCTIONSELECTOR` +Get the function selector of the contract function being executed -[See in table.](#isa-table-feeperl2gas) +[See in table.](#isa-table-functionselector) - **Opcode**: 0x12 - **Category**: Execution Environment @@ -907,35 +906,17 @@ Get the fee to be paid per "L2 gas" - constant for entire transaction - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.feePerL2Gas` -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png) - -### `FEEPERDAGAS` -Get the fee to be paid per "DA gas" - constant for entire transaction - -[See in table.](#isa-table-feeperdagas) - -- **Opcode**: 0x13 -- **Category**: Execution Environment -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.feePerDaGas` -- **Tag updates**: `T[dstOffset] = field` +- **Expression**: `M[dstOffset] = context.environment.functionSelector` +- **Tag updates**: `T[dstOffset] = u32` - **Bit-size**: 56 -[![](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png) ### `TRANSACTIONFEE` Get the computed transaction fee during teardown phase, zero otherwise [See in table.](#isa-table-transactionfee) -- **Opcode**: 0x14 +- **Opcode**: 0x13 - **Category**: Execution Environment - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -946,30 +927,12 @@ Get the computed transaction fee during teardown phase, zero otherwise - **Bit-size**: 56 -### `CONTRACTCALLDEPTH` -Get how many contract calls deep the current call context is - -[See in table.](#isa-table-contractcalldepth) - -- **Opcode**: 0x15 -- **Category**: Execution Environment -- **Flags**: - - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. -- **Args**: - - **dstOffset**: memory offset specifying where to store operation's result -- **Expression**: `M[dstOffset] = context.environment.contractCallDepth` -- **Details**: Note: security issues with EVM's tx.origin can be resolved by asserting `calldepth == 0`. -- **Tag updates**: `T[dstOffset] = field` -- **Bit-size**: 56 - -[![](/img/protocol-specs/public-vm/bit-formats/CONTRACTCALLDEPTH.png)](/img/protocol-specs/public-vm/bit-formats/CONTRACTCALLDEPTH.png) - ### `CHAINID` Get this rollup's L1 chain ID [See in table.](#isa-table-chainid) -- **Opcode**: 0x16 +- **Opcode**: 0x14 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -986,7 +949,7 @@ Get this rollup's L2 version ID [See in table.](#isa-table-version) -- **Opcode**: 0x17 +- **Opcode**: 0x15 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1003,7 +966,7 @@ Get this L2 block's number [See in table.](#isa-table-blocknumber) -- **Opcode**: 0x18 +- **Opcode**: 0x16 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1020,7 +983,7 @@ Get this L2 block's timestamp [See in table.](#isa-table-timestamp) -- **Opcode**: 0x19 +- **Opcode**: 0x17 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1033,11 +996,11 @@ Get this L2 block's timestamp [![](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png)](/img/protocol-specs/public-vm/bit-formats/TIMESTAMP.png) ### `COINBASE` -Get the block's beneficiary address +(UNIMPLEMENTED) Get the block's beneficiary address [See in table.](#isa-table-coinbase) -- **Opcode**: 0x1a +- **Opcode**: 0x18 - **Category**: Execution Environment - Globals - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. @@ -1049,8 +1012,42 @@ Get the block's beneficiary address [![](/img/protocol-specs/public-vm/bit-formats/COINBASE.png)](/img/protocol-specs/public-vm/bit-formats/COINBASE.png) +### `FEEPERL2GAS` +Get the fee to be paid per "L2 gas" - constant for entire transaction + +[See in table.](#isa-table-feeperl2gas) + +- **Opcode**: 0x19 +- **Category**: Execution Environment - Globals - Gas +- **Flags**: + - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = context.environment.globals.feePerL2Gas` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 56 + +[![](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERL2GAS.png) + +### `FEEPERDAGAS` +Get the fee to be paid per "DA gas" - constant for entire transaction + +[See in table.](#isa-table-feeperdagas) + +- **Opcode**: 0x1a +- **Category**: Execution Environment - Globals - Gas +- **Flags**: + - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. +- **Args**: + - **dstOffset**: memory offset specifying where to store operation's result +- **Expression**: `M[dstOffset] = context.environment.globals.feePerDaGas` +- **Tag updates**: `T[dstOffset] = field` +- **Bit-size**: 56 + +[![](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png)](/img/protocol-specs/public-vm/bit-formats/FEEPERDAGAS.png) + ### `BLOCKL2GASLIMIT` -Total amount of "L2 gas" that a block can consume +(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume [See in table.](#isa-table-blockl2gaslimit) @@ -1067,7 +1064,7 @@ Total amount of "L2 gas" that a block can consume [![](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png)](/img/protocol-specs/public-vm/bit-formats/BLOCKL2GASLIMIT.png) ### `BLOCKDAGASLIMIT` -Total amount of "DA gas" that a block can consume +(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume [See in table.](#isa-table-blockdagaslimit) @@ -1401,7 +1398,7 @@ Emit a new note hash to be inserted into the note hash tree - **World State access tracing**: -{`context.worldStateAccessTrace.newNoteHashes.append( +{`context.worldStateAccessTrace.noteHashes.append( TracedNoteHash { callPointer: context.environment.callPointer, noteHash: M[noteHashOffset], // unsiloed note hash @@ -1470,7 +1467,7 @@ Emit a new nullifier to be inserted into the nullifier tree - **World State access tracing**: -{`context.worldStateAccessTrace.newNullifiers.append( +{`context.worldStateAccessTrace.nullifiers.append( TracedNullifier { callPointer: context.environment.callPointer, nullifier: M[nullifierOffset], // unsiloed nullifier @@ -1523,7 +1520,7 @@ M[existsOffset] = exists`} ### `HEADERMEMBER` -Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so +(UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so [See in table.](#isa-table-headermember) @@ -1605,20 +1602,18 @@ Emit an unencrypted log - **Flags**: - **indirect**: Toggles whether each memory-offset argument is an indirect offset. Rightmost bit corresponds to 0th offset arg, etc. Indirect offsets result in memory accesses like `M[M[offset]]` instead of the more standard `M[offset]`. - **Args**: - - **eventSelectorOffset**: memory offset of the event selector - **logOffset**: memory offset of the data to log - - **logSize**: number of words to log + - **logSizeOffset**: memory offset to number of words to log - **Expression**: {`context.accruedSubstate.unencryptedLogs.append( UnencryptedLog { address: context.environment.address, - eventSelector: M[eventSelectorOffset], - log: M[logOffset:logOffset+logSize], + log: M[logOffset:logOffset+M[logSizeOffset]], } )`} -- **Bit-size**: 120 +- **Bit-size**: 88 [![](/img/protocol-specs/public-vm/bit-formats/EMITUNENCRYPTEDLOG.png)](/img/protocol-specs/public-vm/bit-formats/EMITUNENCRYPTEDLOG.png) @@ -1740,7 +1735,7 @@ T[retOffset:retOffset+retSize] = field`} [![](/img/protocol-specs/public-vm/bit-formats/STATICCALL.png)](/img/protocol-specs/public-vm/bit-formats/STATICCALL.png) ### `DELEGATECALL` -Call into another contract, but keep the caller's `sender` and `storageAddress` +(UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress` [See in table.](#isa-table-delegatecall) diff --git a/docs/docs/protocol-specs/public-vm/intro.md b/docs/docs/protocol-specs/public-vm/intro.md index e27ea9e1ced6..a89e45fc1b2a 100644 --- a/docs/docs/protocol-specs/public-vm/intro.md +++ b/docs/docs/protocol-specs/public-vm/intro.md @@ -38,4 +38,9 @@ A contract's public bytecode is a series of execution instructions for the AVM. The entirety of a contract's public code is represented as a single block of bytecode with a maximum of `MAX_PUBLIC_INSTRUCTIONS_PER_CONTRACT` ($2^{15} = 32768$) instructions. The mechanism used to distinguish between different "functions" in an AVM bytecode program is left as a higher-level abstraction (_e.g._ similar to Solidity's concept of a function selector). +::: warning +Ultimately, function selectors _may_ be removed as an enshrined protocol mechanism as described above. For now, each public function on a contract has a distinct bytecode that can be selected for execution via a function selector. +::: + + > See the [Bytecode Validation Circuit](./bytecode-validation-circuit) to see how a contract's bytecode can be validated and committed to. diff --git a/docs/docs/protocol-specs/public-vm/state.md b/docs/docs/protocol-specs/public-vm/state.md index bd2498b42182..e81b6299c839 100644 --- a/docs/docs/protocol-specs/public-vm/state.md +++ b/docs/docs/protocol-specs/public-vm/state.md @@ -77,9 +77,9 @@ Each entry in the world state access trace is listed below along with its type a | `publicStorageReads` | Public Storage | `Vector` | [`SLOAD`](./instruction-set#isa-section-sload) | | `publicStorageWrites` | Public Storage | `Vector` | [`SSTORE`](./instruction-set#isa-section-sstore) | | `noteHashChecks` | Note Hashes | `Vector` | [`NOTEHASHEXISTS`](./instruction-set#isa-section-notehashexists) | -| `newNoteHashes` | Note Hashes | `Vector` | [`EMITNOTEHASH`](./instruction-set#isa-section-emitnotehash) | +| `noteHashes` | Note Hashes | `Vector` | [`EMITNOTEHASH`](./instruction-set#isa-section-emitnotehash) | | `nullifierChecks` | Nullifiers | `Vector` | [`NULLIFIERSEXISTS`](./instruction-set#isa-section-nullifierexists) | -| `newNullifiers` | Nullifiers | `Vector` | [`EMITNULLIFIER`](./instruction-set#isa-section-emitnullifier) | +| `nullifiers` | Nullifiers | `Vector` | [`EMITNULLIFIER`](./instruction-set#isa-section-emitnullifier) | | `l1ToL2MessageChecks` | L1-To-L2 Messages | `Vector` | [`L1TOL2MSGEXISTS`](./instruction-set#isa-section-l1tol2msgexists) | | `archiveChecks` | Headers | `Vector` | [`HEADERMEMBER`](./instruction-set#isa-section-headermember) | diff --git a/docs/docs/protocol-specs/rollup-circuits/index.md b/docs/docs/protocol-specs/rollup-circuits/index.md index 1e2523f27197..d85df805dd27 100644 --- a/docs/docs/protocol-specs/rollup-circuits/index.md +++ b/docs/docs/protocol-specs/rollup-circuits/index.md @@ -19,9 +19,9 @@ Note that we have two different types of "merger" circuits, depending on what th For transactions we have: - The `merge` rollup - - Merges two `base` rollup proofs OR two `merge` rollup proofs + - Merges two rollup proofs of either `base` or `merge` and constructs outputs for further proving - The `root` rollup - - Merges two `merge` rollup proofs + - Merges two rollup proofs of either `base` or `merge` and constructs outputs for L1 And for the message parity we have: @@ -30,7 +30,7 @@ And for the message parity we have: - The `base_parity` circuit - Merges `N` l1 to l2 messages in a subtree -In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs. +In the diagram the size of the tree is limited for demonstration purposes, but a larger tree would have more layers of merge rollups proofs. Exactly how many layers and what combination of `base` and/or `merge` circuits are consumed is based on filling a [wonky tree](../state/tree-implementations.md#wonky-merkle-trees) with N transactions. Circles mark the different types of proofs, while squares mark the different circuit types. ```mermaid @@ -465,7 +465,7 @@ Furthermore, the `OutHash` is a computed from a subset of the data in `TxsHash` Since we strive to minimize the compute requirements to prove blocks, we amortize the commitment cost across the full tree. We can do so by building merkle trees of partial "commitments", whose roots are ultimately computed in the final root rollup circuit. -Below, we outline the `TxsHash` merkle tree that is based on the `TxEffect`s and a `OutHash` which is based on the `l2_to_l1_msgs` (cross-chain messages) for each transaction. +Below, we outline the `TxsHash` merkle tree that is based on the `TxEffect`s and a `OutHash` which is based on the `l2_to_l1_msgs` (cross-chain messages) for each transaction, with four transactions in this rollup. While the `TxsHash` implicitly includes the `OutHash` we need it separately such that it can be passed to the `Outbox` for consumption by the portals with minimal work. ```mermaid @@ -588,6 +588,8 @@ graph BT While the `TxsHash` merely require the data to be published and known to L1, the `InHash` and `OutHash` needs to be computable on L1 as well. This reason require them to be efficiently computable on L1 while still being non-horrible inside a snark - leading us to rely on SHA256. + + The L2 to L1 messages from each transaction form a variable height tree. In the diagram above, transactions 0 and 3 have four messages, so require a tree with two layers, whereas the others only have two messages and so require a single layer tree. The base rollup calculates the root of this tree and passes it as the to the next layer. Merge rollups simply hash both of these roots together and pass it up as the `OutHash`. ## Next Steps diff --git a/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md b/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md index f1ebdce1245c..5d8ce56943f7 100644 --- a/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md +++ b/docs/docs/protocol-specs/rollup-circuits/merge-rollup.md @@ -82,13 +82,12 @@ def MergeRollupCircuit( assert left.public_inputs.constants == right.public_inputs.constants assert left.public_inputs.end == right.public_inputs.start - assert left.public_inputs.type == right.public_inputs.type - assert left.public_inputs.height_in_block_tree == right.public_inputs.height_in_block_tree + assert left.public_inputs.num_txs >= right.public_inputs.num_txs return BaseOrMergeRollupPublicInputs( type=1, - height_in_block_tree=left.public_inputs.height_in_block_tree + 1, - txs_hash=SHA256(left.public_inputs.txs_hash | right.public_inputs.txs_hash), + num_txs=left.public_inputs.num_txs + right.public_inputs.num_txs, + txs_effect_hash=SHA256(left.public_inputs.txs_effect_hash | right.public_inputs.txs_effect_hash), out_hash=SHA256(left.public_inputs.out_hash | right.public_inputs.out_hash), start=left.public_inputs.start, end=right.public_inputs.end, diff --git a/docs/docs/protocol-specs/rollup-circuits/root-rollup.md b/docs/docs/protocol-specs/rollup-circuits/root-rollup.md index d214a01011f3..0e09c4663ff9 100644 --- a/docs/docs/protocol-specs/rollup-circuits/root-rollup.md +++ b/docs/docs/protocol-specs/rollup-circuits/root-rollup.md @@ -183,8 +183,7 @@ def RootRollupCircuit( assert left.public_inputs.constants == right.public_inputs.constants assert left.public_inputs.end == right.public_inputs.start - assert left.public_inputs.type == right.public_inputs.type - assert left.public_inputs.height_in_block_tree == right.public_inputs.height_in_block_tree + assert left.public_inputs.num_txs >= right.public_inputs.num_txs assert parent.state.partial == left.public_inputs.start @@ -208,8 +207,8 @@ def RootRollupCircuit( header = Header( last_archive = left.public_inputs.constants.last_archive, content_commitment: ContentCommitment( - tx_tree_height = left.public_inputs.height_in_block_tree + 1, - txs_hash = SHA256(left.public_inputs.txs_hash | right.public_inputs.txs_hash), + num_txs=left.public_inputs.num_txs + right.public_inputs.num_txs, + txs_effect_hash=SHA256(left.public_inputs.txs_effect_hash | right.public_inputs.txs_effect_hash), in_hash = l1_to_l2_roots.public_inputs.sha_root, out_hash = SHA256(left.public_inputs.out_hash | right.public_inputs.out_hash), ), diff --git a/docs/docs/protocol-specs/state/tree-implementations.md b/docs/docs/protocol-specs/state/tree-implementations.md index cf0f9cf8ccf7..b40a5557d65a 100644 --- a/docs/docs/protocol-specs/state/tree-implementations.md +++ b/docs/docs/protocol-specs/state/tree-implementations.md @@ -8,6 +8,12 @@ In an append-only Merkle tree, new leaves are inserted in order from left to rig Append-only trees allow for more efficient syncing than sparse trees, since clients can sync from left to right starting with their last known value. Updates to the tree root, when inserting new leaves, can be computed from the rightmost "frontier" of the tree (i.e., from the sibling path of the rightmost nonzero leaf). Batch insertions can be computed with fewer hashes than in a sparse tree. The historical snapshots of append-only trees also enable efficient membership proofs; as older roots can be computed by completing the merkle path from a past left subtree with an empty right subtree. +### Wonky Merkle Trees + +We also use a special type of append-only tree to structure the rollup circuits. Given `n` leaves, we fill from left to right and attempt to pair them to produce the next layer. If `n` is a power of 2, this tree looks exactly like a standard append-only merkle tree. Otherwise, once we reach an odd-sized row we shift the final node up until we reach another odd row to combine them. + +This results in an unbalanced tree where there are no empty leaves. For rollups, this means we don't have to pad empty transactions and process them through the rollup circuits. A full explanation is given [here](./wonky-tree.md). + ## Indexed Merkle trees Indexed Merkle trees, introduced [here](https://eprint.iacr.org/2021/1263.pdf), allow for proofs of non-inclusion more efficiently than sparse Merkle trees. Each leaf in the tree is a tuple of: the leaf value, the next-highest value in the tree, and the index of the leaf where that next-highest value is stored. New leaves are inserted from left to right, as in the append-only tree, but existing leaves can be _modified_ to update the next-highest value and next-highest index (a.k.a. the "pointer") if a new leaf with a "closer value" is added to the tree. An Indexed Merkle trees behaves as a Merkle tree over a sorted linked list. diff --git a/docs/docs/protocol-specs/state/wonky-tree.md b/docs/docs/protocol-specs/state/wonky-tree.md new file mode 100644 index 000000000000..14d1a9776754 --- /dev/null +++ b/docs/docs/protocol-specs/state/wonky-tree.md @@ -0,0 +1,422 @@ +# Wonky Tree + +A 'wonky' tree is an append-only unbalanced merkle tree, filled from left to right. It is used to construct [rollup](../rollup-circuits/index.md) proofs without padding empty transactions. + +For example, using a balanced merkle tree to rollup 5 transactions requires padding of 3 empty transactions: + +```mermaid +graph BT + R_c[Root] + + M4_c[Merge] + M5_c[Merge] + M4_c --> R_c + M5_c --> R_c + + + M0_c[Merge] + M1_c[Merge] + M0_c --> M4_c + M1_c --> M4_c + + B0_c[Base] + B1_c[Base] + B2_c[Base] + B3_c[Base] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M2_c[Merge] + M3_c[Merge*] + M2_c --> M5_c + M3_c --> M5_c + + B4_c[Base] + B5_c[Base*] + B6_c[Base*] + B7_c[Base*] + B4_c --> M2_c + B5_c --> M2_c + B6_c --> M3_c + B7_c --> M3_c + + Tx0_c((Tx 0)) + Tx1_c((Tx 1)) + Tx2_c((Tx 2)) + Tx3_c((Tx 3)) + Tx4_c((Tx 4)) + + Tx0_c --> B0_c + Tx1_c --> B1_c + Tx2_c --> B2_c + Tx3_c --> B3_c + Tx4_c --> B4_c +``` + +Where each node marked with `*` indicates a circuit proving entirely empty information. While the above structure does allow us to easily construct balanced trees later on consisting of `out_hash`es and `tx_effects_hash`es, it will lead to wasted compute and higher block processing costs unless we provide a number of transactions equal to a power of 2. + +Our wonky tree implementation instead gives the below structure for 5 transactions: + +```mermaid +graph BT + R_c[Root] + + M4_c[Merge] + M4_c --> R_c + + + M0_c[Merge] + M1_c[Merge] + M0_c --> M4_c + M1_c --> M4_c + + B0_c[Base] + B1_c[Base] + B2_c[Base] + B3_c[Base] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + + B4_c[Base] + B4_c --> R_c + + Tx0_c((Tx 0)) + Tx1_c((Tx 1)) + Tx2_c((Tx 2)) + Tx3_c((Tx 3)) + Tx4_c((Tx 4)) + + Tx0_c --> B0_c + Tx1_c --> B1_c + Tx2_c --> B2_c + Tx3_c --> B3_c + Tx4_c --> B4_c +``` + +Here, each circuit is proving useful transaction information with no wasted compute. We can construct a tree like this one for any number of transactions by greedy filling from left to right. Given the required 5 base circuits: + +```mermaid +graph + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B4_c[Base 4] +``` + +...we theh pair these base circuits up to form merges: + +```mermaid +graph BT + M0_c[Merge 0] + M1_c[Merge 1] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + B4_c[Base 4] +``` + +Since we have an odd number of transactions, we cannot pair up the final base. Instead, we continue to pair the next layers until we reach a layer with an odd number of members. In this example, that's when we reach merge 2: + +```mermaid +graph BT + M0_c[Merge 0] + M1_c[Merge 1] + M2_c[Merge 2] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M0_c --> M2_c + M1_c --> M2_c + + B4_c[Base 4] +``` + +Once paired, the base layer has length 4, the next merge layer has 2, and the final merge layer has 1. After reaching a layer with odd length, the orchestrator can now pair base 4: + +```mermaid +graph BT + R_c[Root] + + M0_c[Merge 0] + M1_c[Merge 1] + M2_c[Merge 2] + + B0_c[Base 0] + B1_c[Base 1] + B2_c[Base 2] + B3_c[Base 3] + B0_c --> M0_c + B1_c --> M0_c + B2_c --> M1_c + B3_c --> M1_c + + M0_c --> M2_c + M1_c --> M2_c + + B4_c[Base 4] + M2_c --> R_c + B4_c --> R_c +``` +Since we have processed all base circuits, this final pair will be input to a root circuit. + +Filling from left to right means that we can easily reconstruct the tree only from the number of transactions `n`. The above method ensures that the final tree is a combination of *balanced* subtrees of descending size. The widths of these subtrees are given by the decomposition of `n` into powers of 2. For example, 5 transactions: + +``` +Subtrees: [4, 1] -> + left_subtree_root = balanced_tree(txs[0..4]) + right_subtree_root = balanced_tree(txs[4]) = txs[4] + root = left_subtree_root | right_subtree_root +``` + +For 31 transactions: +``` +Subtrees: [16, 8, 4, 2, 1] -> + Merge D: left_subtree_root = balanced_tree(txs[0..16]) + right_subtree_root = Subtrees: [8, 4, 2, 1] --> { + Merge C: left_subtree_root = balanced_tree(txs[16..24]) + right_subtree_root = Subtrees: [4, 2, 1] --> { + Merge B: left_subtree_root = balanced_tree(txs[24..28]) + right_subtree_root = Subtrees: [2, 1] --> { + Merge A: left_subtree_root = balanced_tree(txs[28..30]) + right_subtree_root = balanced_tree(txs[30]) = txs[30] + Merge 0: root = left_subtree_root | right_subtree_root + } + Merge 1: root = left_subtree_root | right_subtree_root + } + Merge 2: root = left_subtree_root | right_subtree_root + } + root = left_subtree_root | right_subtree_root +``` +An unrolled recursive algorithm is not the easiest thing to read. This diagram represents the 31 transactions rolled up in our wonky structure, where each `Merge ` is a 'subroot' above: + +```mermaid +graph BT + M2_c[Merge 2] + M3_c[Merge D + Subtree of 16 txs] + R_c[Root] + + + B4_c[Merge C + Subtree of 8 txs] + B5_c[Merge 1] + + B4_c --> M2_c + B5_c --> M2_c + + B6_c[Merge B + Subtree of 4 txs] + B7_c[Merge 0] + + B6_c --> B5_c + B7_c --> B5_c + + B8_c[Merge A + Subtree of 2 txs] + B9_c[Base 30] + + B8_c --> B7_c + B9_c --> B7_c + + + M3_c --> R_c + M2_c --> R_c +``` +The tree is reconstructed to check the `txs_effects_hash` (= the root of a wonky tree given by leaves of each tx's `tx_effects`) on L1. We also reconstruct it to provide a membership path against the stored `out_hash` (= the root of a wonky tree given by leaves of each tx's L2 to L1 message tree root) for consuming a L2 to L1 message. + +Currently, this tree is built via the [orchestrator](../../../../yarn-project/prover-client/src/orchestrator/proving-state.ts#74) given the number of transactions to rollup (`this.totalNumTxs`). Each 'node' is assigned a level (0 at the root) and index in that level. The below function finds the parent level: + +``` + // Calculates the index and level of the parent rollup circuit + public findMergeLevel(currentLevel: bigint, currentIndex: bigint) { + const moveUpMergeLevel = (levelSize: number, index: bigint, nodeToShift: boolean) => { + levelSize /= 2; + if (levelSize & 1) { + [levelSize, nodeToShift] = nodeToShift ? [levelSize + 1, false] : [levelSize - 1, true]; + } + index >>= 1n; + return { thisLevelSize: levelSize, thisIndex: index, shiftUp: nodeToShift }; + }; + let [thisLevelSize, shiftUp] = this.totalNumTxs & 1 ? [this.totalNumTxs - 1, true] : [this.totalNumTxs, false]; + const maxLevel = this.numMergeLevels + 1n; + let placeholder = currentIndex; + for (let i = 0; i < maxLevel - currentLevel; i++) { + ({ thisLevelSize, thisIndex: placeholder, shiftUp } = moveUpMergeLevel(thisLevelSize, placeholder, shiftUp)); + } + let thisIndex = currentIndex; + let mergeLevel = currentLevel; + while (thisIndex >= thisLevelSize && mergeLevel != 0n) { + mergeLevel -= 1n; + ({ thisLevelSize, thisIndex, shiftUp } = moveUpMergeLevel(thisLevelSize, thisIndex, shiftUp)); + } + return [mergeLevel - 1n, thisIndex >> 1n, thisIndex & 1n]; + } +``` + For example, `Base 4` above starts with `level = 3` and `index = 4`. Since we have an odd number of transactions at this level, `thisLevelSize` is set to 4 with `shiftUp = true`. + + The while loop triggers and shifts up our node to `level = 2` and `index = 2`. This level (containing `Merge 0` and `Merge 1`) is of even length, so the loop continues. The next iteration shifts up to `level = 1` and `index = 1` - we now have an odd level, so the loop stops. The actual position of `Base 4` is therefore at `level = 1` and `index = 1`. This function returns the parent level of the input node, so we return `level = 0`, `index = 0`, correctly indicating that the parent of `Base 4` is the root. + + +### Flexible wonky trees + +We can also encode the structure of *any* binary merkle tree by tracking `number_of_branches` and `number_of_leaves` for each node in the tree. This encoding was originally designed for [logs](../logs/index.md) before they were included in the `txs_effects_hash`, so the below explanation references the leaves stored in relation to logs and transactions. + +The benefit of this method as opposed to the one above is allowing for any binary structure and therefore allowing for 'skipping' leaves with no information. However, the encoding grows as the tree grows, by at least 2 bytes per node. The above implementation only requires the number of leaves to be encoded, which will likely only require a single field to store. + + + +#### Encoding + +1. The encoded logs data of a transaction is a flattened array of all logs data within the transaction: + + _`tx_logs_data = [number_of_logs, ...log_data_0, ...log_data_1, ...]`_ + +2. The encoded logs data of a block is a flatten array of a collection of the above _tx_logs_data_, with hints facilitating hashing replay in a binary tree structure: + + _`block_logs_data = [number_of_branches, number_of_transactions, ...tx_logs_data_0, ...tx_logs_data_1, ...]`_ + + - _number_of_transactions_ is the number of leaves in the left-most branch, restricted to either _1_ or _2_. + - _number_of_branches_ is the depth of the parent node of the left-most leaf. + +Here is a step-by-step example to construct the _`block_logs_data`_: + +1. A rollup, _R01_, merges two transactions: _tx0_ containing _tx_logs_data_0_, and _tx1_ containing _tx_logs_data_1_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + ``` + + _block_logs_data_: _`[0, 2, ...tx_logs_data_0, ...tx_logs_data_1]`_ + + Where _0_ is the depth of the node _R01_, and _2_ is the number of aggregated _tx_logs_data_ of _R01_. + +2. Another rollup, _R23_, merges two transactions: _tx3_ containing _tx_logs_data_3_, and _tx2_ without any logs: + + ```mermaid + flowchart BT + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -. no logs .- R23 + tx3 --- R23 + ``` + + _block_logs_data_: _`[0, 1, ...tx_logs_data_3]`_ + + Here, the number of aggregated _tx_logs_data_ is _1_. + +3. A rollup, _RA_, merges the two rollups _R01_ and _R23_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -.- R23 + tx3 --- R23 + RA((RA)) + R01 --- RA + R23 --- RA + ``` + + _block_logs_data_: _`[1, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3]`_ + + The result is the _block_logs_data_ of _R01_ concatenated with the _block_logs_data_ of _R23_, with the _number_of_branches_ of _R01_ incremented by _1_. The updated value of _number_of_branches_ (_0 + 1_) is also the depth of the node _R01_. + +4. A rollup, _RB_, merges the above rollup _RA_ and another rollup _R45_: + + ```mermaid + flowchart BT + tx0((tx0)) + tx1((tx1)) + R01((R01)) + tx0 --- R01 + tx1 --- R01 + tx2((tx2)) + tx3((tx3)) + R23((R23)) + tx2 -.- R23 + tx3 --- R23 + RA((RA)) + R01 --- RA + R23 --- RA + tx4((tx4)) + tx5((tx5)) + R45((R45)) + tx4 --- R45 + tx5 --- R45 + RB((RB)) + RA --- RB + R45 --- RB + ``` + + _block_logs_data_: _`[2, 2, ...tx_logs_data_0, ...tx_logs_data_1, 0, 1, ...tx_logs_data_3, 0, 2, ...tx_logs_data_4, ...tx_logs_data_5]`_ + + The result is the concatenation of the _block_logs_data_ from both rollups, with the _number_of_branches_ of the left-side rollup, _RA_, incremented by _1_. + +#### Verification + +Upon receiving a proof and its encoded logs data, the entity can ensure the correctness of the provided _block_logs_data_ by verifying that the _accumulated_logs_hash_ in the proof can be derived from it: + +```js +const accumulated_logs_hash = compute_accumulated_logs_hash(block_logs_data); +assert(accumulated_logs_hash == proof.accumulated_logs_hash); +assert(block_logs_data.accumulated_logs_length == proof.accumulated_logs_length); + +function compute_accumulated_logs_hash(logs_data) { + const number_of_branches = logs_data.read_u32(); + + const number_of_transactions = logs_data.read_u32(); + let res = hash_tx_logs_data(logs_data); + if number_of_transactions == 2 { + res = hash(res, hash_tx_logs_data(logs_data)); + } + + for (let i = 0; i < number_of_branches; ++i) { + const res_right = compute_accumulated_logs_hash(logs_data); + res = hash(res, res_right); + } + + return res; +} + +function hash_tx_logs_data(logs_data) { + const number_of_logs = logs_data.read_u32(); + let res = hash_log_data(logs_data); + for (let i = 1; i < number_of_logs; ++i) { + const log_hash = hash_log_data(logs_data); + res = hash(res, log_hash); + } + return res; +} +``` \ No newline at end of file diff --git a/docs/docs/protocol-specs/transactions/tx-object.md b/docs/docs/protocol-specs/transactions/tx-object.md index 9bec884dcfd5..821927edb39e 100644 --- a/docs/docs/protocol-specs/transactions/tx-object.md +++ b/docs/docs/protocol-specs/transactions/tx-object.md @@ -40,12 +40,12 @@ Output of the last iteration of the private kernel circuit. Includes _accumulate | Field | Type | Description | |-------|------|-------------| -| newNoteHashes | Field[] | The new note hashes made in this transaction. | -| newNullifiers | Field[] | The new nullifiers made in this transaction. | +| noteHashes | Field[] | The new note hashes made in this transaction. | +| nullifiers | Field[] | The new nullifiers made in this transaction. | | nullifiedNoteHashes | Field[] | The note hashes which are nullified by a nullifier in the above list. | | privateCallStack | Field[] | Current private call stack. | | publicCallStack | Field[] | Current public call stack. | -| newL2ToL1Msgs | Field[] | All the new L2 to L1 messages created in this transaction. | +| l2ToL1Msgs | Field[] | All the new L2 to L1 messages created in this transaction. | | encryptedLogsHash | Field[] | Accumulated encrypted logs hash from all the previous kernel iterations. | | unencryptedLogsHash | Field[] | Accumulated unencrypted logs hash from all the previous kernel iterations. | | encryptedLogPreimagesLength | Field | Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations. | diff --git a/docs/docs/reference/smart_contract_reference/history_lib_reference.md b/docs/docs/reference/smart_contract_reference/history_lib_reference.md index 825d2ddb8ccd..a717c3fb9e60 100644 --- a/docs/docs/reference/smart_contract_reference/history_lib_reference.md +++ b/docs/docs/reference/smart_contract_reference/history_lib_reference.md @@ -7,43 +7,26 @@ sidebar_position: 3 ## Note inclusion -Note inclusion proves that a note existed (its hash was included in a note hash tree) at a specific block number. There exists a version that tests for note inclusion at current block number. It is recommended to use this version whenever possible to reduce cost. +Note inclusion proves that a note existed (its hash was included in a note hash tree) in a block header. ### prove_note_inclusion -`prove_note_inclusion_at` takes 3 parameters: +`prove_note_inclusion` takes 1 parameter: -| Name | Type | Description | -| ---------------- | -------------- | ----------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| ---- | ---- | -------------------------------------- | +| note | Note | The note you are proving inclusion for | -## prove_note_commitment_inclusion +#### Example -A **commitment**, also referred to as a **note hash** is a public acknowledgment of the existence of a note without revealing the content of the note. You can learn more about how to compress a note to a note hash [here](../../aztec/concepts/storage/trees/index.md#example-note). - -`prove_note_commitment_inclusion` takes 2 parameters: - -| Name | Type | Description | -| ---------------- | -------------- | -------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_note_inclusion noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust ## Note validity -This proves that a note exists and has not been nullified at a specified block. Again as above, there exists a version that tests for validity at current block. It is recommended to use this version whenever possible to reduce cost. +This proves that a note exists and has not been nullified in a specific block header. ### prove_note_validity -`prove_note_validity_at` takes 3 parameters: - -| Name | Type | Description | -| ---------------- | -------------- | ----------------------------------------- | -| note_with_header | Note | The note you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | - `prove_note_validity` takes 2 parameters: | Name | Type | Description | @@ -51,56 +34,58 @@ This proves that a note exists and has not been nullified at a specified block. | note_with_header | Note | The note you are proving inclusion for | | context | PrivateContext | Private context | +#### Example + +#include_code prove_note_validity noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + ## Nullifier inclusion -This proves that a nullifier was included in a certain block (can be used to prove that a note had been nullified). The same disclaimer above holds true for this, and subsequent functions that specify another version without a block_number argument. +This proves that a nullifier exists in a given block header (can be used to prove that a note had been nullified). ### prove_nullifier_inclusion -`prove_nullifier_inclusion_at` takes 3 parameters: +`prove_nullifier_inclusion` takes 1 parameter: -| Name | Type | Description | -| ------------ | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| --------- | ----- | ------------------------------------------- | +| nullifier | Field | The nullifier you are proving inclusion for | -`prove_nullifier_inclusion` takes 2 parameters: +#### Example -| Name | Type | Description | -| --------- | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_nullifier_inclusion noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust -### prove_note_is_nullified_at / prove_note_is_nullified +### prove_note_is_nullified Instead of passing the nullifier, you can check that a note has been nullified by passing the note. +#### Implementation + +#include_code prove_note_is_nullified noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr rust + ## Nullifier non inclusion -This proves that a nullifier was not included in a certain block (can be used to prove that a note had not yet been nullified in a given block). +This proves that a nullifier was not included in a certain block, given the block header (can be used to prove that a note had not yet been nullified in a given block). -### prove_nullifier_not_included +### prove_nullifier_non_inclusion -`prove_nullifier_not_included_at` takes 3 parameters: +`prove_nullifier_non_inclusion` takes 1 parameters: -| Name | Type | Description | -| ------------ | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| block_number | u32 | Block number for proving note's existence | -| context | PrivateContext | Private context | +| Name | Type | Description | +| --------- | ----- | ------------------------------------------- | +| nullifier | Field | The nullifier you are proving inclusion for | -`prove_nullifier_not_included` takes 2 parameters: +#### Example -| Name | Type | Description | -| --------- | -------------- | ------------------------------------------- | -| nullifier | Field | The nullifier you are proving inclusion for | -| context | PrivateContext | Private context | +#include_code prove_nullifier_non_inclusion noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr rust -### prove_note_not_nullified_at / prove_note_not_nullified +### prove_note_not_nullified Instead of passing the nullifier, you can check that a note has not been nullified by passing the note. +#### Implementation + +#include_code prove_note_not_nullified noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr rust + ## Public storage historical reads These return the value stored in a public storage slot of a given contract at the end of the execution of a certain block (the latest one if using `public_storage_historical_read`). @@ -109,36 +94,65 @@ Note that it is never possible to read the _current_ value in a public storage s ### public_storage_historical_read -`public_storage_historical_read_at` takes 4 parameters: +`public_storage_historical_read` takes 2 parameters: -| Name | Type | Description | -| ---------------- | -------------- | ---------------------------------------- | -| context | PrivateContext | Private context | -| storage_slot | Field | Storage slot | -| contract_address | AztecAddress | The contract that owns the storage slot | -| block_number | u32 | Historical block number in which to read | +| Name | Type | Description | +| ---------------- | ------------ | --------------------------------------- | +| storage_slot | Field | Storage slot | +| contract_address | AztecAddress | The contract that owns the storage slot | -`public_storage_historical_read` takes 3 parameters. `block_number` is implicitly the historical block number from the context: +#### Example -| Name | Type | Description | -| ---------------- | -------------- | --------------------------------------- | -| context | PrivateContext | Private context | -| storage_slot | Field | Storage slot | -| contract_address | AztecAddress | The contract that owns the storage slot | +#include_code public_storage_historical_read noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust ## Contract inclusion This proves that a contract exists in, ie had been deployed before or in, a certain block. -### prove_contract_inclusion +### prove_contract_deployment + +`prove_contract_deployment` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove deployment of | + +#### Example + +#include_code prove_contract_deployment noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_non_deployment + +`prove_contract_non_deployment` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ----------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove non-deployment of | + +#### Example + +#include_code prove_contract_non_deployment noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_initialization + +`prove_contract_initialization` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | ----------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove initialization of | + +#### Example + +#include_code prove_contract_initialization noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust + +### prove_contract_non_initialization + +`prove_contract_non_initialization` takes 1 parameter: + +| Name | Type | Description | +| ---------------- | ------------ | --------------------------------------------------- | +| contract_address | AztecAddress | The contract address to prove non-initialization of | -`prove_contract_inclusion_at` takes 7 parameters: +#### Example -| Name | Type | Description | -| --------------------- | -------------- | -------------------------------------------- | -| deployer_public_key | GrumpkinPoint | Public key of the contract deployer | -| contract_address_salt | Field | Unique identifier for the contract's address | -| function_tree_root | Field | Root of the contract's function tree | -| constructor_hash | Field | Hash of the contract's constructor | -| block_number | u32 | Block number for proof verification | -| context | PrivateContext | Private context | +#include_code prove_contract_non_initialization noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr rust diff --git a/docs/docs/reference/smart_contract_reference/macros.md b/docs/docs/reference/smart_contract_reference/macros.md new file mode 100644 index 000000000000..91798ffbcd21 --- /dev/null +++ b/docs/docs/reference/smart_contract_reference/macros.md @@ -0,0 +1,19 @@ +--- +title: Aztec macros +sidebar_position: 6 +--- + +## All Aztec macros + +In addition to the function macros in Noir, Aztec also has its own macros for specific functions. An Aztec contract function can be annotated with more than 1 macro. +It is also worth mentioning Noir's `unconstrained` function type [here](https://noir-lang.org/docs/noir/concepts/unconstrained/). + +- `#[aztec(public)]` or `#[aztec(private)]` - Whether the function is to be executed from a public or private context (see Further Reading) +- `#[aztec(initializer)]` - If one or more functions are marked as an initializer, then one of them must be called before any non-initilizer functions +- `#[aztec(noinitcheck)]` - The function is able to be called before an initializer (if one exists) +- `#[aztec(view)]` - Makes calls to the function static (see also [Static calls](../../../../protocol-specs/calls/static-calls)) +- `#[aztec(internal)]` - Function can only be called from within the contract +- `#[aztec(note)]` - Creates a custom note + +## Further reading +[How do Aztec macros work?](../../aztec/concepts/smart_contracts/functions/inner_workings.md) diff --git a/docs/docs/tutorials/contract_tutorials/advanced/token_bridge/4_typescript_glue_code.md b/docs/docs/tutorials/contract_tutorials/advanced/token_bridge/4_typescript_glue_code.md index 17cb3abec0d9..d00987b585fb 100644 --- a/docs/docs/tutorials/contract_tutorials/advanced/token_bridge/4_typescript_glue_code.md +++ b/docs/docs/tutorials/contract_tutorials/advanced/token_bridge/4_typescript_glue_code.md @@ -39,7 +39,7 @@ Open `cross_chain_messaging.test.ts` and paste the initial description of the te ```typescript import { beforeAll, describe, beforeEach, expect, jest, it} from '@jest/globals' -import { AccountWallet, AztecAddress, BatchCall, type DebugLogger, EthAddress, Fr, computeAuthWitMessageHash, createDebugLogger, createPXEClient, waitForPXE, L1ToL2Message, L1Actor, L2Actor, type Wallet } from '@aztec/aztec.js'; +import { AccountWallet, AztecAddress, BatchCall, type DebugLogger, EthAddress, Fr, computeAuthWitMessageHash, createDebugLogger, createPXEClient, waitForPXE, L1ToL2Message, L1Actor, L2Actor, type PXE, type Wallet } from '@aztec/aztec.js'; import { getInitialTestAccountsWallets } from '@aztec/accounts/testing'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { sha256ToField } from '@aztec/foundation/crypto'; @@ -48,7 +48,6 @@ import { createAztecNodeClient } from '@aztec/circuit-types'; import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment'; import { SchnorrAccountContractArtifact } from '@aztec/accounts/schnorr'; - import { CrossChainTestHarness } from './shared/cross_chain_test_harness.js'; import { mnemonicToAccount } from 'viem/accounts'; import { createPublicClient, createWalletClient, http, toFunctionSelector } from 'viem'; @@ -61,14 +60,21 @@ const aztecNode = createAztecNodeClient(PXE_URL); export const NO_L1_TO_L2_MSG_ERROR = /No non-nullified L1 to L2 message found for message hash|Tried to consume nonexistent L1-to-L2 message/; -async function publicDeployAccounts(sender: Wallet, accountsToDeploy: Wallet[]) { - const accountAddressesToDeploy = accountsToDeploy.map(a => a.getAddress()); - const instances = await Promise.all(accountAddressesToDeploy.map(account => sender.getContractInstance(account))); - const batch = new BatchCall(sender, [ - (await registerContractClass(sender, SchnorrAccountContractArtifact)).request(), - ...instances.map(instance => deployInstance(sender, instance!).request()), - ]); - await batch.send().wait(); +async function publicDeployAccounts(sender: Wallet, accountsToDeploy: Wallet[], pxe: PXE) { + const accountAddressesToDeploy = await Promise.all( + accountsToDeploy.map(async a => { + const address = await a.getAddress(); + const isDeployed = await pxe.isContractPubliclyDeployed(address); + return { address, isDeployed }; + }) + ).then(results => results.filter(result => !result.isDeployed).map(result => result.address)); + if (accountAddressesToDeploy.length === 0) return + const instances = await Promise.all(accountAddressesToDeploy.map(account => sender.getContractInstance(account))); + const batch = new BatchCall(sender, [ + (await registerContractClass(sender, SchnorrAccountContractArtifact)).request(), + ...instances.map(instance => deployInstance(sender, instance!).request()), + ]); + await batch.send().wait(); } describe('e2e_cross_chain_messaging', () => { @@ -93,7 +99,7 @@ describe('e2e_cross_chain_messaging', () => { wallets = await getInitialTestAccountsWallets(pxe); // deploy the accounts publicly to use public authwits - await publicDeployAccounts(wallets[0], wallets); + await publicDeployAccounts(wallets[0], wallets, pxe); }) beforeEach(async () => { @@ -127,7 +133,6 @@ describe('e2e_cross_chain_messaging', () => { outbox = crossChainTestHarness.outbox; user1Wallet = wallets[0]; user2Wallet = wallets[1]; - logger('Successfully deployed contracts and initialized portal'); }); ``` diff --git a/docs/sidebars.js b/docs/sidebars.js index 9e9383590d82..0093b1ab1b07 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -109,6 +109,7 @@ export default { "protocol-specs/state/note-hash-tree", "protocol-specs/state/nullifier-tree", "protocol-specs/state/public-data-tree", + "protocol-specs/state/wonky-tree", ], }, { diff --git a/docs/src/katex-macros.js b/docs/src/katex-macros.js index f60a6f0b66b9..ee4e8d907380 100644 --- a/docs/src/katex-macros.js +++ b/docs/src/katex-macros.js @@ -1,80 +1,75 @@ module.exports = { - "\\sk": "\\color{red}{sk}\\color{black}{}", - "\\seed": "\\color{red}\\text{{seed}}\\color{black}{}", - "\\nskm": "\\color{red}{nsk_m}\\color{black}{}", - "\\tskm": "\\color{red}{tsk_m}\\color{black}{}", - "\\ivskm": "\\color{red}{ivsk_m}\\color{black}{}", - "\\ovskm": "\\color{red}{ovsk_m}\\color{black}{}", - - "\\Npkm": "\\color{green}{Npk_m}\\color{black}{}", - "\\Tpkm": "\\color{green}{Tpk_m}\\color{black}{}", - "\\Ivpkm": "\\color{green}{Ivpk_m}\\color{black}{}", - "\\Ovpkm": "\\color{green}{Ovpk_m}\\color{black}{}", - - "\\address": "\\color{green}{address}\\color{black}{}", - "\\codehash": "\\color{green}{code_hash}\\color{black}{}", - "\\constructorhash": "\\color{green}{constructor_hash}\\color{black}{}", - "\\classid": "\\color{green}{classid}\\color{black}{}", - - "\\nskapp": "\\color{red}{nsk_{app}}\\color{black}{}", - "\\tskapp": "\\color{red}{tsk_{app}}\\color{black}{}", - "\\ivskapp": "\\color{red}{ivsk_{app}}\\color{black}{}", - "\\ovskapp": "\\color{red}{ovsk_{app}}\\color{black}{}", - - "\\Nkapp": "\\color{orange}{Nk_{app}}\\color{black}{}", - - "\\Npkapp": "\\color{green}{Npk_{app}}\\color{black}{}", - - "\\Ivpkapp": "\\color{green}{Ivpk_{app}}\\color{black}{}", - - "\\happL": "\\color{green}{h_{app}^L}\\color{black}{}", - "\\happn": "\\color{green}{h_{app}^n}\\color{black}{}", - "\\happiv": "\\color{green}{h_{app}^{iv}}\\color{black}{}", - - "\\d": "\\color{green}{d}\\color{black}{}", - "\\Gd": "\\color{green}{G_d}\\color{black}{}", - - "\\Ivpkappd": "\\color{violet}{Ivpk_{app,d}}\\color{black}{}", - "\\shareableIvpkappd": - "\\color{violet}{\\widetilde{Ivpk_{app,d}}}\\color{black}{}", - "\\Ivpkmd": "\\color{violet}{Ivpk_{m,d}}\\color{black}{}", - "\\shareableIvpkmd": - "\\color{violet}{\\widetilde{Ivpk_{m,d}}}\\color{black}{}", - - "\\ivskappstealth": "\\color{red}{ivsk_{app,stealth}}\\color{black}{}", - "\\Ivpkappdstealth": "\\color{violet}{Ivpk_{app,d,stealth}}\\color{black}{}", - "\\Pkappdstealth": "\\color{violet}{Pk_{app,d,stealth}}\\color{black}{}", - "\\ivskmstealth": "\\color{red}{ivsk_{m,stealth}}\\color{black}{}", - "\\Ivpkmdstealth": "\\color{violet}{Ivpk_{m,d,stealth}}\\color{black}{}", - "\\Pkmdstealth": "\\color{violet}{Pk_{m,d,stealth}}\\color{black}{}", - - "\\hstealth": "\\color{violet}{h_{stealth}}\\color{black}{}", - - "\\esk": "\\color{red}{esk}\\color{black}{}", - "\\Epk": "\\color{green}{Epk}\\color{black}{}", - "\\Epkd": "\\color{green}{Epk_d}\\color{black}{}", - "\\eskheader": "\\color{red}{esk_{header}}\\color{black}{}", - "\\Epkheader": "\\color{green}{Epk_{header}}\\color{black}{}", - "\\Epkdheader": "\\color{green}{Epk_{d,header}}\\color{black}{}", - - "\\sharedsecret": "\\color{violet}{\\text{S}}\\color{black}{}", - "\\sharedsecretmheader": - "\\color{violet}{\\text{S_{m,header}}}\\color{black}{}", - "\\sharedsecretappheader": - "\\color{violet}{\\text{S_{app,header}}}\\color{black}{}", - - "\\hmencheader": "\\color{violet}{h_{m,enc,header}}\\color{black}{}", - "\\happencheader": "\\color{violet}{h_{app,enc,header}}\\color{black}{}", - "\\hmenc": "\\color{violet}{h_{m,enc}}\\color{black}{}", - "\\happenc": "\\color{violet}{h_{app,enc}}\\color{black}{}", - "\\incomingenckey": "\\color{violet}{h_{incoming_enc_key}}\\color{black}{}", - - "\\plaintext": "\\color{red}{\\text{plaintext}}\\color{black}{}", - "\\ciphertext": "\\color{green}{\\text{ciphertext}}\\color{black}{}", - "\\ciphertextheader": - "\\color{green}{\\text{ciphertext\\_header}}\\color{black}{}", - "\\payload": "\\color{green}{\\text{payload}}\\color{black}{}", - - "\\tagg": "\\color{green}{\\text{tag}}\\color{black}{}", - "\\Taghs": "\\color{green}{\\text{Tag}\\_{hs}}\\color{black}{}", + "\\sk": "{\\color{red}{sk}}", + "\\seed": "{\\color{red}\\text{{seed}}}", + "\\nskm": "{\\color{red}{nsk_m}}", + "\\tskm": "{\\color{red}{tsk_m}}", + "\\ivskm": "{\\color{red}{ivsk_m}}", + "\\ovskm": "{\\color{red}{ovsk_m}}", + + "\\Npkm": "{\\color{green}{Npk_m}}", + "\\Tpkm": "{\\color{green}{Tpk_m}}", + "\\Ivpkm": "{\\color{green}{Ivpk_m}}", + "\\Ovpkm": "{\\color{green}{Ovpk_m}}", + + "\\address": "{\\color{green}{address}}", + "\\codehash": "{\\color{green}{code_hash}}", + "\\constructorhash": "{\\color{green}{constructor_hash}}", + "\\classid": "{\\color{green}{classid}}", + + "\\nskapp": "{\\color{red}{nsk_{app}}}", + "\\tskapp": "{\\color{red}{tsk_{app}}}", + "\\ivskapp": "{\\color{red}{ivsk_{app}}}", + "\\ovskapp": "{\\color{red}{ovsk_{app}}}", + + "\\Nkapp": "{\\color{orange}{Nk_{app}}}", + + "\\Npkapp": "{\\color{green}{Npk_{app}}}", + + "\\Ivpkapp": "{\\color{green}{Ivpk_{app}}}", + + "\\happL": "{\\color{green}{h_{app}^L}}", + "\\happn": "{\\color{green}{h_{app}^n}}", + "\\happiv": "{\\color{green}{h_{app}^{iv}}}", + + "\\d": "{\\color{green}{d}}", + "\\Gd": "{\\color{green}{G_d}}", + + "\\Ivpkappd": "{\\color{violet}{Ivpk_{app,d}}}", + "\\shareableIvpkappd": "{\\color{violet}{\\widetilde{Ivpk_{app,d}}}}", + "\\Ivpkmd": "{\\color{violet}{Ivpk_{m,d}}}", + "\\shareableIvpkmd": "{\\color{violet}{\\widetilde{Ivpk_{m,d}}}}", + + "\\ivskappstealth": "{\\color{red}{ivsk_{app,stealth}}}", + "\\Ivpkappdstealth": "{\\color{violet}{Ivpk_{app,d,stealth}}}", + "\\Pkappdstealth": "{\\color{violet}{Pk_{app,d,stealth}}}", + "\\ivskmstealth": "{\\color{red}{ivsk_{m,stealth}}}", + "\\Ivpkmdstealth": "{\\color{violet}{Ivpk_{m,d,stealth}}}", + "\\Pkmdstealth": "{\\color{violet}{Pk_{m,d,stealth}}}", + + "\\hstealth": "{\\color{violet}{h_{stealth}}}", + + "\\esk": "{\\color{red}{esk}}", + "\\Epk": "{\\color{green}{Epk}}", + "\\Epkd": "{\\color{green}{Epk_d}}", + "\\eskheader": "{\\color{red}{esk_{header}}}", + "\\Epkheader": "{\\color{green}{Epk_{header}}}", + "\\Epkdheader": "{\\color{green}{Epk_{d,header}}}", + + "\\sharedsecret": "{\\color{violet}{\\text{S}}}", + "\\sharedsecretmheader": "{\\color{violet}{\\text{S_{m,header}}}}", + "\\sharedsecretappheader": "{\\color{violet}{\\text{S_{app,header}}}}", + + "\\hmencheader": "{\\color{violet}{h_{m,enc,header}}}", + "\\happencheader": "{\\color{violet}{h_{app,enc,header}}}", + "\\hmenc": "{\\color{violet}{h_{m,enc}}}", + "\\happenc": "{\\color{violet}{h_{app,enc}}}", + "\\incomingenckey": "{\\color{violet}{h_{incoming_enc_key}}}", + + "\\plaintext": "{\\color{red}{\\text{plaintext}}}", + "\\ciphertext": "{\\color{green}{\\text{ciphertext}}}", + "\\ciphertextheader": "{\\color{green}{\\text{ciphertext\\_header}}}", + "\\payload": "{\\color{green}{\\text{payload}}}", + + "\\tagg": "{\\color{green}{\\text{tag}}}", + "\\Taghs": "{\\color{green}{\\text{Tag}\\_{hs}}}", }; diff --git a/docs/src/preprocess/InstructionSet/InstructionSet.js b/docs/src/preprocess/InstructionSet/InstructionSet.js index 492236d3c1cf..129a41a6e1ab 100644 --- a/docs/src/preprocess/InstructionSet/InstructionSet.js +++ b/docs/src/preprocess/InstructionSet/InstructionSet.js @@ -550,27 +550,8 @@ const INSTRUCTION_SET_RAW = [ "Tag updates": "`T[dstOffset] = field`", }, { - id: "feeperl2gas", - Name: "`FEEPERL2GAS`", - Category: "Execution Environment", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.feePerL2Gas`", - Summary: - 'Get the fee to be paid per "L2 gas" - constant for entire transaction', - Details: "", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, - { - id: "feeperdagas", - Name: "`FEEPERDAGAS`", + id: "functionselector", + Name: "`FUNCTIONSELECTOR`", Category: "Execution Environment", Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], Args: [ @@ -580,12 +561,11 @@ const INSTRUCTION_SET_RAW = [ "memory offset specifying where to store operation's result", }, ], - Expression: "`M[dstOffset] = context.environment.feePerDaGas`", - Summary: - 'Get the fee to be paid per "DA gas" - constant for entire transaction', + Expression: "`M[dstOffset] = context.environment.functionSelector`", + Summary: "Get the function selector of the contract function being executed", Details: "", "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", + "Tag updates": "`T[dstOffset] = u32`", }, { id: "transactionfee", @@ -606,25 +586,6 @@ const INSTRUCTION_SET_RAW = [ "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", }, - { - id: "contractcalldepth", - Name: "`CONTRACTCALLDEPTH`", - Category: "Execution Environment", - Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], - Args: [ - { - name: "dstOffset", - description: - "memory offset specifying where to store operation's result", - }, - ], - Expression: "`M[dstOffset] = context.environment.contractCallDepth`", - Summary: "Get how many contract calls deep the current call context is", - Details: - "Note: security issues with EVM's tx.origin can be resolved by asserting `calldepth == 0`.", - "Tag checks": "", - "Tag updates": "`T[dstOffset] = field`", - }, { id: "chainid", Name: "`CHAINID`", @@ -710,7 +671,45 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.coinbase`", - Summary: "Get the block's beneficiary address", + Summary: "(UNIMPLEMENTED) Get the block's beneficiary address", + Details: "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + id: "feeperl2gas", + Name: "`FEEPERL2GAS`", + Category: "Execution Environment - Globals - Gas", + Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], + Args: [ + { + name: "dstOffset", + description: + "memory offset specifying where to store operation's result", + }, + ], + Expression: "`M[dstOffset] = context.environment.globals.feePerL2Gas`", + Summary: + 'Get the fee to be paid per "L2 gas" - constant for entire transaction', + Details: "", + "Tag checks": "", + "Tag updates": "`T[dstOffset] = field`", + }, + { + id: "feeperdagas", + Name: "`FEEPERDAGAS`", + Category: "Execution Environment - Globals - Gas", + Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], + Args: [ + { + name: "dstOffset", + description: + "memory offset specifying where to store operation's result", + }, + ], + Expression: "`M[dstOffset] = context.environment.globals.feePerDaGas`", + Summary: + 'Get the fee to be paid per "DA gas" - constant for entire transaction', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -728,7 +727,7 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.l2GasLimit`", - Summary: 'Total amount of "L2 gas" that a block can consume', + Summary: '(UNIMPLEMENTED) Total amount of "L2 gas" that a block can consume', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -746,7 +745,7 @@ const INSTRUCTION_SET_RAW = [ }, ], Expression: "`M[dstOffset] = context.environment.globals.daGasLimit`", - Summary: 'Total amount of "DA gas" that a block can consume', + Summary: '(UNIMPLEMENTED) Total amount of "DA gas" that a block can consume', Details: "", "Tag checks": "", "Tag updates": "`T[dstOffset] = field`", @@ -1120,7 +1119,7 @@ context.worldState.noteHashes.append( `, Summary: "Emit a new note hash to be inserted into the note hash tree", "World State access tracing": ` -context.worldStateAccessTrace.newNoteHashes.append( +context.worldStateAccessTrace.noteHashes.append( TracedNoteHash { callPointer: context.environment.callPointer, noteHash: M[noteHashOffset], // unsiloed note hash @@ -1192,7 +1191,7 @@ context.worldState.nullifiers.append( `, Summary: "Emit a new nullifier to be inserted into the nullifier tree", "World State access tracing": ` -context.worldStateAccessTrace.newNullifiers.append( +context.worldStateAccessTrace.nullifiers.append( TracedNullifier { callPointer: context.environment.callPointer, nullifier: M[nullifierOffset], // unsiloed nullifier @@ -1287,7 +1286,7 @@ if exists: M[dstOffset] = header[M[memberIndexOffset]] // member `, Summary: - "Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so", + "(UNIMPLEMENTED) Check if a header exists in the [archive tree](../state/archive) and retrieve the specified member if so", "World State access tracing": ` context.worldStateAccessTrace.archiveChecks.append( TracedArchiveLeafCheck { @@ -1343,24 +1342,17 @@ M[dstOffset:dstOffset+CONTRACT_INSTANCE_SIZE+1] = [ Category: "Accrued Substate - Logging", Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }], Args: [ - { - name: "eventSelectorOffset", - description: "memory offset of the event selector", - }, { name: "logOffset", description: "memory offset of the data to log" }, { - name: "logSize", - description: "number of words to log", - mode: "immediate", - type: "u32", + name: "logSizeOffset", + description: "memory offset to number of words to log", }, ], Expression: ` context.accruedSubstate.unencryptedLogs.append( UnencryptedLog { address: context.environment.address, - eventSelector: M[eventSelectorOffset], - log: M[logOffset:logOffset+logSize], + log: M[logOffset:logOffset+M[logSizeOffset]], } ) `, @@ -1469,7 +1461,7 @@ execute(nestedContext) updateContextAfterNestedCall(context, instr.args, nestedContext) `, Summary: - "Call into another contract, but keep the caller's `sender` and `storageAddress`", + "(UNIMPLEMENTED) Call into another contract, but keep the caller's `sender` and `storageAddress`", Details: `Same as \`CALL\`, but \`sender\` and \`storageAddress\` remains the same in the nested call as they were in the caller. ` + diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 2ac9123a82f9..130463085715 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -16,6 +16,7 @@ import {HeaderLib} from "./libraries/HeaderLib.sol"; import {Hash} from "./libraries/Hash.sol"; import {Errors} from "./libraries/Errors.sol"; import {Constants} from "./libraries/ConstantsGen.sol"; +import {MerkleLib} from "./libraries/MerkleLib.sol"; import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol"; // Contracts @@ -149,10 +150,10 @@ contract Rollup is IRollup { revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); } - // Currently trying out storing each tx's L2 to L1 messages in variable height trees (smallest tree required) - // => path lengths will differ and we cannot provide one here - // We can provide a minimum which is the height of the rollup layers (txTreeHeight) and the smallest 'tree' (1 layer) - uint256 l2ToL1TreeMinHeight = header.contentCommitment.txTreeHeight + 1; + // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim + // Min size = smallest path of the rollup tree + 1 + (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); + uint256 l2ToL1TreeMinHeight = min + 1; OUTBOX.insert( header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight ); diff --git a/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol b/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol index c01b2f378f13..6eba97fca437 100644 --- a/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol +++ b/l1-contracts/src/core/interfaces/messagebridge/IOutbox.sol @@ -11,7 +11,7 @@ import {DataStructures} from "../../libraries/DataStructures.sol"; * and will be consumed by the portal contracts. */ interface IOutbox { - event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root, uint256 height); + event RootAdded(uint256 indexed l2BlockNumber, bytes32 indexed root, uint256 minHeight); event MessageConsumed( uint256 indexed l2BlockNumber, bytes32 indexed root, diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index e031af8cbd8b..8059d997c241 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -15,33 +15,33 @@ library Constants { uint256 internal constant MAX_FIELD_VALUE = P - 1; uint256 internal constant ARGS_LENGTH = 16; - uint256 internal constant MAX_NEW_NOTE_HASHES_PER_CALL = 16; - uint256 internal constant MAX_NEW_NULLIFIERS_PER_CALL = 16; + uint256 internal constant MAX_NOTE_HASHES_PER_CALL = 16; + uint256 internal constant MAX_NULLIFIERS_PER_CALL = 16; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; - uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; + uint256 internal constant MAX_L2_TO_L1_MSGS_PER_CALL = 2; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 32; uint256 internal constant MAX_PUBLIC_DATA_READS_PER_CALL = 32; - uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; - uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 32; - uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 32; + uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 16; + uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 16; + uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_KEY_VALIDATION_REQUESTS_PER_CALL = 16; uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; 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_NOTE_HASHES_PER_TX = 64; + uint256 internal constant MAX_NULLIFIERS_PER_TX = 64; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; uint256 internal constant MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; uint256 internal constant MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 63; uint256 internal constant PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 1; uint256 internal constant MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 64; uint256 internal constant MAX_PUBLIC_DATA_READS_PER_TX = 64; - uint256 internal constant MAX_NEW_L2_TO_L1_MSGS_PER_TX = 8; - uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; - uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 128; - uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 128; + uint256 internal constant MAX_L2_TO_L1_MSGS_PER_TX = 8; + uint256 internal constant MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 64; + uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 64; + uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 64; uint256 internal constant MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX = 64; uint256 internal constant MAX_KEY_VALIDATION_REQUESTS_PER_TX = 64; uint256 internal constant MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; @@ -149,22 +149,22 @@ library Constants { uint256 internal constant TX_REQUEST_LENGTH = 13; uint256 internal constant TOTAL_FEES_LENGTH = 1; uint256 internal constant HEADER_LENGTH = 23; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 457; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 578; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 460; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 393; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 482; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 396; uint256 internal constant PUBLIC_CONTEXT_INPUTS_LENGTH = 41; uint256 internal constant AGGREGATION_OBJECT_LENGTH = 16; uint256 internal constant SCOPED_READ_REQUEST_LEN = 3; uint256 internal constant PUBLIC_DATA_READ_LENGTH = 2; - uint256 internal constant VALIDATION_REQUESTS_LENGTH = 1602; + uint256 internal constant VALIDATION_REQUESTS_LENGTH = 1026; uint256 internal constant PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; uint256 internal constant COMBINED_ACCUMULATED_DATA_LENGTH = 333; uint256 internal constant COMBINED_CONSTANT_DATA_LENGTH = 40; uint256 internal constant CALL_REQUEST_LENGTH = 7; uint256 internal constant PRIVATE_ACCUMULATED_DATA_LENGTH = 1152; - uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2803; + uint256 internal constant PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2227; uint256 internal constant PUBLIC_ACCUMULATED_DATA_LENGTH = 983; - uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3834; + uint256 internal constant PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3258; uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 383; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 14; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 31; @@ -183,4 +183,30 @@ library Constants { uint256 internal constant RECURSIVE_PROOF_LENGTH = 93; uint256 internal constant NESTED_RECURSIVE_PROOF_LENGTH = 109; uint256 internal constant VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; + uint256 internal constant SENDER_SELECTOR = 0; + uint256 internal constant ADDRESS_SELECTOR = 1; + uint256 internal constant STORAGE_ADDRESS_SELECTOR = 1; + uint256 internal constant FUNCTION_SELECTOR_SELECTOR = 2; + uint256 internal constant START_GLOBAL_VARIABLES = 29; + uint256 internal constant CHAIN_ID_SELECTOR = 29; + uint256 internal constant VERSION_SELECTOR = 30; + uint256 internal constant BLOCK_NUMBER_SELECTOR = 31; + uint256 internal constant TIMESTAMP_SELECTOR = 32; + uint256 internal constant COINBASE_SELECTOR = 33; + uint256 internal constant UNUSED_FEE_RECIPIENT_SELECTOR = 34; + uint256 internal constant FEE_PER_DA_GAS_SELECTOR = 35; + uint256 internal constant FEE_PER_L2_GAS_SELECTOR = 36; + uint256 internal constant END_GLOBAL_VARIABLES = 37; + uint256 internal constant START_SIDE_EFFECT_COUNTER = 37; + uint256 internal constant TRANSACTION_FEE_SELECTOR = 40; + uint256 internal constant START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; + uint256 internal constant START_NULLIFIER_EXISTS_OFFSET = 16; + uint256 internal constant START_NULLIFIER_NON_EXISTS_OFFSET = 32; + uint256 internal constant START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET = 48; + uint256 internal constant START_SSTORE_WRITE_OFFSET = 64; + uint256 internal constant START_SLOAD_WRITE_OFFSET = 96; + uint256 internal constant START_EMIT_NOTE_HASH_WRITE_OFFSET = 128; + uint256 internal constant START_EMIT_NULLIFIER_WRITE_OFFSET = 144; + uint256 internal constant START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET = 160; + uint256 internal constant START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = 162; } diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 7481445954dd..e2c82cf54967 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -46,7 +46,7 @@ library Errors { error Rollup__TimestampInFuture(); // 0xbc1ce916 error Rollup__TimestampTooOld(); // 0x72ed9c81 error Rollup__UnavailableTxs(bytes32 txsHash); // 0x414906c3 - error Rollup__InvalidSequencer(address sequencer); + error Rollup__InvalidSequencer(address sequencer); // 0xa127a106 // Registry error Registry__RollupNotRegistered(address rollup); // 0xa1fee4cf @@ -54,6 +54,7 @@ library Errors { //TxsDecoder error TxsDecoder__InvalidLogsLength(uint256 expected, uint256 actual); // 0x829ca981 + error TxsDecoder__TxsTooLarge(uint256 expected, uint256 actual); // 0xc7d44a62 // HeaderLib error HeaderLib__InvalidHeaderSize(uint256 expected, uint256 actual); // 0xf3ccb247 diff --git a/l1-contracts/src/core/libraries/HeaderLib.sol b/l1-contracts/src/core/libraries/HeaderLib.sol index 877c617d7fa6..e461b1381f16 100644 --- a/l1-contracts/src/core/libraries/HeaderLib.sol +++ b/l1-contracts/src/core/libraries/HeaderLib.sol @@ -25,7 +25,7 @@ import {Hash} from "./Hash.sol"; * | 0x0000 | 0x20 | lastArchive.root * | 0x0020 | 0x04 | lastArchive.nextAvailableLeafIndex * | | | ContentCommitment { - * | 0x0024 | 0x20 | txTreeHeight + * | 0x0024 | 0x20 | numTxs * | 0x0044 | 0x20 | txsEffectsHash * | 0x0064 | 0x20 | inHash * | 0x0084 | 0x20 | outHash @@ -90,7 +90,7 @@ library HeaderLib { } struct ContentCommitment { - uint256 txTreeHeight; + uint256 numTxs; bytes32 txsEffectsHash; bytes32 inHash; bytes32 outHash; @@ -163,7 +163,7 @@ library HeaderLib { ); // Reading ContentCommitment - header.contentCommitment.txTreeHeight = uint256(bytes32(_header[0x0024:0x0044])); + header.contentCommitment.numTxs = uint256(bytes32(_header[0x0024:0x0044])); header.contentCommitment.txsEffectsHash = bytes32(_header[0x0044:0x0064]); header.contentCommitment.inHash = bytes32(_header[0x0064:0x0084]); header.contentCommitment.outHash = bytes32(_header[0x0084:0x00a4]); @@ -204,7 +204,7 @@ library HeaderLib { // must match the order in the Header.getFields fields[0] = _header.lastArchive.root; fields[1] = bytes32(uint256(_header.lastArchive.nextAvailableLeafIndex)); - fields[2] = bytes32(_header.contentCommitment.txTreeHeight); + fields[2] = bytes32(_header.contentCommitment.numTxs); fields[3] = _header.contentCommitment.txsEffectsHash; fields[4] = _header.contentCommitment.inHash; fields[5] = _header.contentCommitment.outHash; diff --git a/l1-contracts/src/core/libraries/MerkleLib.sol b/l1-contracts/src/core/libraries/MerkleLib.sol index c7ab82502b0e..89dc020a5a25 100644 --- a/l1-contracts/src/core/libraries/MerkleLib.sol +++ b/l1-contracts/src/core/libraries/MerkleLib.sol @@ -51,4 +51,64 @@ library MerkleLib { revert Errors.MerkleLib__InvalidRoot(_expectedRoot, subtreeRoot, _leaf, _index); } } + + /** + * @notice Computes the minimum and maximum path size of an unbalanced tree. + * @dev Follows structure of rollup circuits by greedy filling subtrees. + * @param _numTxs - The number of txs to form into subtrees. + * @return (min, max) - The min and max path sizes. + */ + function computeMinMaxPathLength(uint256 _numTxs) internal pure returns (uint256, uint256) { + uint256 numTxs = _numTxs < 2 ? 2 : _numTxs; + uint256 numSubtrees = 0; + uint256 currentSubtreeSize = 1; + uint256 currentSubtreeHeight = 0; + uint256 firstSubtreeHeight; + uint256 finalSubtreeHeight; + while (numTxs != 0) { + // If size & txs == 0, the subtree doesn't exist for this number of txs + if (currentSubtreeSize & numTxs == 0) { + currentSubtreeSize <<= 1; + currentSubtreeHeight++; + continue; + } + // Assign the smallest rightmost subtree height + if (numSubtrees == 0) finalSubtreeHeight = currentSubtreeHeight; + // Assign the largest leftmost subtree height + if (numTxs - currentSubtreeSize == 0) firstSubtreeHeight = currentSubtreeHeight; + numTxs -= currentSubtreeSize; + currentSubtreeSize <<= 1; + currentSubtreeHeight++; + numSubtrees++; + } + if (numSubtrees == 1) { + // We have a balanced tree + return (firstSubtreeHeight, firstSubtreeHeight); + } + uint256 min = finalSubtreeHeight + numSubtrees - 1; + uint256 max = firstSubtreeHeight + 1; + return (min, max); + } + + /** + * @notice Calculates a tree height from the amount of elements in the tree + * @dev - This mirrors the function in TestUtil, but assumes _size is an exact power of 2 or = 1 + * @param _size - The number of elements in the tree + */ + function calculateTreeHeightFromSize(uint256 _size) internal pure returns (uint256) { + /// We need the height of the tree that will contain all of our leaves, + /// hence the next highest power of two from the amount of leaves - Math.ceil(Math.log2(x)) + uint256 height = 0; + + if (_size == 1) { + return 0; + } + + /// While size > 1, we divide by two, and count how many times we do this; producing a rudimentary way of calculating Math.Floor(Math.log2(x)) + while (_size > 1) { + _size >>= 1; + height++; + } + return height; + } } diff --git a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol index 43f00cc5b8e9..e3ecc6ecb2c9 100644 --- a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol @@ -261,7 +261,7 @@ library TxsDecoder { } } - return computeRoot(vars.baseLeaves); + return computeUnbalancedRoot(vars.baseLeaves); } /** @@ -516,6 +516,40 @@ library TxsDecoder { return _leafs[0]; } + /** + * @notice Computes the root for a binary unbalanced Merkle-tree given the leaves. + * @dev Filled in greedily with subtrees. Useful for txsEffectHash and outHash tree. + * @param _leaves - The 32 bytes leafs to build the tree of. + * @return The root of the Merkle tree. + */ + function computeUnbalancedRoot(bytes32[] memory _leaves) internal pure returns (bytes32) { + // e.g. an unbalanced tree of 7 txs will contain subtrees of 4, 2, and 1 tx(s) = 111 + // e.g. an unbalanced tree of 9 txs will contain subtrees of 8 and 1 tx(s) = 1001 + // We collect the roots of each subtree + bytes32 root; + uint256 currentSubtreeSize = 1; + uint256 numTxs = _leaves.length; + // We must calculate the smaller rightmost subtrees first, hence starting at 1 + while (numTxs != 0) { + // If size & txs == 0, the subtree doesn't exist for this number of txs + if (currentSubtreeSize & numTxs == 0) { + currentSubtreeSize <<= 1; + continue; + } + bytes32[] memory leavesInSubtree = new bytes32[](currentSubtreeSize); + uint256 start = numTxs - currentSubtreeSize; + for (uint256 i = start; i < numTxs; i++) { + leavesInSubtree[i - start] = _leaves[i]; + } + bytes32 subtreeRoot = computeRoot(leavesInSubtree); + root = + numTxs == _leaves.length ? subtreeRoot : Hash.sha256ToField(bytes.concat(subtreeRoot, root)); + numTxs -= currentSubtreeSize; + currentSubtreeSize <<= 1; + } + return root; + } + /** * @notice Wrapper around the slicing to avoid some stack too deep * @param _data - The data to slice @@ -592,18 +626,6 @@ library TxsDecoder { } else if (_numTxEffects == 1) { return 1; } - - uint32 v = _numTxEffects; - - // the following rounds _numTxEffects up to the next power of 2 (works only for 4 bytes value!) - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - - return v - _numTxEffects; + return 0; } } diff --git a/l1-contracts/src/core/messagebridge/Outbox.sol b/l1-contracts/src/core/messagebridge/Outbox.sol index b62665d8a872..db1ccb764472 100644 --- a/l1-contracts/src/core/messagebridge/Outbox.sol +++ b/l1-contracts/src/core/messagebridge/Outbox.sol @@ -100,19 +100,14 @@ contract Outbox is IOutbox { if (rootData.nullified[_leafIndex]) { revert Errors.Outbox__AlreadyNullified(_l2BlockNumber, _leafIndex); } + // TODO(#7218): We will eventually move back to a balanced tree and constrain the path length + // to be equal to height - for now we just check the min // Min height = height of rollup layers // The smallest num of messages will require a subtree of height 1 - uint256 treeHeight = rootData.minHeight; - if (treeHeight > _path.length) { - revert Errors.Outbox__InvalidPathLength(treeHeight, _path.length); - } - - // Max height = height of rollup layers + max possible subtree height - // The max num of messages N will require a subtree of height log2(N) - uint256 maxSubtreeHeight = calculateTreeHeightFromSize(Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX); - if (treeHeight + maxSubtreeHeight < _path.length) { - revert Errors.Outbox__InvalidPathLength(treeHeight + maxSubtreeHeight, _path.length); + uint256 minHeight = rootData.minHeight; + if (minHeight > _path.length) { + revert Errors.Outbox__InvalidPathLength(minHeight, _path.length); } bytes32 messageHash = _message.sha256ToField(); @@ -138,22 +133,4 @@ contract Outbox is IOutbox { { return roots[_l2BlockNumber].nullified[_leafIndex]; } - - /** - * @notice Calculates a tree height from the amount of elements in the tree - * @dev - This mirrors the function in TestUtil, but assumes _size is an exact power of 2 - * @param _size - The number of elements in the tree - */ - function calculateTreeHeightFromSize(uint256 _size) internal pure returns (uint256) { - /// We need the height of the tree that will contain all of our leaves, - /// hence the next highest power of two from the amount of leaves - Math.ceil(Math.log2(x)) - uint256 height = 0; - - /// While size > 1, we divide by two, and count how many times we do this; producing a rudimentary way of calculating Math.Floor(Math.log2(x)) - while (_size > 1) { - _size >>= 1; - height++; - } - return height; - } } diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 4d8613db0274..97f6080fb04f 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -162,15 +162,15 @@ contract RollupTest is DecoderBase { // NB: The below works with full blocks because we require the largest possible subtrees // for L2 to L1 messages - usually we make variable height subtrees, the roots of which // form a balanced tree - uint256 numTxsWithPadding = txsHelper.computeNumTxEffectsToPad(numTxs) + numTxs; + // The below is a little janky - we know that this test deals with full txs with equal numbers // of msgs or txs with no messages, so the division works // TODO edit full.messages to include information about msgs per tx? uint256 subTreeHeight = merkleTestUtil.calculateTreeHeightFromSize( full.messages.l2ToL1Messages.length == 0 ? 0 : full.messages.l2ToL1Messages.length / numTxs ); - uint256 outHashTreeHeight = merkleTestUtil.calculateTreeHeightFromSize(numTxsWithPadding); - uint256 numMessagesWithPadding = numTxsWithPadding * Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX; + uint256 outHashTreeHeight = merkleTestUtil.calculateTreeHeightFromSize(numTxs); + uint256 numMessagesWithPadding = numTxs * Constants.MAX_L2_TO_L1_MSGS_PER_TX; uint256 treeHeight = subTreeHeight + outHashTreeHeight; NaiveMerkle tree = new NaiveMerkle(treeHeight); diff --git a/l1-contracts/test/decoders/Base.sol b/l1-contracts/test/decoders/Base.sol index 8301379c8f2b..d962bbac3769 100644 --- a/l1-contracts/test/decoders/Base.sol +++ b/l1-contracts/test/decoders/Base.sol @@ -73,8 +73,8 @@ contract DecoderBase is Test { struct ContentCommitment { bytes32 inHash; + uint256 numTxs; bytes32 outHash; - uint256 txTreeHeight; bytes32 txsEffectsHash; } diff --git a/l1-contracts/test/decoders/Decoders.t.sol b/l1-contracts/test/decoders/Decoders.t.sol index bd7eef2bf4b8..a3f6c3958ca2 100644 --- a/l1-contracts/test/decoders/Decoders.t.sol +++ b/l1-contracts/test/decoders/Decoders.t.sol @@ -72,11 +72,7 @@ contract DecodersTest is DecoderBase { { DecoderBase.ContentCommitment memory contentCommitment = referenceHeader.contentCommitment; - assertEq( - header.contentCommitment.txTreeHeight, - contentCommitment.txTreeHeight, - "Invalid txTreeSize" - ); + assertEq(header.contentCommitment.numTxs, contentCommitment.numTxs, "Invalid txTreeSize"); assertEq( header.contentCommitment.txsEffectsHash, contentCommitment.txsEffectsHash, @@ -332,26 +328,10 @@ contract DecodersTest is DecoderBase { numTxEffects = 3; paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 2 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 5; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 8; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 10; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad"); - - numTxEffects = 16; - paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad"); + assertEq(paddedNumTxEffects, 0, "Incorrect number of tx effects to pad"); numTxEffects = 17; paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects); - assertEq(paddedNumTxEffects, 2 ** 5 - numTxEffects, "Incorrect number of tx effects to pad"); + assertEq(paddedNumTxEffects, 0, "Incorrect number of tx effects to pad"); } } diff --git a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol index 41b5352b270b..f34fd9c34372 100644 --- a/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol +++ b/l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.18; import {TxsDecoder} from "../../../src/core/libraries/decoders/TxsDecoder.sol"; +import {MerkleLib} from "../../../src/core/libraries/MerkleLib.sol"; contract TxsDecoderHelper { // A wrapper used such that we get "calldata" and not memory @@ -21,4 +22,12 @@ contract TxsDecoderHelper { function computeNumTxEffectsToPad(uint32 _numTxEffects) external pure returns (uint32) { return TxsDecoder.computeNumTxEffectsToPad(_numTxEffects); } + + function computeUnbalancedRoot(bytes32[] memory _leaves) external pure returns (bytes32) { + return TxsDecoder.computeUnbalancedRoot(_leaves); + } + + function computeMinMaxPathLength(uint32 _numTxEffects) external pure returns (uint256, uint256) { + return MerkleLib.computeMinMaxPathLength(_numTxEffects); + } } diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index 3f6e46d2c1f5..8698dda56e86 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -8,14 +8,14 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f0890523", + "archive": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", - "txTreeHeight": 1, + "numTxs": 2, "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { @@ -23,8 +23,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0x154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6", - "feeRecipient": "0x301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626", + "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", + "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -55,8 +55,8 @@ } } }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000100d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00e1b985afe7ad2360a25bc829b614b5ef63e5cae914a38d99f59d5b2a5522fe", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b600000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000006adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x002aa4bb5409ae75e705b167d45ba569055b2ae62c67c1608f4cf17ac5129ad6", "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 018b043a71a8..a0706e4b24f9 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,23 +8,23 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2074c6a0cc1f2dd305c8614df3a7426eb3b20dac06850c5d6cb64910a5a1caef", + "archive": "0x0f049707f5cee10d833aea2adf93e1e3462eaa5b328576342fbea7837195c91a", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3", - "txTreeHeight": 1, + "numTxs": 2, "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1718108388, + "timestamp": 1719332523, "version": 1, - "coinbase": "0x154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6", - "feeRecipient": "0x301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626", + "coinbase": "0x6adca08f06cc255a12c609d284c5861c1cad740c", + "feeRecipient": "0x09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -32,7 +32,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f0890523" + "root": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad" }, "stateReference": { "l1ToL2MessageTree": { @@ -55,8 +55,8 @@ } } }, - "header": "0x1cf715c65eecea3dda1833ca8e9f7b23ca588a7ece864b957f919bb7f089052300000002000000000000000000000000000000000000000000000000000000000000000100d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000666840e4154e0eb6154e0eb6154e0eb6154e0eb6154e0eb6301bf845ed245d172febeaa6c1a11d59b6041b79531a00694f9042df161e2626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x002d5e3fa366ee431f598f8bc6060165320453e2ad908c3ad80b1e7d3c1a8006", + "header": "0x062d0b928c3e1fa5529032c8c663c4b3b1a359d03943f20667b02d87bf71a7ad00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aeeab6adca08f06cc255a12c609d284c5861c1cad740c09d7dc61a2ee0c764bc8f5954500c7b43d5422958e67d20144b3e738b04dfc07000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00d8e0d4aa3b09294fa37c11ca7f356dc35c160e2ec9a95363a07dca826e1397", "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 c0bc6a5c453d..f9b76ee0dec9 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -58,14 +58,14 @@ ] }, "block": { - "archive": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d", + "archive": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e08000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003410000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003440000000000000000000000000000000000000000000000000000000000000345000000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003473f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be08000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000385000000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003873f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c73f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e08000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004010000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000000000000000000000000405000000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004073f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3", "decodedHeader": { "contentCommitment": { "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb2230", - "txTreeHeight": 2, + "numTxs": 4, "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3" }, "globalVariables": { @@ -73,8 +73,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xcb460eb6cb460eb6cb460eb6cb460eb6cb460eb6", - "feeRecipient": "0x0cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c", + "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", + "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -105,8 +105,8 @@ } } }, - "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000002006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cb460eb6cb460eb6cb460eb6cb460eb6cb460eb60cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00c13e59e7ffaa51e87daa6e5e2983fa353c47ff1883bfef731b9e784ade8399", + "header": "0x0afb332dff10b3b4221c5c26ead8202d94bb977f644c91b06dec3ee098acc2b6000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000038e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0086d49b8b947a0b784ea6e86697292895d7f54a547fa954ab820140274340d4", "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 62963048eb1c..b3d023bdcdab 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,23 +58,23 @@ ] }, "block": { - "archive": "0x1782e665d3991213a60e4add07b2bdf3c49bd81f93ca6ca1d79da91b937cebb2", + "archive": "0x0796e4e2dcd2e9d783732a42084fd8fd79acd7bbc7e9d511f5d0c59d4de6aa80", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004410000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000445000000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004473f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004810000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004840000000000000000000000000000000000000000000000000000000000000485000000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004873f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c73f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e08000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050300000000000000000000000000000000000000000000000000000000000005040000000000000000000000000000000000000000000000000000000000000505000000000000000000000000000000000000000000000000000000000000050600000000000000000000000000000000000000000000000000000000000005073f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b", "decodedHeader": { "contentCommitment": { "inHash": "0x00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937", "outHash": "0x008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e8", - "txTreeHeight": 2, + "numTxs": 4, "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b" }, "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1718108261, + "timestamp": 1719332461, "version": 1, - "coinbase": "0xcb460eb6cb460eb6cb460eb6cb460eb6cb460eb6", - "feeRecipient": "0x0cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c", + "coinbase": "0x38e74ed15dd5ab05fff041b5037372cce88aa7e9", + "feeRecipient": "0x1bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -82,7 +82,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d" + "root": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c8" }, "stateReference": { "l1ToL2MessageTree": { @@ -105,8 +105,8 @@ } } }, - "header": "0x20fbe5614957ca8c09d74fd86ebbab70e3c95d6996b4e0086f7809f9d03a302d00000002000000000000000000000000000000000000000000000000000000000000000200c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000066684065cb460eb6cb460eb6cb460eb6cb460eb6cb460eb60cacc1f59212369f15989d55449e2460f787453f9a729749d363f4eee29d4c8c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x008ce3a989d35090e9f9539ddecbc7b3f9f11b7c58321cf5c3b02ade618d3f67", + "header": "0x1caafe747155b2a72a6f44744dc68fa9d6c3b605e5dc661383c5a202dd7ee7c800000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000667aee6d38e74ed15dd5ab05fff041b5037372cce88aa7e91bf48a8c128750df4186da470571948ac0d14d79b3de69978f5a779fbdf547be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x006abc0437c6efc01d8f9e20d9bc15d8181ffcbf03c5869276d004c087bc117a", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/merkle/UnbalancedMerkle.t.sol b/l1-contracts/test/merkle/UnbalancedMerkle.t.sol new file mode 100644 index 000000000000..ce3604351ab0 --- /dev/null +++ b/l1-contracts/test/merkle/UnbalancedMerkle.t.sol @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs. +pragma solidity >=0.8.18; + +import {Test} from "forge-std/Test.sol"; +import {Hash} from "../../src/core/libraries/Hash.sol"; + +import {TxsDecoderHelper} from "../decoders/helpers/TxsDecoderHelper.sol"; +/** + * Tests the tree construction for unbalanced rollups. + * Used for calculating txsEffectsHash over non balanced rollups - each leaf is one baseLeaf + * calculated in TxsDecoder.sol. + */ + +contract UnbalancedMerkleTest is Test { + /** + * Rollups are constructed greedily, with a set of N transactions split into subtrees of decreasing + * powers of 2. + * We list them in reverse order as we compute subtree roots from R to L + */ + TxsDecoderHelper internal txsHelper; + + function setUp() public { + txsHelper = new TxsDecoderHelper(); + } + + function testDecomp() public { + // Worst case - max num txs + uint32 numTxs = 65535; + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 15); + assertEq(max, 16); + // Single tree of 2**15 + numTxs = 32768; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 15); + assertEq(max, 15); + // Single tree of 2**13 + numTxs = 8192; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 13); + assertEq(max, 13); + // Trees of 2**12, 2**11, ... 2**0 + numTxs = 8191; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 12); + assertEq(max, 13); + // Single tree of 2**8 + numTxs = 256; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 8); + assertEq(max, 8); + // Left subtree of 2**8, right subtree of single leaf + numTxs = 257; + (min, max) = txsHelper.computeMinMaxPathLength(numTxs); + assertEq(min, 1); + assertEq(max, 9); + } + + // Example - 2 txs: + // + // root + // / \ + // base base + function testComputeTxsEffectsHash2() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](2); + for (uint256 i = 0; i < 2; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + // We have just one 'balanced' branch, so depth is 0 with 2 elements + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(2); + assertEq(min, 1); + assertEq(max, 1); + bytes32 rootTxsEffectsHash = Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + // Example - 3 txs: + // + // root + // / \ + // merge base + // / \ + // base base + + function testComputeTxsEffectsHash3() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](3); + for (uint256 i = 0; i < 3; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(3); + assertEq(min, 1); + assertEq(max, 2); + bytes32 mergeTxsEffectsHash = Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(mergeTxsEffectsHash, baseLeaves[2])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 5 txs: + // + // root + // / \ + // merge base + // / \ + // merge merge + // / \ / \ + // base base base base + function testComputeTxsEffectsHash5() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](5); + for (uint256 i = 0; i < 5; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(5); + assertEq(min, 1); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(thirdMergeTxsEffectsHash, baseLeaves[4])); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 6 txs: + // + // root + // / \ + // merge4 merge3 + // / \ / \ + // merge1 merge2 base base + // / \ / \ + // base base base base + function testComputeTxsEffectsHash6() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](6); + for (uint256 i = 0; i < 6; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(6); + assertEq(min, 2); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[4], baseLeaves[5])); + bytes32 fourthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(fourthMergeTxsEffectsHash, thirdMergeTxsEffectsHash)); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } + + // Example - 7 txs: + // + // root + // / \ + // merge3 merge5 + // / \ / \ + // merge1 merge2 merge4 base + // / \ / \ / \ + // base base base base base base + function testComputeTxsEffectsHash7() public { + // Generate some base leaves + bytes32[] memory baseLeaves = new bytes32[](7); + for (uint256 i = 0; i < 6; i++) { + baseLeaves[i] = Hash.sha256ToField(abi.encodePacked(i)); + } + (uint256 min, uint256 max) = txsHelper.computeMinMaxPathLength(7); + assertEq(min, 2); + assertEq(max, 3); + bytes32 firstMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[0], baseLeaves[1])); + bytes32 secondMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[2], baseLeaves[3])); + bytes32 thirdMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(firstMergeTxsEffectsHash, secondMergeTxsEffectsHash)); + bytes32 fourthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(baseLeaves[4], baseLeaves[5])); + bytes32 fifthMergeTxsEffectsHash = + Hash.sha256ToField(bytes.concat(fourthMergeTxsEffectsHash, baseLeaves[6])); + + bytes32 rootTxsEffectsHash = + Hash.sha256ToField(bytes.concat(thirdMergeTxsEffectsHash, fifthMergeTxsEffectsHash)); + bytes32 calculatedTxsEffectsHash = txsHelper.computeUnbalancedRoot(baseLeaves); + assertEq(calculatedTxsEffectsHash, rootTxsEffectsHash); + } +} diff --git a/noir-projects/Dockerfile b/noir-projects/Dockerfile index dc2ecf463622..1a3e43e4abe1 100644 --- a/noir-projects/Dockerfile +++ b/noir-projects/Dockerfile @@ -19,7 +19,7 @@ RUN ./bootstrap.sh WORKDIR /usr/src/noir-projects/noir-protocol-circuits RUN ./bootstrap.sh WORKDIR /usr/src/noir-projects/aztec-nr -RUN nargo compile --silence-warnings +RUN nargo compile --use-legacy --silence-warnings FROM scratch COPY --from=builder /usr/src/noir-projects /usr/src/noir-projects \ No newline at end of file diff --git a/noir-projects/Dockerfile.test b/noir-projects/Dockerfile.test index 91adc723c6a5..0ff6fb26b78f 100644 --- a/noir-projects/Dockerfile.test +++ b/noir-projects/Dockerfile.test @@ -22,19 +22,19 @@ WORKDIR /usr/src/noir-projects COPY . . # Build & test -RUN cd ./noir-protocol-circuits && ./bootstrap.sh && nargo test --silence-warnings +RUN cd ./noir-protocol-circuits && ./bootstrap.sh && nargo test --use-legacy --silence-warnings -RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ +RUN cd /usr/src/yarn-project/txe && yarn start & \ # Wait for TXE to initialize sleep 5 && \ cd ./noir-contracts && \ # We need to increase the timeout since all tests running in parallel hammer TXE at the same time, and processing slows down leading to timeouts # The only way we currently have to batch tests is via RAYON_NUM_THREADS, which is not ideal - ./bootstrap.sh && NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ - kill $(cat /tmp/txe.pid) + ./bootstrap.sh && \ + NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --use-legacy --silence-warnings --oracle-resolver http://localhost:8080 -RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ +RUN cd /usr/src/yarn-project/txe && yarn start & \ # Wait for TXE to initialize sleep 5 && \ cd ./aztec-nr && \ - nargo test --silence-warnings --oracle-resolver http://localhost:8080 \ No newline at end of file + nargo test --use-legacy --silence-warnings --oracle-resolver http://localhost:8080 \ No newline at end of file diff --git a/noir-projects/Earthfile b/noir-projects/Earthfile index a828544fea27..6325ad83e4e3 100644 --- a/noir-projects/Earthfile +++ b/noir-projects/Earthfile @@ -49,20 +49,19 @@ test: COPY +build/. /usr/src/noir-projects RUN cd /usr/src/noir-projects/noir-protocol-circuits && nargo test --silence-warnings - RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ + + RUN cd /usr/src/yarn-project/txe && yarn start & \ # Wait for TXE to initialize sleep 5 && \ - cd /usr/src/noir-projects/aztec-nr && nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ - kill $(cat /tmp/txe.pid) + cd /usr/src/noir-projects/aztec-nr && nargo test --use-legacy --silence-warnings --oracle-resolver http://localhost:8080 - RUN cd /usr/src/yarn-project/txe && yarn start & echo $! > /tmp/txe.pid && \ + RUN cd /usr/src/yarn-project/txe && yarn start & \ # Wait for TXE to initialize sleep 5 && \ cd /usr/src/noir-projects/noir-contracts && \ # We need to increase the timeout since all tests running in parallel hammer TXE at the same time and processing slows down, leading to timeouts # The only way we currently have to batch tests is via RAYON_NUM_THREADS, which is not ideal - NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --silence-warnings --oracle-resolver http://localhost:8080 ; \ - kill $(cat /tmp/txe.pid) + NARGO_FOREIGN_CALL_TIMEOUT=300000 nargo test --use-legacy --silence-warnings --oracle-resolver http://localhost:8080 format: FROM +build @@ -77,7 +76,7 @@ format: RUN nargo fmt --check gates-report: - FROM +build + FROM +build-protocol-circuits WORKDIR /usr/src/noir-projects COPY ./gates_report.sh ./gates_report.sh diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 3f39ac213c50..d6370b435cf3 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 = 65a04245e871878b76ba738dc13d2a8cc1cda2e3 + commit = 727b4a0a68969966edd2a65671b6ff57243a2367 method = merge cmdver = 0.4.6 - parent = f6b4d721f92ed87d3f865254c240e80f26a36c30 + parent = c43eb7eb222928b2b9b92f6cde49199a231ff33e diff --git a/noir-projects/aztec-nr/authwit/src/account.nr b/noir-projects/aztec-nr/authwit/src/account.nr index 3f63137f08cc..d64de349db1c 100644 --- a/noir-projects/aztec-nr/authwit/src/account.nr +++ b/noir-projects/aztec-nr/authwit/src/account.nr @@ -2,7 +2,7 @@ use dep::aztec::context::{PrivateContext, PublicContext}; use dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash}; use crate::entrypoint::{app::AppPayload, fee::FeePayload}; -use crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash}; +use crate::auth::{IS_VALID_SELECTOR, compute_authwit_message_hash}; struct AccountActions { context: Context, @@ -15,7 +15,22 @@ impl AccountActions { } } +/** + * An implementation of the Account Action struct for the private context. + * + * Implements logic to verify authorization and execute payloads. + */ impl AccountActions<&mut PrivateContext> { + + /** + * Verifies that the `app_hash` and `fee_hash` are authorized and then executes them. + * + * Executes the `fee_payload` and `app_payload` in sequence. + * Will execute the `fee_payload` as part of the setup, and then enter the app phase. + * + * @param app_payload The payload that contains the calls to be executed in the app phase. + * @param fee_payload The payload that contains the calls to be executed in the setup phase. + */ // docs:start:entrypoint pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) { let valid_fn = self.is_valid_impl; @@ -31,12 +46,22 @@ impl AccountActions<&mut PrivateContext> { } // docs:end:entrypoint + /** + * Verifies that the `msg_sender` is authorized to consume `inner_hash` by the account. + * + * Computes the `message_hash` using the `msg_sender`, `chain_id`, `version` and `inner_hash`. + * Then executes the `is_valid_impl` function to verify that the message is authorized. + * + * Will revert if the message is not authorized. + * + * @param inner_hash The hash of the message that the `msg_sender` is trying to consume. + */ // docs:start:verify_private_authwit pub fn verify_private_authwit(self, inner_hash: Field) -> Field { // The `inner_hash` is "siloed" with the `msg_sender` to ensure that only it can // consume the message. // This ensures that contracts cannot consume messages that are not intended for them. - let message_hash = compute_outer_authwit_hash( + let message_hash = compute_authwit_message_hash( self.context.msg_sender(), self.context.chain_id(), self.context.version(), diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index 18342ce4f7b6..de42feab3541 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -8,16 +8,213 @@ use dep::aztec::protocol_types::{ }; use dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array}; +/** + * Authenticaion witness helper library + * + * Authentication Witness is a scheme for authenticating actions on Aztec, so users can allow third-parties + * (e.g. protocols or other users) to execute an action on their behalf. + * + * This library provides helper functions to manage such witnesses. + * The authentication witness, is some "witness" (data) that authenticates a `message_hash`. + * The simplest example of an authentication witness, is a signature. The signature is the "evidence", + * that the signer has seen the message, agrees with it, and has allowed it. + * It does not need to be a signature. It could be any kind of "proof" that the message is allowed. + * Another proof could be knowing some kind of secret, or having some kind of "token" that allows the message. + * + * The `message_hash` is a hash of the following structure: + * hash(consumer, chain_id, version, inner_hash) + * - consumer: the address of the contract that is "consuming" the message, + * - chain_id: the chain id of the chain that the message is being consumed on, + * - version: the version of the chain that the message is being consumed on, + * - inner_hash: the hash of the "inner" message that is being consumed, this is the "actual" message or action. + * + * While the `inner_hash` could be anything, such as showing you signed a specific message, it will often be + * a hash of the "action" to approve, along with who made the call. As part of this library, we provide a few + * helper functions to deal with such messages. + * + * For example, we provide helper function that is used for checking that the message is an encoding of the current call. + * This can be used to let some contract "allow" another contract to act on its behalf, as long as it can + * show that it is acting on behalf of the contract. + * + * If we take a case of allowing a contract to transfer tokens on behalf of an account, the `inner_hash` can be + * derived as: + * inner_hash = hash(caller, "transfer", hash(to, amount)) + * + * Where the `caller` would be the address of the contract that is trying to transfer the tokens, and `to` and `amount` + * the arguments for the transfer. + * + * Note that we have both a `caller` and a `consumer`, the `consumer` will be the contract that is consuming the message, + * in the case of the transfer, it would be the `Token` contract itself, while the caller, will be the actor that is + * allowed to transfer the tokens. + * + * + * The authentication mechanism works differently in public and private contexts. In private, we recall that everything + * is executed on the user's device, so we can use `oracles` to "ask" the user (not contract) for information. In public + * we cannot do this, since it is executed by the sequencer (someone else). Therefore we can instead use a "registry" + * to store the messages that we have approved. + * + * A simple example would be a "token" that is being "pulled" from one account into another. We will first outline + * how this would look in private, and then in public later. + * + * Say that a user `Alice` wants to deposit some tokens into a DeFi protocol (say a DEX). + * `Alice` would make a `deposit` transaction, that she is executing using her account contract. + * The account would call the `DeFi` contract to execute `deposit`, which would try to pull funds from the `Token` + * contract. Since the `DeFi` contract is trying to pull funds from an account that is not its own, it needs to + * convince the `Token` contract that it is allowed to do so. + * + * This is where the authentication witness comes in! The `Token` contract computes a `message_hash` from the + * `transfer` call, and then asks `Alice Account` contract to verify that the `DeFi` contract is allowed to + * execute that call. + * + * `Alice Account` contract can then ask `Alice` if she wants to allow the `DeFi` contract to pull funds from her + * account. If she does, she will sign the `message_hash` and return the signature to the `Alice Account` which + * will validate it and return success to the `Token` contract which will then allow the `DeFi` contract to pull + * funds from `Alice`. + * + * To ensure that the same "approval" cannot be used multiple times, we also compute a `nullifier` for the + * authentication witness, and emit it from the `Token` contract (consumer). + * + * Note that we can do this flow as we are in private were we can do oracle calls out from contracts. + * + * + * Person Contract Contract Contract + * Alice Alice Account Token DeFi + * | | | | + * | Defi.deposit(Token, 1000) | | + * |----------------->| | | + * | | deposit(Token, 1000) | + * | |---------------------------------------->| + * | | | | + * | | | transfer(Alice, Defi, 1000) + * | | |<---------------------| + * | | | | + * | | Check if Defi may call transfer(Alice, Defi, 1000) + * | |<-----------------| | + * | | | | + * | Please give me AuthWit for DeFi | | + * | calling transfer(Alice, Defi, 1000) | | + * |<-----------------| | | + * | | | | + * | | | | + * | AuthWit for transfer(Alice, Defi, 1000) | + * |----------------->| | | + * | | AuthWit validity | | + * | |----------------->| | + * | | | | + * | | throw if invalid AuthWit | + * | | | | + * | | emit AuthWit nullifier | + * | | | | + * | | transfer(Alice, Defi, 1000) | + * | | | | + * | | | | + * | | | success | + * | | |--------------------->| + * | | | | + * | | | | + * | | | deposit(Token, 1000) + * | | | | + * | | | | + * + * + * If we instead were in public, we cannot do the same flow. Instead we would use an authentication registry to store + * the messages that we have approved. + * + * To approve a message, `Alice Account` can make a `set_authorized` call to the registry, to set a `message_hash` + * as authorized. This is essentially a mapping from `message_hash` to `true` for `Alice Contract`. Every account + * has its own map in the registry, so `Alice` cannot approve a message for `Bob`. + * + * The `Token` contract can then try to "spend" the approval by calling `consume` on the registry. If the message + * was approved, the value is updated to `false`, and we return the success flag. For more information on the + * registry, see `main.nr` in `auth_registry_contract`. + * + * Person Contract Contract Contract Contract + * Alice Alice Account Registry Token DeFi + * | | | | | + * | Registry.set_authorized(..., true) | | | + * |----------------->| | | | + * | | set_authorized(..., true) | | + * | |------------------->| | | + * | | | | | + * | | set authorized to true | | + * | | | | | + * | | | | | + * | Defi.deposit(Token, 1000) | | | + * |----------------->| | | | + * | | deposit(Token, 1000) | | + * | |-------------------------------------------------------------->| + * | | | | | + * | | | transfer(Alice, Defi, 1000) | + * | | | |<---------------------| + * | | | | | + * | | | Check if Defi may call transfer(Alice, Defi, 1000) + * | | |<------------------| | + * | | | | | + * | | throw if invalid AuthWit | | + * | | | | | + * | | | | | + * | | set authorized to false | | + * | | | | | + * | | | | | + * | | | AuthWit validity | | + * | | |------------------>| | + * | | | | | + * | | | | transfer(Alice, Defi, 1000) + * | | | |<-------------------->| + * | | | | | + * | | | | success | + * | | | |--------------------->| + * | | | | | + * | | | | deposit(Token, 1000) + * | | | | | + * + * + * --- FAQ --- + * Q: Why are we using a success flag of `keccak256("IS_VALID()")` instead of just returning a boolean? + * A: We want to make sure that we don't accidentally return `true` if there is a collision in the function selector. + * By returning a hash of `IS_VALID()`, it becomes very unlikely that there is both a colission and we return + * a success flag. + * + * Q: Why are we using static calls? + * A: We are using static calls to ensure that the account contract cannot re-enter. If it was a normal call, it + * could make a new call and do a re-entry attack. Using a static ensures that it cannot update any state. + * + * Q: Would it not be cheaper to use a nullifier instead of updating state in public? + * A: At a quick glance, a public state update + nullifier is 96 bytes, but two state updates are 128, so it would be + * cheaper to use a nullifier, if this is the way it would always be done. However, if both the approval and the + * consumption is done in the same transaction, then we will be able to squash the updates (only final tx state diff is posted to DA), and now it is cheaper. + * + * Q: Why is the chain id and the version part of the message hash? + * A: The chain id and the version is part of the message hash to ensure that the message is only valid on a specific + * chain to avoid a case where the same message could be used across multiple chains. + */ + global IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256("IS_VALID()") +/** + * Assert that `on_behalf_of` have authorized the current call with a valid authentication witness + * + * Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the + * `on_behalf_of` contract to verify that the `inner_hash` is valid. + * + * @param on_behalf_of The address that have authorized the current call + */ // docs:start:assert_current_call_valid_authwit -// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness pub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) { let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]); assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash); } // docs:end:assert_current_call_valid_authwit +/** + * Assert that a specific `inner_hash` is valid for the `on_behalf_of` address + * + * Used as an internal function for `assert_current_call_valid_authwit` and can be used as a standalone function when + * the `inner_hash` is from a different source, e.g., say a block of text etc. + * + * @param on_behalf_of The address that have authorized the current call + * @param inner_hash The hash of the message to authorize + */ pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) { // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter. let result: Field = context.static_call_private_function( @@ -29,11 +226,21 @@ pub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_o // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version. // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors. let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } +/** + * Assert that `on_behalf_of` have authorized the current call in the authentication registry + * + * Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the + * `on_behalf_of` contract to verify that the `inner_hash` is valid. + * + * Note that the authentication registry will take the `msg_sender` into account as the consumer, so this will only + * work if the `msg_sender` is the same as the `consumer` when the `message_hash` was inserted into the registry. + * + * @param on_behalf_of The address that have authorized the current call + */ // docs:start:assert_current_call_valid_authwit_public -// Assert that `on_behalf_of` have authorized the current call in a public context pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) { let inner_hash = compute_inner_authwit_hash( [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()] @@ -42,6 +249,17 @@ pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_ } // docs:end:assert_current_call_valid_authwit_public +/** + * Assert that `on_behalf_of` have authorized a speicifc `inner_hash` in the authentication registry + * + * Computing the `inner_hash` using the `msg_sender`, `selector` and `args_hash` and then making a call out to the + * `on_behalf_of` contract to verify that the `inner_hash` is valid. + * + * Note that the authentication registry will take the `msg_sender` into account as the consumer, so this will only + * work if the `msg_sender` is the same as the `consumer` when the `message_hash` was inserted into the registry. + * + * @param on_behalf_of The address that have authorized the the `inner_hash` + */ pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) { let result: Field = context.call_public_function( AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS), @@ -52,9 +270,22 @@ pub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_be assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); } -// docs:start:compute_call_authwit_hash -// Compute the message hash to be used by an authentication witness -pub fn compute_call_authwit_hash( +/** + * Compute the `message_hash` from a function call to be used by an authentication witness + * + * Useful for when you need a non-account contract to approve during execution. For example if you need a contract + * to make a call to nested contract, e.g., contract A wants to exit token T to L1 using bridge B, so it needs to allow + * B to transfer T on its behalf. + * + * @param caller The address of the contract that is calling the function, in the example above, this would be B + * @param consumer The address of the contract that is consuming the message, in the example above, this would be T + * @param chain_id The chain id of the chain that the message is being consumed on + * @param version The version of the chain that the message is being consumed on + * @param selector The function selector of the function that is being called + * @param args The arguments of the function that is being called + */ +// docs:start:compute_authwit_message_hash_from_call +pub fn compute_authwit_message_hash_from_call( caller: AztecAddress, consumer: AztecAddress, chain_id: Field, @@ -64,14 +295,30 @@ pub fn compute_call_authwit_hash( ) -> Field { let args_hash = hash_args_array(args); let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); - compute_outer_authwit_hash(consumer, chain_id, version, inner_hash) + compute_authwit_message_hash(consumer, chain_id, version, inner_hash) } -// docs:end:compute_call_authwit_hash +// docs:end:compute_authwit_message_hash_from_call +/** + * Computes the `inner_hash` of the authentication witness + * + * This is used internally, but also useful in cases where you want to compute the `inner_hash` for a specific message + * that is not necessarily a call, but just some "bytes" or text. + * + * @param args The arguments to hash + */ pub fn compute_inner_authwit_hash(args: [Field; N]) -> Field { pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER) } +/** + * Computs the `authwit_nullifier` for a specific `on_behalf_of` and `inner_hash` + * + * Using the `on_behalf_of` and the `inner_hash` to ensure that the nullifier is siloed for a specific `on_behalf_of`. + * + * @param on_behalf_of The address that have authorized the the `inner_hash` + * @param inner_hash The hash of the message to authorize + */ pub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field { pedersen_hash( [on_behalf_of.to_field(), inner_hash], @@ -79,12 +326,15 @@ pub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) ) } -pub fn compute_outer_authwit_hash( - consumer: AztecAddress, - chain_id: Field, - version: Field, - inner_hash: Field -) -> Field { +/** + * Computes the `message_hash` for the authentication witness + * + * @param consumer The address of the contract that is consuming the message + * @param chain_id The chain id of the chain that the message is being consumed on + * @param version The version of the chain that the message is being consumed on + * @param inner_hash The hash of the "inner" message that is being consumed + */ +pub fn compute_authwit_message_hash(consumer: AztecAddress, chain_id: Field, version: Field, inner_hash: Field) -> Field { pedersen_hash( [ consumer.to_field(), @@ -99,6 +349,8 @@ pub fn compute_outer_authwit_hash( /** * Helper function to set the authorization status of a message hash * + * Wraps a public call to the authentication registry to set the authorization status of a `message_hash` + * * @param message_hash The hash of the message to authorize * @param authorize True if the message should be authorized, false if it should be revoked */ @@ -113,6 +365,8 @@ pub fn set_authorized(context: &mut PublicContext, message_hash: Field, authoriz /** * Helper function to reject all authwits + * + * Wraps a public call to the authentication registry to set the `reject_all` flag * * @param reject True if all authwits should be rejected, false otherwise */ diff --git a/noir-projects/aztec-nr/authwit/src/auth_witness.nr b/noir-projects/aztec-nr/authwit/src/auth_witness.nr index 83f876385f65..2efa77defeaa 100644 --- a/noir-projects/aztec-nr/authwit/src/auth_witness.nr +++ b/noir-projects/aztec-nr/authwit/src/auth_witness.nr @@ -1,6 +1,12 @@ #[oracle(getAuthWitness)] unconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {} +/** + * Oracle wrapper to fetch an `auth_witness` for a given `message_hash` from the PXE. + * + * @param message_hash The hash of the message for which the `auth_witness` is to be fetched. + * @return The `auth_witness` for the given `message_hash` as Field array. + */ unconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] { get_auth_witness_oracle(message_hash) } diff --git a/noir-projects/aztec-nr/authwit/src/cheatcodes.nr b/noir-projects/aztec-nr/authwit/src/cheatcodes.nr index f673a2032772..baec83f8016c 100644 --- a/noir-projects/aztec-nr/authwit/src/cheatcodes.nr +++ b/noir-projects/aztec-nr/authwit/src/cheatcodes.nr @@ -4,7 +4,7 @@ use dep::aztec::{ hash::hash_args }; -use crate::auth::{compute_inner_authwit_hash, compute_outer_authwit_hash, set_authorized}; +use crate::auth::{compute_inner_authwit_hash, compute_authwit_message_hash, set_authorized}; pub fn add_private_authwit_from_call_interface( on_behalf_of: AztecAddress, @@ -18,7 +18,7 @@ pub fn add_private_authwit_from_call_interface( let args_hash = hash_args(call_interface.get_args()); let selector = call_interface.get_selector(); let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); - let message_hash = compute_outer_authwit_hash(target, chain_id, version, inner_hash); + let message_hash = compute_authwit_message_hash(target, chain_id, version, inner_hash); cheatcodes::add_authwit(on_behalf_of, message_hash); } @@ -36,7 +36,7 @@ pub fn add_public_authwit_from_call_interface( let args_hash = hash_args(call_interface.get_args()); let selector = call_interface.get_selector(); let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); - let message_hash = compute_outer_authwit_hash(target, chain_id, version, inner_hash); + let message_hash = compute_authwit_message_hash(target, chain_id, version, inner_hash); let mut inputs = cheatcodes::get_public_context_inputs(); let mut context = PublicContext::new(inputs); set_authorized(&mut context, message_hash, true); diff --git a/noir-projects/aztec-nr/authwit/src/entrypoint.nr b/noir-projects/aztec-nr/authwit/src/entrypoint/mod.nr similarity index 100% rename from noir-projects/aztec-nr/authwit/src/entrypoint.nr rename to noir-projects/aztec-nr/authwit/src/entrypoint/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/context/globals.nr b/noir-projects/aztec-nr/aztec/src/context/globals/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/context/globals.nr rename to noir-projects/aztec-nr/aztec/src/context/globals/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/context/inputs.nr rename to noir-projects/aztec-nr/aztec/src/context/inputs/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr index 9075e5a207dc..aa7bb176c0fb 100644 --- a/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr +++ b/noir-projects/aztec-nr/aztec/src/context/inputs/public_context_inputs.nr @@ -2,7 +2,6 @@ use dep::protocol_types::traits::Empty; // These inputs will likely go away once the AVM processes 1 public kernel per enqueued call. struct PublicContextInputs { - selector: Field, args_hash: Field, is_static_call: bool } @@ -10,7 +9,6 @@ struct PublicContextInputs { impl Empty for PublicContextInputs { fn empty() -> Self { PublicContextInputs { - selector: 0, args_hash: 0, is_static_call: false } diff --git a/noir-projects/aztec-nr/aztec/src/context.nr b/noir-projects/aztec-nr/aztec/src/context/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/context.nr rename to noir-projects/aztec-nr/aztec/src/context/mod.nr 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 25bb33ba6633..4f8b7f657f5e 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -1,17 +1,11 @@ use crate::{ context::{inputs::PrivateContextInputs, packed_returns::PackedReturns}, - messaging::process_l1_to_l2_message, - hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash}, + messaging::process_l1_to_l2_message, hash::{hash_args_array, ArgsHasher}, keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators}, - note::note_interface::NoteInterface, oracle::{ key_validation_request::get_key_validation_request, arguments, returns::pack_returns, call_private_function::call_private_function_internal, header::get_header_at, - logs::{ - emit_encrypted_note_log, emit_encrypted_event_log, - emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal -}, - logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog}, + logs::{emit_encrypted_note_log, emit_encrypted_event_log}, enqueue_public_function_call::{ enqueue_public_function_call_internal, set_public_teardown_function_call_internal, parse_public_call_stack_item_from_oracle @@ -19,7 +13,6 @@ use crate::{ } }; use dep::protocol_types::{ - hash::sha256_to_field, abis::{ caller_context::CallerContext, function_selector::FunctionSelector, max_block_number::MaxBlockNumber, @@ -30,16 +23,13 @@ use dep::protocol_types::{ }, address::{AztecAddress, EthAddress}, constants::{ - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, - contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, - grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header, - messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty}, - utils::arrays::find_index + header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::Empty }; // When finished, one can call .finish() to convert back to the abi @@ -60,13 +50,13 @@ struct PrivateContext { nullifier_read_requests: BoundedVec, key_validation_requests_and_generators: BoundedVec, - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, + note_hashes: BoundedVec, + nullifiers: BoundedVec, private_call_requests : BoundedVec, public_call_stack_hashes : BoundedVec, public_teardown_function_hash: Field, - new_l2_to_l1_msgs : BoundedVec, + l2_to_l1_msgs : BoundedVec, // docs:end:private-context // Header of a block whose state is used during private execution (not the block the transaction is included in). @@ -95,13 +85,13 @@ impl PrivateContext { note_hash_read_requests: BoundedVec::new(), nullifier_read_requests: BoundedVec::new(), key_validation_requests_and_generators: BoundedVec::new(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), historical_header: inputs.historical_header, private_call_requests: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), public_teardown_function_hash: 0, - new_l2_to_l1_msgs: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), @@ -133,14 +123,14 @@ impl PrivateContext { self.args_hash } - fn push_new_note_hash(&mut self, note_hash: Field) { - self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() }); + fn push_note_hash(&mut self, note_hash: Field) { + self.note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() }); } // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo // - consider creating a separate function with 1 arg for the zero note hash case. - fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) { - self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() }); + fn push_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) { + self.nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() }); } // Returns the header of a block whose state is used during private execution (not the block the transaction is @@ -171,12 +161,12 @@ impl PrivateContext { note_hash_read_requests: self.note_hash_read_requests.storage, nullifier_read_requests: self.nullifier_read_requests.storage, key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage, - new_note_hashes: self.new_note_hashes.storage, - new_nullifiers: self.new_nullifiers.storage, + note_hashes: self.note_hashes.storage, + nullifiers: self.nullifiers.storage, private_call_requests: self.private_call_requests.storage, public_call_stack_hashes: self.public_call_stack_hashes.storage, public_teardown_function_hash: self.public_teardown_function_hash, - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, + l2_to_l1_msgs: self.l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, @@ -248,7 +238,7 @@ impl PrivateContext { pub fn message_portal(&mut self, recipient: EthAddress, content: Field) { // docs:end:context_message_portal let message = L2ToL1Message { recipient, content, counter: self.next_counter() }; - self.new_l2_to_l1_msgs.push(message); + self.l2_to_l1_msgs.push(message); } // docs:start:context_consume_l1_to_l2_message @@ -266,67 +256,29 @@ impl PrivateContext { ); // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_new_nullifier(nullifier, 0) + self.push_nullifier(nullifier, 0) } // docs:end:consume_l1_to_l2_message - // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy. - // --> might be a better approach to force devs to make a public function call that emits the log if needed then - // it would be less easy to accidentally leak information. - // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log. - pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog { - let event_selector = 5; // TODO: compute actual event selector. - let contract_address = self.this_address(); - let counter = self.next_counter(); - let log_slice = log.to_be_bytes_arr(); - let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log); - // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - let len = 44 + log_slice.len().to_field(); - let side_effect = LogHash { value: log_hash, counter, length: len }; - self.unencrypted_logs_hashes.push(side_effect); - // call oracle - let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter); - } - - // This fn exists separately from emit_unencrypted_log because sha hashing the preimage - // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it - // It is ONLY used with contract_class_registerer_contract since we already assert correctness: - // - Contract class -> we will commit to the packed bytecode (currently a TODO) - // - Private function -> we provide a membership proof - // - Unconstrained function -> we provide a membership proof - // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else - pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) { - let event_selector = 5; // TODO: compute actual event selector. - let contract_address = self.this_address(); - let counter = self.next_counter(); - let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); - // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) - let len = 44 + N * 32; - let side_effect = LogHash { value: log_hash, counter, length: len }; - self.unencrypted_logs_hashes.push(side_effect); - } - // NB: A randomness value of 0 signals that the kernels should not mask the contract address // used in siloing later on e.g. 'handshaking' contract w/ known address. - pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) { + pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, log: [u8; M], log_hash: Field) { let counter = self.next_counter(); let contract_address = self.this_address(); - let len = encrypted_log.len() as Field + 4; - let log_hash = sha256_to_field(encrypted_log); + let len = log.len() as Field + 4; let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness }; self.encrypted_logs_hashes.push(side_effect); - emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter); + emit_encrypted_event_log(contract_address, randomness, log, counter); } - pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) { + pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, log: [u8; M], log_hash: Field) { let counter = self.next_counter(); - let len = encrypted_log.len() as Field + 4; - let log_hash = sha256_to_field(encrypted_log); + let len = log.len() as Field + 4; let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter }; self.note_encrypted_logs_hashes.push(side_effect); - emit_encrypted_note_log(note_hash_counter, encrypted_log, counter); + emit_encrypted_note_log(note_hash_counter, log, counter); } pub fn call_private_function( @@ -646,12 +598,12 @@ impl Empty for PrivateContext { note_hash_read_requests: BoundedVec::new(), nullifier_read_requests: BoundedVec::new(), key_validation_requests_and_generators: BoundedVec::new(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), private_call_requests: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), public_teardown_function_hash: 0, - new_l2_to_l1_msgs: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), historical_header: Header::empty(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), 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 979ddeb2b554..1bfaea42d392 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -14,51 +14,18 @@ impl PublicContext { PublicContext { inputs } } - pub fn storage_address(self) -> AztecAddress { - storage_address() - } - pub fn fee_per_l2_gas(self) -> Field { - fee_per_l2_gas() - } - pub fn fee_per_da_gas(self) -> Field { - fee_per_da_gas() - } - /** - * Emit a log with the given event selector and message. - * - * @param event_selector The event selector for the log. - * @param message The message to emit in the log. - */ - pub fn emit_unencrypted_log_with_selector( - &mut self, - event_selector: Field, - log: T - ) where T: Serialize { - emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice()); - } - // For compatibility with the selector-less API. We'll probably rename the above one. pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize { - self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log); + emit_unencrypted_log(Serialize::serialize(log).as_slice()); } + pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool { note_hash_exists(note_hash, leaf_index) == 1 } + pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } - fn block_number(self) -> Field { - block_number() - } - - fn timestamp(self) -> u64 { - timestamp() - } - - fn transaction_fee(self) -> Field { - transaction_fee() - } - fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool { nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 } @@ -89,7 +56,7 @@ impl PublicContext { ); // Push nullifier (and the "commitment" corresponding to this can be "empty") - self.push_new_nullifier(nullifier, 0); + self.push_nullifier(nullifier, 0); } fn message_portal(&mut self, recipient: EthAddress, content: Field) { @@ -99,7 +66,7 @@ impl PublicContext { fn call_public_function( self: &mut Self, contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, + function_selector: FunctionSelector, args: [Field], gas_opts: GasOpts ) -> FunctionReturns { @@ -107,7 +74,7 @@ impl PublicContext { gas_for_call(gas_opts), contract_address, args, - temporary_function_selector.to_field() + function_selector.to_field() ); let data_to_return: [Field; RETURNS_COUNT] = results.0; let success: u8 = results.1; @@ -119,7 +86,7 @@ impl PublicContext { fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, - temporary_function_selector: FunctionSelector, + function_selector: FunctionSelector, args: [Field], gas_opts: GasOpts ) -> FunctionReturns { @@ -127,7 +94,7 @@ impl PublicContext { gas_for_call(gas_opts), contract_address, args, - temporary_function_selector.to_field() + function_selector.to_field() ); assert(success == 1, "Nested static call failed!"); @@ -144,37 +111,74 @@ impl PublicContext { FunctionReturns::new([0; RETURNS_COUNT]) } - fn push_new_note_hash(&mut self, note_hash: Field) { + fn push_note_hash(&mut self, note_hash: Field) { emit_note_hash(note_hash); } - fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) { + fn push_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) { // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used emit_nullifier(nullifier); } + + fn this_address(self) -> AztecAddress { + address() + } + pub fn storage_address(self) -> AztecAddress { + storage_address() + } fn msg_sender(self) -> AztecAddress { sender() } - fn this_address(self) -> AztecAddress { - address() + fn selector(self) -> FunctionSelector { + FunctionSelector::from_u32(function_selector()) + } + fn get_args_hash(self) -> Field { + self.inputs.args_hash } + fn transaction_fee(self) -> Field { + transaction_fee() + } + fn chain_id(self) -> Field { chain_id() } fn version(self) -> Field { version() } - fn selector(self) -> FunctionSelector { - FunctionSelector::from_field(self.inputs.selector) + fn block_number(self) -> Field { + block_number() } - fn get_args_hash(self) -> Field { - self.inputs.args_hash + fn timestamp(self) -> u64 { + timestamp() + } + pub fn fee_per_l2_gas(self) -> Field { + fee_per_l2_gas() + } + pub fn fee_per_da_gas(self) -> Field { + fee_per_da_gas() } + fn l2_gas_left(self) -> Field { l2_gas_left() } fn da_gas_left(self) -> Field { da_gas_left() } + + fn raw_storage_read(_self: Self, storage_slot: Field) -> [Field; N] { + storage_read(storage_slot) + } + + fn storage_read(self, storage_slot: Field) -> T where T: Deserialize { + T::deserialize(self.raw_storage_read(storage_slot)) + } + + fn raw_storage_write(_self: Self, storage_slot: Field, values: [Field; N]) { + storage_write(storage_slot, values); + } + + fn storage_write(self, storage_slot: Field, value: T) where T: Serialize { + self.raw_storage_write(storage_slot, value.serialize()); + } } // Helper functions @@ -202,11 +206,8 @@ unconstrained fn sender() -> AztecAddress { unconstrained fn portal() -> EthAddress { portal_opcode() } -unconstrained fn fee_per_l2_gas() -> Field { - fee_per_l2_gas_opcode() -} -unconstrained fn fee_per_da_gas() -> Field { - fee_per_da_gas_opcode() +unconstrained fn function_selector() -> u32 { + function_selector_opcode() } unconstrained fn transaction_fee() -> Field { transaction_fee_opcode() @@ -223,6 +224,12 @@ unconstrained fn block_number() -> Field { unconstrained fn timestamp() -> u64 { timestamp_opcode() } +unconstrained fn fee_per_l2_gas() -> Field { + fee_per_l2_gas_opcode() +} +unconstrained fn fee_per_da_gas() -> Field { + fee_per_da_gas_opcode() +} unconstrained fn l2_gas_left() -> Field { l2_gas_left_opcode() } @@ -241,8 +248,8 @@ unconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 { unconstrained fn emit_nullifier(nullifier: Field) { emit_nullifier_opcode(nullifier) } -unconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) { - emit_unencrypted_log_opcode(event_selector, message) +unconstrained fn emit_unencrypted_log(message: [Field]) { + emit_unencrypted_log_opcode(message) } unconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 { l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index) @@ -267,6 +274,14 @@ unconstrained fn call_static( call_static_opcode(gas, address, args, function_selector) } +unconstrained fn storage_read(storage_slot: Field) -> [Field; N] { + storage_read_opcode(storage_slot, N) +} + +unconstrained fn storage_write(storage_slot: Field, values: [Field; N]) { + storage_write_opcode(storage_slot, values); +} + impl Empty for PublicContext { fn empty() -> Self { PublicContext::new(PublicContextInputs::empty()) @@ -286,11 +301,8 @@ unconstrained fn sender_opcode() -> AztecAddress {} #[oracle(avmOpcodePortal)] unconstrained fn portal_opcode() -> EthAddress {} -#[oracle(avmOpcodeFeePerL2Gas)] -unconstrained fn fee_per_l2_gas_opcode() -> Field {} - -#[oracle(avmOpcodeFeePerDaGas)] -unconstrained fn fee_per_da_gas_opcode() -> Field {} +#[oracle(avmOpcodeFunctionSelector)] +unconstrained fn function_selector_opcode() -> u32 {} #[oracle(avmOpcodeTransactionFee)] unconstrained fn transaction_fee_opcode() -> Field {} @@ -307,6 +319,12 @@ unconstrained fn block_number_opcode() -> Field {} #[oracle(avmOpcodeTimestamp)] unconstrained fn timestamp_opcode() -> u64 {} +#[oracle(avmOpcodeFeePerL2Gas)] +unconstrained fn fee_per_l2_gas_opcode() -> Field {} + +#[oracle(avmOpcodeFeePerDaGas)] +unconstrained fn fee_per_da_gas_opcode() -> Field {} + #[oracle(avmOpcodeL2GasLeft)] unconstrained fn l2_gas_left_opcode() -> Field {} @@ -325,8 +343,8 @@ unconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 #[oracle(avmOpcodeEmitNullifier)] unconstrained fn emit_nullifier_opcode(nullifier: Field) {} -#[oracle(amvOpcodeEmitUnencryptedLog)] -unconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {} +#[oracle(avmOpcodeEmitUnencryptedLog)] +unconstrained fn emit_unencrypted_log_opcode(message: [Field]) {} #[oracle(avmOpcodeL1ToL2MsgExists)] unconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {} @@ -354,6 +372,12 @@ unconstrained fn call_static_opcode( ) -> ([Field; RET_SIZE], u8) {} // ^ return data ^ success +#[oracle(avmOpcodeStorageRead)] +unconstrained fn storage_read_opcode(storage_slot: Field, length: Field) -> [Field; N] {} + +#[oracle(avmOpcodeStorageWrite)] +unconstrained fn storage_write_opcode(storage_slot: Field, values: [Field; N]) {} + struct FunctionReturns { values: [Field; N] } diff --git a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr index 8811a048c0db..eedd97aa8d66 100644 --- a/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr @@ -1,4 +1,5 @@ -use dep::protocol_types::address::AztecAddress; +use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; +use crate::oracle::storage::{raw_storage_read, storage_read}; struct UnconstrainedContext { block_number: u32, @@ -8,7 +9,7 @@ struct UnconstrainedContext { } impl UnconstrainedContext { - fn new() -> Self { + unconstrained fn new() -> Self { // We could call these oracles on the getters instead of at creation, which makes sense given that they might // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not @@ -35,6 +36,14 @@ impl UnconstrainedContext { fn chain_id(self) -> Field { self.chain_id } + + unconstrained fn raw_storage_read(self: Self, storage_slot: Field) -> [Field; N] { + storage_read(self.this_address(), storage_slot, self.block_number()) + } + + unconstrained fn storage_read(self, storage_slot: Field) -> T where T: Deserialize { + T::deserialize(self.raw_storage_read(storage_slot)) + } } #[oracle(getContractAddress)] diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr index a027c1685150..f5366a161749 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_event_emission.nr @@ -1,25 +1,91 @@ use crate::{ context::PrivateContext, event::event_interface::EventInterface, - encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent + encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent, + oracle::unsafe_rand::unsafe_rand }; -use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, hash::sha256_to_field}; + +unconstrained fn compute_unconstrained( + contract_address: AztecAddress, + randomness: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + event: Event +) -> ([u8; OB], Field) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event) +} + +fn compute( + contract_address: AztecAddress, + randomness: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + event: Event +) -> ([u8; OB], Field) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event); + let log_hash = sha256_to_field(encrypted_log); + (encrypted_log, log_hash) +} fn emit_with_keys( context: &mut PrivateContext, randomness: Field, event: Event, ovpk: GrumpkinPoint, - ivpk: GrumpkinPoint + ivpk: GrumpkinPoint, + inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Event) -> ([u8; OB], Field) ) where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { let contract_address: AztecAddress = context.this_address(); let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); + let (encrypted_log, log_hash) = inner_compute(contract_address, randomness, ovsk_app, ovpk, ivpk, event); + context.emit_raw_event_log_with_masked_address(randomness, encrypted_log, log_hash); +} - let encrypted_log: [u8; OB] = compute_encrypted_event_log(contract_address, randomness, ovsk_app, ovpk, ivpk, event); +pub fn encode_and_encrypt_event( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} - context.emit_raw_event_log_with_masked_address(randomness, encrypted_log); +pub fn encode_and_encrypt_event_unconstrained( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); + } } -pub fn encode_and_encrypt_event( +pub fn encode_and_encrypt_event_with_randomness( + context: &mut PrivateContext, + randomness: Field, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress, Field)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_randomness_unconstrained( context: &mut PrivateContext, randomness: Field, ov: AztecAddress, @@ -29,17 +95,50 @@ pub fn encode_and_encrypt_event( let header = context.get_header(); let ovpk = header.get_ovpk_m(context, ov); let ivpk = header.get_ivpk_m(context, iv); - emit_with_keys(context, randomness, e, ovpk, ivpk); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); } } pub fn encode_and_encrypt_event_with_keys( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_keys_unconstrained( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + let randomness = unsafe_rand(); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); + } +} + +pub fn encode_and_encrypt_event_with_keys_with_randomness( + context: &mut PrivateContext, + randomness: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { + | e: Event | { + emit_with_keys(context, randomness, e, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_event_with_keys_with_randomness_unconstrained( context: &mut PrivateContext, randomness: Field, ovpk: GrumpkinPoint, ivpk: GrumpkinPoint ) -> fn[(&mut PrivateContext, Field, GrumpkinPoint, GrumpkinPoint)](Event) -> () where Event: EventInterface, [u8; NB]: LensForEncryptedEvent { | e: Event | { - emit_with_keys(context, randomness, e, ovpk, ivpk); + emit_with_keys(context, randomness, e, ovpk, ivpk, compute_unconstrained); } } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr index 5b66e2e80270..5c05dce4d202 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr @@ -3,34 +3,59 @@ use crate::{ encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog }; use dep::protocol_types::{ - address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index + hash::sha256_to_field, address::AztecAddress, grumpkin_point::GrumpkinPoint, + abis::note_hash::NoteHash, constants::MAX_NOTE_HASHES_PER_CALL, utils::arrays::find_index }; +unconstrained fn compute_unconstrained( + contract_address: AztecAddress, + storage_slot: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + note: Note +) -> ([u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note) +} + +fn compute( + contract_address: AztecAddress, + storage_slot: Field, + ovsk_app: Field, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint, + note: Note +) -> ([u8; M], Field) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); + let log_hash = sha256_to_field(encrypted_log); + (encrypted_log, log_hash) +} + fn emit_with_keys( context: &mut PrivateContext, note: Note, ovpk: GrumpkinPoint, - ivpk: GrumpkinPoint + ivpk: GrumpkinPoint, + inner_compute: fn(AztecAddress, Field, Field, GrumpkinPoint, GrumpkinPoint, Note) -> ([u8; M], Field) ) where Note: NoteInterface, [Field; N]: LensForEncryptedLog { let note_header = note.get_header(); let note_hash_counter = note_header.note_hash_counter; let storage_slot = note_header.storage_slot; let note_exists_index = find_index( - context.new_note_hashes.storage, + context.note_hashes.storage, |n: NoteHash| n.counter == note_hash_counter ); assert( - note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, "Can only emit a note log for an existing note." + note_exists_index as u32 != MAX_NOTE_HASHES_PER_CALL, "Can only emit a note log for an existing note." ); let contract_address: AztecAddress = context.this_address(); let ovsk_app: Field = context.request_ovsk_app(ovpk.hash()); - let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); + let (encrypted_log, log_hash) = inner_compute(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note); - context.emit_raw_note_log(note_hash_counter, encrypted_log); + context.emit_raw_note_log(note_hash_counter, encrypted_log, log_hash); } pub fn encode_and_encrypt_note( @@ -42,7 +67,20 @@ pub fn encode_and_encrypt_note( let header = context.get_header(); let ovpk = header.get_ovpk_m(context, ov); let ivpk = header.get_ivpk_m(context, iv); - emit_with_keys(context, e.note, ovpk, ivpk); + emit_with_keys(context, e.note, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_note_unconstrained( + context: &mut PrivateContext, + ov: AztecAddress, + iv: AztecAddress +) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + let header = context.get_header(); + let ovpk = header.get_ovpk_m(context, ov); + let ivpk = header.get_ivpk_m(context, iv); + emit_with_keys(context, e.note, ovpk, ivpk, compute_unconstrained); } } @@ -52,6 +90,16 @@ pub fn encode_and_encrypt_note_with_keys( ivpk: GrumpkinPoint ) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { | e: NoteEmission | { - emit_with_keys(context, e.note, ovpk, ivpk); + emit_with_keys(context, e.note, ovpk, ivpk, compute); + } +} + +pub fn encode_and_encrypt_note_with_keys_unconstrained( + context: &mut PrivateContext, + ovpk: GrumpkinPoint, + ivpk: GrumpkinPoint +) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog { + | e: NoteEmission | { + emit_with_keys(context, e.note, ovpk, ivpk, compute_unconstrained); } } diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr index 8819906d2b02..3ab22f46ce82 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_private_key::GrumpkinP use crate::keys::point_to_symmetric_key::point_to_symmetric_key; -use dep::std::aes128::aes128_encrypt; +use std::aes128::aes128_encrypt; struct EncryptedLogHeader { address: AztecAddress, diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr index 07e0cb74b123..d8ce5b60133f 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr @@ -2,7 +2,7 @@ use crate::note::note_interface::NoteInterface; use crate::event::event_interface::EventInterface; use dep::protocol_types::{grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint}; -use dep::std::aes128::aes128_encrypt; +use std::aes128::aes128_encrypt; use crate::keys::point_to_symmetric_key::point_to_symmetric_key; struct EncryptedLogIncomingBody { diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/encrypted_logs.nr rename to noir-projects/aztec-nr/aztec/src/encrypted_logs/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr index 460cc73bb852..76a009d56a6c 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr @@ -3,8 +3,7 @@ use dep::protocol_types::{ constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash }; -use dep::std::aes128::aes128_encrypt; -use dep::std::println; +use std::aes128::aes128_encrypt; use crate::keys::point_to_symmetric_key::point_to_symmetric_key; diff --git a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr index 16454145ec4c..8227a9b072ed 100644 --- a/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr +++ b/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr @@ -3,7 +3,7 @@ use dep::protocol_types::{ constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash }; -use dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field}; +use std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field}; use crate::oracle::unsafe_rand::unsafe_rand; diff --git a/noir-projects/aztec-nr/aztec/src/event.nr b/noir-projects/aztec-nr/aztec/src/event/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/event.nr rename to noir-projects/aztec-nr/aztec/src/event/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr index 986ccc39e2ff..78ce23575e4d 100644 --- a/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/contract_inclusion.nr @@ -31,7 +31,9 @@ impl ProveContractNonDeployment for Header { contract_address.to_field() ); + // docs:start:prove_nullifier_non_inclusion self.prove_nullifier_non_inclusion(nullifier); + // docs:end:prove_nullifier_non_inclusion } } diff --git a/noir-projects/aztec-nr/aztec/src/history.nr b/noir-projects/aztec-nr/aztec/src/history/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/history.nr rename to noir-projects/aztec-nr/aztec/src/history/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr index c7d8d9060e0b..de67c9a4a9ed 100644 --- a/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/note_inclusion.nr @@ -1,4 +1,4 @@ -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use dep::protocol_types::header::Header; use crate::{ diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr index 14173d330f07..ea2a199d75c2 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr @@ -1,4 +1,4 @@ -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use dep::protocol_types::header::Header; use crate::{ @@ -36,9 +36,11 @@ trait ProveNoteIsNullified { } impl ProveNoteIsNullified for Header { + // docs:start:prove_note_is_nullified fn prove_note_is_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface { let nullifier = compute_siloed_nullifier(note, context); self.prove_nullifier_inclusion(nullifier); } + // docs:end:prove_note_is_nullified } diff --git a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr index 54f0ea1202bc..d43b7c3e1cdd 100644 --- a/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr +++ b/noir-projects/aztec-nr/aztec/src/history/nullifier_non_inclusion.nr @@ -1,4 +1,4 @@ -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use dep::protocol_types::{header::Header, utils::field::{full_field_less_than, full_field_greater_than}}; use crate::{ context::PrivateContext, note::{utils::compute_siloed_nullifier, note_interface::NoteInterface}, @@ -44,9 +44,11 @@ trait ProveNoteNotNullified { } impl ProveNoteNotNullified for Header { + // docs:start:prove_note_not_nullified fn prove_note_not_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface { let nullifier = compute_siloed_nullifier(note, context); self.prove_nullifier_non_inclusion(nullifier); } + // docs:end:prove_note_not_nullified } diff --git a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr index 44a53db94dbb..6f1922122e7e 100644 --- a/noir-projects/aztec-nr/aztec/src/history/public_storage.nr +++ b/noir-projects/aztec-nr/aztec/src/history/public_storage.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{ constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress, header::Header, utils::field::full_field_less_than }; -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness}; diff --git a/noir-projects/aztec-nr/aztec/src/initializer.nr b/noir-projects/aztec-nr/aztec/src/initializer.nr index 4bf7c8170533..3dff18d094bd 100644 --- a/noir-projects/aztec-nr/aztec/src/initializer.nr +++ b/noir-projects/aztec-nr/aztec/src/initializer.nr @@ -10,12 +10,12 @@ use crate::{ pub fn mark_as_initialized_public(context: &mut PublicContext) { let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address()); - context.push_new_nullifier(init_nullifier, 0); + context.push_nullifier(init_nullifier, 0); } pub fn mark_as_initialized_private(context: &mut PrivateContext) { let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address()); - context.push_new_nullifier(init_nullifier, 0); + context.push_nullifier(init_nullifier, 0); } pub fn assert_is_initialized_public(context: &mut PublicContext) { diff --git a/noir-projects/aztec-nr/aztec/src/keys.nr b/noir-projects/aztec-nr/aztec/src/keys/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/keys.nr rename to noir-projects/aztec-nr/aztec/src/keys/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index 4fa31d5813ec..a6f72f546ef7 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -2,7 +2,7 @@ use dep::protocol_types::{ constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, utils::arr_copy_slice }; -use dep::std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}}; +use std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}}; // TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since // point is not the only input of the function. Unify naming with TS once we have a better name. diff --git a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr index fe65ff9e37ed..f723365df9ef 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr @@ -1,6 +1,6 @@ use dep::protocol_types::{ address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash, - grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize} + grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize, Empty, is_empty} }; use crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX}; @@ -13,22 +13,46 @@ struct PublicKeys { tpk_m: GrumpkinPoint, } +impl Empty for PublicKeys { + fn empty() -> Self { + PublicKeys { + npk_m : GrumpkinPoint::empty(), + ivpk_m : GrumpkinPoint::empty(), + ovpk_m : GrumpkinPoint::empty(), + tpk_m : GrumpkinPoint::empty() + } + } +} + +impl Eq for PublicKeys { + fn eq(self, other: PublicKeys) -> bool { + ( self.npk_m == other.npk_m ) & + ( self.ivpk_m == other.ivpk_m ) & + ( self.ovpk_m == other.ovpk_m ) & + ( self.tpk_m == other.tpk_m ) + } +} + impl PublicKeys { pub fn hash(self) -> PublicKeysHash { PublicKeysHash::from_field( + if is_empty(self) { + 0 + } else { poseidon2_hash( [ - self.npk_m.x, - self.npk_m.y, - self.ivpk_m.x, - self.ivpk_m.y, - self.ovpk_m.x, - self.ovpk_m.y, - self.tpk_m.x, - self.tpk_m.y, - GENERATOR_INDEX__PUBLIC_KEYS_HASH - ] + self.npk_m.x, + self.npk_m.y, + self.ivpk_m.x, + self.ivpk_m.y, + self.ovpk_m.x, + self.ovpk_m.y, + self.tpk_m.x, + self.tpk_m.y, + GENERATOR_INDEX__PUBLIC_KEYS_HASH + ] ) + } ) } diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index 7e7b1af2a8a6..d4b1abf35e71 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -10,8 +10,8 @@ mod event; mod oracle; mod state_vars; mod prelude; -mod public_storage; mod encrypted_logs; +mod unencrypted_logs; use dep::protocol_types; mod utils; diff --git a/noir-projects/aztec-nr/aztec/src/messaging.nr b/noir-projects/aztec-nr/aztec/src/messaging.nr index 77087758f824..169907942dd4 100644 --- a/noir-projects/aztec-nr/aztec/src/messaging.nr +++ b/noir-projects/aztec-nr/aztec/src/messaging.nr @@ -3,7 +3,7 @@ use crate::{ oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness }; -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use dep::protocol_types::{constants::L1_TO_L2_MSG_TREE_HEIGHT, address::{AztecAddress, EthAddress}, utils::arr_copy_slice}; pub fn process_l1_to_l2_message( diff --git a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr index 7fe6021326a6..e9b4ac556f60 100644 --- a/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr +++ b/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr @@ -30,7 +30,7 @@ pub fn create_note( == 0 ); - context.push_new_note_hash(inner_note_hash); + context.push_note_hash(inner_note_hash); NoteEmission::new(*note) } @@ -46,7 +46,7 @@ pub fn create_note_hash_from_public( note.set_header(header); let inner_note_hash = compute_inner_note_hash(*note); - context.push_new_note_hash(inner_note_hash); + context.push_note_hash(inner_note_hash); } pub fn destroy_note( @@ -71,5 +71,5 @@ pub fn destroy_note( let nullifier_counter = context.side_effect_counter; assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0); - context.push_new_nullifier(nullifier, note_hash_for_consumption) + context.push_nullifier(nullifier, note_hash_for_consumption) } diff --git a/noir-projects/aztec-nr/aztec/src/note.nr b/noir-projects/aztec-nr/aztec/src/note/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/note.nr rename to noir-projects/aztec-nr/aztec/src/note/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr similarity index 97% rename from noir-projects/aztec-nr/aztec/src/note/note_getter.nr rename to noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr index 536488751241..b5df4dd7ce7b 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter/mod.nr @@ -127,7 +127,7 @@ fn constrain_get_notes_internal( let filtered_notes = filter_fn(opt_notes, filter_args); let mut prev_fields = [0; N]; - for i in 0..filtered_notes.len() { + for i in 0..options.limit { let opt_note = filtered_notes[i]; if opt_note.is_some() { let note = opt_note.unwrap_unchecked(); @@ -154,7 +154,13 @@ fn constrain_get_notes_internal( }; } + // As long as we only loop till `options.limit` the array will be guaranteed to be at most of length `options.limit`. assert(returned_notes.len() <= options.limit, "Got more notes than limit."); + // We will however check that nothing else was returned after the limit. + for i in options.limit..filtered_notes.len() { + assert(filtered_notes[i].is_none(), "Got more notes than limit."); + } + assert(returned_notes.len() != 0, "Cannot return zero notes"); returned_notes diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter/test.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter/test.nr index 42d28e25a058..4699cc9a3fd8 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter/test.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter/test.nr @@ -77,7 +77,6 @@ fn collapses_notes_at_the_beginning_of_the_array() { opt_notes[5] = Option::some(build_valid_note(3)); opt_notes[8] = Option::some(build_valid_note(4)); opt_notes[13] = Option::some(build_valid_note(5)); - opt_notes[21] = Option::some(build_valid_note(6)); let options = NoteGetterOptions::new(); let returned = constrain_get_notes_internal(&mut context, storage_slot, opt_notes, options); @@ -89,7 +88,6 @@ fn collapses_notes_at_the_beginning_of_the_array() { expected[3] = Option::some(build_valid_note(3)); expected[4] = Option::some(build_valid_note(4)); expected[5] = Option::some(build_valid_note(5)); - expected[6] = Option::some(build_valid_note(6)); assert_equivalent_vec_and_array(returned, expected); } diff --git a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr index 64f053e3a81a..04b44f47fc9e 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_getter_options.nr @@ -1,4 +1,4 @@ -use dep::std::option::Option; +use std::option::Option; use dep::protocol_types::{constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, traits::ToField}; use crate::note::note_interface::NoteInterface; diff --git a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr index 72ab18206fb0..dbdccc19cce8 100644 --- a/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr +++ b/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr @@ -1,4 +1,4 @@ -use dep::std::option::Option; +use std::option::Option; use crate::note::note_getter_options::{PropertySelector, Select, Sort, Comparator, NoteStatus}; use dep::protocol_types::traits::ToField; use crate::note::note_interface::NoteInterface; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr index d512a3bf0708..7d9e03222172 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr @@ -10,7 +10,7 @@ use dep::protocol_types::{ utils::reader::Reader, constants::{ MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, @@ -94,9 +94,9 @@ pub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_F contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], - new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0, end_side_effect_counter: 0, unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], diff --git a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr index 2cb2a370ce5c..84a017a5ea0f 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr @@ -14,7 +14,7 @@ unconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field get_contract_instance_oracle(address) } -unconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] { +unconstrained pub fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] { get_contract_instance_oracle_avm(address) } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/header.nr b/noir-projects/aztec-nr/aztec/src/oracle/header.nr index 92e854e9350c..93b5bd17c9e7 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/header.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/header.nr @@ -1,4 +1,4 @@ -use dep::std::merkle::compute_merkle_root; +use std::merkle::compute_merkle_root; use dep::protocol_types::{constants::HEADER_LENGTH, header::Header}; use crate::{context::PrivateContext, oracle::get_membership_witness::get_archive_membership_witness}; diff --git a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr index 899f7f0d0d10..c3d2cfb83c76 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr @@ -40,6 +40,30 @@ impl LensForEncryptedLog<6, 672> for [Field; 6] { fn output_fields(self) -> [Field; 6] {[self[0]; 6]} fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]} } +impl LensForEncryptedLog<7, 704> for [Field; 7] { + fn output_fields(self) -> [Field; 7] {[self[0]; 7]} + fn output_bytes(self) -> [u8; 704] {[self[0] as u8; 704]} +} +impl LensForEncryptedLog<8, 736> for [Field; 8] { + fn output_fields(self) -> [Field; 8] {[self[0]; 8]} + fn output_bytes(self) -> [u8; 736] {[self[0] as u8; 736]} +} +impl LensForEncryptedLog<9, 768> for [Field; 9] { + fn output_fields(self) -> [Field; 9] {[self[0]; 9]} + fn output_bytes(self) -> [u8; 768] {[self[0] as u8; 768]} +} +impl LensForEncryptedLog<10, 800> for [Field; 10] { + fn output_fields(self) -> [Field; 10] {[self[0]; 10]} + fn output_bytes(self) -> [u8; 800] {[self[0] as u8; 800]} +} +impl LensForEncryptedLog<11, 832> for [Field; 11] { + fn output_fields(self) -> [Field; 11] {[self[0]; 11]} + fn output_bytes(self) -> [u8; 832] {[self[0] as u8; 832]} +} +impl LensForEncryptedLog<12, 864> for [Field; 12] { + fn output_fields(self) -> [Field; 12] {[self[0]; 12]} + fn output_bytes(self) -> [u8; 864] {[self[0] as u8; 864]} +} trait LensForEncryptedEvent { // N = event preimage input in bytes diff --git a/noir-projects/aztec-nr/aztec/src/oracle.nr b/noir-projects/aztec-nr/aztec/src/oracle/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/oracle.nr rename to noir-projects/aztec-nr/aztec/src/oracle/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr index b25e4a3b55c1..b4a6b1f91024 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/storage.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/storage.nr @@ -1,19 +1,59 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; +use dep::protocol_types::{address::AztecAddress, traits::Deserialize}; #[oracle(storageRead)] -unconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {} +unconstrained fn storage_read_oracle( + address: Field, + storage_slot: Field, + block_number: Field, + length: Field +) -> [Field; N] {} -unconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] { - storage_read_oracle(_storage_slot, N) +unconstrained pub fn raw_storage_read( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> [Field; N] { + storage_read_oracle(address.to_field(), storage_slot, block_number as Field, N) } -pub fn storage_read(storage_slot: Field) -> [Field; N] { - storage_read_oracle_wrapper(storage_slot) +unconstrained pub fn storage_read( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> T where T: Deserialize { + T::deserialize(raw_storage_read(address, storage_slot, block_number)) } -#[oracle(storageWrite)] -unconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {} +mod tests { + use crate::oracle::storage::{raw_storage_read, storage_read}; + use dep::protocol_types::address::AztecAddress; -unconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) { - let _hash = storage_write_oracle(storage_slot, fields); + use std::test::OracleMock; + use crate::test::mocks::mock_struct::MockStruct; + + global address = AztecAddress::from_field(29); + global slot = 7; + global block_number = 17; + + #[test] + fn test_raw_storage_read() { + let written = MockStruct { a: 13, b: 42 }; + + let _ = OracleMock::mock("storageRead").returns(written.serialize()); + + let read: [Field; 2] = raw_storage_read(address, slot, block_number); + assert_eq(read[0], 13); + assert_eq(read[1], 42); + } + + #[test] + fn test_storage_read() { + let written = MockStruct { a: 13, b: 42 }; + + let _ = OracleMock::mock("storageRead").returns(written.serialize()); + + let read: MockStruct = storage_read(address, slot, block_number); + assert_eq(read.a, 13); + assert_eq(read.b, 42); + } } diff --git a/noir-projects/aztec-nr/aztec/src/public_storage.nr b/noir-projects/aztec-nr/aztec/src/public_storage.nr deleted file mode 100644 index d46b2c5ffca9..000000000000 --- a/noir-projects/aztec-nr/aztec/src/public_storage.nr +++ /dev/null @@ -1,72 +0,0 @@ -use dep::protocol_types::traits::{Deserialize, Serialize}; -use crate::oracle::storage::{storage_read, storage_write}; - -pub fn read(storage_slot: Field) -> T where T: Deserialize { - T::deserialize(storage_read(storage_slot)) -} - -pub fn write(storage_slot: Field, value: T) where T: Serialize { - storage_write(storage_slot, value.serialize()); -} - -// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633 -// pub fn read_historical( -// storage_slot: Field, -// context: PrivateContext -// ) -> T where T: Deserialize { -// let mut fields = [0; N]; -// for i in 0..N { -// fields[i] = public_storage_historical_read( -// context, -// storage_slot + i as Field, -// context.this_address() -// ); -// } -// T::deserialize(fields) -// } - -mod tests { - use dep::std::test::OracleMock; - use dep::protocol_types::traits::{Deserialize, Serialize}; - use crate::public_storage; - - struct TestStruct { - a: Field, - b: Field, - } - - impl Deserialize<2> for TestStruct { - fn deserialize(fields: [Field; 2]) -> TestStruct { - TestStruct { a: fields[0], b: fields[1] } - } - } - - impl Serialize<2> for TestStruct { - fn serialize(self) -> [Field; 2] { - [self.a, self.b] - } - } - - #[test] - fn test_read() { - let slot = 7; - let written = TestStruct { a: 13, b: 42 }; - - OracleMock::mock("storageRead").with_params((slot, 2)).returns(written.serialize()); - - let read: TestStruct = public_storage::read(slot); - assert_eq(read.a, 13); - assert_eq(read.b, 42); - } - - #[test] - fn test_write() { - let slot = 7; - let to_write = TestStruct { a: 13, b: 42 }; - - let mock = OracleMock::mock("storageWrite").returns([0; 2]); // The return value is unused - - public_storage::write(slot, to_write); - assert_eq(mock.get_last_params(), (slot, to_write.serialize())); - } -} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars.nr b/noir-projects/aztec-nr/aztec/src/state_vars/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/state_vars.nr rename to noir-projects/aztec-nr/aztec/src/state_vars/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr index 0c310180181f..cb909e64a4bb 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr @@ -50,7 +50,7 @@ impl PrivateImmutable { ) -> NoteEmission where Note: NoteInterface { // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); - self.context.push_new_nullifier(nullifier, 0); + self.context.push_nullifier(nullifier, 0); create_note(self.context, self.storage_slot, note) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr index cf0ee4d7aac9..d36c5af8b3a1 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable.nr @@ -54,7 +54,7 @@ impl PrivateMutable { ) -> NoteEmission where Note: NoteInterface { // Nullify the storage slot. let nullifier = self.compute_initialization_nullifier(); - self.context.push_new_nullifier(nullifier, 0); + self.context.push_nullifier(nullifier, 0); create_note(self.context, self.storage_slot, note) } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr index c3949a8e03ea..61f142c1161a 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/private_mutable/test.nr @@ -1,7 +1,7 @@ use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint}; use crate::{context::PrivateContext, state_vars::private_mutable::PrivateMutable}; use crate::test::{mocks::mock_note::MockNote, helpers::{cheatcodes, test_environment::TestEnvironment}}; -use dep::std::{unsafe::zeroed, test::OracleMock}; +use std::{unsafe::zeroed, test::OracleMock}; global storage_slot = 17; @@ -36,13 +36,13 @@ fn test_initialize_or_replace_without_nullifier() { // - a new note being created // - no notes being read // - the initialization nullifier being emitted - assert_eq(state_var.context.new_note_hashes.len(), 1); + assert_eq(state_var.context.note_hashes.len(), 1); assert_eq(state_var.context.note_hash_read_requests.len(), 0); - assert_eq(state_var.context.new_nullifiers.len(), 1); + assert_eq(state_var.context.nullifiers.len(), 1); // Note that if the oracle was wrong and the initialization nullifier did exist, this attempt to write it again // would cause the sequencer to revert this transaction - we are therefore safe from bad oracles. - let nullifier = state_var.context.new_nullifiers.get(0); + let nullifier = state_var.context.nullifiers.get(0); assert_eq(nullifier.value, state_var.compute_initialization_nullifier()); assert_eq(nullifier.note_hash, 0); } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr index b8f2c1d2dde6..1206916cf798 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_immutable.nr @@ -1,5 +1,5 @@ use crate::{ - context::{PublicContext, UnconstrainedContext}, oracle::{storage::{storage_read, storage_write}}, + context::{PublicContext, UnconstrainedContext}, oracle::storage::storage_read, state_vars::storage::Storage }; use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}}; @@ -30,39 +30,27 @@ impl PublicImmutable { impl PublicImmutable { // docs:start:public_immutable_struct_write pub fn initialize(self, value: T) where T: Serialize { - // TODO(#4738): Uncomment the following assert - // assert( - // self.context.public.unwrap_unchecked().is_deployment(), "PublicImmutable can only be initialized during contract deployment" - // ); - // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; - let fields_read: [Field; 1] = storage_read(initialization_slot); - assert(fields_read[0] == 0, "PublicImmutable already initialized"); + let init_field: Field = self.context.storage_read(initialization_slot); + assert(init_field == 0, "PublicImmutable already initialized"); // We populate the initialization slot with a non-zero value to indicate that the struct is initialized - storage_write(initialization_slot, [0xdead]); - - let fields_write = T::serialize(value); - storage_write(self.storage_slot, fields_write); + self.context.storage_write(initialization_slot, 0xdead); + self.context.storage_write(self.storage_slot, value); } // docs:end:public_immutable_struct_write // Note that we don't access the context, but we do call oracles that are only available in public // docs:start:public_immutable_struct_read pub fn read(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } // docs:end:public_immutable_struct_read } impl PublicImmutable { - pub fn read(self) -> T where T: Deserialize { - // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the - // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns - // historical data. - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr index 69a6a0f8a482..07038e14984d 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr @@ -1,6 +1,5 @@ use crate::context::{PublicContext, UnconstrainedContext}; use crate::oracle::storage::storage_read; -use crate::oracle::storage::storage_write; use dep::protocol_types::traits::{Deserialize, Serialize}; use crate::state_vars::storage::Storage; @@ -29,25 +28,19 @@ impl PublicMutable { impl PublicMutable { // docs:start:public_mutable_struct_read pub fn read(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } // docs:end:public_mutable_struct_read // docs:start:public_mutable_struct_write pub fn write(self, value: T) where T: Serialize { - let fields = T::serialize(value); - storage_write(self.storage_slot, fields); + self.context.storage_write(self.storage_slot, value); } // docs:end:public_mutable_struct_write } impl PublicMutable { - pub fn read(self) -> T where T: Deserialize { - // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the - // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns - // historical data. - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr index 086c47aca56f..c366a38cfd1e 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr @@ -1,6 +1,6 @@ use crate::{ - context::{PrivateContext, PublicContext, UnconstrainedContext}, - oracle::{storage::{storage_read, storage_write}}, state_vars::storage::Storage + context::{PrivateContext, PublicContext, UnconstrainedContext}, oracle::storage::storage_read, + state_vars::storage::Storage }; use dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}}; @@ -26,33 +26,24 @@ impl SharedImmutable { impl SharedImmutable { // Intended to be only called once. pub fn initialize(self, value: T) where T: Serialize { - // TODO(#4738): Uncomment the following assert - // assert( - // self.context.public.unwrap_unchecked().is_deployment(), "SharedImmutable can only be initialized during contract deployment" - // ); - // We check that the struct is not yet initialized by checking if the initialization slot is 0 let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot; - let fields_read: [Field; 1] = storage_read(initialization_slot); - assert(fields_read[0] == 0, "SharedImmutable already initialized"); + let init_field: Field = self.context.storage_read(initialization_slot); + assert(init_field == 0, "SharedImmutable already initialized"); // We populate the initialization slot with a non-zero value to indicate that the struct is initialized - storage_write(initialization_slot, [0xdead]); - - let fields_write = T::serialize(value); - storage_write(self.storage_slot, fields_write); + self.context.storage_write(initialization_slot, 0xdead); + self.context.storage_write(self.storage_slot, value); } pub fn read_public(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + self.context.storage_read(self.storage_slot) } } impl SharedImmutable { - pub fn read_public(self) -> T where T: Deserialize { - let fields = storage_read(self.storage_slot); - T::deserialize(fields) + unconstrained pub fn read_public(self) -> T where T: Deserialize { + self.context.storage_read(self.storage_slot) } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr index b35b4f572aad..7710c73f6a31 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr @@ -1,5 +1,5 @@ use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField}; -use dep::std::cmp::min; +use std::cmp::min; mod test; @@ -171,3 +171,9 @@ impl Deserialize<1> for ScheduledDelayChange { } } } + +impl Eq for ScheduledDelayChange { + fn eq(self, other: Self) -> bool { + (self.pre == other.pre) & (self.post == other.post) & (self.block_of_change == other.block_of_change) + } +} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr index 5e4a6d9bcf90..c569510e2cdf 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change/test.nr @@ -7,6 +7,7 @@ fn assert_equal_after_conversion(original: ScheduledDelayChange = ScheduledDelayChange::deserialize((original).serialize()); + assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); assert_eq(original.post, converted.post); assert_eq(original.block_of_change, converted.block_of_change); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr index 3b7a8bc35215..d0d84ad94c06 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr @@ -1,5 +1,5 @@ use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField}; -use dep::std::cmp::min; +use std::cmp::min; mod test; @@ -152,3 +152,9 @@ impl Deserialize<3> for ScheduledValueChange { } } } + +impl Eq for ScheduledValueChange { + fn eq(self, other: Self) -> bool where T: Eq { + (self.pre == other.pre) & (self.post == other.post) & (self.block_of_change == other.block_of_change) + } +} diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr index 8a48ee013be9..5dab89c9701b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change/test.nr @@ -11,6 +11,7 @@ fn test_serde() { let original = ScheduledValueChange::new(pre, post, block_of_change); let converted = ScheduledValueChange::deserialize((original).serialize()); + assert_eq(original, converted); // This also tests the Eq impl assert_eq(original.pre, converted.pre); assert_eq(original.post, converted.post); assert_eq(original.block_of_change, converted.block_of_change); diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 91c864a03b23..9823b25d8c95 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -1,11 +1,15 @@ -use dep::protocol_types::{hash::pedersen_hash, traits::FromField}; +use dep::protocol_types::{ + hash::{pedersen_hash, poseidon2_hash}, header::Header, address::AztecAddress, + traits::{FromField, ToField} +}; use crate::context::{PrivateContext, PublicContext}; -use crate::public_storage; use crate::state_vars::{ storage::Storage, shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange} }; +use crate::oracle::storage::storage_read; +use dep::std::unsafe::zeroed; mod test; @@ -19,10 +23,23 @@ struct SharedMutable { // - a ScheduledValueChange, which requires 1 + 2 * M storage slots, where M is the serialization length of T // - a ScheduledDelayChange, which requires another storage slot // -// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we +// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we // can actually use it here impl Storage for SharedMutable {} +// TODO: extract into a utils module once we can do arithmetic on generics, i.e. https://github.com/noir-lang/noir/issues/4784 +fn concat_arrays(arr_n: [Field; N], arr_m: [Field; M]) -> [Field; O] { + assert_eq(N + M, O); + let mut out: [Field; O] = [0; O]; + for i in 0..N { + out[i] = arr_n[i]; + } + for i in 0..M { + out[N+i] = arr_m[i]; + } + out +} + // SharedMutable stores a value of type T that is: // - publicly known (i.e. unencrypted) // - mutable in public @@ -30,9 +47,9 @@ impl Storage for SharedMutable SharedMutable { pub fn new(context: Context, storage_slot: Field) -> Self { @@ -40,10 +57,24 @@ impl SharedMutable { Self { context, storage_slot } } + fn hash_scheduled_data( + value_change: ScheduledValueChange, + delay_change: ScheduledDelayChange + ) -> Field where T: ToField { + // TODO(#5491 and https://github.com/noir-lang/noir/issues/4784): update this so that we don't need to rely on + // ScheduledValueChange serializing to 3 and ScheduledDelayChange serializing to 1 + let concatenated: [Field; 4] = concat_arrays(value_change.serialize(), delay_change.serialize()); + poseidon2_hash(concatenated) + } + // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in - // which we can safely store as much data as we need. - // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and + // which we can safely store as much data as we need. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and // https://github.com/AztecProtocol/aztec-packages/issues/5736 + // We store three things in public storage: + // - a ScheduledValueChange + // - a ScheduledDelaChange + // - the hash of both of these (via `hash_scheduled_data`) fn get_value_change_storage_slot(self) -> Field { pedersen_hash([self.storage_slot, 0], 0) } @@ -51,10 +82,53 @@ impl SharedMutable { fn get_delay_change_storage_slot(self) -> Field { pedersen_hash([self.storage_slot, 1], 0) } + + fn get_hash_storage_slot(self) -> Field { + pedersen_hash([self.storage_slot, 2], 0) + } + + // It may seem odd that we take a header and address instead of reading from e.g. a PrivateContext, but this lets us + // reuse this function in SharedMutablePrivateGetter. + fn historical_read_from_public_storage( + self, + header: Header, + address: AztecAddress + ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField + ToField + Eq { + let historical_block_number = header.global_variables.block_number as u32; + + // We could simply produce historical inclusion proofs for both the ScheduledValueChange and + // ScheduledDelayChange, but that'd require one full sibling path per storage slot (since due to kernel siloing + // the storage is not contiguous), and in the best case in which T is a single field that'd be 4 slots. + // Instead, we get an oracle to provide us the correct values for both the value and delay changes, and instead + // prove inclusion of their hash, which is both a much smaller proof (a single slot), and also independent of + // the size of T. + let (value_change_hint, delay_change_hint) = get_public_storage_hints(address, self.storage_slot, historical_block_number); + + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let hash = header.public_storage_historical_read(self.get_hash_storage_slot(), address); + + // @todo This is written strangely to bypass a formatting issue with the if that is breaking ci. + let (a, b, c) = if hash != 0 { + let a = SharedMutable::hash_scheduled_data(value_change_hint, delay_change_hint); + (a, value_change_hint, delay_change_hint) + } else { + // The hash slot can only hold a zero if it is uninitialized, meaning no value or delay change was ever + // scheduled. Therefore, the hints must then correspond to uninitialized scheduled changes. + let b = ScheduledValueChange::deserialize(zeroed()); + let c = ScheduledDelayChange::deserialize(zeroed()); + (hash, b, c) + }; + + assert_eq(hash, a, "Hint values do not match hash"); + assert_eq(value_change_hint, b, "Non-zero value change for zero hash"); + assert_eq(delay_change_hint, c, "Non-zero delay change for zero hash"); + + (value_change_hint, delay_change_hint, historical_block_number) + } } impl SharedMutable { - pub fn schedule_value_change(self, new_value: T) { + pub fn schedule_value_change(self, new_value: T) where T: ToField { let mut value_change = self.read_value_change(); let delay_change = self.read_delay_change(); @@ -66,17 +140,17 @@ impl SharedMutable { let block_of_change = block_number + current_delay; value_change.schedule_change(new_value, block_number, current_delay, block_of_change); - self.write_value_change(value_change); + self.write(value_change, delay_change); } - pub fn schedule_delay_change(self, new_delay: u32) { + pub fn schedule_delay_change(self, new_delay: u32) where T: ToField { let mut delay_change = self.read_delay_change(); let block_number = self.context.block_number() as u32; delay_change.schedule_change(new_delay, block_number); - self.write_delay_change(delay_change); + self.write(self.read_value_change(), delay_change); } pub fn get_current_value_in_public(self) -> T { @@ -98,71 +172,71 @@ impl SharedMutable { } fn read_value_change(self) -> ScheduledValueChange { - public_storage::read(self.get_value_change_storage_slot()) + self.context.storage_read(self.get_value_change_storage_slot()) } fn read_delay_change(self) -> ScheduledDelayChange { - public_storage::read(self.get_delay_change_storage_slot()) + self.context.storage_read(self.get_delay_change_storage_slot()) } - fn write_value_change(self, value_change: ScheduledValueChange) { - public_storage::write(self.get_value_change_storage_slot(), value_change); - } - - fn write_delay_change(self, delay_change: ScheduledDelayChange) { - public_storage::write(self.get_delay_change_storage_slot(), delay_change); + fn write( + self, + value_change: ScheduledValueChange, + delay_change: ScheduledDelayChange + ) where T: ToField { + // Whenever we write to public storage, we write both the value change and delay change as well as the hash of + // them both. This guarantees that the hash is always kept up to date. + // While this makes for more costly writes, it also makes private proofs much simpler because they only need to + // produce a historical proof for the hash, which results in a single inclusion proof (as opposed to 4 in the + // best case scenario in which T is a single field). Private shared mutable reads are assumed to be much more + // frequent than public writes, so this tradeoff makes sense. + self.context.storage_write(self.get_value_change_storage_slot(), value_change); + self.context.storage_write(self.get_delay_change_storage_slot(), delay_change); + self.context.storage_write( + self.get_hash_storage_slot(), + SharedMutable::hash_scheduled_data(value_change, delay_change) + ); } } impl SharedMutable { - pub fn get_current_value_in_private(self) -> T where T: FromField { + pub fn get_current_value_in_private(self) -> T where T: FromField + ToField + Eq { // When reading the current value in private we construct a historical state proof for the public value. // However, since this value might change, we must constrain the maximum transaction block number as this proof // will only be valid for however many blocks we can ensure the value will not change, which will depend on the // current delay and any scheduled delay changes. - let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context); + let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(self.context.get_header(), self.context.this_address()); // We use the effective minimum delay as opposed to the current delay at the historical block as this one also - // takes into consideration any scheduled delay changes. + // takes into consideration any scheduled delay changes. // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that // the earliest we could change the value would be at block 251 by scheduling immediately after the historical - // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 - // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is + // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 + // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is // earlier than what we'd expect if we only considered the current delay. let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number); let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay); - // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // 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. self.context.set_tx_max_block_number(block_horizon); value_change.get_current_at(historical_block_number) } +} - fn historical_read_from_public_storage( - self, - context: PrivateContext - ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField { - let header = context.get_header(); - // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. - let value_change_slot = self.get_value_change_storage_slot(); - let mut raw_value_change_fields = [0; 3]; - for i in 0..3 { - raw_value_change_fields[i] = header.public_storage_historical_read( - value_change_slot + i as Field, - context.this_address() - ); - } - - // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. - let delay_change_slot = self.get_delay_change_storage_slot(); - let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())]; - - let value_change = ScheduledValueChange::deserialize(raw_value_change_fields); - let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields); - - let historical_block_number = context.historical_header.global_variables.block_number as u32; - - (value_change, delay_change, historical_block_number) - } +unconstrained fn get_public_storage_hints( + address: AztecAddress, + storage_slot: Field, + block_number: u32 +) -> (ScheduledValueChange, ScheduledDelayChange) { + // This function cannot be part of the &mut PrivateContext impl because that'd mean that by passing `self` we'd also + // be passing a mutable reference to an unconstrained function, which is not allowed. We therefore create a dummy + // state variable here so that we can access the methods to compute storage slots. This will all be removed in the + // future once we do proper storage slot allocation (#5492). + let dummy = SharedMutable::new((), storage_slot); + + ( + storage_read(address, dummy.get_value_change_storage_slot(), block_number), storage_read(address, dummy.get_delay_change_storage_slot(), block_number) + ) } 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 index 5a6ad9ad6fde..78c7cc66bb3e 100644 --- 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 @@ -1,10 +1,15 @@ -use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header}; +use dep::protocol_types::{ + hash::{pedersen_hash, poseidon2_hash}, traits::{FromField, ToField}, address::AztecAddress, + header::Header +}; use crate::context::PrivateContext; -use crate::public_storage; use crate::state_vars::{ storage::Storage, - shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange} + shared_mutable::{ + shared_mutable::SharedMutable, scheduled_delay_change::ScheduledDelayChange, + scheduled_value_change::ScheduledValueChange +} }; struct SharedMutablePrivateGetter { @@ -31,8 +36,12 @@ impl SharedMutablePrivateGetter { Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] } } - pub fn get_value_in_private(self, header: Header) -> T where T: FromField { - let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header); + pub fn get_value_in_private(self, header: Header) -> T where T: FromField + ToField + Eq { + // We create a dummy SharedMutable state variable so that we can reuse its historical_read_from_public_storage + // method, greatly reducing code duplication. + let dummy: SharedMutable = SharedMutable::new((), self.storage_slot); + let (value_change, delay_change, historical_block_number) = dummy.historical_read_from_public_storage(header, self.other_contract_address); + let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number); let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay); @@ -45,36 +54,4 @@ impl SharedMutablePrivateGetter { value_change.get_current_at(historical_block_number) } - - fn historical_read_from_public_storage( - self, - header: Header - ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField { - let value_change_slot = self.get_value_change_storage_slot(); - let mut raw_value_change_fields = [0; 3]; - for i in 0..3 { - raw_value_change_fields[i] = header.public_storage_historical_read( - value_change_slot + i as Field, - self.other_contract_address - ); - } - - let delay_change_slot = self.get_delay_change_storage_slot(); - let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)]; - - let value_change = ScheduledValueChange::deserialize(raw_value_change_fields); - let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields); - - let historical_block_number = header.global_variables.block_number as u32; - - (value_change, delay_change, historical_block_number) - } - - fn get_value_change_storage_slot(self) -> Field { - pedersen_hash([self.storage_slot, 0], 0) - } - - fn get_delay_change_storage_slot(self) -> Field { - pedersen_hash([self.storage_slot, 1], 0) - } } diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index b193640a54b2..e162a642eaae 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -1,18 +1,22 @@ use crate::{ - context::{PublicContext, PrivateContext}, state_vars::shared_mutable::shared_mutable::SharedMutable, + context::{PublicContext, PrivateContext}, + state_vars::shared_mutable::{ + shared_mutable::SharedMutable, scheduled_value_change::ScheduledValueChange, + scheduled_delay_change::ScheduledDelayChange +}, test::helpers::test_environment::TestEnvironment }; use dep::protocol_types::address::AztecAddress; +use dep::std::{test::OracleMock, unsafe::zeroed}; -global new_value = 57; +global new_value = 17; -global pre_delay = 20; -global post_delay = 15; +global new_delay = 20; -global storage_slot = 57; +global storage_slot = 47; -global TEST_INITIAL_DELAY: u32 = 30; +global TEST_INITIAL_DELAY: u32 = 32; fn setup() -> TestEnvironment { TestEnvironment::new() @@ -29,335 +33,307 @@ fn in_private( SharedMutable::new(&mut env.private_at(historical_block_number), storage_slot) } -// #[test] -// fn test_get_current_value_in_public_initial() { -// let env = setup(); -// let state_var = in_public(env); +#[test] +fn test_get_current_value_in_public_initial() { + let env = setup(); + let state_var = in_public(env); -// // 0 is the default empty value for a Field -// assert_eq(state_var.get_current_value_in_public(), 0); -// } + assert_eq(state_var.get_current_value_in_public(), zeroed()); +} + +#[test] +fn test_get_scheduled_value_in_public() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); + + let (scheduled, block_of_change) = state_var.get_scheduled_value_in_public(); + assert_eq(scheduled, new_value); + assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY); +} + +#[test] +fn test_get_current_value_in_public_before_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); + + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); + + let original_value = zeroed(); + + // The current value has not changed + assert_eq(state_var.get_current_value_in_public(), original_value); + + // The current value still does not change right before the block of change + env.advance_block_to(block_of_change - 1); + assert_eq(state_var.get_current_value_in_public(), original_value); +} + +#[test] +fn test_get_current_value_in_public_at_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); + + state_var.schedule_value_change(new_value); -// #[test] -// fn test_get_current_value_in_public_before_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); -// state_var.schedule_value_change(new_value); + env.advance_block_to(block_of_change); + assert_eq(state_var.get_current_value_in_public(), new_value); +} -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_current_value_in_public_after_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let original_value = 0; + state_var.schedule_value_change(new_value); -// // The current value has not changed -// assert_eq(state_var.get_current_value_in_public(), original_value); + let (_, block_of_change) = state_var.get_scheduled_value_in_public(); -// // The current value still does not change right before the block of change -// env.advance_block_to(block_of_change - 1); -// assert_eq(state_var.get_current_value_in_public(), original_value); -// } + env.advance_block_to(block_of_change + 10); + assert_eq(state_var.get_current_value_in_public(), new_value); +} -// #[test] -// fn test_get_current_value_in_public_at_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); +#[test] +fn test_get_current_delay_in_public_initial() { + let env = setup(); + let state_var = in_public(env); -// state_var.schedule_value_change(new_value); + assert_eq(state_var.get_current_delay_in_public(), TEST_INITIAL_DELAY); +} -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_scheduled_delay_in_public() { + let mut env = setup(); + let state_var = in_public(env); -// env.advance_block_to(block_of_change); -// assert_eq(state_var.get_current_value_in_public(), new_value); -// } + state_var.schedule_delay_change(new_delay); -// #[test] -// fn test_get_current_value_in_public_after_scheduled_change() { -// let mut env = setup(); -// let state_var = in_public(env); + let (scheduled, block_of_change) = state_var.get_scheduled_delay_in_public(); + assert_eq(scheduled, new_delay); + // The new delay is smaller, therefore we need to wait for the difference between current and new + assert_eq(block_of_change, env.block_number() + TEST_INITIAL_DELAY - new_delay); +} -// state_var.schedule_value_change(new_value); +#[test] +fn test_get_current_delay_in_public_before_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let (_, block_of_change) = state_var.get_scheduled_value_in_public(); + state_var.schedule_delay_change(new_delay); -// env.advance_block_to(block_of_change + 10); -// assert_eq(state_var.get_current_value_in_public(), new_value); -// } + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// #[test] -// fn test_get_current_value_in_private_before_change() { -// let mut env = setup(); + let original_delay = TEST_INITIAL_DELAY; + + // The current delay has not changed + assert_eq(state_var.get_current_delay_in_public(), original_delay); + + // The current delay still does not change right before the block of change + env.advance_block_to(block_of_change - 1); + assert_eq(state_var.get_current_delay_in_public(), original_delay); +} -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); +#[test] +fn test_get_current_delay_in_public_at_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + state_var.schedule_delay_change(new_delay); -// let schedule_block_number = env.block_number(); + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// let private_state_var = in_private(&mut env, schedule_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), 0); -// assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); -// } + env.advance_block_to(block_of_change); + assert_eq(state_var.get_current_delay_in_public(), new_delay); +} -// #[test] -// fn test_get_current_value_in_private_immediately_before_change() { -// let mut env = setup(); +#[test] +fn test_get_current_delay_in_public_after_scheduled_change() { + let mut env = setup(); + let state_var = in_public(env); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + state_var.schedule_delay_change(new_delay); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + let (_, block_of_change) = state_var.get_scheduled_delay_in_public(); -// let private_state_var = in_private(&mut env, block_of_change - 1); + env.advance_block_to(block_of_change + 10); + assert_eq(state_var.get_current_delay_in_public(), new_delay); +} -// assert_eq(private_state_var.get_current_value_in_private(), 0); -// assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); -// } +#[test] +fn test_get_current_value_in_private_initial() { + let mut env = setup(); -// #[test] -// fn test_get_current_value_in_private_at_change() { -// let mut env = setup(); + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + assert_eq(state_var.get_current_value_in_private(), zeroed()); + assert_eq(state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY); +} -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); +#[test] +fn test_get_current_value_in_private_before_change() { + let mut env = setup(); -// let historical_block_number = block_of_change; -// let private_state_var = in_private(&mut env, historical_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), new_value); -// assert_eq( -// private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY -// ); -// } + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// #[test] -// fn test_get_current_value_in_private_after_change() { -// let mut env = setup(); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// let public_state_var = in_public(env); -// public_state_var.schedule_value_change(new_value); + let schedule_block_number = env.block_number(); -// let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); + let private_state_var = in_private(&mut env, schedule_block_number); + assert_eq(private_state_var.get_current_value_in_private(), 0); + assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); +} -// let historical_block_number = block_of_change + 10; -// let private_state_var = in_private(&mut env, historical_block_number); -// assert_eq(private_state_var.get_current_value_in_private(), new_value); -// assert_eq( -// private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY -// ); -// } +#[test] +fn test_get_current_value_in_private_immediately_before_change() { + let mut env = setup(); -// #[test] -// fn test_get_current_delay_in_public() { -// let (state_var, block_number) = setup(); + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// // Uninitialized -// mock_delay_change_read_uninitialized(state_var); -// assert_eq(state_var.get_current_delay_in_public(), TEST_INITIAL_DELAY as u32); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Change in the future, current value is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// assert_eq(state_var.get_current_delay_in_public(), pre_delay as u32); + let private_state_var = in_private(&mut env, block_of_change - 1); -// // Change in the current block, current value is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number); -// assert_eq(state_var.get_current_delay_in_public(), post_delay as u32); + // Note that this transaction would never be valid since the max block number is the same as the historical block + // used to built the proof, i.e. in the past. + assert_eq(private_state_var.get_current_value_in_private(), 0); + assert_eq(private_state_var.context.max_block_number.unwrap(), block_of_change - 1); +} -// // Change in the past, current value is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// assert_eq(state_var.get_current_delay_in_public(), post_delay as u32); -// } +#[test] +fn test_get_current_value_in_private_at_change() { + let mut env = setup(); -// #[test] -// fn test_get_scheduled_delay_in_public_before_change() { -// let (state_var, block_number) = setup(); + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// // Uninitialized -// mock_delay_change_read_uninitialized(state_var); -// assert_eq(state_var.get_scheduled_delay_in_public(), (TEST_INITIAL_DELAY as u32, 0)); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Change in the future, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, (block_number + 1) as u32)); + let historical_block_number = block_of_change; + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq( + private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY + ); +} -// // Change in the current block, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, block_number as u32)); +#[test] +fn test_get_current_value_in_private_after_change() { + let mut env = setup(); -// // Change in the past, scheduled is post (always is) -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// assert_eq(state_var.get_scheduled_delay_in_public(), (post_delay as u32, (block_number - 1) as u32)); -// } + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); -// #[test] -// fn test_schedule_value_change_no_delay() { -// let (state_var, block_number) = setup(); + let (_, block_of_change) = public_state_var.get_scheduled_value_in_public(); -// // Last value change was in the past -// mock_value_change_read(state_var, pre_value, post_value, 0); - -// // Current delay is 0 -// mock_delay_change_read(state_var, 0, 0, block_number); - -// let write_mock = mock_value_change_write(); + let historical_block_number = block_of_change + 10; + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq( + private_state_var.context.max_block_number.unwrap(), historical_block_number + TEST_INITIAL_DELAY + ); +} -// state_var.schedule_value_change(new_value); - -// // The new value has a block of change equal to the current block, i.e. it is the current value -// assert_value_change_write(state_var, write_mock, post_value, new_value, block_number); -// } - -// #[test] -// fn test_schedule_value_change_before_change_no_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the future, delay change in the past -// mock_value_and_delay_read(state_var, block_number + 1, block_number - 1); -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The new scheduled value change replaces the old one, post delay (current) is used -// assert_value_change_write( -// state_var, -// write_mock, -// pre_value, -// new_value, -// block_number + post_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_before_change_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the future, delay change in the future -// mock_value_and_delay_read(state_var, block_number + 1, block_number + 1); - -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The new scheduled value change replaces the old one, pre delay (current, not scheduled) is used -// assert_value_change_write( -// state_var, -// write_mock, -// pre_value, -// new_value, -// block_number + pre_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_after_change_no_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the past, delay change in the past -// mock_value_and_delay_read(state_var, block_number - 1, block_number - 1); -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The previous post value becomes the pre value, post delay (current) is used -// assert_value_change_write( -// state_var, -// write_mock, -// post_value, -// new_value, -// block_number + post_delay -// ); -// } - -// #[test] -// fn test_schedule_value_change_after_change_scheduled_delay() { -// let (state_var, block_number) = setup(); - -// // Value change in the past, delay change in the future -// mock_value_and_delay_read(state_var, block_number - 1, block_number + 1); - -// let write_mock = mock_value_change_write(); - -// state_var.schedule_value_change(new_value); - -// // The previous post value becomes the pre value, pre delay (current, not scheduled) is used -// assert_value_change_write( -// state_var, -// write_mock, -// post_value, -// new_value, -// block_number + pre_delay -// ); -// } - -// #[test] -// fn test_schedule_delay_increase_before_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in future, current delay is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = pre_delay + 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The previous scheduled change is lost, change is immediate (due to increase) -// assert_delay_change_write(state_var, write_mock, pre_delay, new_delay, block_number); -// } - -// #[test] -// fn test_schedule_delay_reduction_before_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in future, current delay is pre -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number + 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = pre_delay - 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The previous scheduled change is lost, change delay equals difference (due to reduction) -// assert_delay_change_write( -// state_var, -// write_mock, -// pre_delay, -// new_delay, -// block_number + pre_delay - new_delay -// ); -// } - -// #[test] -// fn test_schedule_delay_increase_after_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in the past, current delay is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = post_delay + 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The current value becomes pre, change is immediate (due to increase) -// assert_delay_change_write(state_var, write_mock, post_delay, new_delay, block_number); -// } - -// #[test] -// fn test_schedule_delay_reduction_after_change() { -// let (state_var, block_number) = setup(); - -// // Delay change in the past, current delay is post -// mock_delay_change_read(state_var, pre_delay, post_delay, block_number - 1); -// let write_mock = mock_delay_change_write(); - -// let new_delay = post_delay - 1; -// state_var.schedule_delay_change(new_delay as u32); - -// // The current value becomes pre, change delay equals difference (due to reduction) -// assert_delay_change_write( -// state_var, -// write_mock, -// post_delay, -// new_delay, -// block_number + post_delay - new_delay -// ); -// } \ No newline at end of file +#[test] +fn test_get_current_value_in_private_with_non_initial_delay() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + public_state_var.schedule_delay_change(new_delay); + + let (_, value_block_of_change) = public_state_var.get_scheduled_value_in_public(); + let (_, delay_block_of_change) = public_state_var.get_scheduled_delay_in_public(); + + let historical_block_number = if value_block_of_change > delay_block_of_change { + value_block_of_change + } else { + delay_block_of_change + }; + + let private_state_var = in_private(&mut env, historical_block_number); + assert_eq(private_state_var.get_current_value_in_private(), new_value); + assert_eq(private_state_var.context.max_block_number.unwrap(), historical_block_number + new_delay); +} + +#[test(should_fail_with="Hint values do not match hash")] +fn test_get_current_value_in_private_bad_value_hints() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + + let schedule_block_number = env.block_number(); + let private_state_var = in_private(&mut env, schedule_block_number); + + let mocked: ScheduledValueChange = ScheduledValueChange::new(0, new_value + 1, schedule_block_number); + let _ = OracleMock::mock("storageRead").with_params( + ( + env.contract_address().to_field(), private_state_var.get_value_change_storage_slot(), schedule_block_number, 3 + ) + ).returns(mocked.serialize()).times(1); + + let _ = private_state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Hint values do not match hash")] +fn test_get_current_value_in_private_bad_delay_hints() { + let mut env = setup(); + + let public_state_var = in_public(env); + public_state_var.schedule_value_change(new_value); + + let schedule_block_number = env.block_number(); + let private_state_var = in_private(&mut env, schedule_block_number); + + let mocked: ScheduledDelayChange = ScheduledDelayChange::new(Option::none(), Option::some(42), schedule_block_number); + let _ = OracleMock::mock("storageRead").with_params( + ( + env.contract_address().to_field(), private_state_var.get_delay_change_storage_slot(), schedule_block_number, 1 + ) + ).returns(mocked.serialize()).times(1); + + let _ = private_state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Non-zero value change for zero hash")] +fn test_get_current_value_in_private_bad_zero_hash_value_hints() { + let mut env = setup(); + + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); + + let mocked: ScheduledValueChange = ScheduledValueChange::new(0, new_value, 0); + let _ = OracleMock::mock("storageRead").with_params( + ( + env.contract_address().to_field(), state_var.get_value_change_storage_slot(), historical_block_number, 3 + ) + ).returns(mocked.serialize()).times(1); + + let _ = state_var.get_current_value_in_private(); +} + +#[test(should_fail_with="Non-zero delay change for zero hash")] +fn test_get_current_value_in_private_bad_zero_hash_delay_hints() { + let mut env = setup(); + + let historical_block_number = env.block_number(); + let state_var = in_private(&mut env, historical_block_number); + + let mocked: ScheduledDelayChange = ScheduledDelayChange::new(Option::none(), Option::some(new_delay), 0); + let _ = OracleMock::mock("storageRead").with_params( + ( + env.contract_address().to_field(), state_var.get_delay_change_storage_slot(), historical_block_number, 1 + ) + ).returns(mocked.serialize()).times(1); + + let _ = state_var.get_current_value_in_private(); +} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr index db5e13ed4240..3d6b791e8334 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr @@ -101,6 +101,14 @@ unconstrained pub fn add_note_hashes(contractAddress: AztecAddress, inner_note_h oracle_add_note_hashes(contractAddress, inner_note_hashes) } +unconstrained pub fn get_function_selector() -> FunctionSelector { + oracle_get_function_selector() +} + +unconstrained pub fn set_fn_selector(selector: FunctionSelector) { + oracle_set_function_selector(selector) +} + #[oracle(reset)] fn oracle_reset() {} @@ -181,3 +189,8 @@ fn oracle_add_nullifiers(contractAddress: AztecAddress, nullifiers: [Field]) {} #[oracle(addNoteHashes)] fn oracle_add_note_hashes(contractAddress: AztecAddress, inner_note_hashes: [Field]) {} +#[oracle(getFunctionSelector)] +fn oracle_get_function_selector() -> FunctionSelector {} + +#[oracle(setFunctionSelector)] +fn oracle_set_function_selector(selector: FunctionSelector) {} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/test/helpers.nr rename to noir-projects/aztec-nr/aztec/src/test/helpers/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index 9b66e64264b3..e045ca4b8bc5 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -30,6 +30,10 @@ impl TestEnvironment { cheatcodes::get_block_number() } + fn contract_address(self) -> AztecAddress { + cheatcodes::get_contract_address() + } + fn advance_block_to(&mut self, block_number: u32) { let difference = block_number - cheatcodes::get_block_number(); self.advance_block_by(difference); @@ -40,7 +44,8 @@ impl TestEnvironment { } fn public(self) -> PublicContext { - PublicContext::empty() + let mut inputs = cheatcodes::get_public_context_inputs(); + PublicContext::new(inputs) } fn private(&mut self) -> PrivateContext { @@ -159,16 +164,19 @@ impl TestEnvironment { let original_fn = call_interface.get_original(); let original_msg_sender = cheatcodes::get_msg_sender(); let original_contract_address = cheatcodes::get_contract_address(); + let original_fn_selector = cheatcodes::get_function_selector(); let target_address = call_interface.get_contract_address(); + let fn_selector = call_interface.get_selector(); + cheatcodes::set_fn_selector(fn_selector); cheatcodes::set_contract_address(target_address); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.selector = call_interface.get_selector().to_field(); inputs.args_hash = hash_args(call_interface.get_args()); inputs.is_static_call = call_interface.get_is_static(); let result = original_fn(inputs); + cheatcodes::set_fn_selector(original_fn_selector); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); result diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr index 808b5ad37f5f..12b5fddf2633 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/utils.nr @@ -14,14 +14,14 @@ use crate::oracle::notes::notify_nullified_note; pub fn apply_side_effects_private(contract_address: AztecAddress, public_inputs: PrivateCircuitPublicInputs) { let mut nullifiers = &[]; - for nullifier in public_inputs.new_nullifiers { + for nullifier in public_inputs.nullifiers { if nullifier.value != 0 { nullifiers = nullifiers.push_back(nullifier.value); } } cheatcodes::add_nullifiers(contract_address, nullifiers); let mut note_hashes = &[]; - for note_hash in public_inputs.new_note_hashes { + for note_hash in public_inputs.note_hashes { if note_hash.value != 0 { note_hashes = note_hashes.push_back(note_hash.value); } @@ -78,14 +78,16 @@ impl Deployer { let original_fn = call_interface.get_original(); let original_msg_sender = cheatcodes::get_msg_sender(); let original_contract_address = cheatcodes::get_contract_address(); + let original_fn_selector = cheatcodes::get_function_selector(); + cheatcodes::set_fn_selector(call_interface.get_selector()); cheatcodes::set_contract_address(instance.to_address()); cheatcodes::set_msg_sender(original_contract_address); let mut inputs = cheatcodes::get_public_context_inputs(); - inputs.selector = call_interface.get_selector().to_field(); inputs.args_hash = hash_args(call_interface.get_args()); let _result: T = original_fn(inputs); + cheatcodes::set_fn_selector(original_fn_selector); cheatcodes::set_contract_address(original_contract_address); cheatcodes::set_msg_sender(original_msg_sender); instance diff --git a/noir-projects/aztec-nr/aztec/src/test/mocks.nr b/noir-projects/aztec-nr/aztec/src/test/mocks/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/test/mocks.nr rename to noir-projects/aztec-nr/aztec/src/test/mocks/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/test.nr b/noir-projects/aztec-nr/aztec/src/test/mod.nr similarity index 100% rename from noir-projects/aztec-nr/aztec/src/test.nr rename to noir-projects/aztec-nr/aztec/src/test/mod.nr diff --git a/noir-projects/aztec-nr/aztec/src/unencrypted_logs/mod.nr b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/mod.nr new file mode 100644 index 000000000000..3eae1f8dc8e5 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/mod.nr @@ -0,0 +1 @@ +mod unencrypted_event_emission; diff --git a/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr new file mode 100644 index 000000000000..f374a2a1195d --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/unencrypted_logs/unencrypted_event_emission.nr @@ -0,0 +1,58 @@ +use crate::{ + context::{PrivateContext, PublicContext}, event::event_interface::EventInterface, + encrypted_logs::payload::compute_encrypted_event_log, oracle::logs_traits::LensForEncryptedEvent +}; +use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint, traits::Serialize}; + +fn emit( + context: &mut PublicContext, + event: Event +) where Event: EventInterface, Event: Serialize, [Field; N]: LensForEventSelector { + let selector = Event::get_event_type_id(); + + let serialized_event = event.serialize(); + let mut emitted_log = [0; M]; + + // We put the selector in the "last" place, to avoid reading or assigning to an expression in an index + for i in 0..serialized_event.len() { + emitted_log[i] = serialized_event[i]; + } + + emitted_log[serialized_event.len()] = selector.to_field(); + + context.emit_unencrypted_log(emitted_log); +} + +pub fn encode_event(context: &mut PublicContext) -> fn[(&mut PublicContext,)](Event) -> () where Event: EventInterface, Event: Serialize, [Field; N]: LensForEventSelector { + | e: Event | { + emit( + context, + e, + ); + } +} + +trait LensForEventSelector { + // N = event preimage input in fields + // M = event preimage input in fields + event selector as field + fn output(self: [Field; N]) -> [Field; M]; +} + +impl LensForEventSelector<1, 2> for [Field; 1] { + fn output(self) -> [Field; 2] {[self[0] as Field; 2]} +} +impl LensForEventSelector<2, 3> for [Field; 2] { + fn output(self) -> [Field; 3] {[self[0] as Field; 3]} +} +impl LensForEventSelector<3, 4> for [Field; 3] { + fn output(self) -> [Field; 4] {[self[0] as Field; 4]} +} +impl LensForEventSelector<4, 5> for [Field; 4] { + fn output(self) -> [Field; 5] {[self[0] as Field; 5]} +} +impl LensForEventSelector<5, 6> for [Field; 5] { + fn output(self) -> [Field; 6] {[self[0] as Field; 6]} +} +impl LensForEventSelector<6, 7> for [Field; 6] { + fn output(self) -> [Field; 7] {[self[0] as Field; 7]} +} diff --git a/noir-projects/aztec-nr/aztec/src/utils.nr b/noir-projects/aztec-nr/aztec/src/utils/mod.nr similarity index 97% rename from noir-projects/aztec-nr/aztec/src/utils.nr rename to noir-projects/aztec-nr/aztec/src/utils/mod.nr index 3d3d8910a465..bdc40229f0ee 100644 --- a/noir-projects/aztec-nr/aztec/src/utils.nr +++ b/noir-projects/aztec-nr/aztec/src/utils/mod.nr @@ -58,7 +58,7 @@ fn verify_collapse_hints( } else { // BoundedVec assumes that the unused parts of the storage are zeroed out (e.g. in the Eq impl), so we make // sure that this property holds. - assert_eq(collapsed.get_unchecked(i), dep::std::unsafe::zeroed(), "Dirty collapsed vec storage"); + assert_eq(collapsed.get_unchecked(i), std::unsafe::zeroed(), "Dirty collapsed vec storage"); } } // We now know that: diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 4e0dae683c95..534ec69b457a 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -30,6 +30,8 @@ members = [ "contracts/parent_contract", "contracts/pending_note_hashes_contract", "contracts/price_feed_contract", + "contracts/private_fpc_contract", + "contracts/private_token_contract", "contracts/schnorr_account_contract", "contracts/schnorr_hardcoded_account_contract", "contracts/schnorr_single_key_account_contract", diff --git a/noir-projects/noir-contracts/bootstrap.sh b/noir-projects/noir-contracts/bootstrap.sh index 3eb62c4530f3..19de570b3291 100755 --- a/noir-projects/noir-contracts/bootstrap.sh +++ b/noir-projects/noir-contracts/bootstrap.sh @@ -17,7 +17,7 @@ fi echo "Compiling contracts..." NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} -$NARGO compile --silence-warnings +$NARGO compile --silence-warnings --use-legacy echo "Transpiling contracts..." scripts/transpile.sh \ 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 d9c5e6e6b1d9..5721632d5426 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 @@ -3,18 +3,18 @@ mod dapp_payload; contract AppSubscription { use crate::{dapp_payload::DAppPayload, subscription_note::{SubscriptionNote, SUBSCRIPTION_NOTE_LEN}}; - use dep::{ - aztec::{ + + use aztec::{ prelude::{ AztecAddress, FunctionSelector, PrivateContext, NoteHeader, Map, PrivateMutable, PublicMutable, SharedImmutable }, encrypted_logs::encrypted_note_emission::encode_and_encrypt_note, protocol_types::{traits::is_empty, grumpkin_point::GrumpkinPoint} - }, - authwit::{auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}, - gas_token::GasToken, token::Token }; + use authwit::{auth_witness::get_auth_witness, auth::assert_current_call_valid_authwit}; + use gas_token::GasToken; + use token::Token; #[aztec(storage)] struct Storage { diff --git a/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr index 2992e6cf4967..12b35516ba26 100644 --- a/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr @@ -1,6 +1,6 @@ contract AuthRegistry { use dep::aztec::{state_vars::{PublicMutable, Map}, protocol_types::address::AztecAddress}; - use dep::authwit::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash, assert_current_call_valid_authwit}; + use dep::authwit::auth::{IS_VALID_SELECTOR, compute_authwit_message_hash, assert_current_call_valid_authwit}; #[aztec(storage)] struct Storage { @@ -46,7 +46,7 @@ contract AuthRegistry { fn consume(on_behalf_of: AztecAddress, inner_hash: Field) -> Field { assert_eq(false, storage.reject_all.at(on_behalf_of).read(), "rejecting all"); - let message_hash = compute_outer_authwit_hash( + let message_hash = compute_authwit_message_hash( context.msg_sender(), context.chain_id(), context.version(), 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 a9dd932bdace..4560fbf61511 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 @@ -24,7 +24,7 @@ contract AvmTest { global big_field_136_bits: Field = 0x991234567890abcdef1234567890abcdef; // Libs - use dep::std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; + use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; use dep::aztec::protocol_types::constants::CONTRACT_INSTANCE_LENGTH; use dep::aztec::prelude::{Map, Deserialize}; use dep::aztec::state_vars::PublicMutable; @@ -76,7 +76,7 @@ contract AvmTest { fn set_storage_map(to: AztecAddress, amount: u32) -> Field { storage.map.at(to).write(amount); // returns storage slot for key - dep::std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) + std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) } #[aztec(public)] @@ -84,7 +84,7 @@ contract AvmTest { let new_balance = storage.map.at(to).read().add(amount); storage.map.at(to).write(new_balance); // returns storage slot for key - dep::std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) + std::hash::pedersen_hash([storage.map.storage_slot, to.to_field()]) } #[aztec(public)] @@ -209,27 +209,27 @@ contract AvmTest { ************************************************************************/ #[aztec(public)] fn keccak_hash(data: [u8; 10]) -> [u8; 32] { - dep::std::hash::keccak256(data, data.len() as u32) + std::hash::keccak256(data, data.len() as u32) } #[aztec(public)] fn poseidon2_hash(data: [Field; 10]) -> Field { - dep::std::hash::poseidon2::Poseidon2::hash(data, data.len()) + std::hash::poseidon2::Poseidon2::hash(data, data.len()) } #[aztec(public)] fn sha256_hash(data: [u8; 10]) -> [u8; 32] { - dep::std::hash::sha256(data) + std::hash::sha256(data) } #[aztec(public)] fn pedersen_hash(data: [Field; 10]) -> Field { - dep::std::hash::pedersen_hash(data) + std::hash::pedersen_hash(data) } #[aztec(public)] fn pedersen_hash_with_index(data: [Field; 10]) -> Field { - dep::std::hash::pedersen_hash_with_separator(data, /*index=*/ 20) + std::hash::pedersen_hash_with_separator(data, /*index=*/ 20) } /************************************************************************ @@ -273,13 +273,8 @@ contract AvmTest { } #[aztec(public)] - fn get_fee_per_l2_gas() -> Field { - context.fee_per_l2_gas() - } - - #[aztec(public)] - fn get_fee_per_da_gas() -> Field { - context.fee_per_da_gas() + fn get_function_selector() -> FunctionSelector { + context.selector() } #[aztec(public)] @@ -307,6 +302,16 @@ contract AvmTest { context.timestamp() } + #[aztec(public)] + fn get_fee_per_l2_gas() -> Field { + context.fee_per_l2_gas() + } + + #[aztec(public)] + fn get_fee_per_da_gas() -> Field { + context.fee_per_da_gas() + } + #[aztec(public)] fn get_l2_gas_left() -> Field { context.l2_gas_left() @@ -351,13 +356,13 @@ contract AvmTest { // Use the standard context interface to emit a new note hash #[aztec(public)] fn new_note_hash(note_hash: Field) { - context.push_new_note_hash(note_hash); + context.push_note_hash(note_hash); } // Use the standard context interface to emit a new nullifier #[aztec(public)] fn new_nullifier(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } // Use the standard context interface to check for a nullifier @@ -374,7 +379,7 @@ contract AvmTest { // Use the standard context interface to emit a new nullifier #[aztec(public)] fn emit_nullifier_and_check(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); let exists = context.nullifier_exists(nullifier, context.storage_address()); assert(exists, "Nullifier was just created, but its existence wasn't detected!"); } @@ -382,9 +387,9 @@ contract AvmTest { // Create the same nullifier twice (shouldn't work!) #[aztec(public)] fn nullifier_collision(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); // Can't do this twice! - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } #[aztec(public)] @@ -430,13 +435,13 @@ contract AvmTest { #[aztec(public)] fn create_same_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); AvmTest::at(nestedAddress).new_nullifier(nullifier).call(&mut context); } #[aztec(public)] fn create_different_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); AvmTest::at(nestedAddress).new_nullifier(nullifier + 1).call(&mut context); } diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr index 7065267bc2e4..a7c265c45281 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/cards.nr @@ -9,8 +9,6 @@ use dep::aztec::{ encrypted_logs::encrypted_note_emission::encode_and_encrypt_note_with_keys, note::note_getter::view_notes, state_vars::PrivateSet, note::constants::MAX_NOTES_PER_PAGE }; -use dep::std; -use dep::std::{option::Option}; use dep::value_note::{value_note::{ValueNote, VALUE_NOTE_LEN}}; struct Card { 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 d191ca8fe8a4..0d7fe868d50b 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -39,7 +39,7 @@ contract Claim { // The nullifier is unique to the note and THIS contract because the protocol siloes all nullifiers with // the address of a contract it was emitted from. let (_, nullifier) = proof_note.compute_note_hash_and_nullifier(&mut context); - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); // 4) Finally we mint the reward token to the sender of the transaction Token::at(storage.reward_token.read_private()).mint_public(recipient, proof_note.value).enqueue(&mut context); diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/mod.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events.nr rename to noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/mod.nr diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index aa5e3bf242d2..3d2a944e38b9 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -9,9 +9,11 @@ contract ContractClassRegisterer { ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT, MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE }, - traits::Serialize + traits::Serialize, abis::log_hash::LogHash }; + use dep::aztec::{context::PrivateContext, oracle::logs::emit_contract_class_unencrypted_log_private_internal}; + use crate::events::{ class_registered::ContractClassRegistered, private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction}, @@ -40,7 +42,7 @@ contract ContractClassRegisterer { // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode }; - context.push_new_nullifier(contract_class_id.to_field(), 0); + context.push_nullifier(contract_class_id.to_field(), 0); // Broadcast class info including public bytecode dep::aztec::oracle::debug_log::debug_log_format( @@ -52,7 +54,7 @@ contract ContractClassRegisterer { public_bytecode_commitment ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); } #[aztec(private)] @@ -87,7 +89,7 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); } #[aztec(private)] @@ -117,6 +119,25 @@ contract ContractClassRegisterer { function_data.metadata_hash ] ); - context.emit_contract_class_unencrypted_log(event.serialize()); + emit_contract_class_unencrypted_log(&mut context, event.serialize()); + } + + // This fn exists separately from emit_unencrypted_log because sha hashing the preimage + // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it + // It is ONLY used with contract_class_registerer_contract since we already assert correctness: + // - Contract class -> we will commit to the packed bytecode (currently a TODO) + // - Private function -> we provide a membership proof + // - Unconstrained function -> we provide a membership proof + // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else + #[contract_library_method] + pub fn emit_contract_class_unencrypted_log(context: &mut PrivateContext, log: [Field; N]) { + let event_selector = 5; // TODO: compute actual event selector. + let contract_address = context.this_address(); + let counter = context.next_counter(); + let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter); + // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) + let len = 44 + N * 32; + let side_effect = LogHash { value: log_hash, counter, length: len }; + context.unencrypted_logs_hashes.push(side_effect); } } diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr deleted file mode 100644 index d2b6ed6033f6..000000000000 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events.nr +++ /dev/null @@ -1 +0,0 @@ -mod instance_deployed; diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr deleted file mode 100644 index 638a08db001e..000000000000 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/events/instance_deployed.nr +++ /dev/null @@ -1,33 +0,0 @@ -use dep::aztec::protocol_types::{ - contract_class_id::ContractClassId, - address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress}, - constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, traits::Serialize -}; - -// #[aztec(event)] -struct ContractInstanceDeployed { - address: AztecAddress, - version: u8, - salt: Field, - contract_class_id: ContractClassId, - initialization_hash: Field, - public_keys_hash: PublicKeysHash, - deployer: AztecAddress, -} - -global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 8; - -impl Serialize for ContractInstanceDeployed { - fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] { - [ - DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, - self.address.to_field(), - self.version as Field, - self.salt, - self.contract_class_id.to_field(), - self.initialization_hash, - self.public_keys_hash.to_field(), - self.deployer.to_field(), - ] - } -} diff --git a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr index 43e7d45c6559..6b9582d3d799 100644 --- a/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr @@ -1,13 +1,42 @@ -mod events; - contract ContractInstanceDeployer { use dep::aztec::protocol_types::{ address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress}, contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, - traits::Serialize + traits::Serialize, abis::log_hash::LogHash + }; + use dep::aztec::{ + context::PrivateContext, hash::compute_unencrypted_log_hash, + oracle::logs::emit_unencrypted_log_private_internal }; - use crate::events::{instance_deployed::ContractInstanceDeployed}; + // @todo This should be using an event, but currently we only support fields in the struct. + // #[aztec(event)] + struct ContractInstanceDeployed { + address: AztecAddress, + version: u8, + salt: Field, + contract_class_id: ContractClassId, + initialization_hash: Field, + public_keys_hash: PublicKeysHash, + deployer: AztecAddress, + } + + global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 8; + + impl Serialize for ContractInstanceDeployed { + fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] { + [ + DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE, + self.address.to_field(), + self.version as Field, + self.salt, + self.contract_class_id.to_field(), + self.initialization_hash, + self.public_keys_hash.to_field(), + self.deployer.to_field(), + ] + } + } #[aztec(private)] fn deploy( @@ -30,12 +59,29 @@ contract ContractInstanceDeployer { let address = AztecAddress::compute(public_keys_hash, partial_address); // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed - context.push_new_nullifier(address.to_field(), 0); + context.push_nullifier(address.to_field(), 0); // Broadcast the event let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 }; - let event_payload = event.serialize(); - dep::aztec::oracle::debug_log::debug_log_format("ContractInstanceDeployed: {}", event_payload); - context.emit_unencrypted_log(event_payload); + + let payload = event.serialize(); + dep::aztec::oracle::debug_log::debug_log_format("ContractInstanceDeployed: {}", payload); + + let contract_address = context.this_address(); + let counter = context.next_counter(); + + // The event_type_id is not strictly needed. So i'm setting it to 0 here, and we can then purge it + // later on. + let event_type_id = 0; + + // @todo This is very inefficient, we are doing a lot of back and forth conversions. + let log_slice = payload.to_be_bytes_arr(); + let log_hash = compute_unencrypted_log_hash(contract_address, event_type_id, payload); + // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) + let len = 44 + log_slice.len().to_field(); + let side_effect = LogHash { value: log_hash, counter, length: len }; + context.unencrypted_logs_hashes.push(side_effect); + + let _void = emit_unencrypted_log_private_internal(contract_address, event_type_id, payload, counter); } } 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 9e43661a329b..4eb7657462e2 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -4,13 +4,11 @@ contract Crowdfunding { // docs:start:all-deps use dep::aztec::{ - protocol_types::{ - abis::function_selector::FunctionSelector, address::AztecAddress, traits::Serialize, - grumpkin_point::GrumpkinPoint - }, + protocol_types::address::AztecAddress, encrypted_logs::encrypted_note_emission::encode_and_encrypt_note, state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; + use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event; use dep::value_note::value_note::ValueNote; use dep::token::Token; // docs:end:all-deps @@ -95,10 +93,14 @@ contract Crowdfunding { // 2) Transfer the donation tokens from this contract to the operator Token::at(storage.donation_token.read_private()).transfer(operator_address, amount as Field).call(&mut context); - // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn - let event = WithdrawalProcessed { amount: amount as Field, who: operator_address.to_field() }; - context.emit_unencrypted_log(event.serialize()); + Crowdfunding::at(context.this_address())._publish_donation_receipts(amount, operator_address).enqueue(&mut context); } // docs:end:operator-withdrawals + + #[aztec(public)] + #[aztec(internal)] + fn _publish_donation_receipts(amount: u64, to: AztecAddress) { + WithdrawalProcessed { amount: amount as Field, who: to.to_field() }.emit(encode_event(&mut context)); + } } 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 8dcc252fdfdb..774034e276ac 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 @@ -34,8 +34,8 @@ contract EasyPrivateVoting { let msg_sender_npk_m_hash = header_at_active_at_block.get_npk_m_hash(&mut context, context.msg_sender()); let secret = context.request_nsk_app(msg_sender_npk_m_hash); // get secret key of caller of function - let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret - context.push_new_nullifier(nullifier, 0); // push nullifier + let nullifier = std::hash::pedersen_hash([context.msg_sender().to_field(), secret]); // derive nullifier from sender and secret + context.push_nullifier(nullifier, 0); // push nullifier 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/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index 71cc8d803f7a..35f5a5aace65 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -179,7 +179,7 @@ contract InclusionProofs { #[aztec(public)] fn push_nullifier_public(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } // Proves nullifier existed at latest block @@ -194,9 +194,11 @@ contract InclusionProofs { let header = context.get_header_at(block_number); assert_eq( + // docs:start:public_storage_historical_read header.public_storage_historical_read( storage.public_unused_value.storage_slot, context.this_address() + // docs:end:public_storage_historical_read ), 0 ); } @@ -229,10 +231,14 @@ contract InclusionProofs { let header = context.get_header_at(block_number); if test_deployment { + // docs:start:prove_contract_deployment header.prove_contract_deployment(contract_address); + // docs:end:prove_contract_deployment } if test_initialization { + // docs:start:prove_contract_initialization header.prove_contract_initialization(contract_address); + // docs:end:prove_contract_initialization } } @@ -247,10 +253,14 @@ contract InclusionProofs { let header = context.get_header_at(block_number); if test_deployment { + // docs:start:prove_contract_non_deployment header.prove_contract_non_deployment(contract_address); + // docs:end:prove_contract_non_deployment } if test_initialization { + // docs:start:prove_contract_non_initialization header.prove_contract_non_initialization(contract_address); + // docs:end:prove_contract_non_initialization } } } 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 index aef32ca61331..f51631c1f1c8 100644 --- a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -41,8 +41,15 @@ contract KeyRegistry { npk_m_y_registry.schedule_value_change(new_npk_m.y); } + // We need to have two separate register functions because a single one would produce too many storage writes, since + // each SharedMutable.schedule_value_change call results in 5 writes (pre, post, block_of_change, delay and hash), + // totaling 40 writes, while the kernels only accept up to 32 writes. + // Once SharedMutable accepts multi-field values, we can have a single state variable hold all keys, and that way + // also have a single block of change, hash, and delay. + // TODO (#5491): make this be a single function with a single schedule call. + #[aztec(public)] - fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { + fn register_npk_and_ivpk(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { let computed_address = AztecAddress::compute(keys.hash(), partial_address); assert(computed_address.eq(address), "Computed address does not match supplied address"); @@ -51,15 +58,24 @@ contract KeyRegistry { let npk_m_y_registry = storage.npk_m_y_registry.at(address); let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address); let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address); - let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address); - let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address); - let tpk_m_x_registry = storage.tpk_m_x_registry.at(address); - let tpk_m_y_registry = storage.tpk_m_y_registry.at(address); npk_m_x_registry.schedule_value_change(keys.npk_m.x); npk_m_y_registry.schedule_value_change(keys.npk_m.y); ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x); ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y); + } + + #[aztec(public)] + fn register_ovpk_and_tpk(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) { + let computed_address = AztecAddress::compute(keys.hash(), partial_address); + + assert(computed_address.eq(address), "Computed address does not match supplied address"); + + let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address); + let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address); + let tpk_m_x_registry = storage.tpk_m_x_registry.at(address); + let tpk_m_y_registry = storage.tpk_m_y_registry.at(address); + ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x); ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y); tpk_m_x_registry.schedule_value_change(keys.tpk_m.x); diff --git a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr index c35c36d6eb52..a3ecd0781a26 100644 --- a/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/pending_note_hashes_contract/src/main.nr @@ -7,7 +7,7 @@ contract PendingNoteHashes { use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, Map, PrivateSet}; use dep::value_note::{balance_utils, filter::filter_notes_min_sum, value_note::{VALUE_NOTE_LEN, ValueNote}}; use dep::aztec::protocol_types::grumpkin_point::GrumpkinPoint; - use dep::aztec::protocol_types::constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL}; + use dep::aztec::protocol_types::constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL}; use dep::aztec::encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys}; use dep::aztec::note::note_emission::NoteEmission; @@ -395,10 +395,10 @@ contract PendingNoteHashes { #[contract_library_method] fn max_notes_per_call() -> u32 { - if MAX_NEW_NOTE_HASHES_PER_CALL > MAX_NOTE_HASH_READ_REQUESTS_PER_CALL { + if MAX_NOTE_HASHES_PER_CALL > MAX_NOTE_HASH_READ_REQUESTS_PER_CALL { MAX_NOTE_HASH_READ_REQUESTS_PER_CALL } else { - MAX_NEW_NOTE_HASHES_PER_CALL + MAX_NOTE_HASHES_PER_CALL } } } diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml new file mode 100644 index 000000000000..94f9996c80b6 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "private_fpc_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +authwit = { path = "../../../aztec-nr/authwit" } +private_token = { path = "../private_token_contract" } diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/lib.nr b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/lib.nr new file mode 100644 index 000000000000..3b1345c3a3e3 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/lib.nr @@ -0,0 +1,16 @@ +use dep::aztec::protocol_types::abis::log_hash::LogHash; +use dep::aztec::oracle::logs::emit_unencrypted_log_private_internal; +use dep::aztec::hash::compute_unencrypted_log_hash; +use dep::aztec::context::PrivateContext; + +fn emit_nonce_as_unencrypted_log(context: &mut PrivateContext, nonce: Field) { + let counter = context.next_counter(); + let event_type_id = 0; + let log_slice = nonce.to_be_bytes_arr(); + let log_hash = compute_unencrypted_log_hash(context.this_address(), event_type_id, nonce); + // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4) + let len = 44 + log_slice.len().to_field(); + let side_effect = LogHash { value: log_hash, counter, length: len }; + context.unencrypted_logs_hashes.push(side_effect); + let _void = emit_unencrypted_log_private_internal(context.this_address(), event_type_id, nonce, counter); +} diff --git a/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr new file mode 100644 index 000000000000..5476f6fdb777 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_fpc_contract/src/main.nr @@ -0,0 +1,39 @@ +mod lib; + +contract PrivateFPC { + use dep::aztec::protocol_types::{abis::log_hash::LogHash, address::AztecAddress}; + use dep::aztec::state_vars::SharedImmutable; + use dep::private_token::PrivateToken; + use crate::lib::emit_nonce_as_unencrypted_log; + + #[aztec(storage)] + struct Storage { + other_asset: SharedImmutable, + admin_npk_m_hash: SharedImmutable + } + + #[aztec(public)] + #[aztec(initializer)] + fn constructor(other_asset: AztecAddress, admin_npk_m_hash: Field) { + storage.other_asset.initialize(other_asset); + storage.admin_npk_m_hash.initialize(admin_npk_m_hash); + } + + #[aztec(private)] + fn fund_transaction_privately(amount: Field, asset: AztecAddress, nonce: Field) { + assert(asset == storage.other_asset.read_private()); + // convince the FPC we are not cheating + context.push_nullifier(nonce, 0); + + // allow the FPC to reconstruct their fee note + emit_nonce_as_unencrypted_log(&mut context, nonce); + + PrivateToken::at(asset).setup_refund( + storage.admin_npk_m_hash.read_private(), + context.msg_sender(), + amount, + nonce + ).call(&mut context); + context.set_as_fee_payer(); + } +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml new file mode 100644 index 000000000000..8d410f64565b --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "private_token_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +compressed_string = { path = "../../../aztec-nr/compressed-string" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr new file mode 100644 index 000000000000..c3643b1ff39b --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/main.nr @@ -0,0 +1,239 @@ +mod types; +mod test; + +// Minimal token implementation that supports `AuthWit` accounts and private refunds + +contract PrivateToken { + use dep::compressed_string::FieldCompressedString; + use dep::aztec::{ + hash::compute_secret_hash, + prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, + protocol_types::{ + abis::function_selector::FunctionSelector, hash::pedersen_hash, + constants::GENERATOR_INDEX__INNER_NOTE_HASH + }, + oracle::unsafe_rand::unsafe_rand, + encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys} + }; + use dep::authwit::{auth::{assert_current_call_valid_authwit, assert_current_call_valid_authwit_public}}; + use crate::types::{token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; + use dep::std::embedded_curve_ops::EmbeddedCurvePoint; + use dep::std::ec::tecurve::affine::Point; + + #[aztec(storage)] + struct Storage { + admin: PublicMutable, + minters: Map>, + balances: BalancesMap, + total_supply: PublicMutable, + symbol: SharedImmutable, + name: SharedImmutable, + decimals: SharedImmutable, + } + + #[aztec(public)] + #[aztec(initializer)] + fn constructor(admin: AztecAddress, name: str<31>, symbol: str<31>, decimals: u8) { + assert(!admin.is_zero(), "invalid admin"); + storage.admin.write(admin); + storage.minters.at(admin).write(true); + storage.name.initialize(FieldCompressedString::from_string(name)); + storage.symbol.initialize(FieldCompressedString::from_string(symbol)); + storage.decimals.initialize(decimals); + } + + #[aztec(public)] + fn set_admin(new_admin: AztecAddress) { + assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + storage.admin.write(new_admin); + } + + #[aztec(public)] + fn public_get_name() -> pub FieldCompressedString { + storage.name.read_public() + } + + #[aztec(private)] + fn private_get_name() -> pub FieldCompressedString { + storage.name.read_private() + } + + unconstrained fn un_get_name() -> pub [u8; 31] { + storage.name.read_public().to_bytes() + } + + #[aztec(public)] + fn public_get_symbol() -> pub FieldCompressedString { + storage.symbol.read_public() + } + + #[aztec(private)] + fn private_get_symbol() -> pub FieldCompressedString { + storage.symbol.read_private() + } + + unconstrained fn un_get_symbol() -> pub [u8; 31] { + storage.symbol.read_public().to_bytes() + } + + #[aztec(public)] + fn public_get_decimals() -> pub u8 { + storage.decimals.read_public() + } + + #[aztec(private)] + fn private_get_decimals() -> pub u8 { + storage.decimals.read_private() + } + + unconstrained fn un_get_decimals() -> pub u8 { + storage.decimals.read_public() + } + + #[aztec(public)] + fn set_minter(minter: AztecAddress, approve: bool) { + assert(storage.admin.read().eq(context.msg_sender()), "caller is not admin"); + storage.minters.at(minter).write(approve); + } + + #[aztec(private)] + fn privately_mint_private_note(amount: Field) { + let caller = context.msg_sender(); + let header = context.get_header(); + let caller_npk_m_hash = header.get_npk_m_hash(&mut context, caller); + storage.balances.add(caller_npk_m_hash, U128::from_integer(amount)).emit(encode_and_encrypt_note(&mut context, caller, caller)); + PrivateToken::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); + } + + #[aztec(public)] + fn assert_minter_and_mint(minter: AztecAddress, amount: Field) { + assert(storage.minters.at(minter).read(), "caller is not minter"); + let supply = storage.total_supply.read() + U128::from_integer(amount); + storage.total_supply.write(supply); + } + + #[aztec(private)] + fn transfer_from(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { + if (!from.eq(context.msg_sender())) { + assert_current_call_valid_authwit(&mut context, from); + } else { + assert(nonce == 0, "invalid nonce"); + } + + let header = context.get_header(); + let from_ovpk = header.get_ovpk_m(&mut context, from); + let from_ivpk = header.get_ivpk_m(&mut context, from); + let from_npk_m_hash = header.get_npk_m_hash(&mut context, from); + let to_ivpk = header.get_ivpk_m(&mut context, to); + let to_npk_m_hash = header.get_npk_m_hash(&mut context, to); + + let amount = U128::from_integer(amount); + storage.balances.sub(from_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); + storage.balances.add(to_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); + } + + #[aztec(private)] + fn transfer(to: AztecAddress, amount: Field) { + let from = context.msg_sender(); + let header = context.get_header(); + let from_ovpk = header.get_ovpk_m(&mut context, from); + let from_ivpk = header.get_ivpk_m(&mut context, from); + let from_npk_m_hash = header.get_npk_m_hash(&mut context, from); + let to_ivpk = header.get_ivpk_m(&mut context, to); + let to_npk_m_hash = header.get_npk_m_hash(&mut context, to); + + let amount = U128::from_integer(amount); + storage.balances.sub(from_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); + storage.balances.add(to_npk_m_hash, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); + } + + #[aztec(private)] + fn balance_of_private(owner: AztecAddress) -> pub Field { + let header = context.get_header(); + let owner_npk_m_hash = header.get_npk_m_hash(&mut context, owner); + storage.balances.to_unconstrained().balance_of(owner_npk_m_hash).to_integer() + } + + unconstrained fn balance_of_unconstrained(owner_npk_m_hash: Field) -> pub Field { + storage.balances.balance_of(owner_npk_m_hash).to_integer() + } + + #[aztec(private)] + fn setup_refund( + fee_payer_npk_m_hash: Field, + sponsored_user: AztecAddress, + funded_amount: Field, + refund_nonce: Field + ) { + assert_current_call_valid_authwit(&mut context, sponsored_user); + let header = context.get_header(); + let sponsored_user_npk_m_hash = header.get_npk_m_hash(&mut context, sponsored_user); + let sponsored_user_ovpk = header.get_ovpk_m(&mut context, sponsored_user); + let sponsored_user_ivpk = header.get_ivpk_m(&mut context, sponsored_user); + storage.balances.sub(sponsored_user_npk_m_hash, U128::from_integer(funded_amount)).emit(encode_and_encrypt_note_with_keys(&mut context, sponsored_user_ovpk, sponsored_user_ivpk)); + let points = TokenNote::generate_refund_points( + fee_payer_npk_m_hash, + sponsored_user_npk_m_hash, + funded_amount, + refund_nonce + ); + context.set_public_teardown_function( + context.this_address(), + FunctionSelector::from_signature("complete_refund(Field,Field,Field,Field)"), + [points[0].x, points[0].y, points[1].x, points[1].y] + ); + } + + #[aztec(public)] + #[aztec(internal)] + fn complete_refund( + fpc_point_x: Field, + fpc_point_y: Field, + user_point_x: Field, + user_point_y: Field + ) { + let fpc_point = EmbeddedCurvePoint { x: fpc_point_x, y: fpc_point_y, is_infinite: false }; + let user_point = EmbeddedCurvePoint { x: user_point_x, y: user_point_y, is_infinite: false }; + let tx_fee = context.transaction_fee(); + let note_hashes = TokenNote::complete_refund(fpc_point, user_point, tx_fee); + + // `compute_inner_note_hash` manually, without constructing the note + // `3` is the storage slot of the balances + context.push_note_hash( + pedersen_hash( + [PrivateToken::storage().balances.slot, note_hashes[0]], + GENERATOR_INDEX__INNER_NOTE_HASH + ) + ); + context.push_note_hash( + pedersen_hash( + [PrivateToken::storage().balances.slot, note_hashes[1]], + GENERATOR_INDEX__INNER_NOTE_HASH + ) + ); + } + + /// Internal /// + + #[aztec(public)] + #[aztec(internal)] + fn _reduce_total_supply(amount: Field) { + // Only to be called from burn. + let new_supply = storage.total_supply.read().sub(U128::from_integer(amount)); + storage.total_supply.write(new_supply); + } + + /// Unconstrained /// + + unconstrained fn admin() -> pub Field { + storage.admin.read().to_field() + } + + unconstrained fn is_minter(minter: AztecAddress) -> pub bool { + storage.minters.at(minter).read() + } + + unconstrained fn total_supply() -> pub Field { + storage.total_supply.read().to_integer() + } +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr new file mode 100644 index 000000000000..f606967d1ac1 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/test.nr @@ -0,0 +1,2 @@ +mod basic; +mod utils; diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr new file mode 100644 index 000000000000..3f7f75ed93b5 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/basic.nr @@ -0,0 +1,98 @@ +use crate::test::utils; +use dep::aztec::{ + test::helpers::cheatcodes, oracle::unsafe_rand::unsafe_rand, hash::compute_secret_hash, + prelude::NoteHeader +}; +use crate::PrivateToken; +use crate::types::token_note::TokenNote; +use dep::authwit::cheatcodes as authwit_cheatcodes; + +#[test] +unconstrained fn transfer_success() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); + + let transfer_amount = 1_000; + + let transfer_private_from_call_interface = PrivateToken::at(token_contract_address).transfer_from(owner, recipient, transfer_amount, 1); + + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, transfer_private_from_call_interface); + + cheatcodes::set_contract_address(recipient); + // Transfer tokens + env.call_private_void(transfer_private_from_call_interface); + // Check balances + utils::check_private_balance( + &mut env.private(), + token_contract_address, + owner, + mint_amount - transfer_amount + ); + utils::check_private_balance( + &mut env.private(), + token_contract_address, + recipient, + transfer_amount + ); +} + +#[test] +unconstrained fn setup_refund_success() { + let (env, token_contract_address, owner, recipient, mint_amount) = utils::setup_and_mint(true); + + let funded_amount = 1_000; + let refund_nonce = 42; + let mut context = env.private(); + let recipient_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, recipient); + + let setup_refund_from_call_interface = PrivateToken::at(token_contract_address).setup_refund( + recipient_npk_m_hash, // fee payer + owner, // sponsored user + funded_amount, + refund_nonce + ); + + authwit_cheatcodes::add_private_authwit_from_call_interface(owner, recipient, setup_refund_from_call_interface); + + cheatcodes::set_contract_address(recipient); + + env.call_private_void(setup_refund_from_call_interface); + let mut context = env.private(); + let owner_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, owner); + let recipient_npk_m_hash = context.get_header().get_npk_m_hash(&mut context, recipient); + + // when the refund was set up, we would've broken the note worth mint_amount, and added back a note worth + // mint_amount - funded_amount + // then when completing the refund, we would've constructed a hash corresponding to a note worth + // funded_amount - transaction_fee + // we "know" the transaction fee was 1 (it is hardcoded in TXE oracle) + // but we need to notify TXE of the note (preimage) + env.store_note_in_cache( + &mut TokenNote { + amount: U128::from_integer(funded_amount - 1), + npk_m_hash: owner_npk_m_hash, + randomness: refund_nonce, + header: NoteHeader::empty() + }, + PrivateToken::storage().balances.slot, + token_contract_address + ); + env.store_note_in_cache( + &mut TokenNote { + amount: U128::from_integer(1), + npk_m_hash: recipient_npk_m_hash, + randomness: refund_nonce, + header: NoteHeader::empty() + }, + PrivateToken::storage().balances.slot, + token_contract_address + ); + + utils::check_private_balance( + &mut env.private(), + token_contract_address, + owner, + mint_amount - 1 + ); + utils::check_private_balance(&mut env.private(), token_contract_address, recipient, 1) +} + diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr new file mode 100644 index 000000000000..ab6a658ecc90 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/test/utils.nr @@ -0,0 +1,70 @@ +use dep::aztec::{ + hash::compute_secret_hash, prelude::AztecAddress, + test::helpers::{cheatcodes, test_environment::TestEnvironment}, + protocol_types::storage::map::derive_storage_slot_in_map, + note::{note_getter::{MAX_NOTES_PER_PAGE, view_notes}, note_viewer_options::NoteViewerOptions}, + oracle::{unsafe_rand::unsafe_rand, storage::storage_read}, context::PrivateContext +}; + +use crate::{types::{token_note::TokenNote}, PrivateToken}; + +pub fn setup(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress) { + // Setup env, generate keys + let mut env = TestEnvironment::new(); + let (owner, recipient) = if with_account_contracts { + let owner = env.create_account_contract(1); + let recipient = env.create_account_contract(2); + // Deploy canonical auth registry + let _auth_registry = env.deploy("@aztec/noir-contracts.js/AuthRegistry").without_initializer(); + (owner, recipient) + } else { + let owner = env.create_account(); + let recipient = env.create_account(); + (owner, recipient) + }; + + // Start the test in the account contract address + cheatcodes::set_contract_address(owner); + + // Deploy token contract + let initializer_call_interface = PrivateToken::interface().constructor( + owner, + "TestToken0000000000000000000000", + "TT00000000000000000000000000000", + 18 + ); + let token_contract = env.deploy("@aztec/noir-contracts.js/PrivateToken").with_public_initializer(initializer_call_interface); + let token_contract_address = token_contract.to_address(); + env.advance_block_by(6); + (&mut env, token_contract_address, owner, recipient) +} + +pub fn setup_and_mint(with_account_contracts: bool) -> (&mut TestEnvironment, AztecAddress, AztecAddress, AztecAddress, Field) { + // Setup + let (env, token_contract_address, owner, recipient) = setup(with_account_contracts); + let mint_amount = 10_000; + let mint_private_call_interface = PrivateToken::at(token_contract_address).privately_mint_private_note(mint_amount); + env.call_private_void(mint_private_call_interface); + env.advance_block_by(6); + + check_private_balance(&mut env.private(), token_contract_address, owner, mint_amount); + + (env, token_contract_address, owner, recipient, mint_amount) +} + +pub fn check_private_balance( + context: &mut PrivateContext, + token_contract_address: AztecAddress, + address: AztecAddress, + address_amount: Field +) { + let current_contract_address = cheatcodes::get_contract_address(); + cheatcodes::set_contract_address(token_contract_address); + + let header = context.get_header(); + let owner_npk_m_hash = header.get_npk_m_hash(context, address); + + let balance_of_private = PrivateToken::balance_of_unconstrained(owner_npk_m_hash); + assert(balance_of_private == address_amount, "Private balance is not correct"); + cheatcodes::set_contract_address(current_contract_address); +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr new file mode 100644 index 000000000000..ac754901ded1 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types.nr @@ -0,0 +1,2 @@ +mod balances_map; +mod token_note; diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr new file mode 100644 index 000000000000..7ce8857dd2d5 --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/balances_map.nr @@ -0,0 +1,132 @@ +use dep::aztec::prelude::{ + AztecAddress, NoteGetterOptions, NoteViewerOptions, NoteHeader, NoteInterface, PrivateContext, + PrivateSet, Map +}; +use dep::aztec::{ + hash::pedersen_hash, protocol_types::constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + note::{ + note_getter::view_notes, note_getter_options::{SortOrder, Comparator}, + note_emission::OuterNoteEmission +}, + context::UnconstrainedContext +}; +use crate::types::token_note::{TokenNote, OwnedNote}; + +struct BalancesMap { + map: PrivateSet +} + +impl BalancesMap { + pub fn new(context: Context, storage_slot: Field) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + Self { map: PrivateSet::new(context, storage_slot) } + } +} + +impl BalancesMap { + unconstrained fn balance_of( + self: Self, + owner_npk_m_hash: Field + ) -> U128 where T: NoteInterface + OwnedNote { + self.balance_of_with_offset(owner_npk_m_hash, 0) + } + + unconstrained fn balance_of_with_offset( + self: Self, + owner_npk_m_hash: Field, + offset: u32 + ) -> U128 where T: NoteInterface + OwnedNote { + let mut balance = U128::from_integer(0); + let mut options = NoteViewerOptions::new(); + + let notes = self.map.view_notes( + options.select( + T::get_owner_selector(), + owner_npk_m_hash, + Option::some(Comparator.EQ) + ) + ); + + for i in 0..options.limit { + if i < notes.len() { + balance = balance + notes.get_unchecked(i).get_amount(); + } + } + if (notes.len() == options.limit) { + balance = balance + self.balance_of_with_offset(owner_npk_m_hash, offset + options.limit); + } + + balance + } +} + +impl BalancesMap { + + pub fn to_unconstrained(self: Self) -> BalancesMap { + BalancesMap { map: PrivateSet::new(UnconstrainedContext::new(), self.map.storage_slot) } + } + + pub fn add( + self: Self, + owner_npk_m_hash: Field, + addend: U128 + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + let mut addend_note = T::new(addend, owner_npk_m_hash); + OuterNoteEmission::new(Option::some(self.map.insert(&mut addend_note))) + } + + pub fn sub( + self: Self, + owner_npk_m_hash: Field, + subtrahend: U128 + ) -> OuterNoteEmission where T: NoteInterface + OwnedNote { + let mut options = NoteGetterOptions::with_filter(filter_notes_min_sum, subtrahend); + let notes = self.map.get_notes( + options.select( + T::get_owner_selector(), + owner_npk_m_hash, + Option::some(Comparator.EQ) + ) + ); + + let mut minuend: U128 = U128::from_integer(0); + for i in 0..options.limit { + if i < notes.len() { + let note = notes.get_unchecked(i); + + // Removes the note from the owner's set of notes. + // This will call the the `compute_nullifer` function of the `token_note` + // which require knowledge of the secret key (currently the users encryption key). + // The contract logic must ensure that the spending key is used as well. + // docs:start:remove + self.map.remove(note); + // docs:end:remove + + minuend = minuend + note.get_amount(); + } + } + + // This is to provide a nicer error msg, + // without it minuend-subtrahend would still catch it, but more generic error then. + // without the == true, it includes 'minuend.ge(subtrahend)' as part of the error. + assert(minuend >= subtrahend, "Balance too low"); + + self.add(owner_npk_m_hash, minuend - subtrahend) + } +} + +pub fn filter_notes_min_sum( + notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], + min_sum: U128 +) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where T: NoteInterface + OwnedNote { + let mut selected = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]; + let mut sum = U128::from_integer(0); + for i in 0..notes.len() { + if notes[i].is_some() & sum < min_sum { + let note = notes[i].unwrap_unchecked(); + selected[i] = Option::some(note); + sum = sum.add(note.get_amount()); + } + } + selected +} diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr new file mode 100644 index 000000000000..b389ad10fb2a --- /dev/null +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -0,0 +1,251 @@ +use dep::aztec::{ + prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, + protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}, + note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, + keys::getters::get_nsk_app, note::note_getter_options::PropertySelector +}; +use dep::std::field::bn254::decompose; +use dep::std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, fixed_base_scalar_mul}; + +trait OwnedNote { + fn new(amount: U128, owner_npk_m_hash: Field) -> Self; + fn get_amount(self) -> U128; + fn get_owner_npk_m_hash(self) -> Field; + fn get_owner_selector() -> PropertySelector; +} + +trait PrivatelyRefundable { + fn generate_refund_points( + fee_payer_npk_m_hash: Field, + sponsored_user_npk_m_hash: Field, + funded_amount: Field, + refund_nonce: Field + ) -> [EmbeddedCurvePoint; 2]; + + fn complete_refund( + fee_payer_point: EmbeddedCurvePoint, + sponsored_user_point: EmbeddedCurvePoint, + transaction_fee: Field + ) -> [Field; 2]; +} + +global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. +global TOKEN_NOTE_BYTES_LEN: Field = 3 * 32 + 64; +// Grumpkin generator point. +global G1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + +#[aztec(note)] +struct TokenNote { + // The amount of tokens in the note + amount: U128, + // The nullifying public key hash is used with the nsk_app to ensure that the note can be privately spent. + npk_m_hash: Field, + // Randomness of the note to hide its contents + randomness: Field, +} + +impl NoteInterface for TokenNote { + // docs:start:nullifier + fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> ( Field, Field ) { + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + let secret = context.request_nsk_app(self.npk_m_hash); + let nullifier = poseidon2_hash([ + note_hash_for_nullify, + secret, + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]); + (note_hash_for_nullify, nullifier) + } + // docs:end:nullifier + + fn compute_note_hash_and_nullifier_without_context(self) -> ( Field, Field ) { + let note_hash_for_nullify = compute_note_hash_for_consumption(self); + let secret = get_nsk_app(self.npk_m_hash); + let nullifier = poseidon2_hash([ + note_hash_for_nullify, + secret, + GENERATOR_INDEX__NOTE_NULLIFIER as Field, + ]); + (note_hash_for_nullify, nullifier) + } + + + + fn compute_note_content_hash(self) -> Field { + let (npk_lo, npk_hi) = decompose(self.npk_m_hash); + let (random_lo, random_hi) = decompose(self.randomness); + multi_scalar_mul( + [G1, G1, G1], + [EmbeddedCurveScalar { + lo: self.amount.to_integer(), + hi: 0 + }, + EmbeddedCurveScalar { + lo: npk_lo, + hi: npk_hi + }, + EmbeddedCurveScalar { + lo: random_lo, + hi: random_hi, + }] + )[0] + } +} + +impl OwnedNote for TokenNote { + fn new(amount: U128, owner_npk_m_hash: Field) -> Self { + Self { + amount, + npk_m_hash: owner_npk_m_hash, + randomness: unsafe_rand(), + header: NoteHeader::empty(), + } + } + + fn get_amount(self) -> U128 { + self.amount + } + + fn get_owner_npk_m_hash(self) -> Field { + self.npk_m_hash + } + + fn get_owner_selector() -> PropertySelector { + PropertySelector { index: 1, offset: 0, length: 32 } + } +} + +impl PrivatelyRefundable for TokenNote { + fn generate_refund_points(fee_payer_npk_m_hash: Field, sponsored_user_npk_m_hash: Field, funded_amount: Field, refund_nonce: Field) -> [EmbeddedCurvePoint; 2] { + let (refund_nonce_lo, refund_nonce_hi) = decompose(refund_nonce); + let (fee_payer_lo, fee_payer_hi) = decompose(fee_payer_npk_m_hash); + + let fee_payer_point = multi_scalar_mul( + [G1, G1], + [EmbeddedCurveScalar { + lo: fee_payer_lo, + hi: fee_payer_hi + }, + EmbeddedCurveScalar { + lo: refund_nonce_lo, + hi: refund_nonce_hi + }] + ); + + let (sponsored_user_lo, sponsored_user_hi) = decompose(sponsored_user_npk_m_hash); + let (funded_amount_lo, funded_amount_hi) = decompose(funded_amount); + let sponsored_user_point = multi_scalar_mul( + [G1, G1, G1], + [EmbeddedCurveScalar { + lo: sponsored_user_lo, + hi: sponsored_user_hi + }, + EmbeddedCurveScalar { + lo: funded_amount_lo, + hi: funded_amount_hi + }, + EmbeddedCurveScalar { + lo: refund_nonce_lo, + hi: refund_nonce_hi + }] + ); + + [EmbeddedCurvePoint { + x: fee_payer_point[0], + y: fee_payer_point[1], + is_infinite: fee_payer_point[2] == 1 + },EmbeddedCurvePoint { + x: sponsored_user_point[0], + y: sponsored_user_point[1], + is_infinite: sponsored_user_point[2] == 1 + } ] + } + + fn complete_refund(fee_payer_point: EmbeddedCurvePoint, sponsored_user_point: EmbeddedCurvePoint, transaction_fee: Field) -> [Field; 2] { + + let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); + let fee_point_raw = multi_scalar_mul( + [G1], + [EmbeddedCurveScalar { + lo: transaction_fee_lo, + hi: transaction_fee_hi, + }] + ); + let fee_point = EmbeddedCurvePoint { + x: fee_point_raw[0], + y: fee_point_raw[1], + is_infinite: fee_point_raw[2] ==1 + }; + + /** + What is happening here? + + Back up in generate_refund_points, we created two points on the grumpkin curve; + these are going to be eventually turned into notes: + one for the user, and one for the FPC. + + So you can think of these (x,y) points as "partial notes": they encode part of the internals of the notes. + + This is because the compute_note_content_hash function above defines the the content hash to be + the x-coordinate of a point defined as: + + amount * G + npk * G + randomness * G + = (amount + npk + randomness) * G + + where G is a generator point. Interesting point here is that we actually need to convert + - amount + - npk + - randomness + from grumpkin Field elements + (which have a modulus of 21888242871839275222246405745257275088548364400416034343698204186575808495617) + into a grumpkin scalar + (which have a modulus of 21888242871839275222246405745257275088696311157297823662689037894645226208583) + + The intuition for this is that the Field elements define the domain of the x,y coordinates for points on the curves, + but the number of points on the curve is actually greater than the size of that domain. + + (Consider, e.g. if the curve were defined over a field of 10 elements, and each x coord had two corresponding y for +/-) + + For a bit more info, see + https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations + + + Anyway, if we have a secret scalar n := amount + npk + randomness, and then we reveal a point n * G, there is no efficient way to + deduce what n is. This is the discrete log problem. + + However we can still perform addition/subtraction on points! That is why we generate those two points, which are: + fee_payer_point := (fee_payer_npk + nonce) * G + sponsored_user_point := (sponsored_user_npk + funded_amount + nonce) * G + + where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which the transaction fee will be subtracted. + + So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction fee as just + + fee_point := transaction_fee * G + + Then we arrive at the final points via addition/subtraction of that transaction fee point: + + completed_fpc_point := fee_payer_point + fee_point + = (fee_payer_npk + nonce) * G + transaction_fee * G + = (fee_payer_npk + nonce + transaction_fee) * G + + completed_user_point := sponsored_user_point - fee_point + = (sponsored_user_npk + funded_amount + nonce) * G - transaction_fee * G + = (sponsored_user_npk + nonce + (funded_amount - transaction_fee)) * G + + When we return the x-coordinate of those points, it identically matches the note_content_hash of (and therefore *is*) notes like: + { + amount: (funded_amount - transaction_fee), + npk_m_hash: sponsored_user_npk, + randomness: nonce + } + */ + + let completed_fpc_point = fee_payer_point + fee_point; + + let completed_user_point = sponsored_user_point - fee_point; + assert_eq(completed_user_point.is_infinite, false); + + [completed_fpc_point.x, completed_user_point.x] + } +} diff --git a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr index 8632a64bc62b..e918e42d2f4d 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr @@ -9,7 +9,7 @@ contract SchnorrAccount { use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; use dep::authwit::{ entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions, - auth_witness::get_auth_witness, auth::{compute_authwit_nullifier, compute_outer_authwit_hash} + auth_witness::get_auth_witness, auth::{compute_authwit_nullifier, compute_authwit_message_hash} }; use dep::aztec::hash::compute_siloed_nullifier; use dep::aztec::oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness; @@ -92,7 +92,7 @@ contract SchnorrAccount { unconstrained fn lookup_validity(consumer: AztecAddress, inner_hash: Field) -> pub bool { let public_key = storage.signing_public_key.view_note(); - let message_hash = compute_outer_authwit_hash(consumer, context.chain_id(), context.version(), inner_hash); + let message_hash = compute_authwit_message_hash(consumer, context.chain_id(), context.version(), inner_hash); let witness: [Field; 64] = get_auth_witness(message_hash); let mut signature: [u8; 64] = [0; 64]; diff --git a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr index 5086c2cda4cc..8d15cc3211f4 100644 --- a/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr +++ b/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr @@ -1,4 +1,4 @@ -use dep::std::{schnorr::verify_signature_slice}; +use std::{schnorr::verify_signature_slice}; use dep::aztec::prelude::AztecAddress; use crate::auth_oracle::AuthWitness; 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 eb34674b095c..fbf10bc18066 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -8,7 +8,7 @@ contract Test { PrivateContext, PrivateImmutable, PrivateSet, SharedImmutable }; use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note; - use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys; + use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_keys_with_randomness; use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, @@ -247,13 +247,13 @@ contract Test { // Purely exists for testing #[aztec(public)] fn emit_nullifier_public(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } // Forcefully emits a nullifier (for testing purposes) #[aztec(private)] fn emit_nullifier(nullifier: Field) { - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } // For testing non-note encrypted logs @@ -271,7 +271,7 @@ contract Test { let event = ExampleEvent { value0: fields[0], value1: fields[1], value2: fields[2], value3: fields[3], value4: fields[4] }; event.emit( - encode_and_encrypt_event_with_keys( + encode_and_encrypt_event_with_keys_with_randomness( &mut context, // testing only - a secret random value is passed in here to salt / mask the address 5, @@ -288,7 +288,7 @@ contract Test { let otherEvent = ExampleEvent { value0: 1, value1: 2, value2: 3, value3: 4, value4: 5 }; otherEvent.emit( - encode_and_encrypt_event_with_keys( + encode_and_encrypt_event_with_keys_with_randomness( &mut context, // testing only - a randomness of 0 signals the kerels to not mask the address 0, @@ -299,25 +299,6 @@ contract Test { } } - #[aztec(private)] - fn emit_msg_sender() { - context.emit_unencrypted_log(context.msg_sender()); - } - - #[aztec(private)] - fn emit_unencrypted_logs(fields: [Field; 5], nest: bool) { - // Merged two fns to avoid hitting max #functions limit: - // nest -> emit_unencrypted_logs_nested - // else -> emit_array_as_unencrypted_log - if nest { - Test::at(context.this_address()).emit_msg_sender().call(&mut context); - Test::at(context.this_address()).emit_unencrypted_logs(fields, false).call(&mut context); - context.emit_unencrypted_log("test"); - } else { - context.emit_unencrypted_log(fields); - } - } - #[aztec(private)] fn emit_encrypted_logs_nested(value: Field, owner: AztecAddress, outgoing_viewer: AztecAddress) { let mut storage_slot = storage.example_constant.get_storage_slot() + 1; diff --git a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr index f42cb2ffd7a7..0d1d06b731d8 100644 --- a/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_log_contract/src/main.nr @@ -1,10 +1,14 @@ contract TestLog { use dep::aztec::prelude::PrivateSet; - use dep::aztec::protocol_types::{traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey}; + use dep::aztec::protocol_types::{ + traits::Serialize, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, + address::AztecAddress + }; use dep::value_note::value_note::ValueNote; use dep::aztec::encrypted_logs::incoming_body::EncryptedLogIncomingBody; use dep::aztec::event::event_interface::EventInterface; - use dep::aztec::encrypted_logs::encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys}; + use dep::aztec::encrypted_logs::encrypted_event_emission::encode_and_encrypt_event_with_randomness; + use dep::aztec::unencrypted_logs::unencrypted_event_emission::encode_event; #[aztec(event)] struct ExampleEvent0 { @@ -41,27 +45,51 @@ contract TestLog { } #[aztec(private)] - fn emit_encrypted_events(randomness: [Field; 2], preimages: [Field; 4]) { + fn emit_encrypted_events(other: AztecAddress, randomness: [Field; 2], preimages: [Field; 4]) { let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; event0.emit( - encode_and_encrypt_event( + encode_and_encrypt_event_with_randomness( &mut context, randomness[0], - context.msg_sender(), + // outgoing is set to other, incoming is set to msg sender + other, context.msg_sender() ) ); + // We duplicate the emission, but specifying different incoming and outgoing parties + event0.emit( + encode_and_encrypt_event_with_randomness( + &mut context, + randomness[0], + // outgoing is set to msg sender, incoming is set to other + context.msg_sender(), + other + ) + ); + let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] }; event1.emit( - encode_and_encrypt_event( + encode_and_encrypt_event_with_randomness( &mut context, randomness[1], - context.msg_sender(), + // outgoing is set to other, incoming is set to msg sender + other, context.msg_sender() ) ); } + + #[aztec(public)] + fn emit_unencrypted_events(preimages: [Field; 4]) { + let event0 = ExampleEvent0 { value0: preimages[0], value1: preimages[1] }; + + event0.emit(encode_event(&mut context)); + + let event1 = ExampleEvent1 { value2: preimages[2], value3: preimages[3] }; + + event1.emit(encode_event(&mut context)); + } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/mod.nr similarity index 100% rename from noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types.nr rename to noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/mod.nr diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr index 4321a2a7f28c..bbb93b0efa43 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/types/roles.nr @@ -41,6 +41,12 @@ impl ToField for UserFlags { } } +impl Eq for UserFlags { + fn eq(self, other: Self) -> bool { + (self.is_admin == other.is_admin) & (self.is_minter == other.is_minter) & (self.is_blacklisted == other.is_blacklisted) + } +} + // We implement this as it is used when serializing the state variable into return values // This is very inefficient if used to store the state variable. // We are currently "abusing" that the `to_field` is called in the `scheduled_value_change` 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 d13145c89e2e..3f8bdfd8bea4 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -18,7 +18,13 @@ contract Token { use dep::aztec::{ hash::compute_secret_hash, prelude::{NoteGetterOptions, Map, PublicMutable, SharedImmutable, PrivateSet, AztecAddress}, - encrypted_logs::encrypted_note_emission::{encode_and_encrypt_note, encode_and_encrypt_note_with_keys} + encrypted_logs::{ + encrypted_note_emission::{ + encode_and_encrypt_note, encode_and_encrypt_note_with_keys, + encode_and_encrypt_note_with_keys_unconstrained + }, + encrypted_event_emission::{encode_and_encrypt_event, encode_and_encrypt_event_with_keys_unconstrained} + } }; // docs:start:import_authwit @@ -28,6 +34,13 @@ contract Token { use crate::types::{transparent_note::TransparentNote, token_note::{TokenNote, TOKEN_NOTE_LEN}, balances_map::BalancesMap}; // docs:end::imports + #[aztec(event)] + struct Transfer { + from: Field, + to: Field, + amount: Field, + } + // docs:start:storage_struct #[aztec(storage)] struct Storage { @@ -322,8 +335,10 @@ contract Token { let to_ivpk = header.get_ivpk_m(&mut context, to); let amount = U128::from_integer(amount); - storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, from_ivpk)); - storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys(&mut context, from_ovpk, to_ivpk)); + storage.balances.sub(from, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, from_ivpk)); + storage.balances.add(to, amount).emit(encode_and_encrypt_note_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk)); + + Transfer { from: from.to_field(), to: to.to_field(), amount: amount.to_field() }.emit(encode_and_encrypt_event_with_keys_unconstrained(&mut context, from_ovpk, to_ivpk)); } // docs:end:transfer @@ -335,7 +350,7 @@ contract Token { fn cancel_authwit(inner_hash: Field) { let on_behalf_of = context.msg_sender(); let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash); - context.push_new_nullifier(nullifier, 0); + context.push_nullifier(nullifier, 0); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr index 1801ddd72130..5431b94bc108 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/test/utils.nr @@ -72,11 +72,12 @@ pub fn setup_and_mint(with_account_contracts: bool) -> (&mut TestEnvironment, Az pub fn check_public_balance(token_contract_address: AztecAddress, address: AztecAddress, address_amount: Field) { let current_contract_address = cheatcodes::get_contract_address(); cheatcodes::set_contract_address(token_contract_address); + let block_number = cheatcodes::get_block_number(); let balances_slot = Token::storage().public_balances.slot; let address_slot = derive_storage_slot_in_map(balances_slot, address); - let fields = storage_read(address_slot); - assert(U128::deserialize(fields).to_field() == address_amount, "Public balance is not correct"); + let amount: U128 = storage_read(token_contract_address, address_slot, block_number); + assert(amount.to_field() == address_amount, "Public balance is not correct"); cheatcodes::set_contract_address(current_contract_address); } 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 3bf3f00fb1bc..1581da08f440 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -9,8 +9,8 @@ contract Uniswap { use dep::aztec::context::gas::GasOpts; use dep::authwit::auth::{ - IS_VALID_SELECTOR, assert_current_call_valid_authwit_public, compute_call_authwit_hash, - compute_outer_authwit_hash, set_authorized + IS_VALID_SELECTOR, assert_current_call_valid_authwit_public, + compute_authwit_message_hash_from_call, compute_authwit_message_hash, set_authorized }; use dep::token::Token; @@ -166,7 +166,7 @@ contract Uniswap { let nonce = 0xdeadbeef; let selector = FunctionSelector::from_signature("burn_public((Field),Field,Field)"); - let message_hash = compute_call_authwit_hash( + let message_hash = compute_authwit_message_hash_from_call( token_bridge, token, context.chain_id(), diff --git a/noir-projects/noir-contracts/scripts/flamegraph.sh b/noir-projects/noir-contracts/scripts/flamegraph.sh index 6ee8d6cfb29e..01b8dcc3175a 100755 --- a/noir-projects/noir-contracts/scripts/flamegraph.sh +++ b/noir-projects/noir-contracts/scripts/flamegraph.sh @@ -27,8 +27,20 @@ CONTRACT=$1 # second console arg is the contract function FUNCTION=$2 +function sed_wrapper() { + if sed --version >/dev/null 2>&1; then + sed "$@" + elif gsed --version >/dev/null 2>&1; then + gsed "$@" + else + echo "No suitable sed found" + echo "You can install gsed with 'brew install gnu-sed'" + exit 1 + fi +} + # convert contract name to following format: token_bridge_contract-TokenBridge.json -ARTIFACT=$(echo "$CONTRACT" | sed -r 's/^([A-Z])/\L\1/; s/([a-z0-9])([A-Z])/\1_\L\2/g') +ARTIFACT=$(echo "$CONTRACT" | sed_wrapper -r 's/^([A-Z])/\L\1/; s/([a-z0-9])([A-Z])/\1_\L\2/g') ARTIFACT_NAME="${ARTIFACT}_contract-${CONTRACT}" # Extract artifact for the specific function diff --git a/noir-projects/noir-protocol-circuits/bootstrap.sh b/noir-projects/noir-protocol-circuits/bootstrap.sh index 735ac9e19823..874fe97e3e2b 100755 --- a/noir-projects/noir-protocol-circuits/bootstrap.sh +++ b/noir-projects/noir-protocol-circuits/bootstrap.sh @@ -20,4 +20,4 @@ node ./index.js echo "Compiling protocol circuits..." NARGO=${NARGO:-../../noir/noir-repo/target/release/nargo} -$NARGO compile --silence-warnings \ No newline at end of file +$NARGO compile --silence-warnings --use-legacy \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/parity-lib/src/base.nr rename to noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/parity-lib/src/root.nr rename to noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr index d9dd5c3b1710..f1536fb0ab4f 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr @@ -23,7 +23,7 @@ impl Empty for RootParityInput { impl Verifiable for RootParityInput { fn verify(self) { let inputs = ParityPublicInputs::serialize(self.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.verification_key.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr index 8687d049867b..4646d6837db8 100644 --- a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_rollup_parity_input.nr @@ -23,7 +23,7 @@ impl Empty for RootRollupParityInput { impl Verifiable for RootRollupParityInput { fn verify(self) { let inputs = ParityPublicInputs::serialize(self.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.verification_key.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr rename to noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_public_inputs_composer.nr deleted file mode 100644 index f06b4c02ef20..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_public_inputs_composer.nr +++ /dev/null @@ -1,255 +0,0 @@ -use dep::types::{ - abis::{ - private_kernel_data::PrivateKernelData, - kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsBuilder, PublicKernelCircuitPublicInputs}, - note_hash::ScopedNoteHash, nullifier::ScopedNullifier, side_effect::Ordered, - log_hash::{NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash}, gas::Gas, call_request::CallRequest -}, - constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX -}, - hash::{ - silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, - silo_unencrypted_log_hash -}, - utils::arrays::{array_to_bounded_vec, assert_sorted_array} -}; - -fn asc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { - a.counter() < b.counter() -} - -fn desc_sort_by_counters(a: T, b: T) -> bool where T: Ordered { - a.counter() > b.counter() -} - -// Builds: -// .finish -> KernelCircuitPublicInputs (from PrivateKernelTailCircuitPrivateInputs) -// .finish_to_public -> PublicKernelCircuitPublicInputs (from PrivateKernelTailToPublicCircuitPrivateInputs) -struct KernelCircuitPublicInputsComposer { - public_inputs: PrivateKernelCircuitPublicInputsBuilder, - previous_kernel: PrivateKernelData, - // Hints - sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], - sorted_nullifiers_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], - sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_note_encrypted_log_hashes_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX], -} - -impl KernelCircuitPublicInputsComposer { - pub fn new( - previous_kernel: PrivateKernelData, - sorted_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], - sorted_nullifiers_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], - sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_note_encrypted_log_hashes_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX] - ) -> Self { - let public_inputs = PrivateKernelCircuitPublicInputsBuilder::empty(); - - KernelCircuitPublicInputsComposer { - public_inputs, - previous_kernel, - sorted_note_hashes, - sorted_note_hashes_indexes, - sorted_nullifiers, - sorted_nullifiers_indexes, - sorted_note_encrypted_log_hashes, - sorted_note_encrypted_log_hashes_indexes, - sorted_encrypted_log_hashes, - sorted_encrypted_log_hashes_indexes, - sorted_unencrypted_log_hashes, - sorted_unencrypted_log_hashes_indexes - } - } - - pub fn compose(&mut self) -> Self { - self.propagate_rollup_validation_requests(); - - self.propagate_constant_data(); - - self.propagate_sorted_arrays(); - - self.propagate_fee_payer(); - - self.silo_values(); - - *self - } - - pub fn compose_public( - &mut self, - sorted_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], - sorted_call_requests_indexes: [u32; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX] - ) -> Self { - let _ = self.compose(); - - self.propagate_sorted_public_call_requests(sorted_call_requests, sorted_call_requests_indexes); - self.propagate_public_teardown_call_request(); - - *self - } - - pub fn finish(self) -> KernelCircuitPublicInputs { - let teardown_gas = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; - let inputs = self.public_inputs.finish_tail(teardown_gas); - let limits = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits; - assert(inputs.end.gas_used.within(limits), "The gas used exceeds the gas limits"); - inputs - } - - pub fn finish_to_public(self) -> PublicKernelCircuitPublicInputs { - let min_revertible_side_effect_counter = self.previous_kernel.public_inputs.min_revertible_side_effect_counter; - let teardown_gas = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; - let inputs = self.public_inputs.finish_to_public(teardown_gas, min_revertible_side_effect_counter); - let limits = self.previous_kernel.public_inputs.constants.tx_context.gas_settings.gas_limits; - let total_gas_used = inputs.end.gas_used + inputs.end_non_revertible.gas_used; - assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); - inputs - } - - fn silo_values(&mut self) { - self.silo_note_hashes(); - self.silo_nullifiers(); - self.silo_l2_to_l1_messages(); - self.silo_encrypted_logs(); - self.silo_unencrypted_logs(); - } - - fn silo_note_hashes(&mut self) { - let first_nullifier = self.public_inputs.end.new_nullifiers.get_unchecked(0).value(); - // This check is unnecessary. The 0th nullifier will always be set a non-zero value in private_kernel_init. - // assert(first_nullifier != 0, "The 0th nullifier in the accumulated nullifier array is zero"); - - let note_hashes = self.public_inputs.end.new_note_hashes.storage; - for i in 0..note_hashes.len() { - self.public_inputs.end.new_note_hashes.storage[i].note_hash.value = silo_note_hash( - note_hashes[i], - first_nullifier, - i - ); - } - } - - fn silo_nullifiers(&mut self) { - let nullifiers = self.public_inputs.end.new_nullifiers.storage; - for i in 1..nullifiers.len() { // i starts from 1 to skip the first nullifier. - self.public_inputs.end.new_nullifiers.storage[i].nullifier.value = silo_nullifier(nullifiers[i]); - } - } - - fn silo_l2_to_l1_messages(&mut self) { - let l2_to_l1_msgs = self.public_inputs.end.new_l2_to_l1_msgs.storage; - let tx_context = self.previous_kernel.public_inputs.constants.tx_context; - for i in 0..l2_to_l1_msgs.len() { - self.public_inputs.end.new_l2_to_l1_msgs.storage[i].message.content = silo_l2_to_l1_message( - l2_to_l1_msgs[i], - tx_context.version, - tx_context.chain_id, - ); - } - } - - fn silo_encrypted_logs(&mut self) { - let logs = self.public_inputs.end.encrypted_logs_hashes.storage; - for i in 0..logs.len() { - self.public_inputs.end.encrypted_logs_hashes.storage[i].log_hash.value = silo_encrypted_log_hash(logs[i]); - } - } - - fn silo_unencrypted_logs(&mut self) { - let logs = self.public_inputs.end.unencrypted_logs_hashes.storage; - for i in 0..logs.len() { - self.public_inputs.end.unencrypted_logs_hashes.storage[i].log_hash.value = silo_unencrypted_log_hash(logs[i]); - } - } - - fn propagate_rollup_validation_requests(&mut self) { - self.public_inputs.validation_requests.max_block_number = self.previous_kernel.public_inputs.validation_requests.for_rollup.max_block_number; - } - - fn propagate_constant_data(&mut self) { - self.public_inputs.constants = self.previous_kernel.public_inputs.constants; - } - - fn propagate_sorted_arrays(&mut self) { - let accumulated_data = self.previous_kernel.public_inputs.end; - - assert_sorted_array( - accumulated_data.new_note_hashes, - self.sorted_note_hashes, - self.sorted_note_hashes_indexes, - asc_sort_by_counters - ); - self.public_inputs.end.new_note_hashes = array_to_bounded_vec(self.sorted_note_hashes); - - assert_sorted_array( - accumulated_data.new_nullifiers, - self.sorted_nullifiers, - self.sorted_nullifiers_indexes, - asc_sort_by_counters - ); - self.public_inputs.end.new_nullifiers = array_to_bounded_vec(self.sorted_nullifiers); - - assert_sorted_array( - accumulated_data.note_encrypted_logs_hashes, - self.sorted_note_encrypted_log_hashes, - self.sorted_note_encrypted_log_hashes_indexes, - asc_sort_by_counters - ); - self.public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(self.sorted_note_encrypted_log_hashes); - - 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); - } - - fn propagate_sorted_public_call_requests( - &mut self, - sorted_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], - sorted_call_requests_indexes: [u32; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX] - ) { - let accumulated_data = self.previous_kernel.public_inputs.end; - assert_sorted_array( - accumulated_data.public_call_stack, - sorted_call_requests, - sorted_call_requests_indexes, - desc_sort_by_counters - ); - self.public_inputs.end.public_call_stack = array_to_bounded_vec(sorted_call_requests); - } - - fn propagate_public_teardown_call_request(&mut self) { - self.public_inputs.public_teardown_call_request = self.previous_kernel.public_inputs.public_teardown_call_request; - } - - fn propagate_fee_payer(&mut self) { - self.public_inputs.fee_payer = self.previous_kernel.public_inputs.fee_payer; - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr similarity index 55% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr index c98c3b345953..b61366e753c5 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/mod.nr @@ -1,7 +1,8 @@ -mod kernel_circuit_output_hints; -mod kernel_circuit_output_validator; -mod kernel_circuit_public_inputs_composer; mod previous_kernel_validator; mod private_call_data_validator; mod private_kernel_circuit_output_validator; mod private_kernel_circuit_public_inputs_composer; +mod tail_output_composer; +mod tail_output_validator; +mod tail_to_public_output_composer; +mod tail_to_public_output_validator; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr index d0b0bb5959e9..ba886c57e8ae 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/previous_kernel_validator.nr @@ -13,15 +13,17 @@ impl PreviousKernelValidator { } pub fn validate_for_private_tail(self) { - self.validate_empty_private_call_stack(); + self.validate_common(); self.validate_empty_public_call_stack(); - self.verify_empty_validation_requests(); - self.verify_no_transient_data(); } pub fn validate_for_private_tail_to_public(self) { - self.validate_empty_private_call_stack(); + self.validate_common(); self.validate_non_empty_public_call_stack(); + } + + fn validate_common(self) { + self.validate_empty_private_call_stack(); self.verify_empty_validation_requests(); self.verify_no_transient_data(); } @@ -63,11 +65,11 @@ impl PreviousKernelValidator { fn verify_no_transient_data(self) { // Currently all the transient note hashes and nullifiers must be cleared in the reset circuits. // Check that the propagated note hashes don't link to a nullifier, and vice versa. - for note_hash in self.previous_kernel.end.new_note_hashes { + for note_hash in self.previous_kernel.end.note_hashes { assert_eq(note_hash.nullifier_counter, 0, "Unresolved transient note hash"); } - for new_nullifier in self.previous_kernel.end.new_nullifiers { - assert_eq(new_nullifier.nullified_note_hash(), 0, "Unresolved transient nullifier"); + for nullifier in self.previous_kernel.end.nullifiers { + assert_eq(nullifier.nullified_note_hash(), 0, "Unresolved transient nullifier"); } } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr index 9f027a1cd993..affec785a95f 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator.nr @@ -1,10 +1,17 @@ +mod find_first_revertible_item_index; +mod validate_split_ranges; + +use crate::components::private_call_data_validator::{ + find_first_revertible_item_index::find_first_revertible_item_index, + validate_split_ranges::validate_split_ranges +}; use dep::types::{ abis::{ call_context::CallContext, call_request::CallRequest, caller_context::CallerContext, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, log_hash::NoteLogHash, note_hash::ScopedNoteHash, private_call_request::ScopedPrivateCallRequest, private_call_stack_item::PrivateCallStackItem, - private_circuit_public_inputs::PrivateCircuitPublicInputsArrayLengths, + private_circuit_public_inputs::{PrivateCircuitPublicInputs, PrivateCircuitPublicInputsArrayLengths}, private_kernel::private_call_data::PrivateCallData, side_effect::{Ordered, RangeOrdered} }, address::{AztecAddress, PartialAddress}, contract_class_id::ContractClassId, @@ -12,13 +19,23 @@ use dep::types::{ traits::is_empty, transaction::tx_request::TxRequest, utils::arrays::find_index }; -unconstrained fn match_log_to_note(note_log: NoteLogHash, accumulated_note_hashes: [ScopedNoteHash; N]) -> u32 { +unconstrained fn match_log_to_note( + note_log: NoteLogHash, + accumulated_note_hashes: [ScopedNoteHash; N] +) -> u32 { find_index( accumulated_note_hashes, |n: ScopedNoteHash| n.counter() == note_log.note_hash_counter ) } +unconstrained fn find_first_revertible_private_call_request_index(public_inputs: PrivateCircuitPublicInputs) -> u32 { + find_first_revertible_item_index( + public_inputs.min_revertible_side_effect_counter, + public_inputs.private_call_requests + ) +} + fn validate_caller_context(caller_context: CallerContext, this_context: CallContext) { let matching_caller_context = caller_context.msg_sender.eq(this_context.msg_sender) & caller_context.storage_contract_address.eq(this_context.storage_contract_address); @@ -38,12 +55,7 @@ fn validate_call_request(request: CallRequest, hash: Field, caller: PrivateCallS } } -fn validate_incrementing_counters_within_range( - counter_start: u32, - counter_end: u32, - items: [T; N], - num_items: u32 -) where T: Ordered { +fn validate_incrementing_counters_within_range(counter_start: u32, counter_end: u32, items: [T; N], num_items: u32) where T: Ordered { let mut prev_counter = counter_start; let mut should_check = true; for i in 0..N { @@ -83,27 +95,6 @@ fn validate_incrementing_counter_ranges_within_range( ); } -fn validate_clean_split_ranges( - min_revertible_side_effect_counter: u32, - first_revertible_item_index: u32, - items: [T; N], - num_items: u32 -) where T: RangeOrdered { - if first_revertible_item_index != 0 { - let last_non_revertible_item_index = first_revertible_item_index - 1; - let item = items[last_non_revertible_item_index]; - assert( - min_revertible_side_effect_counter > item.counter_end(), "min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item" - ); - } - if first_revertible_item_index != num_items { - let item = items[first_revertible_item_index]; - assert( - min_revertible_side_effect_counter <= item.counter_start(), "min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item" - ); - } -} - struct PrivateCallDataValidator { data: PrivateCallData, array_lengths: PrivateCircuitPublicInputsArrayLengths, @@ -125,18 +116,19 @@ impl PrivateCallDataValidator { self.validate_note_logs(accumulated_note_hashes); } - pub fn validate_as_first_call(self, first_revertible_private_call_request_index: u32) { + pub fn validate_as_first_call(self) { let public_inputs = self.data.call_stack_item.public_inputs; let call_context = public_inputs.call_context; assert(call_context.is_delegate_call == false, "Users cannot make a delegatecall"); assert(call_context.is_static_call == false, "Users cannot make a static call"); let min_revertible_side_effect_counter = public_inputs.min_revertible_side_effect_counter; + let first_revertible_index = find_first_revertible_private_call_request_index(public_inputs); // No need to check that the min_revertible_side_effect_counter falls in the counter range of the private call. // It is valid as long as it does not fall in the middle of any nested call. - validate_clean_split_ranges( + validate_split_ranges( min_revertible_side_effect_counter, - first_revertible_private_call_request_index, + first_revertible_index, public_inputs.private_call_requests, self.array_lengths.private_call_requests ); @@ -207,8 +199,8 @@ impl PrivateCallDataValidator { let private_call_vk_hash = stdlib_recursion_verification_key_compress_native_vk(self.data.vk); assert(!contract_address.is_zero(), "contract address cannot be zero"); - // std::println(f"contract_address={contract_address}"); - // std::println(f"private_call_vk_hash={private_call_vk_hash}"); + // println(f"contract_address={contract_address}"); + // println(f"private_call_vk_hash={private_call_vk_hash}"); // Recompute the contract class id let computed_private_functions_root = private_functions_root_from_siblings( @@ -217,24 +209,24 @@ impl PrivateCallDataValidator { self.data.function_leaf_membership_witness.leaf_index, self.data.function_leaf_membership_witness.sibling_path ); - // std::println(f"computed_private_functions_root={computed_private_functions_root}"); + // println(f"computed_private_functions_root={computed_private_functions_root}"); let computed_contract_class_id = ContractClassId::compute( self.data.contract_class_artifact_hash, computed_private_functions_root, self.data.contract_class_public_bytecode_commitment ); - // std::println(f"computed_contract_class_id={computed_contract_class_id}"); + // println(f"computed_contract_class_id={computed_contract_class_id}"); // Recompute contract address using the preimage which includes the class_id let computed_partial_address = PartialAddress::compute_from_salted_initialization_hash( computed_contract_class_id, self.data.salted_initialization_hash ); - // std::println(f"computed_partial_address={computed_partial_address}"); + // println(f"computed_partial_address={computed_partial_address}"); let computed_address = AztecAddress::compute(self.data.public_keys_hash, computed_partial_address); - // std::println(f"computed_address={computed_address}"); + // println(f"computed_address={computed_address}"); assert( computed_address.eq(contract_address), "computed contract address does not match expected one" @@ -255,11 +247,9 @@ impl PrivateCallDataValidator { if call_context.is_static_call { // No state changes are allowed for static calls: - assert_eq(self.array_lengths.new_note_hashes, 0, "new_note_hashes must be empty for static calls"); - assert_eq(self.array_lengths.new_nullifiers, 0, "new_nullifiers must be empty for static calls"); - assert_eq( - self.array_lengths.new_l2_to_l1_msgs, 0, "new_l2_to_l1_msgs must be empty for static calls" - ); + assert_eq(self.array_lengths.note_hashes, 0, "note_hashes must be empty for static calls"); + assert_eq(self.array_lengths.nullifiers, 0, "nullifiers must be empty for static calls"); + assert_eq(self.array_lengths.l2_to_l1_msgs, 0, "l2_to_l1_msgs must be empty for static calls"); assert_eq( self.array_lengths.note_encrypted_logs_hashes, 0, "note_encrypted_logs_hashes must be empty for static calls" ); @@ -325,20 +315,20 @@ impl PrivateCallDataValidator { validate_incrementing_counters_within_range( counter_start, counter_end, - public_inputs.new_note_hashes, - self.array_lengths.new_note_hashes + public_inputs.note_hashes, + self.array_lengths.note_hashes ); validate_incrementing_counters_within_range( counter_start, counter_end, - public_inputs.new_nullifiers, - self.array_lengths.new_nullifiers + public_inputs.nullifiers, + self.array_lengths.nullifiers ); validate_incrementing_counters_within_range( counter_start, counter_end, - public_inputs.new_l2_to_l1_msgs, - self.array_lengths.new_l2_to_l1_msgs + public_inputs.l2_to_l1_msgs, + self.array_lengths.l2_to_l1_msgs ); validate_incrementing_counters_within_range( counter_start, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr new file mode 100644 index 000000000000..81a87d7b2068 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/find_first_revertible_item_index.nr @@ -0,0 +1,97 @@ +use dep::types::{abis::side_effect::Ordered, traits::Empty, utils::arrays::array_length}; + +pub fn find_first_revertible_item_index( + min_revertible_side_effect_counter: u32, + items: [T; N] +) -> u32 where T: Ordered + Empty + Eq { + let mut index = N; + for i in 0..N { + let item = items[i]; + if (index == N) & (item.counter() >= min_revertible_side_effect_counter) { + index = i; + } + } + if index == N { + index = array_length(items); + } + index +} + +mod tests { + use crate::components::private_call_data_validator::find_first_revertible_item_index::find_first_revertible_item_index; + use dep::types::tests::fixture_builder::FixtureBuilder; + + struct TestBuilder { + private_call: FixtureBuilder + } + + impl TestBuilder { + pub fn new() -> Self { + let private_call = FixtureBuilder::new(); + TestBuilder { private_call } + } + + pub fn execute(self) -> u32 { + let private_call = self.private_call.to_private_circuit_public_inputs(); + find_first_revertible_item_index( + private_call.min_revertible_side_effect_counter, + private_call.private_call_requests + ) + } + } + + #[test] + fn find_first_revertible_item_index_empty() { + let builder = TestBuilder::new(); + let index = builder.execute(); + assert_eq(index, 0); + } + + #[test] + fn find_first_revertible_item_index_empty_with_min_counter() { + let mut builder = TestBuilder::new(); + + builder.private_call.min_revertible_side_effect_counter = 5; + + let index = builder.execute(); + assert_eq(index, 0); + } + + #[test] + fn find_first_revertible_item_index_only_revertible() { + let mut builder = TestBuilder::new(); + + // Revertible. + builder.private_call.end_setup(); + builder.private_call.append_private_call_requests(3); + + let index = builder.execute(); + assert_eq(index, 0); + } + + #[test] + fn find_first_revertible_item_index_only_non_revertible() { + let mut builder = TestBuilder::new(); + + // Non-revertible. + builder.private_call.append_private_call_requests(2); + builder.private_call.end_setup(); + + let index = builder.execute(); + assert_eq(index, 2); + } + + #[test] + fn find_first_revertible_item_index_both() { + let mut builder = TestBuilder::new(); + + // Non-revertible. + builder.private_call.append_private_call_requests(2); + // Revertible. + builder.private_call.end_setup(); + builder.private_call.append_private_call_requests(3); + + let index = builder.execute(); + assert_eq(index, 2); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr new file mode 100644 index 000000000000..6c50ff6c50c6 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_call_data_validator/validate_split_ranges.nr @@ -0,0 +1,184 @@ +use dep::types::abis::side_effect::RangeOrdered; + +pub fn validate_split_ranges( + min_revertible_side_effect_counter: u32, + first_revertible_item_index: u32, + items: [T; N], + num_items: u32 +) where T: RangeOrdered { + if first_revertible_item_index != 0 { + let last_non_revertible_item_index = first_revertible_item_index - 1; + let item = items[last_non_revertible_item_index]; + assert( + min_revertible_side_effect_counter > item.counter_end(), "min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item" + ); + } + if first_revertible_item_index != num_items { + let item = items[first_revertible_item_index]; + assert( + min_revertible_side_effect_counter <= item.counter_start(), "min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item" + ); + } +} + +mod tests { + use crate::components::private_call_data_validator::validate_split_ranges::validate_split_ranges; + use dep::types::tests::fixture_builder::FixtureBuilder; + + struct TestBuilder { + private_call: FixtureBuilder, + first_revertible_private_call_request_index: u32, + } + + impl TestBuilder { + pub fn new() -> Self { + let private_call = FixtureBuilder::new(); + TestBuilder { private_call, first_revertible_private_call_request_index: 0 } + } + + pub fn split_calls(&mut self, counter: u32) { + self.private_call.min_revertible_side_effect_counter = counter; + self.first_revertible_private_call_request_index = self.private_call.private_call_requests.len(); + } + + pub fn add_private_call_request(&mut self, counter_start: u32, counter_end: u32) { + let index = self.private_call.private_call_requests.len(); + self.private_call.append_private_call_requests(1); + self.private_call.private_call_requests.storage[index].call_request.start_side_effect_counter = counter_start; + self.private_call.private_call_requests.storage[index].call_request.end_side_effect_counter = counter_end; + self.private_call.counter = counter_end + 1; + } + + pub fn execute(self) { + validate_split_ranges( + self.private_call.min_revertible_side_effect_counter, + self.first_revertible_private_call_request_index, + self.private_call.private_call_requests.storage, + self.private_call.private_call_requests.len() + ); + } + } + + #[test] + fn validate_split_ranges_succeeds() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + builder.split_calls(60); + builder.add_private_call_request(60, 70); + + builder.execute(); + } + + #[test] + fn validate_split_ranges_empty_revertible_succeeds() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + builder.split_calls(51); + + builder.execute(); + } + + #[test] + fn validate_split_ranges_empty_non_revertible_succeeds() { + let mut builder = TestBuilder::new(); + + builder.split_calls(20); + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + + builder.execute(); + } + + #[test] + fn validate_split_ranges_less_than_first_revertible_success() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + // Tweak the counter to be less than the start counter of the first revertible call. + builder.split_calls(59); + builder.add_private_call_request(60, 70); + + builder.execute(); + } + + #[test(should_fail_with="min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item")] + fn validate_split_ranges_less_than_last_non_revertible_fails() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + // Tweak the counter to be less than the end counter of the last non-revertible call. + builder.split_calls(49); + builder.add_private_call_request(60, 70); + + builder.execute(); + } + + #[test(should_fail_with="min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item")] + fn validate_split_ranges_equal_last_non_revertible_fails() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + // Tweak the counter to equal the end counter of the last non-revertible call. + builder.split_calls(50); + + builder.execute(); + } + + #[test(should_fail_with="min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item")] + fn validate_split_ranges_greater_than_first_revertible_fails() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + // Tweak the counter to be greater than the start counter of the first revertible call. + builder.split_calls(61); + builder.add_private_call_request(60, 70); + + builder.execute(); + } + + #[test] + fn validate_split_ranges_0_succeeds() { + let mut builder = TestBuilder::new(); + + // Set the counter to be 0. + builder.split_calls(0); + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + + builder.execute(); + } + + #[test(should_fail_with="min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item")] + fn validate_split_ranges_0_wrong_hint_fails() { + let mut builder = TestBuilder::new(); + + builder.split_calls(0); + // Set the index hint to be 1. + builder.first_revertible_private_call_request_index = 1; + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + + builder.execute(); + } + + #[test(should_fail_with="min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item")] + fn validate_split_ranges_index_hint_greater_than_len_fails() { + let mut builder = TestBuilder::new(); + + builder.add_private_call_request(20, 30); + builder.add_private_call_request(40, 50); + builder.split_calls(51); + // Increase the index by 1. + builder.first_revertible_private_call_request_index += 1; + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr index 898486eb8d9c..e2050fd93a52 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_output_validator.nr @@ -146,7 +146,7 @@ impl PrivateKernelCircuitOutputValidator { ) { self.validate_initial_values(tx_request, private_call, public_teardown_call_request); let mut offsets = PrivateKernelCircuitPublicInputsArrayLengths::empty(); - offsets.new_nullifiers = 1; // The first nullifier is not propagated from the private call. + offsets.nullifiers = 1; // The first nullifier is not propagated from the private call. self.validate_propagated_from_private_call( private_call, private_call_array_lengths, @@ -198,7 +198,7 @@ impl PrivateKernelCircuitOutputValidator { // First nullifier. let first_nullifier = create_first_nullifier(tx_request); assert_eq( - self.output.end.new_nullifiers[0], first_nullifier, "first nullifier must be the tx request nullifier" + self.output.end.nullifiers[0], first_nullifier, "first nullifier must be the tx request nullifier" ); // Others. @@ -293,19 +293,19 @@ impl PrivateKernelCircuitOutputValidator { array_lengths.scoped_key_validation_requests_and_generators ); validate_array_prepended( - self.output.end.new_note_hashes, - previous_kernel.end.new_note_hashes, - array_lengths.new_note_hashes + self.output.end.note_hashes, + previous_kernel.end.note_hashes, + array_lengths.note_hashes ); validate_array_prepended( - self.output.end.new_nullifiers, - previous_kernel.end.new_nullifiers, - array_lengths.new_nullifiers + self.output.end.nullifiers, + previous_kernel.end.nullifiers, + array_lengths.nullifiers ); validate_array_prepended( - self.output.end.new_l2_to_l1_msgs, - previous_kernel.end.new_l2_to_l1_msgs, - array_lengths.new_l2_to_l1_msgs + self.output.end.l2_to_l1_msgs, + previous_kernel.end.l2_to_l1_msgs, + array_lengths.l2_to_l1_msgs ); validate_array_prepended( self.output.end.note_encrypted_logs_hashes, @@ -369,30 +369,30 @@ impl PrivateKernelCircuitOutputValidator { storage_contract_address ); validate_array_appended_scoped( - self.output.end.new_note_hashes, - private_call.new_note_hashes, - array_lengths.new_note_hashes, - offsets.new_note_hashes, + self.output.end.note_hashes, + private_call.note_hashes, + array_lengths.note_hashes, + offsets.note_hashes, storage_contract_address ); validate_note_hash_nullifier_counters( - self.output.end.new_note_hashes, + self.output.end.note_hashes, note_hash_nullifier_counters, - array_lengths.new_note_hashes, - offsets.new_note_hashes + array_lengths.note_hashes, + offsets.note_hashes ); validate_array_appended_scoped( - self.output.end.new_nullifiers, - private_call.new_nullifiers, - array_lengths.new_nullifiers, - offsets.new_nullifiers, + self.output.end.nullifiers, + private_call.nullifiers, + array_lengths.nullifiers, + offsets.nullifiers, storage_contract_address ); validate_array_appended_scoped( - self.output.end.new_l2_to_l1_msgs, - private_call.new_l2_to_l1_msgs, - array_lengths.new_l2_to_l1_msgs, - offsets.new_l2_to_l1_msgs, + self.output.end.l2_to_l1_msgs, + private_call.l2_to_l1_msgs, + array_lengths.l2_to_l1_msgs, + offsets.l2_to_l1_msgs, storage_contract_address ); validate_array_appended( diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr index b11bf4e76fc1..4b0dc85410b3 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/private_kernel_circuit_public_inputs_composer.nr @@ -7,18 +7,22 @@ use dep::types::{ }, address::AztecAddress, constants::{ - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL +}, + hash::{ + silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, + silo_unencrypted_log_hash }, traits::is_empty, transaction::tx_request::TxRequest, - utils::arrays::{array_length, array_to_bounded_vec} + utils::arrays::{array_length, array_to_bounded_vec, sort_by_counters_asc, sort_by_counters_desc} }; struct DataSource { private_call_public_inputs: PrivateCircuitPublicInputs, contract_address: AztecAddress, storage_contract_address: AztecAddress, - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_call_request: CallRequest, } @@ -40,8 +44,8 @@ impl PrivateKernelCircuitPublicInputsComposer { tx_request.tx_context, ); - // Since it's the first iteration, we need to push the tx hash nullifier into the `new_nullifiers` array - public_inputs.end.new_nullifiers.push(create_first_nullifier(tx_request)); + // Since it's the first iteration, we need to push the tx hash nullifier into the `nullifiers` array + public_inputs.end.nullifiers.push(create_first_nullifier(tx_request)); // Note that we do not need to nullify the transaction request nonce anymore. // Should an account want to additionally use nonces for replay protection or handling cancellations, // they will be able to do so in the account contract logic: @@ -65,24 +69,29 @@ impl PrivateKernelCircuitPublicInputsComposer { public_inputs.validation_requests.scoped_key_validation_requests_and_generators = array_to_bounded_vec(start.scoped_key_validation_requests_and_generators); let start = previous_kernel_public_inputs.end; - public_inputs.end.new_note_hashes = array_to_bounded_vec(start.new_note_hashes); - public_inputs.end.new_nullifiers = array_to_bounded_vec(start.new_nullifiers); - public_inputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(start.new_l2_to_l1_msgs); + public_inputs.end.note_hashes = array_to_bounded_vec(start.note_hashes); + public_inputs.end.nullifiers = array_to_bounded_vec(start.nullifiers); + public_inputs.end.l2_to_l1_msgs = array_to_bounded_vec(start.l2_to_l1_msgs); public_inputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); 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.private_call_stack = array_to_bounded_vec(start.private_call_stack); - let _call_request = public_inputs.end.private_call_stack.pop(); public_inputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack); PrivateKernelCircuitPublicInputsComposer { public_inputs } } - pub fn compose( + pub fn pop_top_call_request(&mut self) -> Self { + // Pop the top item in the call stack, which is the caller of the current call, and shouldn't be propagated to the output. + let _call_request = self.public_inputs.end.private_call_stack.pop(); + *self + } + + pub fn with_private_call( &mut self, private_call_public_inputs: PrivateCircuitPublicInputs, contract_address: AztecAddress, - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_call_request: CallRequest ) -> Self { @@ -95,11 +104,17 @@ impl PrivateKernelCircuitPublicInputsComposer { public_call_requests, public_teardown_call_request }; + self.propagate_from_private_call(source); *self } + pub fn sort_and_silo(&mut self) { + self.sort_ordered_values(); + self.silo_scoped_values(); + } + pub fn finish(self) -> PrivateKernelCircuitPublicInputs { self.public_inputs.finish() } @@ -166,7 +181,7 @@ impl PrivateKernelCircuitPublicInputsComposer { } fn propagate_note_hashes(&mut self, source: DataSource) { - let note_hashes = source.private_call_public_inputs.new_note_hashes; + let note_hashes = source.private_call_public_inputs.note_hashes; for i in 0..note_hashes.len() { let mut note_hash = note_hashes[i]; if note_hash.value != 0 { @@ -174,27 +189,27 @@ impl PrivateKernelCircuitPublicInputsComposer { assert( (nullifier_counter == 0) | (nullifier_counter > note_hash.counter), "Invalid nullifier counter" ); - self.public_inputs.end.new_note_hashes.push(note_hash.scope(nullifier_counter, source.storage_contract_address)); + self.public_inputs.end.note_hashes.push(note_hash.scope(nullifier_counter, source.storage_contract_address)); } } } fn propagate_nullifiers(&mut self, source: DataSource) { - let nullifiers = source.private_call_public_inputs.new_nullifiers; + let nullifiers = source.private_call_public_inputs.nullifiers; for i in 0..nullifiers.len() { let nullifier = nullifiers[i]; if nullifier.value != 0 { - self.public_inputs.end.new_nullifiers.push(nullifier.scope(source.storage_contract_address)); + self.public_inputs.end.nullifiers.push(nullifier.scope(source.storage_contract_address)); } } } fn propagate_l2_to_l1_messages(&mut self, source: DataSource) { - let l2_to_l1_msgs = source.private_call_public_inputs.new_l2_to_l1_msgs; + let l2_to_l1_msgs = source.private_call_public_inputs.l2_to_l1_msgs; for i in 0..l2_to_l1_msgs.len() { let msg = l2_to_l1_msgs[i]; if !is_empty(msg) { - self.public_inputs.end.new_l2_to_l1_msgs.push(msg.scope(source.storage_contract_address)); + self.public_inputs.end.l2_to_l1_msgs.push(msg.scope(source.storage_contract_address)); } } } @@ -264,4 +279,67 @@ impl PrivateKernelCircuitPublicInputsComposer { self.public_inputs.fee_payer = source.storage_contract_address; } } + + fn sort_ordered_values(&mut self) { + self.public_inputs.end.note_hashes.storage = sort_by_counters_asc(self.public_inputs.end.note_hashes.storage); + self.public_inputs.end.nullifiers.storage = sort_by_counters_asc(self.public_inputs.end.nullifiers.storage); + self.public_inputs.end.l2_to_l1_msgs.storage = sort_by_counters_asc(self.public_inputs.end.l2_to_l1_msgs.storage); + self.public_inputs.end.note_encrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.note_encrypted_logs_hashes.storage); + self.public_inputs.end.encrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.encrypted_logs_hashes.storage); + self.public_inputs.end.unencrypted_logs_hashes.storage = sort_by_counters_asc(self.public_inputs.end.unencrypted_logs_hashes.storage); + self.public_inputs.end.public_call_stack.storage = sort_by_counters_desc(self.public_inputs.end.public_call_stack.storage); + } + + fn silo_scoped_values(&mut self) { + self.silo_note_hashes(); + self.silo_nullifiers(); + self.silo_l2_to_l1_messages(); + self.silo_encrypted_logs(); + self.silo_unencrypted_logs(); + } + + fn silo_note_hashes(&mut self) { + let first_nullifier = self.public_inputs.end.nullifiers.get_unchecked(0).value(); + let note_hashes = self.public_inputs.end.note_hashes.storage; + for i in 0..note_hashes.len() { + self.public_inputs.end.note_hashes.storage[i].note_hash.value = silo_note_hash( + note_hashes[i], + first_nullifier, + i + ); + } + } + + fn silo_nullifiers(&mut self) { + let nullifiers = self.public_inputs.end.nullifiers.storage; + for i in 0..nullifiers.len() { + self.public_inputs.end.nullifiers.storage[i].nullifier.value = silo_nullifier(nullifiers[i]); + } + } + + fn silo_l2_to_l1_messages(&mut self) { + let l2_to_l1_msgs = self.public_inputs.end.l2_to_l1_msgs.storage; + let tx_context = self.public_inputs.constants.tx_context; + for i in 0..l2_to_l1_msgs.len() { + self.public_inputs.end.l2_to_l1_msgs.storage[i].message.content = silo_l2_to_l1_message( + l2_to_l1_msgs[i], + tx_context.version, + tx_context.chain_id, + ); + } + } + + fn silo_encrypted_logs(&mut self) { + let logs = self.public_inputs.end.encrypted_logs_hashes.storage; + for i in 0..logs.len() { + self.public_inputs.end.encrypted_logs_hashes.storage[i].log_hash.value = silo_encrypted_log_hash(logs[i]); + } + } + + fn silo_unencrypted_logs(&mut self) { + let logs = self.public_inputs.end.unencrypted_logs_hashes.storage; + for i in 0..logs.len() { + self.public_inputs.end.unencrypted_logs_hashes.storage[i].log_hash.value = silo_unencrypted_log_hash(logs[i]); + } + } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr new file mode 100644 index 000000000000..c958fab4182d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr @@ -0,0 +1,69 @@ +use crate::components::private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer; +use dep::types::{ + abis::{ + accumulated_data::combined_accumulated_data::CombinedAccumulatedData, gas::Gas, + kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs}, + log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, + nullifier::ScopedNullifier +}, + constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE}, + hash::{compute_tx_logs_hash, compute_tx_note_logs_hash}, + messaging::l2_to_l1_message::ScopedL2ToL1Message +}; + +struct TailOutputComposer { + output_composer: PrivateKernelCircuitPublicInputsComposer, +} + +impl TailOutputComposer { + pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { + let mut output_composer = PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel); + output_composer.sort_and_silo(); + + TailOutputComposer { output_composer } + } + + pub fn finish(self) -> KernelCircuitPublicInputs { + let source = self.output_composer.finish(); + let mut output = KernelCircuitPublicInputs::empty(); + output.rollup_validation_requests = source.validation_requests.for_rollup; + output.end = self.build_combined_accumulated_data(); + output.constants = source.constants; + output.fee_payer = source.fee_payer; + output + } + + fn build_combined_accumulated_data(self) -> CombinedAccumulatedData { + let source = self.output_composer.public_inputs.end; + let mut data = CombinedAccumulatedData::empty(); + data.note_hashes = source.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value); + data.nullifiers = source.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value); + data.l2_to_l1_msgs = source.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content); + data.note_encrypted_logs_hash = compute_tx_note_logs_hash(source.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| l.expose_to_public())); + data.encrypted_logs_hash = compute_tx_logs_hash(source.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.expose_to_public())); + data.unencrypted_logs_hash = compute_tx_logs_hash(source.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.expose_to_public())); + data.note_encrypted_log_preimages_length = source.note_encrypted_logs_hashes.storage.fold(0, |len, l: NoteLogHash| len + l.length); + data.encrypted_log_preimages_length = source.encrypted_logs_hashes.storage.fold(0, |len, l: ScopedEncryptedLogHash| len + l.log_hash.length); + data.unencrypted_log_preimages_length = source.unencrypted_logs_hashes.storage.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + data.gas_used = self.meter_gas_used(data); + data + } + + fn meter_gas_used(self, data: CombinedAccumulatedData) -> Gas { + let mut metered_bytes = 0; + + let data_builder = self.output_composer.public_inputs.end; + // IMPORTANT: Must use data_builder.__.len(), which is the the number of items pushed to the BoundedVec. + // Do not use data.__.len(), which is the array's max length. + metered_bytes += data_builder.note_hashes.len() * DA_BYTES_PER_FIELD; + metered_bytes += data_builder.nullifiers.len() * DA_BYTES_PER_FIELD; + metered_bytes += data_builder.l2_to_l1_msgs.len() * DA_BYTES_PER_FIELD; + + metered_bytes += data.note_encrypted_log_preimages_length as u32; + metered_bytes += data.encrypted_log_preimages_length as u32; + metered_bytes += data.unencrypted_log_preimages_length as u32; + + let teardown_gas = self.output_composer.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; + Gas::new(metered_bytes * DA_GAS_PER_BYTE, 0) + Gas::tx_overhead() + teardown_gas + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr similarity index 70% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_validator.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index 5d8b04952372..81f3d225a47c 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -1,57 +1,42 @@ -use crate::components::{kernel_circuit_output_hints::{Hints, OrderHint}}; +mod kernel_circuit_output_hints; +mod validate_value_transformation; + +use crate::components::tail_output_validator::{ + kernel_circuit_output_hints::{generate_kernel_circuit_output_hints, Hints}, + validate_value_transformation::{validate_transformed_values, validate_value_transformation} +}; use dep::types::{ abis::{ kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs}, log_hash::{LogHash, NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash} }, - constants::MAX_NEW_NOTE_HASHES_PER_TX, hash::{ compute_tx_logs_hash, compute_tx_note_logs_hash, silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, silo_unencrypted_log_hash }, - traits::{Empty, is_empty}, utils::arrays::assert_sorted_transformed_value_array + traits::is_empty, utils::arrays::assert_sorted_transformed_value_array }; -fn validate_transformed_value_array( - original_array: [T; N], - transformed_value_array: [S; N], - is_transformed: fn[Env](T, S) -> bool -) { - for i in 0..N { - assert(is_transformed(original_array[i], transformed_value_array[i]), "invalid transformed value"); - } -} - -fn validate_siloed_value_array( - original_array: [T; N], - transformed_value_array: [S; N], - silo_value: fn[Env](T) -> S -) where S: Empty + Eq { - validate_transformed_value_array( - original_array, - transformed_value_array, - |original: T, transformed: S| transformed == silo_value(original) - ); -} - -struct KernelCircuitOutputValidator { +struct TailOutputValidator { output: KernelCircuitPublicInputs, - previous_kernel: PrivateKernelCircuitPublicInputs + previous_kernel: PrivateKernelCircuitPublicInputs, } -impl KernelCircuitOutputValidator { +impl TailOutputValidator { pub fn new( output: KernelCircuitPublicInputs, previous_kernel: PrivateKernelCircuitPublicInputs ) -> Self { - KernelCircuitOutputValidator { output, previous_kernel } + TailOutputValidator { output, previous_kernel } } - pub fn validate(self, hints: Hints) { + pub fn validate(self) { + let hints = generate_kernel_circuit_output_hints(self.previous_kernel); self.validate_empty_values(); self.validate_propagated_values(); self.validate_propagated_sorted_siloed_values(hints); self.validate_accumulated_values(hints); + self.validate_gas_limits(); } fn validate_empty_values(self) { @@ -70,54 +55,54 @@ impl KernelCircuitOutputValidator { } fn validate_propagated_sorted_siloed_values(self, hints: Hints) { - // new_note_hashes - let first_nullifier = self.output.end.new_nullifiers[0]; - let unsiloed_note_hashes = self.previous_kernel.end.new_note_hashes; + // First nullifier is tx hash. + let tx_hash = self.output.end.nullifiers[0]; + let unsiloed_note_hashes = self.previous_kernel.end.note_hashes; for i in 0..unsiloed_note_hashes.len() { - let siloed_note_hash = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); + let siloed_note_hash = silo_note_hash(unsiloed_note_hashes[i], tx_hash, i); assert_eq(hints.siloed_note_hashes[i], siloed_note_hash, "mismatch siloed note hashes"); } assert_sorted_transformed_value_array( - self.previous_kernel.end.new_note_hashes, + self.previous_kernel.end.note_hashes, hints.siloed_note_hashes, - self.output.end.new_note_hashes, + self.output.end.note_hashes, hints.sorted_note_hash_hints ); - // new_nullifiers - validate_siloed_value_array( - self.previous_kernel.end.new_nullifiers, + // nullifiers + validate_transformed_values( + self.previous_kernel.end.nullifiers, hints.siloed_nullifiers, silo_nullifier ); assert_sorted_transformed_value_array( - self.previous_kernel.end.new_nullifiers, + self.previous_kernel.end.nullifiers, hints.siloed_nullifiers, - self.output.end.new_nullifiers, + self.output.end.nullifiers, hints.sorted_nullifier_hints ); - // new_l2_to_l1_msgs + // l2_to_l1_msgs let tx_context = self.previous_kernel.constants.tx_context; - validate_siloed_value_array( - self.previous_kernel.end.new_l2_to_l1_msgs, + validate_transformed_values( + self.previous_kernel.end.l2_to_l1_msgs, hints.siloed_l2_to_l1_msgs, |msg| silo_l2_to_l1_message(msg, tx_context.version, tx_context.chain_id) ); assert_sorted_transformed_value_array( - self.previous_kernel.end.new_l2_to_l1_msgs, + self.previous_kernel.end.l2_to_l1_msgs, hints.siloed_l2_to_l1_msgs, - self.output.end.new_l2_to_l1_msgs, + self.output.end.l2_to_l1_msgs, hints.sorted_l2_to_l1_msg_hints ); } fn validate_accumulated_values(self, hints: Hints) { // note_encrypted_log_hashes - validate_transformed_value_array( + validate_value_transformation( self.previous_kernel.end.note_encrypted_logs_hashes, hints.note_encrypted_log_hashes, |nlh: NoteLogHash, lh: LogHash| (nlh.value == lh.value) & (nlh.length == lh.length) @@ -134,7 +119,7 @@ impl KernelCircuitOutputValidator { assert_eq(hash, self.output.end.note_encrypted_logs_hash, "mismatch note_encrypted_logs_hash"); // encrypted_log_hashes - validate_transformed_value_array( + validate_value_transformation( self.previous_kernel.end.encrypted_logs_hashes, hints.siloed_encrypted_log_hashes, |slh: ScopedEncryptedLogHash, lh: LogHash| (lh.value == silo_encrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) @@ -151,7 +136,7 @@ impl KernelCircuitOutputValidator { assert_eq(hash, self.output.end.encrypted_logs_hash, "mismatch encrypted_logs_hash"); // unencrypted_log_hashes - validate_transformed_value_array( + validate_value_transformation( self.previous_kernel.end.unencrypted_logs_hashes, hints.siloed_unencrypted_log_hashes, |slh: ScopedLogHash, lh: LogHash| (lh.value == silo_unencrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) @@ -167,4 +152,9 @@ impl KernelCircuitOutputValidator { let hash = compute_tx_logs_hash(hints.sorted_siloed_unencrypted_log_hashes); assert_eq(hash, self.output.end.unencrypted_logs_hash, "mismatch unencrypted_logs_hash"); } + + fn validate_gas_limits(self) { + let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; + assert(self.output.end.gas_used.within(limits), "The gas used exceeds the gas limits"); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr similarity index 78% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_hints.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr index c5f8b18a72aa..8309ae39aa13 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/kernel_circuit_output_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/kernel_circuit_output_hints.nr @@ -4,8 +4,8 @@ use dep::types::{ log_hash::{LogHash, NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash} }, constants::{ - MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX + MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, hash::{ silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, @@ -17,14 +17,14 @@ use dep::types::{ struct Hints { // Note hashes. - sorted_note_hash_hints: [OrderHint; MAX_NEW_NOTE_HASHES_PER_TX], - siloed_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hash_hints: [OrderHint; MAX_NOTE_HASHES_PER_TX], + siloed_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], // Nullifiers. - sorted_nullifier_hints: [OrderHint; MAX_NEW_NULLIFIERS_PER_TX], - siloed_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifier_hints: [OrderHint; MAX_NULLIFIERS_PER_TX], + siloed_nullifiers: [Field; MAX_NULLIFIERS_PER_TX], // L2 to l1 msgs. - sorted_l2_to_l1_msg_hints: [OrderHint; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - siloed_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + sorted_l2_to_l1_msg_hints: [OrderHint; MAX_L2_TO_L1_MSGS_PER_TX], + siloed_l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], // Note encrypted log hashes. note_encrypted_log_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], sorted_note_encrypted_log_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], @@ -39,26 +39,28 @@ struct Hints { sorted_unencrypted_log_hash_hints: [OrderHint; MAX_UNENCRYPTED_LOGS_PER_TX], } -unconstrained pub fn generate_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> Hints { +unconstrained pub fn generate_kernel_circuit_output_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> Hints { // note_hashes - let sorted_note_hash_hints = sort_get_order_hints_asc(previous_kernel.end.new_note_hashes); + let sorted_note_hash_hints = sort_get_order_hints_asc(previous_kernel.end.note_hashes); - let mut siloed_note_hashes = [0; MAX_NEW_NOTE_HASHES_PER_TX]; - let first_nullifier = previous_kernel.end.new_nullifiers[0].value(); - let unsiloed_note_hashes = previous_kernel.end.new_note_hashes; + let mut siloed_note_hashes = [0; MAX_NOTE_HASHES_PER_TX]; + + // First nullifier is tx hash. + let tx_hash = previous_kernel.end.nullifiers[0].value(); + let unsiloed_note_hashes = previous_kernel.end.note_hashes; for i in 0..unsiloed_note_hashes.len() { - siloed_note_hashes[i] = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); + siloed_note_hashes[i] = silo_note_hash(unsiloed_note_hashes[i], tx_hash, i); } // nullifiers - let sorted_nullifier_hints = sort_get_order_hints_asc(previous_kernel.end.new_nullifiers); - let siloed_nullifiers = previous_kernel.end.new_nullifiers.map(silo_nullifier); + let sorted_nullifier_hints = sort_get_order_hints_asc(previous_kernel.end.nullifiers); + let siloed_nullifiers = previous_kernel.end.nullifiers.map(silo_nullifier); // l2_to_l1_msgs - let sorted_l2_to_l1_msg_hints = sort_get_order_hints_asc(previous_kernel.end.new_l2_to_l1_msgs); + let sorted_l2_to_l1_msg_hints = sort_get_order_hints_asc(previous_kernel.end.l2_to_l1_msgs); let tx_context = previous_kernel.constants.tx_context; - let siloed_l2_to_l1_msgs = previous_kernel.end.new_l2_to_l1_msgs.map( + let siloed_l2_to_l1_msgs = previous_kernel.end.l2_to_l1_msgs.map( |m: ScopedL2ToL1Message| silo_l2_to_l1_message( m, tx_context.version, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/validate_value_transformation.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/validate_value_transformation.nr new file mode 100644 index 000000000000..e7b8d392702d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator/validate_value_transformation.nr @@ -0,0 +1,23 @@ +use dep::types::traits::Empty; + +pub fn validate_value_transformation( + original_array: [T; N], + transformed_value_array: [S; N], + is_transformed: fn[Env](T, S) -> bool +) { + for i in 0..N { + assert(is_transformed(original_array[i], transformed_value_array[i]), "invalid transformed value"); + } +} + +pub fn validate_transformed_values( + original_array: [T; N], + transformed_value_array: [S; N], + transform_value: fn[Env](T) -> S +) where S: Empty + Eq { + validate_value_transformation( + original_array, + transformed_value_array, + |original: T, transformed: S| transformed == transform_value(original) + ); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr new file mode 100644 index 000000000000..a51363f34b60 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr @@ -0,0 +1,42 @@ +mod meter_gas_used; +mod split_to_public; + +use crate::components::{ + private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer, + tail_to_public_output_composer::{ + meter_gas_used::{meter_gas_used_non_revertible, meter_gas_used_revertible}, + split_to_public::split_to_public +} +}; +use dep::types::abis::kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}; + +struct TailToPublicOutputComposer { + output_composer: PrivateKernelCircuitPublicInputsComposer, +} + +impl TailToPublicOutputComposer { + pub fn new(previous_kernel: PrivateKernelCircuitPublicInputs) -> Self { + let mut output_composer = PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel); + output_composer.sort_and_silo(); + + TailToPublicOutputComposer { output_composer } + } + + pub fn finish(self) -> PublicKernelCircuitPublicInputs { + let source = self.output_composer.public_inputs; + let mut output = PublicKernelCircuitPublicInputs::empty(); + output.validation_requests = source.validation_requests.finish(); + output.constants = source.constants; + output.public_teardown_call_stack[0] = source.public_teardown_call_request; + output.fee_payer = source.fee_payer; + + let mut (end_non_revertible, end) = split_to_public(source.end, source.min_revertible_side_effect_counter); + end_non_revertible.gas_used = meter_gas_used_non_revertible(end_non_revertible); + let teardown_gas = source.constants.tx_context.gas_settings.teardown_gas_limits; + end.gas_used = meter_gas_used_revertible(end, teardown_gas); + output.end_non_revertible = end_non_revertible.finish(); + output.end = end.finish(); + + output + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr new file mode 100644 index 000000000000..3a2ad4ac4aca --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -0,0 +1,35 @@ +use dep::types::{ + abis::{ + accumulated_data::{public_accumulated_data_builder::PublicAccumulatedDataBuilder}, gas::Gas, + log_hash::LogHash +}, + constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} +}; + +fn meter_gas_used(data: PublicAccumulatedDataBuilder) -> Gas { + let mut metered_bytes = 0; + metered_bytes += data.note_hashes.len() * DA_BYTES_PER_FIELD; + metered_bytes += data.nullifiers.len() * DA_BYTES_PER_FIELD; + metered_bytes += data.l2_to_l1_msgs.len() * DA_BYTES_PER_FIELD; + + let note_encrypted_log_preimages_length = data.note_encrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + metered_bytes += note_encrypted_log_preimages_length as u32; + + let encrypted_log_preimages_length = data.encrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + metered_bytes += encrypted_log_preimages_length as u32; + + let unencrypted_log_preimages_length = data.unencrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + metered_bytes += unencrypted_log_preimages_length as u32; + + // TODO(gas): add AVM_STARTUP_L2_GAS + + Gas::new(metered_bytes * DA_GAS_PER_BYTE, 0) +} + +pub fn meter_gas_used_non_revertible(data: PublicAccumulatedDataBuilder) -> Gas { + meter_gas_used(data) + Gas::tx_overhead() +} + +pub fn meter_gas_used_revertible(data: PublicAccumulatedDataBuilder, teardown_gas: Gas) -> Gas { + meter_gas_used(data) + Gas::new(teardown_gas.da_gas, teardown_gas.l2_gas) +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr new file mode 100644 index 000000000000..424cca62483f --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr @@ -0,0 +1,111 @@ +use dep::types::abis::{ + accumulated_data::{ + private_accumulated_data_builder::PrivateAccumulatedDataBuilder, + public_accumulated_data_builder::PublicAccumulatedDataBuilder +} +}; + +pub fn split_to_public( + data: PrivateAccumulatedDataBuilder, + min_revertible_side_effect_counter: u32 +) -> (PublicAccumulatedDataBuilder, PublicAccumulatedDataBuilder) { + let mut non_revertible_builder = PublicAccumulatedDataBuilder::empty(); + let mut revertible_builder = PublicAccumulatedDataBuilder::empty(); + + let note_hashes = data.note_hashes; + for i in 0..note_hashes.max_len() { + if i < note_hashes.len() { + let note_hash = note_hashes.get_unchecked(i); + let public_note_hash = note_hash.expose_to_public(); + if note_hash.counter() < min_revertible_side_effect_counter { + non_revertible_builder.note_hashes.push(public_note_hash); + } else { + revertible_builder.note_hashes.push(public_note_hash); + } + } + } + + let nullifiers = data.nullifiers; + // First nullifier is always non-revertible. + let first_nullifier = nullifiers.get_unchecked(0).expose_to_public(); + non_revertible_builder.nullifiers.push(first_nullifier); + for i in 1..nullifiers.max_len() { + if i < nullifiers.len() { + let nullifier = nullifiers.get_unchecked(i); + let public_nullifier = nullifier.expose_to_public(); + if nullifier.counter() < min_revertible_side_effect_counter { + non_revertible_builder.nullifiers.push(public_nullifier); + } else { + revertible_builder.nullifiers.push(public_nullifier); + } + } + } + + let l2_to_l1_msgs = data.l2_to_l1_msgs; + for i in 0..l2_to_l1_msgs.max_len() { + if i < l2_to_l1_msgs.len() { + let msg = l2_to_l1_msgs.get_unchecked(i); + if msg.counter() < min_revertible_side_effect_counter { + non_revertible_builder.l2_to_l1_msgs.push(msg.message.content); + } else { + revertible_builder.l2_to_l1_msgs.push(msg.message.content); + } + } + } + + let note_encrypted_logs_hashes = data.note_encrypted_logs_hashes; + for i in 0..note_encrypted_logs_hashes.max_len() { + if i < note_encrypted_logs_hashes.len() { + let note_encrypted_log_hash = note_encrypted_logs_hashes.get_unchecked(i); + let public_log_hash = note_encrypted_log_hash.expose_to_public(); + if note_encrypted_log_hash.counter < min_revertible_side_effect_counter { + non_revertible_builder.note_encrypted_logs_hashes.push(public_log_hash); + } else { + revertible_builder.note_encrypted_logs_hashes.push(public_log_hash); + } + } + } + + let encrypted_logs_hashes = data.encrypted_logs_hashes; + for i in 0..encrypted_logs_hashes.max_len() { + if i < encrypted_logs_hashes.len() { + let encrypted_log_hash = encrypted_logs_hashes.get_unchecked(i); + let public_log_hash = encrypted_log_hash.expose_to_public(); + if encrypted_log_hash.counter() < min_revertible_side_effect_counter { + non_revertible_builder.encrypted_logs_hashes.push(public_log_hash); + } else { + revertible_builder.encrypted_logs_hashes.push(public_log_hash); + } + } + } + + let unencrypted_logs_hashes = data.unencrypted_logs_hashes; + for i in 0..unencrypted_logs_hashes.max_len() { + if i < unencrypted_logs_hashes.len() { + let unencrypted_log_hash = unencrypted_logs_hashes.get_unchecked(i); + let public_log_hash = unencrypted_log_hash.expose_to_public(); + if unencrypted_log_hash.counter() < min_revertible_side_effect_counter { + non_revertible_builder.unencrypted_logs_hashes.push(public_log_hash); + } else { + revertible_builder.unencrypted_logs_hashes.push(public_log_hash); + } + } + } + + let public_call_stack = data.public_call_stack; + for i in 0..public_call_stack.max_len() { + if i < public_call_stack.len() { + let call_stack_item = public_call_stack.get_unchecked(i); + // TODO: Hide the counter of a public call request. + // let public_call_request = call_stack_item.expose_to_public(); + let public_call_request = call_stack_item; + if call_stack_item.start_side_effect_counter < min_revertible_side_effect_counter { + non_revertible_builder.public_call_stack.push(public_call_request); + } else { + revertible_builder.public_call_stack.push(public_call_request); + } + } + } + + (non_revertible_builder, revertible_builder) +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr new file mode 100644 index 000000000000..0cb8a53fa5f9 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -0,0 +1,194 @@ +mod tail_to_public_output_hints; + +use crate::components::{ + tail_output_validator::validate_value_transformation::{validate_transformed_values, validate_value_transformation}, + tail_to_public_output_validator::tail_to_public_output_hints::{generate_tail_to_public_output_hints, TailToPublicOutputHints} +}; +use dep::types::{ + abis::{ + call_request::CallRequest, + kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, + log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, nullifier::Nullifier +}, + hash::{ + silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, + silo_unencrypted_log_hash +}, + traits::{Empty, is_empty_array}, + utils::arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc} +}; + +struct TailToPublicOutputValidator { + output: PublicKernelCircuitPublicInputs, + previous_kernel: PrivateKernelCircuitPublicInputs, +} + +impl TailToPublicOutputValidator { + pub fn new( + output: PublicKernelCircuitPublicInputs, + previous_kernel: PrivateKernelCircuitPublicInputs + ) -> Self { + TailToPublicOutputValidator { output, previous_kernel } + } + + pub fn validate(self) { + let hints = generate_tail_to_public_output_hints(self.previous_kernel); + self.validate_empty_values(); + self.validate_propagated_values(); + self.validate_propagated_sorted_siloed_values(hints); + self.validate_gas_limits(); + } + + fn validate_empty_values(self) { + assert_eq(self.output.revert_code, 0, "revert_code must be empty"); + + assert( + is_empty_array(self.output.end_non_revertible.public_data_update_requests), "non-revertible public_data_update_requests must be empty" + ); + assert( + is_empty_array(self.output.end.public_data_update_requests), "revertible public_data_update_requests must be empty" + ); + } + + fn validate_propagated_values(self) { + assert_eq(self.output.constants, self.previous_kernel.constants, "mismatch constants"); + + assert_eq( + self.output.validation_requests.for_rollup, self.previous_kernel.validation_requests.for_rollup, "mismatch rollup_validation_requests" + ); + + assert_eq(self.output.fee_payer, self.previous_kernel.fee_payer, "mismatch fee_payer"); + } + + fn validate_propagated_sorted_siloed_values(self, hints: TailToPublicOutputHints) { + let split_counter = self.previous_kernel.min_revertible_side_effect_counter; + let prev_data = self.previous_kernel.end; + let output_non_revertible = self.output.end_non_revertible; + let output_revertible = self.output.end; + + // note_hashes + let first_nullifier = output_non_revertible.nullifiers[0].value; + let unsiloed_note_hashes = prev_data.note_hashes; + for i in 0..unsiloed_note_hashes.len() { + let siloed_note_hash = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); + assert_eq(hints.siloed_note_hashes[i].value, siloed_note_hash, "mismatch siloed note hashes"); + assert_eq(hints.siloed_note_hashes[i].counter, 0, "cannot expose note hash counter"); + } + + assert_split_sorted_transformed_value_arrays_asc( + prev_data.note_hashes, + hints.siloed_note_hashes, + split_counter, + output_non_revertible.note_hashes, + output_revertible.note_hashes, + hints.sorted_note_hash_hints + ); + + // nullifiers + validate_value_transformation( + prev_data.nullifiers, + hints.siloed_nullifiers, + |sn, n: Nullifier| (n.value == silo_nullifier(sn)) & (n.counter == 0) & (n.note_hash == 0) + ); + assert_split_sorted_transformed_value_arrays_asc( + prev_data.nullifiers, + hints.siloed_nullifiers, + split_counter, + output_non_revertible.nullifiers, + output_revertible.nullifiers, + hints.sorted_nullifier_hints + ); + + // l2_to_l1_msgs + let tx_context = self.previous_kernel.constants.tx_context; + validate_transformed_values( + prev_data.l2_to_l1_msgs, + hints.siloed_l2_to_l1_msgs, + |msg| silo_l2_to_l1_message(msg, tx_context.version, tx_context.chain_id) + ); + + assert_split_sorted_transformed_value_arrays_asc( + prev_data.l2_to_l1_msgs, + hints.siloed_l2_to_l1_msgs, + split_counter, + output_non_revertible.l2_to_l1_msgs, + output_revertible.l2_to_l1_msgs, + hints.sorted_l2_to_l1_msg_hints + ); + + // note_encrypted_logs_hashes + validate_value_transformation( + prev_data.note_encrypted_logs_hashes, + hints.note_encrypted_logs_hashes, + |nlh: NoteLogHash, lh: LogHash| (lh.value == nlh.value) & (lh.length == nlh.length) & (lh.counter == 0) + ); + + assert_split_sorted_transformed_value_arrays_asc( + prev_data.note_encrypted_logs_hashes, + hints.note_encrypted_logs_hashes, + split_counter, + output_non_revertible.note_encrypted_logs_hashes, + output_revertible.note_encrypted_logs_hashes, + hints.sorted_note_encrypted_log_hash_hints + ); + + // encrypted_logs_hashes + validate_value_transformation( + prev_data.encrypted_logs_hashes, + hints.siloed_encrypted_logs_hashes, + |slh: ScopedEncryptedLogHash, lh: LogHash| (lh.value == silo_encrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) & (lh.counter == 0) + ); + + assert_split_sorted_transformed_value_arrays_asc( + prev_data.encrypted_logs_hashes, + hints.siloed_encrypted_logs_hashes, + split_counter, + output_non_revertible.encrypted_logs_hashes, + output_revertible.encrypted_logs_hashes, + hints.sorted_encrypted_log_hash_hints + ); + + // unencrypted_logs_hashes + validate_value_transformation( + prev_data.unencrypted_logs_hashes, + hints.siloed_unencrypted_logs_hashes, + |slh: ScopedLogHash, lh: LogHash| (lh.value == silo_unencrypted_log_hash(slh)) & (lh.length == slh.log_hash.length) & (lh.counter == 0) + ); + + assert_split_sorted_transformed_value_arrays_asc( + prev_data.unencrypted_logs_hashes, + hints.siloed_unencrypted_logs_hashes, + split_counter, + output_non_revertible.unencrypted_logs_hashes, + output_revertible.unencrypted_logs_hashes, + hints.sorted_unencrypted_log_hash_hints + ); + + // public_call_stack + validate_value_transformation( + prev_data.public_call_stack, + hints.public_call_requests, + |cr: CallRequest, public_cr: CallRequest| (public_cr.hash == cr.hash) + & (public_cr.caller_contract_address == cr.caller_contract_address) + & (public_cr.caller_context == cr.caller_context) + // TODO: Hide the counter of a public call request. + // & (public_cr.start_side_effect_counter == 0) + & (public_cr.end_side_effect_counter == 0) + ); + + assert_split_sorted_transformed_value_arrays_desc( + prev_data.public_call_stack, + hints.public_call_requests, + split_counter, + output_non_revertible.public_call_stack, + output_revertible.public_call_stack, + hints.sorted_public_call_request_hints + ) + } + + fn validate_gas_limits(self) { + let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; + let total_gas_used = self.output.end_non_revertible.gas_used + self.output.end.gas_used; + assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr new file mode 100644 index 000000000000..12643aa6b501 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator/tail_to_public_output_hints.nr @@ -0,0 +1,123 @@ +use dep::types::{ + abis::{ + call_request::CallRequest, kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + log_hash::{LogHash, NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash}, note_hash::NoteHash, + nullifier::Nullifier +}, + constants::{ + MAX_ENCRYPTED_LOGS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX +}, + hash::{ + silo_encrypted_log_hash, silo_l2_to_l1_message, silo_note_hash, silo_nullifier, + silo_unencrypted_log_hash +}, + messaging::l2_to_l1_message::ScopedL2ToL1Message, + utils::arrays::{sort_get_split_order_hints_asc, sort_get_split_order_hints_desc, SplitOrderHints} +}; + +struct TailToPublicOutputHints { + // Note hashes. + siloed_note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_TX], + sorted_note_hash_hints: SplitOrderHints, + // Nullifiers. + siloed_nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], + sorted_nullifier_hints: SplitOrderHints, + // L2 to l1 msgs. + siloed_l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], + sorted_l2_to_l1_msg_hints: SplitOrderHints, + // Note encrypted log hashes. + note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + sorted_note_encrypted_log_hash_hints: SplitOrderHints, + // Encrypted log hashes. + siloed_encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hash_hints: SplitOrderHints, + // Unencrypted log hashes. + siloed_unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hash_hints: SplitOrderHints, + // Public call requests. + public_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], + sorted_public_call_request_hints: SplitOrderHints, +} + +unconstrained pub fn generate_tail_to_public_output_hints(previous_kernel: PrivateKernelCircuitPublicInputs) -> TailToPublicOutputHints { + let split_counter = previous_kernel.min_revertible_side_effect_counter; + + // note_hashes + let unsiloed_note_hashes = previous_kernel.end.note_hashes; + + let first_nullifier = previous_kernel.end.nullifiers[0].value(); + let mut siloed_note_hashes = [NoteHash::empty(); MAX_NOTE_HASHES_PER_TX]; + for i in 0..unsiloed_note_hashes.len() { + siloed_note_hashes[i].value = silo_note_hash(unsiloed_note_hashes[i], first_nullifier, i); + } + + let sorted_note_hash_hints = sort_get_split_order_hints_asc(unsiloed_note_hashes, split_counter); + + // nullifiers + let unsiloed_nullifiers = previous_kernel.end.nullifiers; + + let mut siloed_nullifiers = [Nullifier::empty(); MAX_NULLIFIERS_PER_TX]; + for i in 0..unsiloed_nullifiers.len() { + siloed_nullifiers[i].value = silo_nullifier(unsiloed_nullifiers[i]); + } + + let sorted_nullifier_hints = sort_get_split_order_hints_asc(unsiloed_nullifiers, split_counter); + + // l2_to_l1_msgs + let unsiloed_l2_to_l1_msgs = previous_kernel.end.l2_to_l1_msgs; + + let tx_context = previous_kernel.constants.tx_context; + let siloed_l2_to_l1_msgs = unsiloed_l2_to_l1_msgs.map( + |m: ScopedL2ToL1Message| silo_l2_to_l1_message( + m, + tx_context.version, + tx_context.chain_id, + ) + ); + + let sorted_l2_to_l1_msg_hints = sort_get_split_order_hints_asc(unsiloed_l2_to_l1_msgs, split_counter); + + // note_encrypted_logs + let note_encrypted_logs_hashes = previous_kernel.end.note_encrypted_logs_hashes.map(|h: NoteLogHash| h.expose_to_public()); + let sorted_note_encrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.note_encrypted_logs_hashes, split_counter); + + // encrypted_logs + let mut siloed_log_hashes = previous_kernel.end.encrypted_logs_hashes; + for i in 0..siloed_log_hashes.len() { + siloed_log_hashes[i].log_hash.value = silo_encrypted_log_hash(previous_kernel.end.encrypted_logs_hashes[i]); + } + let siloed_encrypted_logs_hashes = siloed_log_hashes.map(|h: ScopedEncryptedLogHash| h.expose_to_public()); + let sorted_encrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.encrypted_logs_hashes, split_counter); + + // unencrypted_logs + let mut siloed_log_hashes = previous_kernel.end.unencrypted_logs_hashes; + for i in 0..siloed_log_hashes.len() { + siloed_log_hashes[i].log_hash.value = silo_unencrypted_log_hash(previous_kernel.end.unencrypted_logs_hashes[i]); + } + let siloed_unencrypted_logs_hashes = siloed_log_hashes.map(|h: ScopedLogHash| h.inner()); + let sorted_unencrypted_log_hash_hints = sort_get_split_order_hints_asc(previous_kernel.end.unencrypted_logs_hashes, split_counter); + + // public_call_requests + // TODO: Hide the counter of a public call request. + // let public_call_requests = previous_kernel.end.public_call_stack.map(|cr: CallRequest| cr.expose_to_public()); + let public_call_requests = previous_kernel.end.public_call_stack; + let sorted_public_call_request_hints = sort_get_split_order_hints_desc(previous_kernel.end.public_call_stack, split_counter); + + TailToPublicOutputHints { + siloed_note_hashes, + sorted_note_hash_hints, + sorted_nullifier_hints, + siloed_nullifiers, + sorted_l2_to_l1_msg_hints, + siloed_l2_to_l1_msgs, + note_encrypted_logs_hashes, + sorted_note_encrypted_log_hash_hints, + siloed_encrypted_logs_hashes, + sorted_encrypted_log_hash_hints, + siloed_unencrypted_logs_hashes, + sorted_unencrypted_log_hash_hints, + public_call_requests, + sorted_public_call_request_hints + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr index 5b8b48c153ec..3a81cd1c7745 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_empty.nr @@ -10,7 +10,7 @@ struct EmptyNestedCircuitPublicInputs { impl Verifiable for EmptyNestedCircuitPublicInputs { fn verify(self) { - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), &[], 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 84b7a6dc7141..6f2cde1763f9 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 @@ -10,13 +10,12 @@ use dep::types::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, private_kernel::private_call_data::PrivateCallData }, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, transaction::tx_request::TxRequest + constants::MAX_NOTE_HASHES_PER_CALL, transaction::tx_request::TxRequest }; struct PrivateKernelInitHints { - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], - // TODO: Build the following hint in noir. - first_revertible_private_call_request_index: u32, + // TODO: Remove note_hash_nullifier_counters. + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], } // Initialization struct for private inputs to the private kernel @@ -29,7 +28,7 @@ struct PrivateKernelInitCircuitPrivateInputs { impl PrivateKernelInitCircuitPrivateInputs { unconstrained fn generate_output(self) -> PrivateKernelCircuitPublicInputs { let private_call_public_inputs = self.private_call.call_stack_item.public_inputs; - PrivateKernelCircuitPublicInputsComposer::new_from_tx_request(self.tx_request, private_call_public_inputs).compose( + PrivateKernelCircuitPublicInputsComposer::new_from_tx_request(self.tx_request, private_call_public_inputs).with_private_call( private_call_public_inputs, self.private_call.call_stack_item.contract_address, self.hints.note_hash_nullifier_counters, @@ -44,16 +43,16 @@ impl PrivateKernelInitCircuitPrivateInputs { // Validate inputs. let private_call_data_validator = PrivateCallDataValidator::new(self.private_call); - private_call_data_validator.validate_as_first_call(self.hints.first_revertible_private_call_request_index); + private_call_data_validator.validate_as_first_call(); private_call_data_validator.validate_against_tx_request(self.tx_request); - private_call_data_validator.validate(output.end.new_note_hashes); - if !dep::std::runtime::is_unconstrained() { + private_call_data_validator.validate(output.end.note_hashes); + if !std::runtime::is_unconstrained() { // verify/aggregate the private call proof self.private_call.verify(); } // Validate output. - if !dep::std::runtime::is_unconstrained() { + if !std::runtime::is_unconstrained() { PrivateKernelCircuitOutputValidator::new(output).validate_as_first_call( self.tx_request, self.private_call.call_stack_item.public_inputs, @@ -72,7 +71,7 @@ mod tests { use crate::private_kernel_init::{PrivateKernelInitHints, PrivateKernelInitCircuitPrivateInputs}; use dep::types::{ abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs}, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, + constants::MAX_NOTE_HASHES_PER_CALL, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}, transaction::tx_request::TxRequest }; @@ -87,10 +86,7 @@ mod tests { pub fn new() -> Self { let private_call = FixtureBuilder::new(); let tx_request = private_call.build_tx_request(); - let hints = PrivateKernelInitHints { - note_hash_nullifier_counters: [0; MAX_NEW_NOTE_HASHES_PER_CALL], - first_revertible_private_call_request_index: 0 - }; + let hints = PrivateKernelInitHints { note_hash_nullifier_counters: [0; MAX_NOTE_HASHES_PER_CALL] }; PrivateKernelInitInputsBuilder { tx_request, private_call, hints } } 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 1270c6d4f393..dab9e0d9e3fe 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 @@ -10,11 +10,11 @@ use dep::types::{ kernel_circuit_public_inputs::{PrivateKernelCircuitPublicInputs, PrivateKernelCircuitPublicInputsArrayLengths}, private_kernel_data::PrivateKernelData, private_kernel::private_call_data::PrivateCallData }, - constants::MAX_NEW_NOTE_HASHES_PER_CALL + constants::MAX_NOTE_HASHES_PER_CALL }; struct PrivateKernelInnerHints { - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], } struct PrivateKernelInnerCircuitPrivateInputs { @@ -25,7 +25,7 @@ struct PrivateKernelInnerCircuitPrivateInputs { impl PrivateKernelInnerCircuitPrivateInputs { unconstrained fn generate_output(self) -> PrivateKernelCircuitPublicInputs { - PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(self.previous_kernel.public_inputs).compose( + PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(self.previous_kernel.public_inputs).pop_top_call_request().with_private_call( self.private_call.call_stack_item.public_inputs, self.private_call.call_stack_item.contract_address, self.hints.note_hash_nullifier_counters, @@ -45,8 +45,8 @@ impl PrivateKernelInnerCircuitPrivateInputs { let call_request = self.previous_kernel.public_inputs.end.private_call_stack[private_call_stack_size - 1]; private_call_data_validator.validate_against_call_request(call_request); private_call_data_validator.validate_against_previous_kernel(self.previous_kernel.public_inputs); - private_call_data_validator.validate(output.end.new_note_hashes); - if !dep::std::runtime::is_unconstrained() { + private_call_data_validator.validate(output.end.note_hashes); + if !std::runtime::is_unconstrained() { // verify/aggregate the private call proof self.private_call.verify(); // verify/aggregate the previous kernel @@ -54,7 +54,7 @@ impl PrivateKernelInnerCircuitPrivateInputs { } // Validate output. - if !dep::std::runtime::is_unconstrained() { + if !std::runtime::is_unconstrained() { PrivateKernelCircuitOutputValidator::new(output).validate_as_inner_call( self.previous_kernel.public_inputs, previous_kernel_array_lengths, @@ -74,7 +74,7 @@ mod tests { use crate::private_kernel_inner::{PrivateKernelInnerCircuitPrivateInputs, PrivateKernelInnerHints}; use dep::types::{ abis::{kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs}, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, + constants::MAX_NOTE_HASHES_PER_CALL, tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq} }; @@ -88,10 +88,10 @@ mod tests { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new_from_counter(15).as_parent_contract(); let private_call = FixtureBuilder::new_from_counter(200); - let hints = PrivateKernelInnerHints { note_hash_nullifier_counters: [0; MAX_NEW_NOTE_HASHES_PER_CALL] }; + let hints = PrivateKernelInnerHints { note_hash_nullifier_counters: [0; MAX_NOTE_HASHES_PER_CALL] }; // 0th nullifier must be non-zero. - previous_kernel.append_new_nullifiers(1); + previous_kernel.append_nullifiers(1); PrivateKernelInnerInputsBuilder { previous_kernel, private_call, hints } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr index e9179e7ce8d7..36bde997f1ef 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_reset.nr @@ -8,7 +8,7 @@ use dep::types::{ note_hash::ScopedNoteHash, nullifier::ScopedNullifier, log_hash::NoteLogHash }, constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, @@ -18,14 +18,14 @@ use dep::types::{ // Can just be KernelCircuitPublicInputs. struct PrivateKernelResetOutputs { - note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], } struct PrivateKernelResetHints { - transient_nullifier_indexes_for_note_hashes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [u32; MAX_NEW_NULLIFIERS_PER_TX], + transient_nullifier_indexes_for_note_hashes: [u32; MAX_NOTE_HASHES_PER_TX], + transient_note_hash_indexes_for_nullifiers: [u32; MAX_NULLIFIERS_PER_TX], transient_note_hash_indexes_for_logs: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints: NoteHashReadRequestHints, nullifier_read_request_hints: NullifierReadRequestHints, @@ -48,17 +48,17 @@ impl Self { let mut previous_kernel = FixtureBuilder::new(); - previous_kernel.append_new_nullifiers(1); + previous_kernel.append_nullifiers(1); PrivateKernelResetInputsBuilder { previous_kernel, - transient_nullifier_indexes_for_note_hashes: [MAX_NEW_NULLIFIERS_PER_TX; MAX_NEW_NOTE_HASHES_PER_TX], - transient_note_hash_indexes_for_nullifiers: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_indexes_for_logs: [MAX_NEW_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], + transient_nullifier_indexes_for_note_hashes: [MAX_NULLIFIERS_PER_TX; MAX_NOTE_HASHES_PER_TX], + transient_note_hash_indexes_for_nullifiers: [MAX_NOTE_HASHES_PER_TX; MAX_NULLIFIERS_PER_TX], + transient_note_hash_indexes_for_logs: [MAX_NOTE_HASHES_PER_TX; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], note_hash_read_request_hints_builder: NoteHashReadRequestHintsBuilder::new(MAX_NOTE_HASH_READ_REQUESTS_PER_TX), nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX) } @@ -146,9 +146,9 @@ mod tests { } pub fn nullify_pending_note_hash(&mut self, nullifier_index: u32, note_hash_index: u32) { - let note_hash = self.previous_kernel.new_note_hashes.get(note_hash_index).note_hash; - self.previous_kernel.new_note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.new_nullifiers.get(nullifier_index).counter(); - self.previous_kernel.new_nullifiers.storage[nullifier_index].nullifier.note_hash = note_hash.value; + let note_hash = self.previous_kernel.note_hashes.get(note_hash_index).note_hash; + self.previous_kernel.note_hashes.storage[note_hash_index].nullifier_counter = self.previous_kernel.nullifiers.get(nullifier_index).counter(); + self.previous_kernel.nullifiers.storage[nullifier_index].nullifier.note_hash = note_hash.value; self.transient_nullifier_indexes_for_note_hashes[note_hash_index] = nullifier_index; self.transient_note_hash_indexes_for_nullifiers[nullifier_index] = note_hash_index; for i in 0..self.previous_kernel.note_encrypted_logs_hashes.len() { @@ -162,11 +162,11 @@ mod tests { pub fn execute(&mut self) -> PrivateKernelCircuitPublicInputs { let outputs = PrivateKernelResetOutputs { - note_hashes: squash_transient_note_hashes(self.previous_kernel.new_note_hashes.storage), - nullifiers: squash_transient_nullifiers(self.previous_kernel.new_nullifiers.storage), + note_hashes: squash_transient_note_hashes(self.previous_kernel.note_hashes.storage), + nullifiers: squash_transient_nullifiers(self.previous_kernel.nullifiers.storage), note_encrypted_log_hashes: squash_transient_logs( self.previous_kernel.note_encrypted_logs_hashes.storage, - self.previous_kernel.new_note_hashes.storage + self.previous_kernel.note_hashes.storage ) }; @@ -211,7 +211,7 @@ mod tests { unconstrained fn two_pending_note_hash_read_request() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_note_hashes(3); builder.add_pending_note_hash_read_request(1); builder.add_pending_note_hash_read_request(0); @@ -222,7 +222,7 @@ mod tests { unconstrained fn pending_note_hash_read_request_wrong_hint_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_note_hashes(3); builder.add_pending_note_hash_read_request(1); let mut hint = builder.note_hash_read_request_hints_builder.pending_read_hints.pop(); hint.pending_value_index = 2; @@ -235,7 +235,7 @@ mod tests { unconstrained fn one_pending_nullifier_read_request() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); builder.add_pending_nullifier_read_request(1); builder.succeeded(); @@ -245,7 +245,7 @@ mod tests { unconstrained fn two_pending_nullifier_read_requests() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); builder.add_pending_nullifier_read_request(1); builder.add_pending_nullifier_read_request(0); @@ -256,7 +256,7 @@ mod tests { unconstrained fn pending_nullifier_read_request_wrong_hint_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); builder.add_pending_nullifier_read_request(1); let mut hint = builder.nullifier_read_request_hints_builder.pending_read_hints.pop(); assert(hint.pending_value_index == 2); @@ -270,9 +270,9 @@ mod tests { unconstrained fn pending_nullifier_read_request_reads_before_value_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); builder.add_pending_nullifier_read_request(1); - let nullifier_being_read = builder.previous_kernel.new_nullifiers.storage[2]; + let nullifier_being_read = builder.previous_kernel.nullifiers.storage[2]; let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); @@ -284,8 +284,8 @@ mod tests { unconstrained fn propagates_unverified_requests() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_note_hashes(3); + builder.previous_kernel.append_nullifiers(3); builder.add_pending_note_hash_read_request(0); builder.add_pending_nullifier_read_request(1); @@ -311,73 +311,58 @@ mod tests { #[test] unconstrained fn native_squash_one_of_one_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes_with_logs(1); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_note_hashes_with_logs(1); + builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); - let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage; let public_inputs = builder.execute(); - assert(is_empty_array(public_inputs.end.new_note_hashes)); + assert(is_empty_array(public_inputs.end.note_hashes)); // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0], new_nullifiers[2]] - ) - ); + assert(array_eq(public_inputs.end.nullifiers, [nullifiers[0], nullifiers[2]])); assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } #[test] unconstrained fn native_squash_one_of_two_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes_with_logs(2); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_note_hashes_with_logs(2); + builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); - let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; - let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; - let new_note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; + let note_hashes = builder.previous_kernel.note_hashes.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage; + let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; let public_inputs = builder.execute(); // The 0th hash is chopped. - assert(array_eq(public_inputs.end.new_note_hashes, [new_note_hashes[1]])); + assert(array_eq(public_inputs.end.note_hashes, [note_hashes[1]])); // The nullifier at index 1 is chopped. - assert( - array_eq( - public_inputs.end.new_nullifiers, - [new_nullifiers[0], new_nullifiers[2]] - ) - ); + assert(array_eq(public_inputs.end.nullifiers, [nullifiers[0], nullifiers[2]])); // The 0th note log is chopped. - assert( - array_eq( - public_inputs.end.note_encrypted_logs_hashes, - [new_note_logs[1]] - ) - ); + assert(array_eq(public_inputs.end.note_encrypted_logs_hashes, [note_logs[1]])); } #[test] unconstrained fn native_squash_two_of_two_transient_matches_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes_with_logs(2); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_note_hashes_with_logs(2); + builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 1; builder.nullify_pending_note_hash(1, 1); // The nullifier at index 2 is nullifying the hash at index 0; builder.nullify_pending_note_hash(2, 0); - let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage; let public_inputs = builder.execute(); - assert(is_empty_array(public_inputs.end.new_note_hashes)); + assert(is_empty_array(public_inputs.end.note_hashes)); // Only the first nullifier is left after squashing. - assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0]])); + assert(array_eq(public_inputs.end.nullifiers, [nullifiers[0]])); assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } @@ -385,19 +370,19 @@ mod tests { unconstrained fn squash_unordered_transient_notes_works() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes_with_logs(3); + builder.previous_kernel.append_note_hashes_with_logs(3); // Shuffle the note hashes so they will have to be re-ordered. - let tmp = builder.previous_kernel.new_note_hashes.storage[0]; - builder.previous_kernel.new_note_hashes.storage[0] = builder.previous_kernel.new_note_hashes.storage[1]; - builder.previous_kernel.new_note_hashes.storage[1] = builder.previous_kernel.new_note_hashes.storage[2]; - builder.previous_kernel.new_note_hashes.storage[2] = tmp; + let tmp = builder.previous_kernel.note_hashes.storage[0]; + builder.previous_kernel.note_hashes.storage[0] = builder.previous_kernel.note_hashes.storage[1]; + builder.previous_kernel.note_hashes.storage[1] = builder.previous_kernel.note_hashes.storage[2]; + builder.previous_kernel.note_hashes.storage[2] = tmp; - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); // Shuffle the nullifers so they will have to be re-ordered. - let tmp = builder.previous_kernel.new_nullifiers.storage[1]; - builder.previous_kernel.new_nullifiers.storage[1] = builder.previous_kernel.new_nullifiers.storage[3]; - builder.previous_kernel.new_nullifiers.storage[3] = builder.previous_kernel.new_nullifiers.storage[2]; - builder.previous_kernel.new_nullifiers.storage[2] = tmp; + let tmp = builder.previous_kernel.nullifiers.storage[1]; + builder.previous_kernel.nullifiers.storage[1] = builder.previous_kernel.nullifiers.storage[3]; + builder.previous_kernel.nullifiers.storage[3] = builder.previous_kernel.nullifiers.storage[2]; + builder.previous_kernel.nullifiers.storage[2] = tmp; // The nullifier at index 1 is nullifying the note hash at index 1; builder.nullify_pending_note_hash(1, 1); @@ -406,21 +391,21 @@ mod tests { // The nullifier at index 3 is nullifying the note hash at index 0; builder.nullify_pending_note_hash(3, 0); - let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage; let public_inputs = builder.execute(); - assert(is_empty_array(public_inputs.end.new_note_hashes)); + assert(is_empty_array(public_inputs.end.note_hashes)); // Only the first nullifier is left after squashing. - assert(array_eq(public_inputs.end.new_nullifiers, [new_nullifiers[0]])); + assert(array_eq(public_inputs.end.nullifiers, [nullifiers[0]])); assert(is_empty_array(public_inputs.end.note_encrypted_logs_hashes)); } #[test(should_fail_with="Value of the hinted transient note hash does not match")] unconstrained fn wrong_transient_nullifier_index_for_note_hash_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(1); - builder.previous_kernel.append_new_nullifiers(1); + builder.previous_kernel.append_note_hashes(1); + builder.previous_kernel.append_nullifiers(1); // The nullifier at index 1 is nullifying the hash at index 0; builder.nullify_pending_note_hash(1, 0); // Change the hint to be out of bounds. @@ -431,8 +416,8 @@ mod tests { #[test(should_fail_with="Invalid transient nullifier index hint")] unconstrained fn wrong_transient_nullifier_index_hint_fails() { let mut builder = PrivateKernelResetInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_note_hashes(2); + builder.previous_kernel.append_nullifiers(2); // The nullifier at index 1 is nullifying the hash at index 1; builder.nullify_pending_note_hash(1, 1); // The nullifier at index 2 is nullifying the hash at index 0; 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 67d88eed6fdf..f21f036f67e9 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 @@ -1,56 +1,16 @@ use crate::components::{ - kernel_circuit_public_inputs_composer::KernelCircuitPublicInputsComposer, - kernel_circuit_output_hints::generate_hints, - kernel_circuit_output_validator::KernelCircuitOutputValidator, - previous_kernel_validator::PreviousKernelValidator + previous_kernel_validator::PreviousKernelValidator, tail_output_composer::TailOutputComposer, + tail_output_validator::TailOutputValidator }; -use dep::types::{ - abis::{ - private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, - note_hash::ScopedNoteHash, nullifier::ScopedNullifier, - log_hash::{NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash} -}, - constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX -} -}; - -// TODO: Build hints in noir. -struct PrivateKernelTailHints { - sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], - sorted_new_nullifiers_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], - sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_note_encrypted_log_hashes_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX], -} +use dep::types::{abis::{private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::KernelCircuitPublicInputs}}; struct PrivateKernelTailCircuitPrivateInputs { previous_kernel: PrivateKernelData, - hints: PrivateKernelTailHints, } impl PrivateKernelTailCircuitPrivateInputs { unconstrained fn generate_output(self) -> KernelCircuitPublicInputs { - KernelCircuitPublicInputsComposer::new( - self.previous_kernel, - self.hints.sorted_new_note_hashes, - self.hints.sorted_new_note_hashes_indexes, - self.hints.sorted_new_nullifiers, - self.hints.sorted_new_nullifiers_indexes, - self.hints.sorted_note_encrypted_log_hashes, - self.hints.sorted_note_encrypted_log_hashes_indexes, - self.hints.sorted_encrypted_log_hashes, - self.hints.sorted_encrypted_log_hashes_indexes, - self.hints.sorted_unencrypted_log_hashes, - self.hints.sorted_unencrypted_log_hashes_indexes - ).compose().finish() + TailOutputComposer::new(self.previous_kernel.public_inputs).finish() } pub fn execute(self) -> KernelCircuitPublicInputs { @@ -59,50 +19,38 @@ impl PrivateKernelTailCircuitPrivateInputs { // Validate inputs. PreviousKernelValidator::new(self.previous_kernel.public_inputs).validate_for_private_tail(); - if !dep::std::runtime::is_unconstrained() { + if !std::runtime::is_unconstrained() { // verify/aggregate the previous kernel self.previous_kernel.verify(); } // Validate output. - if !dep::std::runtime::is_unconstrained() { - let hints = generate_hints(self.previous_kernel.public_inputs); - KernelCircuitOutputValidator::new(output, self.previous_kernel.public_inputs).validate(hints); + if !std::runtime::is_unconstrained() { + TailOutputValidator::new(output, self.previous_kernel.public_inputs).validate(); } + output } } mod tests { - use crate::private_kernel_tail::{PrivateKernelTailCircuitPrivateInputs, PrivateKernelTailHints}; - use dep::reset_kernel_lib::{ - tests::{ - note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder, - nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} - }, - reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} - }; + use crate::private_kernel_tail::PrivateKernelTailCircuitPrivateInputs; use dep::types::constants::{ - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, GENERATOR_INDEX__IVSK_M + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, + GENERATOR_INDEX__IVSK_M }; use dep::types::{ abis::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, max_block_number::MaxBlockNumber, - note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - log_hash::{NoteLogHash, ScopedLogHash, ScopedEncryptedLogHash}, gas::Gas + note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, gas::Gas }, address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, hash::{ sha256_to_field, silo_note_hash, silo_nullifier, compute_siloed_encrypted_log_hash, compute_siloed_unencrypted_log_hash }, - tests::{fixture_builder::FixtureBuilder, sort::sort_get_sorted_hints}, - utils::{arrays::array_length}, traits::{Empty, is_empty, is_empty_array}, - grumpkin_point::GrumpkinPoint + tests::fixture_builder::FixtureBuilder, utils::{arrays::array_length}, + traits::{Empty, is_empty}, grumpkin_point::GrumpkinPoint }; // TODO: Reduce the duplicated code/tests for PrivateKernelTailInputs and PrivateKernelTailToPublicInputs. @@ -114,8 +62,7 @@ mod tests { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new(); previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1_000_000, 1_000_000); - - previous_kernel.append_new_nullifiers(1); + previous_kernel.set_first_nullifier(); PrivateKernelTailInputsBuilder { previous_kernel } } @@ -123,10 +70,11 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. pub fn compute_output_note_hashes(self, note_hashes: [ScopedNoteHash; N]) -> [Field; N] { - let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0).value(); + // First nullifier is tx hash. + let tx_hash = self.previous_kernel.nullifiers.get_unchecked(0).value(); let mut output = [0; N]; for i in 0..N { - output[i] = silo_note_hash(note_hashes[i], first_nullifier, i); + output[i] = silo_note_hash(note_hashes[i], tx_hash, i); } output } @@ -141,55 +89,7 @@ mod tests { } pub fn execute(&mut self) -> KernelCircuitPublicInputs { - let sorted = sort_get_sorted_hints( - self.previous_kernel.new_note_hashes.storage, - |a: ScopedNoteHash, b: ScopedNoteHash| a.counter() < b.counter() - ); - let sorted_new_note_hashes = sorted.sorted_array; - let sorted_new_note_hashes_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.new_nullifiers.storage, - |a: ScopedNullifier, b: ScopedNullifier| a.counter() < b.counter() - ); - let sorted_new_nullifiers = sorted.sorted_array; - let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.note_encrypted_logs_hashes.storage, - |a: NoteLogHash, b: NoteLogHash| a.counter < b.counter - ); - let sorted_note_encrypted_log_hashes = sorted.sorted_array; - let sorted_note_encrypted_log_hashes_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.encrypted_logs_hashes.storage, - |a: ScopedEncryptedLogHash, b: ScopedEncryptedLogHash| 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: ScopedLogHash, b: ScopedLogHash| a.counter() < b.counter() - ); - let sorted_unencrypted_log_hashes = sorted.sorted_array; - let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; - - let hints = PrivateKernelTailHints { - sorted_new_note_hashes, - sorted_new_note_hashes_indexes, - sorted_new_nullifiers, - sorted_new_nullifiers_indexes, - sorted_note_encrypted_log_hashes, - sorted_note_encrypted_log_hashes_indexes, - sorted_encrypted_log_hashes, - sorted_encrypted_log_hashes_indexes, - sorted_unencrypted_log_hashes, - sorted_unencrypted_log_hashes_indexes - }; - - let kernel = PrivateKernelTailCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), hints }; + let kernel = PrivateKernelTailCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data() }; kernel.execute() } @@ -203,7 +103,7 @@ mod tests { } #[test] - unconstrained fn execution_succeeded() { + fn execution_succeeded() { let mut builder = PrivateKernelTailInputsBuilder::new(); let public_inputs = builder.execute(); @@ -211,7 +111,7 @@ mod tests { } #[test] - unconstrained fn propagate_previous_kernel_max_block_number() { + fn propagate_previous_kernel_max_block_number() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.max_block_number = MaxBlockNumber::new(13); let public_inputs = builder.execute(); @@ -220,7 +120,7 @@ mod tests { } #[test] - unconstrained fn logs_are_handled_as_expected() { + fn logs_are_handled_as_expected() { let mut builder = PrivateKernelTailInputsBuilder::new(); // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; @@ -277,8 +177,15 @@ mod tests { assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); } + unconstrained fn compute_hash_bytes( + siloed_encrypted_logs_hash: Field, + new_siloed_encrypted_logs_hash: Field + ) -> [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] { + siloed_encrypted_logs_hash.to_be_bytes(32).append(new_siloed_encrypted_logs_hash.to_be_bytes(32)).append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 64]).as_array() + } + #[test] - unconstrained fn encrypted_logs_are_hashed_as_expected() { + fn encrypted_logs_are_hashed_as_expected() { let mut builder = PrivateKernelTailInputsBuilder::new(); // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; @@ -312,105 +219,101 @@ mod tests { builder.previous_kernel.encrypted_logs_hashes.storage[1].log_hash.randomness, new_encrypted_logs_hash ); - // noir-fmt:ignore - let hash_bytes: [u8; MAX_ENCRYPTED_LOGS_PER_TX * 32] = siloed_encrypted_logs_hash - .to_be_bytes(32) - .append(new_siloed_encrypted_logs_hash.to_be_bytes(32)) - .append(&[0; MAX_ENCRYPTED_LOGS_PER_TX * 32 - 64]) - .as_array(); + + let hash_bytes = compute_hash_bytes(siloed_encrypted_logs_hash, new_siloed_encrypted_logs_hash); let expected_encrypted_logs_hash = sha256_to_field(hash_bytes); assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); } #[test] - unconstrained fn ordering_of_note_hashes_and_nullifiers() { + fn ordering_of_note_hashes_and_nullifiers() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(10); - builder.previous_kernel.append_new_nullifiers(10); + builder.previous_kernel.append_note_hashes(10); + builder.previous_kernel.append_nullifiers(10); - let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; - let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let sorted_note_hashes = builder.previous_kernel.note_hashes.storage; + let sorted_nullifiers = builder.previous_kernel.nullifiers.storage; let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; let mut reversed_nullifiers = [ScopedNullifier::empty(); 10]; for i in 0..10 { - reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); - reversed_nullifiers[9 - i] = builder.previous_kernel.new_nullifiers.pop(); + reversed_note_hashes[9 - i] = builder.previous_kernel.note_hashes.pop(); + reversed_nullifiers[9 - i] = builder.previous_kernel.nullifiers.pop(); } - builder.previous_kernel.new_note_hashes.extend_from_array(reversed_note_hashes); - builder.previous_kernel.new_nullifiers.extend_from_array(reversed_nullifiers); + builder.previous_kernel.note_hashes.extend_from_array(reversed_note_hashes); + builder.previous_kernel.nullifiers.extend_from_array(reversed_nullifiers); let public_inputs = builder.execute(); let expected_note_hashes = builder.compute_output_note_hashes(sorted_note_hashes); let expected_nullifiers = builder.compute_output_nullifiers(sorted_nullifiers); for i in 0..10 { - assert(public_inputs.end.new_note_hashes[i].eq(expected_note_hashes[i])); - assert(public_inputs.end.new_nullifiers[i].eq(expected_nullifiers[i])); + assert(public_inputs.end.note_hashes[i].eq(expected_note_hashes[i])); + assert(public_inputs.end.nullifiers[i].eq(expected_nullifiers[i])); } } #[test] - unconstrained fn native_empty_nullified_note_hash_means_persistent_nullifier_0() { + fn native_empty_nullified_note_hash_means_persistent_nullifier_0() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_note_hashes(2); + builder.previous_kernel.append_nullifiers(2); let public_inputs = builder.execute(); - assert_eq(array_length(public_inputs.end.new_note_hashes), 2); - assert_eq(array_length(public_inputs.end.new_nullifiers), 3); + assert_eq(array_length(public_inputs.end.note_hashes), 2); + assert_eq(array_length(public_inputs.end.nullifiers), 3); let expected_gas = Gas::tx_overhead() + Gas::new(DA_GAS_PER_BYTE * DA_BYTES_PER_FIELD * 5, 0); assert_eq(public_inputs.end.gas_used, expected_gas); } #[test(should_fail_with="Private call stack must be empty when executing the tail circuit")] - unconstrained fn non_empty_private_call_stack_should_fail() { + fn non_empty_private_call_stack_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.add_private_call_request(1, false); builder.failed(); } #[test(should_fail_with="Public call stack must be empty when executing the tail circuit")] - unconstrained fn non_empty_public_call_stack_should_fail() { + fn non_empty_public_call_stack_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.push_public_call_request(1, false); builder.failed(); } #[test(should_fail_with="Public teardown call request must be empty when executing the tail circuit")] - unconstrained fn non_empty_public_teardown_call_request_should_fail() { + fn non_empty_public_teardown_call_request_should_fail() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.push_public_teardown_call_request(1, false); builder.failed(); } #[test(should_fail_with="Non empty note hash read requests")] - unconstrained fn non_empty_note_hash_read_requests() { + fn non_empty_note_hash_read_requests() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_note_hashes(3); let _void = builder.previous_kernel.add_read_request_for_pending_note_hash(1); builder.failed(); } #[test(should_fail_with="Non empty nullifier read requests")] - unconstrained fn non_empty_nullifier_read_requests() { + fn non_empty_nullifier_read_requests() { let mut builder = PrivateKernelTailInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); let _void = builder.previous_kernel.add_read_request_for_pending_nullifier(1); builder.failed(); } #[test(should_fail_with="Non empty key validation requests")] - unconstrained fn non_empty_key_validations() { + fn non_empty_key_validations() { let mut builder = PrivateKernelTailInputsBuilder::new(); let _void = builder.previous_kernel.add_request_for_key_validation(GrumpkinPoint::new(1, 2), 27, GENERATOR_INDEX__IVSK_M); builder.failed(); } #[test] - unconstrained fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { + fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); let public_inputs = builder.execute(); @@ -426,7 +329,7 @@ mod tests { } #[test(should_fail_with="The gas used exceeds the gas limits")] - unconstrained fn gas_limits_are_enforced() { + fn gas_limits_are_enforced() { let mut builder = PrivateKernelTailInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1, 1); @@ -434,7 +337,7 @@ mod tests { } #[test] - unconstrained fn propagate_fee_payer() { + fn propagate_fee_payer() { // Check that we carry forward if the fee payer is already set let mut builder = PrivateKernelTailInputsBuilder::new(); let fee_payer = AztecAddress::from_field(123); 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 442031e11f2c..3f00cfe49746 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 @@ -1,94 +1,50 @@ use crate::components::{ - kernel_circuit_public_inputs_composer::KernelCircuitPublicInputsComposer, - previous_kernel_validator::PreviousKernelValidator + previous_kernel_validator::PreviousKernelValidator, + tail_to_public_output_composer::TailToPublicOutputComposer, + tail_to_public_output_validator::TailToPublicOutputValidator }; -use dep::types::{ - abis::{ - private_kernel_data::PrivateKernelData, - kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, note_hash::ScopedNoteHash, - nullifier::ScopedNullifier, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, - call_request::CallRequest -}, - constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX -} -}; - -struct PrivateKernelTailToPublicHints { - sorted_new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], - sorted_new_nullifiers_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], - sorted_note_encrypted_log_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_note_encrypted_log_hashes_indexes: [u32; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_encrypted_log_hashes_indexes: [u32; MAX_ENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes: [ScopedLogHash; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_unencrypted_log_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX], - sorted_call_requests: [CallRequest; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], - sorted_call_requests_indexes: [u32; MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX], -} +use dep::types::{abis::{private_kernel_data::PrivateKernelData, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}}; struct PrivateKernelTailToPublicCircuitPrivateInputs { previous_kernel: PrivateKernelData, - hints: PrivateKernelTailToPublicHints, } impl PrivateKernelTailToPublicCircuitPrivateInputs { + unconstrained fn generate_output(self) -> PublicKernelCircuitPublicInputs { + TailToPublicOutputComposer::new(self.previous_kernel.public_inputs).finish() + } + pub fn execute(self) -> PublicKernelCircuitPublicInputs { + // Generate output. + let output = self.generate_output(); + // Validate inputs. PreviousKernelValidator::new(self.previous_kernel.public_inputs).validate_for_private_tail_to_public(); - if !dep::std::runtime::is_unconstrained() { + if !std::runtime::is_unconstrained() { // verify/aggregate the previous kernel self.previous_kernel.verify(); } - KernelCircuitPublicInputsComposer::new( - self.previous_kernel, - self.hints.sorted_new_note_hashes, - self.hints.sorted_new_note_hashes_indexes, - self.hints.sorted_new_nullifiers, - self.hints.sorted_new_nullifiers_indexes, - self.hints.sorted_note_encrypted_log_hashes, - self.hints.sorted_note_encrypted_log_hashes_indexes, - self.hints.sorted_encrypted_log_hashes, - self.hints.sorted_encrypted_log_hashes_indexes, - self.hints.sorted_unencrypted_log_hashes, - self.hints.sorted_unencrypted_log_hashes_indexes - ).compose_public( - self.hints.sorted_call_requests, - self.hints.sorted_call_requests_indexes - ).finish_to_public() + // Validate output. + if !dep::std::runtime::is_unconstrained() { + TailToPublicOutputValidator::new(output, self.previous_kernel.public_inputs).validate(); + } + + output } } mod tests { - use crate::private_kernel_tail_to_public::{PrivateKernelTailToPublicCircuitPrivateInputs, PrivateKernelTailToPublicHints}; - use dep::reset_kernel_lib::{ - tests::{ - note_hash_read_request_hints_builder::NoteHashReadRequestHintsBuilder, - nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - squash_transient_data::{squash_transient_note_hashes, squash_transient_nullifiers, squash_transient_logs} - }, - 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, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, DA_BYTES_PER_FIELD, - DA_GAS_PER_BYTE, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, GENERATOR_INDEX__TSK_M - }; + use crate::private_kernel_tail_to_public::PrivateKernelTailToPublicCircuitPrivateInputs; + use dep::types::constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, GENERATOR_INDEX__TSK_M}; use dep::types::{ abis::{ - call_request::CallRequest, side_effect::Ordered, kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, gas::Gas, note_hash::{NoteHash, ScopedNoteHash}, nullifier::{Nullifier, ScopedNullifier}, - log_hash::{LogHash, ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash} + log_hash::{LogHash, NoteLogHash} }, address::AztecAddress, hash::{silo_note_hash, silo_nullifier}, - tests::{fixture_builder::FixtureBuilder, sort::sort_get_sorted_hints}, - utils::{arrays::{array_eq, array_length}}, traits::is_empty_array, grumpkin_point::GrumpkinPoint + tests::fixture_builder::FixtureBuilder, utils::{arrays::array_eq}, grumpkin_point::GrumpkinPoint }; // TODO: Reduce the duplicated code/tests for PrivateKernelTailToPublicInputs and PrivateKernelTailInputs. @@ -100,7 +56,7 @@ mod tests { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new(); previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1_000_000, 1_000_000); - previous_kernel.append_new_nullifiers(1); + previous_kernel.set_first_nullifier(); previous_kernel.push_public_call_request(1, false); PrivateKernelTailToPublicInputsBuilder { previous_kernel } @@ -109,11 +65,12 @@ mod tests { // A helper function that uses the first nullifer in the previous kernel to compute the unique siloed // note_hashes for the given note_hashes. pub fn compute_output_note_hashes(self, note_hashes: [ScopedNoteHash; N]) -> [NoteHash; N] { - let first_nullifier = self.previous_kernel.new_nullifiers.get_unchecked(0).value(); + // First nullifier is tx hash. + let tx_hash = self.previous_kernel.nullifiers.get_unchecked(0).value(); let mut output = [NoteHash::empty(); N]; for i in 0..N { output[i] = NoteHash { - value: silo_note_hash(note_hashes[i], first_nullifier, i), + value: silo_note_hash(note_hashes[i], tx_hash, i), counter: 0, // Counter is cleared so it's not exposed to the public. }; } @@ -140,64 +97,7 @@ mod tests { } pub fn execute(&mut self) -> PublicKernelCircuitPublicInputs { - let sorted = sort_get_sorted_hints( - self.previous_kernel.new_note_hashes.storage, - |a: ScopedNoteHash, b: ScopedNoteHash| a.counter() < b.counter() - ); - let sorted_new_note_hashes = sorted.sorted_array; - let sorted_new_note_hashes_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.new_nullifiers.storage, - |a: ScopedNullifier, b: ScopedNullifier| a.counter() < b.counter() - ); - let sorted_new_nullifiers = sorted.sorted_array; - let sorted_new_nullifiers_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.note_encrypted_logs_hashes.storage, - |a: NoteLogHash, b: NoteLogHash| a.counter < b.counter - ); - let sorted_note_encrypted_log_hashes = sorted.sorted_array; - let sorted_note_encrypted_log_hashes_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.encrypted_logs_hashes.storage, - |a: ScopedEncryptedLogHash, b: ScopedEncryptedLogHash| 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: ScopedLogHash, b: ScopedLogHash| a.counter() < b.counter() - ); - let sorted_unencrypted_log_hashes = sorted.sorted_array; - let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; - - let sorted = sort_get_sorted_hints( - self.previous_kernel.public_call_requests.storage, - |a: CallRequest, b: CallRequest| a.counter() > b.counter() - ); - let sorted_call_requests = sorted.sorted_array; - let sorted_call_requests_indexes = sorted.sorted_index_hints; - - let hints = PrivateKernelTailToPublicHints { - sorted_new_note_hashes, - sorted_new_note_hashes_indexes, - sorted_new_nullifiers, - sorted_new_nullifiers_indexes, - sorted_note_encrypted_log_hashes, - sorted_note_encrypted_log_hashes_indexes, - sorted_encrypted_log_hashes, - sorted_encrypted_log_hashes_indexes, - sorted_unencrypted_log_hashes, - sorted_unencrypted_log_hashes_indexes, - sorted_call_requests, - sorted_call_requests_indexes - }; - - let kernel = PrivateKernelTailToPublicCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), hints }; + let kernel = PrivateKernelTailToPublicCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data() }; kernel.execute() } @@ -211,52 +111,54 @@ mod tests { } #[test] - unconstrained fn ordering_of_note_hashes_and_nullifiers() { + fn ordering_of_note_hashes_and_nullifiers() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(10); - builder.previous_kernel.append_new_nullifiers(10); + builder.previous_kernel.append_note_hashes(10); + builder.previous_kernel.append_nullifiers(10); - let sorted_note_hashes = builder.previous_kernel.new_note_hashes.storage; - let sorted_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let sorted_note_hashes = builder.previous_kernel.note_hashes.storage; + let sorted_nullifiers = builder.previous_kernel.nullifiers.storage; let mut reversed_note_hashes = [ScopedNoteHash::empty(); 10]; let mut reversed_nullifiers = [ScopedNullifier::empty(); 10]; for i in 0..10 { - reversed_note_hashes[9 - i] = builder.previous_kernel.new_note_hashes.pop(); - reversed_nullifiers[9 - i] = builder.previous_kernel.new_nullifiers.pop(); + reversed_note_hashes[9 - i] = builder.previous_kernel.note_hashes.pop(); + reversed_nullifiers[9 - i] = builder.previous_kernel.nullifiers.pop(); } - builder.previous_kernel.new_note_hashes.extend_from_array(reversed_note_hashes); - builder.previous_kernel.new_nullifiers.extend_from_array(reversed_nullifiers); + builder.previous_kernel.note_hashes.extend_from_array(reversed_note_hashes); + builder.previous_kernel.nullifiers.extend_from_array(reversed_nullifiers); let public_inputs = builder.execute(); + let first_nullifier = builder.previous_kernel.nullifiers.get(0); + assert_eq(public_inputs.end_non_revertible.nullifiers[0], first_nullifier.nullifier); let output_note_hashes = builder.compute_output_note_hashes(sorted_note_hashes); let output_nullifiers = builder.compute_output_nullifiers(sorted_nullifiers); for i in 0..10 { - assert(public_inputs.end.new_note_hashes[i].eq(output_note_hashes[i])); - assert(public_inputs.end.new_nullifiers[i].eq(output_nullifiers[i])); + assert(public_inputs.end.note_hashes[i].eq(output_note_hashes[i])); + assert(public_inputs.end.nullifiers[i].eq(output_nullifiers[i + 1])); } } #[test(should_fail_with="Private call stack must be empty when executing the tail circuit")] - unconstrained fn non_empty_private_call_stack_should_fail() { + fn non_empty_private_call_stack_should_fail() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.add_private_call_request(1, false); builder.failed(); } #[test(should_fail_with="Must have public calls when exporting public kernel data from the tail circuit")] - unconstrained fn no_public_calls_should_fail() { + fn no_public_calls_should_fail() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.public_call_requests = BoundedVec::new(); builder.failed(); } #[test] - unconstrained fn can_run_with_only_teardown() { + fn can_run_with_only_teardown() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.public_call_requests = BoundedVec::new(); builder.previous_kernel.push_public_teardown_call_request(1, false); @@ -265,30 +167,30 @@ mod tests { } #[test] - unconstrained fn split_nullifiers_into_non_revertible() { + fn split_nullifiers_into_non_revertible() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); // expect 3 non-revertible nullifiers: the tx nullifier + 2 new ones - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_nullifiers(2); builder.previous_kernel.end_setup(); // expect 2 revertible nullifiers - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_nullifiers(2); - let new_nullifiers = builder.previous_kernel.new_nullifiers.storage; + let nullifiers = builder.previous_kernel.nullifiers.storage; let public_inputs = builder.execute(); - let output_nullifiers = builder.compute_output_nullifiers(new_nullifiers); + let output_nullifiers = builder.compute_output_nullifiers(nullifiers); assert( array_eq( - public_inputs.end_non_revertible.new_nullifiers, + public_inputs.end_non_revertible.nullifiers, [output_nullifiers[0], output_nullifiers[1], output_nullifiers[2]] ) ); assert( array_eq( - public_inputs.end.new_nullifiers, + public_inputs.end.nullifiers, [output_nullifiers[3], output_nullifiers[4]] ) ); @@ -300,26 +202,26 @@ mod tests { } #[test] - unconstrained fn split_note_hashes_into_non_revertible() { + fn split_note_hashes_into_non_revertible() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); // expect 2 non-revertible note hashes - builder.previous_kernel.append_new_note_hashes_with_logs(2); + builder.previous_kernel.append_note_hashes_with_logs(2); builder.previous_kernel.end_setup(); // expect 2 revertible note hashes - builder.previous_kernel.append_new_note_hashes_with_logs(2); + builder.previous_kernel.append_note_hashes_with_logs(2); - let new_note_hashes = builder.previous_kernel.new_note_hashes.storage; - let new_note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; + let note_hashes = builder.previous_kernel.note_hashes.storage; + let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; let public_inputs = builder.execute(); - let siloed_note_hashes = builder.compute_output_note_hashes(new_note_hashes); - let public_note_logs = builder.compute_output_note_logs(new_note_logs); + let siloed_note_hashes = builder.compute_output_note_hashes(note_hashes); + let public_note_logs = builder.compute_output_note_logs(note_logs); assert( array_eq( - public_inputs.end_non_revertible.new_note_hashes, + public_inputs.end_non_revertible.note_hashes, [siloed_note_hashes[0], siloed_note_hashes[1]] ) ); @@ -333,7 +235,7 @@ mod tests { assert( array_eq( - public_inputs.end.new_note_hashes, + public_inputs.end.note_hashes, [siloed_note_hashes[2], siloed_note_hashes[3]] ) ); @@ -345,8 +247,8 @@ mod tests { ) ); - let revertible_logs_len = (new_note_logs[2].length + new_note_logs[3].length) as u32; - let non_revertible_logs_len = (new_note_logs[0].length + new_note_logs[1].length) as u32; + let revertible_logs_len = (note_logs[2].length + note_logs[3].length) as u32; + let non_revertible_logs_len = (note_logs[0].length + note_logs[1].length) as u32; assert_eq( public_inputs.end.gas_used, Gas::new( @@ -364,40 +266,43 @@ mod tests { } #[test(should_fail_with="Non empty note hash read requests")] - unconstrained fn non_empty_note_hash_read_requests() { + fn non_empty_note_hash_read_requests() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.append_new_note_hashes(3); + builder.previous_kernel.append_note_hashes(3); let _void = builder.previous_kernel.add_read_request_for_pending_note_hash(1); builder.failed(); } #[test(should_fail_with="Non empty nullifier read requests")] - unconstrained fn non_empty_nullifier_read_requests() { + fn non_empty_nullifier_read_requests() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); - builder.previous_kernel.append_new_nullifiers(3); + builder.previous_kernel.append_nullifiers(3); let _void = builder.previous_kernel.add_read_request_for_pending_nullifier(1); builder.failed(); } #[test(should_fail_with="Non empty key validation requests")] - unconstrained fn non_empty_key_validations() { + fn non_empty_key_validations() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); let _void = builder.previous_kernel.add_request_for_key_validation(GrumpkinPoint::new(1, 2), 27, GENERATOR_INDEX__TSK_M); builder.failed(); } #[test] - unconstrained fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { + fn empty_tx_consumes_teardown_limits_plus_fixed_gas() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); let public_inputs = builder.execute(); - let expected_gas_consumed = Gas::new(300, 300) + Gas::tx_overhead(); - assert_eq(public_inputs.end.gas_used, expected_gas_consumed); + let gas_for_first_nullifier = Gas::new(DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE, 0); + let expected_non_revertible_gas_consumed = Gas::tx_overhead() + gas_for_first_nullifier; + assert_eq(public_inputs.end_non_revertible.gas_used, expected_non_revertible_gas_consumed); + let expected_revertible_gas_consumed = Gas::new(300, 300); + assert_eq(public_inputs.end.gas_used, expected_revertible_gas_consumed); } #[test(should_fail_with="The gas used exceeds the gas limits")] - unconstrained fn gas_limits_are_enforced() { + fn gas_limits_are_enforced() { let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = Gas::new(300, 300); builder.previous_kernel.tx_context.gas_settings.gas_limits = Gas::new(1, 1); @@ -405,7 +310,7 @@ mod tests { } #[test] - unconstrained fn propagate_fee_payer() { + fn propagate_fee_payer() { // Check that we carry forward if the fee payer is already set let mut builder = PrivateKernelTailToPublicInputsBuilder::new(); let fee_payer = AztecAddress::from_field(123); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests.nr deleted file mode 100644 index 1ee505ce4194..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests.nr +++ /dev/null @@ -1,4 +0,0 @@ -mod kernel_circuit_output_validator_builder; -mod private_call_data_validator_builder; -mod private_kernel_circuit_output_validator_builder; -mod private_kernel_circuit_public_inputs_composer_builder; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder.nr deleted file mode 100644 index 9b95f4ad859f..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder.nr +++ /dev/null @@ -1,34 +0,0 @@ -mod utils; -mod validate_accumulated_values; -mod validate_empty_values; -mod validate_propagated_sorted_siloed_values; -mod validate_propagated_values; - -use crate::components::{ - kernel_circuit_output_hints::generate_hints, - kernel_circuit_output_validator::KernelCircuitOutputValidator -}; -use dep::types::{abis::nullifier::Nullifier, address::AztecAddress, tests::fixture_builder::FixtureBuilder}; - -struct KernelCircuitOutputValidatorBuilder { - output: FixtureBuilder, - previous_kernel: FixtureBuilder -} - -impl KernelCircuitOutputValidatorBuilder { - pub fn new() -> Self { - let mut output = FixtureBuilder::new(); - let mut previous_kernel = FixtureBuilder::new(); - let first_nullifier = Nullifier { value: 123451234512345, counter: 0, note_hash: 0 }.scope(AztecAddress::zero()); - output.new_nullifiers.push(first_nullifier); - previous_kernel.new_nullifiers.push(first_nullifier); - KernelCircuitOutputValidatorBuilder { output, previous_kernel } - } - - pub fn validate(self) { - let output = self.output.to_kernel_circuit_public_inputs(); - let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - let hints = generate_hints(previous_kernel); - KernelCircuitOutputValidator::new(output, previous_kernel).validate(hints); - } -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/utils.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/utils.nr deleted file mode 100644 index f2c36f8c82af..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/utils.nr +++ /dev/null @@ -1,6 +0,0 @@ -// Swap the items so that they are not ordered by counters. -pub fn swap_items(vec: &mut BoundedVec, from_index: u64, to_index: u64) { - let tmp = vec.storage[from_index]; - vec.storage[from_index] = vec.storage[to_index]; - vec.storage[to_index] = tmp; -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_sorted_siloed_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_sorted_siloed_values.nr deleted file mode 100644 index 12d791671e1a..000000000000 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_sorted_siloed_values.nr +++ /dev/null @@ -1,116 +0,0 @@ -use crate::tests::kernel_circuit_output_validator_builder::{KernelCircuitOutputValidatorBuilder, utils::swap_items}; - -/** - * new_note_hashes - */ - -#[test] -fn validate_propagated_sorted_siloed_values_new_note_hashes_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_note_hashes(3); - builder.output.append_siloed_note_hashes(3); - - builder.validate(); -} - -#[test] -fn validate_propagated_sorted_siloed_values_new_note_hashes_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_note_hashes(3); - swap_items(&mut builder.previous_kernel.new_note_hashes, 0, 2); - for i in 0..3 { - // Need to silo the note hashes in the right order to hash with the correct index. - builder.output.add_siloed_note_hash(builder.previous_kernel.new_note_hashes.storage[i].value()); - } - swap_items(&mut builder.output.new_note_hashes, 0, 2); - - builder.validate(); -} - -#[test(should_fail_with="mismatch sorted values")] -fn validate_propagated_sorted_siloed_values_new_note_hashes_mismatch_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_note_hashes(2); - builder.output.append_siloed_note_hashes(2); - // Tweak the hash in the output. - builder.output.new_note_hashes.storage[0].note_hash.value += 1; - - builder.validate(); -} - -/** - * new_nullifiers - */ - -#[test] -fn validate_propagated_sorted_siloed_values_new_nullifiers_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_nullifiers(3); - builder.output.append_siloed_nullifiers(3); - - builder.validate(); -} - -#[test] -fn validate_propagated_sorted_siloed_values_new_nullifiers_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_nullifiers(3); - swap_items(&mut builder.previous_kernel.new_nullifiers, 0, 3); - builder.output.append_siloed_nullifiers(3); - - builder.validate(); -} - -#[test(should_fail_with="mismatch sorted values")] -fn validate_propagated_sorted_siloed_values_new_nullifiers_mismatch_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_nullifiers(3); - builder.output.append_siloed_nullifiers(3); - // Tweak the hash in the output. - builder.output.new_nullifiers.storage[0].nullifier.value += 1; - - builder.validate(); -} - -/** - * new_l2_to_l1_msgs - */ - -#[test] -fn validate_propagated_sorted_siloed_values_new_l2_to_l1_msgs_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_l2_to_l1_msgs(2); - builder.output.append_siloed_l2_to_l1_msgs(2); - - builder.validate(); -} - -#[test] -fn validate_propagated_sorted_siloed_values_new_l2_to_l1_msgs_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_l2_to_l1_msgs(2); - swap_items(&mut builder.previous_kernel.new_l2_to_l1_msgs, 0, 1); - builder.output.append_siloed_l2_to_l1_msgs(2); - - builder.validate(); -} - -#[test(should_fail_with="mismatch sorted values")] -fn validate_propagated_sorted_siloed_values_new_l2_to_l1_msgs_mismatch_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); - - builder.previous_kernel.append_new_l2_to_l1_msgs(2); - builder.output.append_siloed_l2_to_l1_msgs(2); - // Tweak the content in the output. - builder.output.new_l2_to_l1_msgs.storage[0].message.content += 1; - - builder.validate(); -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/mod.nr new file mode 100644 index 000000000000..c400947751f5 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/mod.nr @@ -0,0 +1,8 @@ +mod previous_kernel_validator_builder; +mod private_call_data_validator_builder; +mod private_kernel_circuit_output_validator_builder; +mod private_kernel_circuit_public_inputs_composer_builder; +mod tail_output_composer_builder; +mod tail_output_validator_builder; +mod tail_to_public_output_composer_builder; +mod tail_to_public_output_validator_builder; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/previous_kernel_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/previous_kernel_validator_builder.nr new file mode 100644 index 000000000000..b5cb4c7866d3 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/previous_kernel_validator_builder.nr @@ -0,0 +1,21 @@ +use crate::components::previous_kernel_validator::PreviousKernelValidator; +use dep::types::tests::fixture_builder::FixtureBuilder; + +struct PreviousKernelValidatorBuilder { + previous_kernel: FixtureBuilder +} + +impl PreviousKernelValidatorBuilder { + pub fn new() -> Self { + let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.set_first_nullifier(); + PreviousKernelValidatorBuilder { previous_kernel } + } + + pub fn validate_for_private_tail(self) { + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + PreviousKernelValidator::new(previous_kernel).validate_for_private_tail(); + } +} + +// TODO: Add tests. \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr similarity index 89% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr index 2dbeb1dbfeea..06e4ad419a29 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/mod.nr @@ -18,7 +18,6 @@ use dep::types::{ struct PrivateCallDataValidatorBuilder { private_call: FixtureBuilder, - first_revertible_private_call_request_index: u32, previous_note_hashes: BoundedVec, } @@ -31,7 +30,7 @@ impl PrivateCallDataValidatorBuilder { pub fn new_from_counter(counter: u32) -> Self { let private_call = FixtureBuilder::new_from_counter(counter); let previous_note_hashes = BoundedVec::new(); - PrivateCallDataValidatorBuilder { private_call, first_revertible_private_call_request_index: 0, previous_note_hashes } + PrivateCallDataValidatorBuilder { private_call, previous_note_hashes } } pub fn is_delegate_call(&mut self) -> Self { @@ -47,13 +46,13 @@ impl PrivateCallDataValidatorBuilder { pub fn validate(self) { let private_call = self.private_call.to_private_call_data(); let mut accumulated_note_hashes = self.previous_note_hashes; - accumulated_note_hashes.extend_from_bounded_vec(self.private_call.new_note_hashes); + accumulated_note_hashes.extend_from_bounded_vec(self.private_call.note_hashes); PrivateCallDataValidator::new(private_call).validate(accumulated_note_hashes.storage); } pub fn validate_as_first_call(self) { let private_call = self.private_call.to_private_call_data(); - PrivateCallDataValidator::new(private_call).validate_as_first_call(self.first_revertible_private_call_request_index); + PrivateCallDataValidator::new(private_call).validate_as_first_call(); } pub fn validate_against_tx_request(self, request: TxRequest) { diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr index 01796cafa0ce..e601fc98569e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_arrays.nr @@ -42,8 +42,8 @@ fn validate_arrays_malformed_key_validation_requests_fails() { fn validate_arrays_malformed_note_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(1); - unshift_empty_item(&mut builder.private_call.new_note_hashes); + builder.private_call.append_note_hashes(1); + unshift_empty_item(&mut builder.private_call.note_hashes); builder.validate(); } @@ -52,8 +52,8 @@ fn validate_arrays_malformed_note_hashes_fails() { fn validate_arrays_malformed_nullifiers_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_nullifiers(1); - unshift_empty_item(&mut builder.private_call.new_nullifiers); + builder.private_call.append_nullifiers(1); + unshift_empty_item(&mut builder.private_call.nullifiers); builder.validate(); } @@ -62,8 +62,8 @@ fn validate_arrays_malformed_nullifiers_fails() { fn validate_arrays_malformed_l2_to_l1_msgs_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_l2_to_l1_msgs(1); - unshift_empty_item(&mut builder.private_call.new_l2_to_l1_msgs); + builder.private_call.append_l2_to_l1_msgs(1); + unshift_empty_item(&mut builder.private_call.l2_to_l1_msgs); builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_as_first_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_as_first_call.nr index 122661c90475..cb2bdf3b8862 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_as_first_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_as_first_call.nr @@ -8,7 +8,6 @@ impl PrivateCallDataValidatorBuilder { pub fn split_calls(&mut self, counter: u32) { self.private_call.min_revertible_side_effect_counter = counter; - self.first_revertible_private_call_request_index = self.private_call.private_call_requests.len(); } pub fn add_private_call_request(&mut self, counter_start: u32, counter_end: u32) { @@ -55,7 +54,7 @@ fn validate_as_first_call_split_private_calls_succeeds() { } #[test] -fn validate_as_first_call_split_private_empty_revertible_succeeds() { +fn validate_as_first_call_split_private_calls_empty_revertible_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); builder.add_private_call_request(20, 30); @@ -66,7 +65,7 @@ fn validate_as_first_call_split_private_empty_revertible_succeeds() { } #[test] -fn validate_as_first_call_split_private_empty_non_revertible_succeeds() { +fn validate_as_first_call_split_private_calls_empty_non_revertible_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); builder.split_calls(20); @@ -77,7 +76,7 @@ fn validate_as_first_call_split_private_empty_non_revertible_succeeds() { } #[test] -fn validate_as_first_call_split_private_full_non_revertible_succeeds() { +fn validate_as_first_call_split_private_calls_full_non_revertible_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); builder.private_call.append_private_call_requests(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL); @@ -124,19 +123,6 @@ fn validate_as_first_call_split_private_calls_equal_last_non_revertible_fails() builder.validate_as_first_call(); } -#[test(should_fail_with="min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item")] -fn validate_as_first_call_split_private_calls_greater_than_first_revertible_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); - - builder.add_private_call_request(20, 30); - builder.add_private_call_request(40, 50); - // Tweak the counter to be greater than the start counter of the first revertible call. - builder.split_calls(61); - builder.add_private_call_request(60, 70); - - builder.validate_as_first_call(); -} - #[test] fn validate_as_first_call_split_private_calls_0_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); @@ -148,29 +134,3 @@ fn validate_as_first_call_split_private_calls_0_succeeds() { builder.validate_as_first_call(); } - -#[test(should_fail_with="min_revertible_side_effect_counter must be greater than the end counter of the last non revertible item")] -fn validate_as_first_call_split_private_calls_0_wrong_hint_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); - - builder.split_calls(0); - // Set the index hint to be 1. - builder.first_revertible_private_call_request_index = 1; - builder.add_private_call_request(20, 30); - builder.add_private_call_request(40, 50); - - builder.validate_as_first_call(); -} - -#[test(should_fail_with="min_revertible_side_effect_counter must be less than or equal to the start counter of the first revertible item")] -fn validate_as_first_call_split_private_calls_index_hint_greater_than_len_fails() { - let mut builder = PrivateCallDataValidatorBuilder::new_first_call(); - - builder.add_private_call_request(20, 30); - builder.add_private_call_request(40, 50); - builder.split_calls(51); - // Increase the index by 1. - builder.first_revertible_private_call_request_index += 1; - - builder.validate_as_first_call(); -} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr index a17eeef9d530..45e332bb2398 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_call.nr @@ -54,29 +54,29 @@ fn validate_call_is_static_mismatch_storage_contract_fails() { builder.validate(); } -#[test(should_fail_with="new_note_hashes must be empty for static calls")] +#[test(should_fail_with="note_hashes must be empty for static calls")] fn validate_call_is_static_creating_note_hashes_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.append_new_note_hashes(1); + builder.private_call.append_note_hashes(1); builder.validate(); } -#[test(should_fail_with="new_nullifiers must be empty for static calls")] +#[test(should_fail_with="nullifiers must be empty for static calls")] fn validate_call_is_static_creating_nullifiers_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.append_new_nullifiers(1); + builder.private_call.append_nullifiers(1); builder.validate(); } -#[test(should_fail_with="new_l2_to_l1_msgs must be empty for static calls")] +#[test(should_fail_with="l2_to_l1_msgs must be empty for static calls")] fn validate_call_is_static_creating_l2_to_l1_msgs_fails() { let mut builder = PrivateCallDataValidatorBuilder::new().is_static_call(); - builder.private_call.append_new_l2_to_l1_msgs(1); + builder.private_call.append_l2_to_l1_msgs(1); builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr index 2f85c7df52f3..02ef4c181a8a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_counters.nr @@ -42,7 +42,7 @@ fn validate_counters_private_call_negative_call_counter_range_fails() { fn validate_counters_note_hashes_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); builder.validate(); } @@ -51,9 +51,9 @@ fn validate_counters_note_hashes_succeeds() { fn validate_counters_note_hash_counter_same_as_call_counter_start_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(1); + builder.private_call.append_note_hashes(1); // Tweak the counter of the first note hash to EQUAL the start counter of the call. - builder.private_call.new_note_hashes.storage[0].note_hash.counter = builder.private_call.counter_start; + builder.private_call.note_hashes.storage[0].note_hash.counter = builder.private_call.counter_start; builder.validate(); } @@ -62,9 +62,9 @@ fn validate_counters_note_hash_counter_same_as_call_counter_start_fails() { fn validate_counters_note_hash_counter_smaller_than_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(1); + builder.private_call.append_note_hashes(1); // Tweak the counter of the first note hash to be LESS than the start counter of the call. - builder.private_call.new_note_hashes.storage[0].note_hash.counter = builder.private_call.counter_start - 1; + builder.private_call.note_hashes.storage[0].note_hash.counter = builder.private_call.counter_start - 1; builder.validate(); } @@ -73,11 +73,11 @@ fn validate_counters_note_hash_counter_smaller_than_call_fails() { fn validate_counters_note_hash_identical_counters_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); let counter_start = builder.private_call.counter_start; // Tweak the counter of the second note hash to EQUAL the counter of the first note hash. - builder.private_call.new_note_hashes.storage[0].note_hash.counter = counter_start + 1; - builder.private_call.new_note_hashes.storage[1].note_hash.counter = counter_start + 1; + builder.private_call.note_hashes.storage[0].note_hash.counter = counter_start + 1; + builder.private_call.note_hashes.storage[1].note_hash.counter = counter_start + 1; builder.validate(); } @@ -86,11 +86,11 @@ fn validate_counters_note_hash_identical_counters_fails() { fn validate_counters_note_hash_unordered_counters_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); let counter_start = builder.private_call.counter_start; // Tweak the counter of the second note hash to be LESS than the counter of the first note hash. - builder.private_call.new_note_hashes.storage[0].note_hash.counter = counter_start + 2; - builder.private_call.new_note_hashes.storage[1].note_hash.counter = counter_start + 1; + builder.private_call.note_hashes.storage[0].note_hash.counter = counter_start + 2; + builder.private_call.note_hashes.storage[1].note_hash.counter = counter_start + 1; builder.validate(); } @@ -99,9 +99,9 @@ fn validate_counters_note_hash_unordered_counters_fails() { fn validate_counters_note_hash_counter_larger_than_call_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); // Tweak the counter of the second note hash to be GREATER than the end counter of the call. - builder.private_call.new_note_hashes.storage[1].note_hash.counter = builder.private_call.counter + 1; + builder.private_call.note_hashes.storage[1].note_hash.counter = builder.private_call.counter + 1; builder.validate(); } @@ -110,9 +110,9 @@ fn validate_counters_note_hash_counter_larger_than_call_fails() { fn validate_counters_note_hash_counter_same_as_call_counter_end_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); // Tweak the counter of the second note hash to EQUAL the end counter of the call. - builder.private_call.new_note_hashes.storage[1].note_hash.counter = builder.private_call.counter; + builder.private_call.note_hashes.storage[1].note_hash.counter = builder.private_call.counter; builder.validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_note_logs.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_note_logs.nr index 958157529fd4..45e3436b12b2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_note_logs.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_call_data_validator_builder/validate_note_logs.nr @@ -5,7 +5,7 @@ use dep::types::{abis::note_hash::NoteHash, address::AztecAddress}; fn validate_note_logs_succeeds() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes_with_logs(2); + builder.private_call.append_note_hashes_with_logs(2); builder.validate(); } @@ -14,7 +14,7 @@ fn validate_note_logs_succeeds() { fn validate_note_logs_random_note_hash_counter_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes_with_logs(2); + builder.private_call.append_note_hashes_with_logs(2); // Tweak the note_hash_counter to not match any note hash's counter. builder.private_call.note_encrypted_logs_hashes.storage[1].note_hash_counter += 100; @@ -25,7 +25,7 @@ fn validate_note_logs_random_note_hash_counter_fails() { fn validate_note_logs_zero_note_hash_counter_fails() { let mut builder = PrivateCallDataValidatorBuilder::new(); - builder.private_call.append_new_note_hashes_with_logs(2); + builder.private_call.append_note_hashes_with_logs(2); // Tweak the note_hash_counter to be 0. builder.private_call.note_encrypted_logs_hashes.storage[1].note_hash_counter = 0; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr similarity index 91% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr index d52c6cf82b17..c80c105734b1 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/mod.nr @@ -15,14 +15,14 @@ use dep::types::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputsArrayLengths, private_circuit_public_inputs::PrivateCircuitPublicInputsArrayLengths }, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, tests::{fixture_builder::FixtureBuilder}, + constants::MAX_NOTE_HASHES_PER_CALL, tests::{fixture_builder::FixtureBuilder}, transaction::tx_request::TxRequest }; struct PrivateKernelCircuitOutputValidatorBuilder { previous_kernel: FixtureBuilder, private_call: FixtureBuilder, - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], output: FixtureBuilder, tx_request: TxRequest, } @@ -31,12 +31,12 @@ impl PrivateKernelCircuitOutputValidatorBuilder { pub fn new() -> Self { let mut previous_kernel = FixtureBuilder::new(); let private_call = FixtureBuilder::new(); - let note_hash_nullifier_counters = [0; MAX_NEW_NOTE_HASHES_PER_CALL]; + let note_hash_nullifier_counters = [0; MAX_NOTE_HASHES_PER_CALL]; let mut output = FixtureBuilder::new(); let tx_request = output.build_tx_request(); let first_nullifier = create_first_nullifier(tx_request); - output.new_nullifiers.push(first_nullifier); - previous_kernel.new_nullifiers.push(first_nullifier); + output.nullifiers.push(first_nullifier); + previous_kernel.nullifiers.push(first_nullifier); PrivateKernelCircuitOutputValidatorBuilder { previous_kernel, private_call, note_hash_nullifier_counters, output, tx_request } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr index 335a05320567..63cd2b9e8791 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_initial_values.nr @@ -46,7 +46,7 @@ fn validate_initial_values_constants_non_empty_global_variables_fails() { fn validate_initial_values_constants_incorrect_first_nullifier_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.output.new_nullifiers.storage[0].nullifier.value += 1; + builder.output.nullifiers.storage[0].nullifier.value += 1; builder.validate_as_first_call(); } @@ -55,7 +55,7 @@ fn validate_initial_values_constants_incorrect_first_nullifier_fails() { fn validate_initial_values_constants_empty_first_nullifier_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.output.new_nullifiers = BoundedVec::new(); + builder.output.nullifiers = BoundedVec::new(); builder.validate_as_first_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr index de27661df47c..7a1ea86602af 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_previous_kernel.nr @@ -113,76 +113,76 @@ fn validate_propagated_from_previous_kernel_key_validation_requests_less_than_fa } /** - * new_note_hashes + * note_hashes */ #[test] -fn validate_propagated_from_previous_kernel_new_note_hashes_succeeds() { +fn validate_propagated_from_previous_kernel_note_hashes_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - builder.output.append_new_note_hashes(2); + builder.previous_kernel.append_note_hashes(2); + builder.output.append_note_hashes(2); builder.validate_as_inner_call(); } #[test(should_fail_with="source item does not prepend to dest")] -fn validate_propagated_from_previous_kernel_new_note_hashes_less_than_fails() { +fn validate_propagated_from_previous_kernel_note_hashes_less_than_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); + builder.previous_kernel.append_note_hashes(2); // Propagate 1 less item to the output. - builder.output.append_new_note_hashes(1); + builder.output.append_note_hashes(1); builder.validate_as_inner_call(); } /** - * new_nullifiers + * nullifiers */ #[test] -fn validate_propagated_from_previous_kernel_new_nullifiers_succeeds() { +fn validate_propagated_from_previous_kernel_nullifiers_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_nullifiers(2); - builder.output.append_new_nullifiers(2); + builder.previous_kernel.append_nullifiers(2); + builder.output.append_nullifiers(2); builder.validate_as_inner_call(); } #[test(should_fail_with="source item does not prepend to dest")] -fn validate_propagated_from_previous_kernel_new_nullifiers_less_than_fails() { +fn validate_propagated_from_previous_kernel_nullifiers_less_than_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_nullifiers(2); + builder.previous_kernel.append_nullifiers(2); // Propagate 1 less item to the output. - builder.output.append_new_nullifiers(1); + builder.output.append_nullifiers(1); builder.validate_as_inner_call(); } /** - * new_l2_to_l1_msgs + * l2_to_l1_msgs */ #[test] -fn validate_propagated_from_previous_kernel_new_l2_to_l1_msgs_succeeds() { +fn validate_propagated_from_previous_kernel_l2_to_l1_msgs_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_l2_to_l1_msgs(2); - builder.output.append_new_l2_to_l1_msgs(2); + builder.previous_kernel.append_l2_to_l1_msgs(2); + builder.output.append_l2_to_l1_msgs(2); builder.validate_as_inner_call(); } #[test(should_fail_with="source item does not prepend to dest")] -fn validate_propagated_from_previous_kernel_new_l2_to_l1_msgs_less_than_fails() { +fn validate_propagated_from_previous_kernel_l2_to_l1_msgs_less_than_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_l2_to_l1_msgs(2); + builder.previous_kernel.append_l2_to_l1_msgs(2); // Propagate 1 less item to the output. - builder.output.append_new_l2_to_l1_msgs(1); + builder.output.append_l2_to_l1_msgs(1); builder.validate_as_inner_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr index 710714c57560..68a4e5f1fff7 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_output_validator_builder/validate_propagated_from_private_call.nr @@ -235,41 +235,41 @@ fn validate_propagated_from_private_call_key_validation_requests_output_one_more } /** - * new_note_hashes + * note_hashes */ #[test] -fn validate_propagated_from_private_call_new_note_hashes_succeeds() { +fn validate_propagated_from_private_call_note_hashes_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); - builder.output.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); + builder.output.append_note_hashes(2); builder.validate_as_inner_call(); } #[test(should_fail_with="output should be appended with empty items")] -fn validate_propagated_from_private_call_new_note_hashes_output_one_more_fails() { +fn validate_propagated_from_private_call_note_hashes_output_one_more_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); + builder.private_call.append_note_hashes(2); // Propagate 1 more item to the output. - builder.output.append_new_note_hashes(3); + builder.output.append_note_hashes(3); builder.validate_as_inner_call(); } /** - * new_note_hashes + * note_hashes * With nullifier counters. */ #[test] -fn validate_propagated_from_private_call_new_note_hashes_non_zero_nullifier_counters_succeeds() { +fn validate_propagated_from_private_call_note_hashes_non_zero_nullifier_counters_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let note_hashes = [builder.private_call.new_note_hashes.storage[0], builder.private_call.new_note_hashes.storage[1]]; + builder.private_call.append_note_hashes(2); + let note_hashes = [builder.private_call.note_hashes.storage[0], builder.private_call.note_hashes.storage[1]]; builder.note_hash_nullifier_counters[0] = note_hashes[0].counter() + 10; builder.note_hash_nullifier_counters[1] = note_hashes[1].counter() + 35; builder.output.add_new_note_hash( @@ -285,15 +285,15 @@ fn validate_propagated_from_private_call_new_note_hashes_non_zero_nullifier_coun } #[test] -fn validate_propagated_from_private_call_new_note_hashes_with_previous_non_zero_nullifier_counters_succeeds() { +fn validate_propagated_from_private_call_note_hashes_with_previous_non_zero_nullifier_counters_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - builder.output.append_new_note_hashes(2); + builder.previous_kernel.append_note_hashes(2); + builder.output.append_note_hashes(2); builder.offset_values(2); // Offset the first 2 note hashes. - builder.private_call.append_new_note_hashes(2); - let note_hashes = [builder.private_call.new_note_hashes.storage[0], builder.private_call.new_note_hashes.storage[1]]; + builder.private_call.append_note_hashes(2); + let note_hashes = [builder.private_call.note_hashes.storage[0], builder.private_call.note_hashes.storage[1]]; builder.note_hash_nullifier_counters[0] = note_hashes[0].counter() + 10; builder.note_hash_nullifier_counters[1] = note_hashes[1].counter() + 35; builder.output.add_new_note_hash( @@ -309,11 +309,11 @@ fn validate_propagated_from_private_call_new_note_hashes_with_previous_non_zero_ } #[test(should_fail_with="invalid nullifier counter")] -fn validate_propagated_from_private_call_new_note_hashes_nullifier_counters_too_small_fails() { +fn validate_propagated_from_private_call_note_hashes_nullifier_counters_too_small_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let note_hashes = [builder.private_call.new_note_hashes.storage[0], builder.private_call.new_note_hashes.storage[1]]; + builder.private_call.append_note_hashes(2); + let note_hashes = [builder.private_call.note_hashes.storage[0], builder.private_call.note_hashes.storage[1]]; builder.note_hash_nullifier_counters[0] = note_hashes[0].counter() + 10; // Tweak the nullifier counter to be less than the counter of the note hash. builder.note_hash_nullifier_counters[1] = note_hashes[1].counter() - 1; @@ -330,11 +330,11 @@ fn validate_propagated_from_private_call_new_note_hashes_nullifier_counters_too_ } #[test(should_fail_with="incorrect nullifier counter assigned to dest")] -fn validate_propagated_from_private_call_new_note_hashes_nullifier_counters_mismatch_fails() { +fn validate_propagated_from_private_call_note_hashes_nullifier_counters_mismatch_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let note_hashes = [builder.private_call.new_note_hashes.storage[0], builder.private_call.new_note_hashes.storage[1]]; + builder.private_call.append_note_hashes(2); + let note_hashes = [builder.private_call.note_hashes.storage[0], builder.private_call.note_hashes.storage[1]]; builder.note_hash_nullifier_counters[0] = note_hashes[0].counter() + 10; builder.note_hash_nullifier_counters[1] = note_hashes[1].counter() + 35; builder.output.add_new_note_hash( @@ -351,53 +351,53 @@ fn validate_propagated_from_private_call_new_note_hashes_nullifier_counters_mism } /** - * new_nullifiers + * nullifiers */ #[test] -fn validate_propagated_from_private_call_new_nullifiers_succeeds() { +fn validate_propagated_from_private_call_nullifiers_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); builder.offset_values(1); // Offset the first nullifier. - builder.private_call.append_new_nullifiers(2); - builder.output.append_new_nullifiers(2); + builder.private_call.append_nullifiers(2); + builder.output.append_nullifiers(2); builder.validate_as_inner_call(); } #[test(should_fail_with="output should be appended with empty items")] -fn validate_propagated_from_private_call_new_nullifiers_output_one_more_fails() { +fn validate_propagated_from_private_call_nullifiers_output_one_more_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); builder.offset_values(1); // Offset the first nullifier. - builder.private_call.append_new_nullifiers(2); + builder.private_call.append_nullifiers(2); // Propagate 1 more item to the output. - builder.output.append_new_nullifiers(3); + builder.output.append_nullifiers(3); builder.validate_as_inner_call(); } /** - * new_l2_to_l1_msgs + * l2_to_l1_msgs */ #[test] -fn validate_propagated_from_private_call_new_l2_to_l1_msgs_succeeds() { +fn validate_propagated_from_private_call_l2_to_l1_msgs_succeeds() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_l2_to_l1_msgs(2); - builder.output.append_new_l2_to_l1_msgs(2); + builder.private_call.append_l2_to_l1_msgs(2); + builder.output.append_l2_to_l1_msgs(2); builder.validate_as_inner_call(); } #[test(should_fail_with="output should be appended with empty items")] -fn validate_propagated_from_private_call_new_l2_to_l1_msgs_output_one_more_fails() { +fn validate_propagated_from_private_call_l2_to_l1_msgs_output_one_more_fails() { let mut builder = PrivateKernelCircuitOutputValidatorBuilder::new(); - builder.private_call.append_new_l2_to_l1_msgs(1); + builder.private_call.append_l2_to_l1_msgs(1); // Propagate 1 more item to the output. - builder.output.append_new_l2_to_l1_msgs(2); + builder.output.append_l2_to_l1_msgs(2); builder.validate_as_inner_call(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr similarity index 83% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr index 3720c01ce064..294c109dff24 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/mod.nr @@ -8,7 +8,7 @@ use dep::types::{ kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, private_call_request::ScopedPrivateCallRequest }, - constants::MAX_NEW_NOTE_HASHES_PER_CALL, tests::fixture_builder::FixtureBuilder, + constants::MAX_NOTE_HASHES_PER_CALL, tests::fixture_builder::FixtureBuilder, transaction::tx_request::TxRequest }; @@ -16,7 +16,7 @@ struct PrivateKernelCircuitPublicInputsComposerBuilder { tx_request: TxRequest, previous_kernel: FixtureBuilder, private_call: FixtureBuilder, - note_hash_nullifier_counters: [u32; MAX_NEW_NOTE_HASHES_PER_CALL], + note_hash_nullifier_counters: [u32; MAX_NOTE_HASHES_PER_CALL], } impl PrivateKernelCircuitPublicInputsComposerBuilder { @@ -28,7 +28,7 @@ impl PrivateKernelCircuitPublicInputsComposerBuilder { private_call.value_offset = 9999; let tx_request = private_call.build_tx_request(); - let note_hash_nullifier_counters = [0; MAX_NEW_NOTE_HASHES_PER_CALL]; + let note_hash_nullifier_counters = [0; MAX_NOTE_HASHES_PER_CALL]; PrivateKernelCircuitPublicInputsComposerBuilder { tx_request, previous_kernel, private_call, note_hash_nullifier_counters } } @@ -38,17 +38,13 @@ impl PrivateKernelCircuitPublicInputsComposerBuilder { } pub fn new_from_previous_kernel(self) -> PrivateKernelCircuitPublicInputsComposer { - let mut previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); - // Append one private call request for the current call. - let num_private_call_requests = self.previous_kernel.private_call_requests.len(); - previous_kernel.end.private_call_stack[num_private_call_requests] = ScopedPrivateCallRequest::empty(); - previous_kernel.end.private_call_stack[num_private_call_requests].call_request.hash = 98765432; + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel) } pub fn compose_from_tx_request(self) -> PrivateKernelCircuitPublicInputs { let private_call = self.private_call.to_private_call_data(); - self.new_from_tx_request().compose( + self.new_from_tx_request().with_private_call( private_call.call_stack_item.public_inputs, private_call.call_stack_item.contract_address, self.note_hash_nullifier_counters, @@ -58,8 +54,15 @@ impl PrivateKernelCircuitPublicInputsComposerBuilder { } pub fn compose_from_previous_kernel(self) -> PrivateKernelCircuitPublicInputs { + // Append one private call request for the previous kernel. + let mut previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + let num_private_call_requests = self.previous_kernel.private_call_requests.len(); + previous_kernel.end.private_call_stack[num_private_call_requests] = ScopedPrivateCallRequest::empty(); + previous_kernel.end.private_call_stack[num_private_call_requests].call_request.hash = 98765432; + let private_call = self.private_call.to_private_call_data(); - self.new_from_previous_kernel().compose( + + PrivateKernelCircuitPublicInputsComposer::new_from_previous_kernel(previous_kernel).pop_top_call_request().with_private_call( private_call.call_stack_item.public_inputs, private_call.call_stack_item.contract_address, self.note_hash_nullifier_counters, diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr index eb2421ac7678..0256b705f12e 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_previous_kernel_with_private_call.nr @@ -149,30 +149,27 @@ fn new_from_previous_kernel_with_private_call_key_validation_requests_succeeds() } #[test] -fn new_from_previous_kernel_with_private_call_new_note_hashes_succeeds() { +fn new_from_previous_kernel_with_private_call_note_hashes_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - let prev = builder.previous_kernel.new_note_hashes.storage; - builder.private_call.append_new_note_hashes(2); - let curr = builder.private_call.new_note_hashes.storage; + builder.previous_kernel.append_note_hashes(2); + let prev = builder.previous_kernel.note_hashes.storage; + builder.private_call.append_note_hashes(2); + let curr = builder.private_call.note_hashes.storage; let output = builder.compose_from_previous_kernel(); - assert_array_eq( - output.end.new_note_hashes, - [prev[0], prev[1], curr[0], curr[1]] - ); + assert_array_eq(output.end.note_hashes, [prev[0], prev[1], curr[0], curr[1]]); } #[test] -fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_counters_succeeds() { +fn new_from_previous_kernel_with_private_call_note_hashes_with_nullifier_counters_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - let prev = builder.previous_kernel.new_note_hashes.storage; - builder.private_call.append_new_note_hashes(2); - let mut curr = builder.private_call.new_note_hashes.storage; + builder.previous_kernel.append_note_hashes(2); + let prev = builder.previous_kernel.note_hashes.storage; + builder.private_call.append_note_hashes(2); + let mut curr = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = curr[0].counter() + 10; builder.note_hash_nullifier_counters[1] = curr[1].counter() + 75; @@ -180,20 +177,17 @@ fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_cou curr[0].nullifier_counter = curr[0].counter() + 10; curr[1].nullifier_counter = curr[1].counter() + 75; - assert_array_eq( - output.end.new_note_hashes, - [prev[0], prev[1], curr[0], curr[1]] - ); + assert_array_eq(output.end.note_hashes, [prev[0], prev[1], curr[0], curr[1]]); } #[test] -fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_counters_more_hints_succeeds() { +fn new_from_previous_kernel_with_private_call_note_hashes_with_nullifier_counters_more_hints_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - let prev = builder.previous_kernel.new_note_hashes.storage; - builder.private_call.append_new_note_hashes(2); - let mut curr = builder.private_call.new_note_hashes.storage; + builder.previous_kernel.append_note_hashes(2); + let prev = builder.previous_kernel.note_hashes.storage; + builder.private_call.append_note_hashes(2); + let mut curr = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = curr[0].counter() + 10; builder.note_hash_nullifier_counters[1] = curr[1].counter() + 75; // Add a random nullifier counter for a non-existent note hash to the hints. @@ -203,22 +197,19 @@ fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_cou curr[0].nullifier_counter = curr[0].counter() + 10; curr[1].nullifier_counter = curr[1].counter() + 75; - assert_array_eq( - output.end.new_note_hashes, - [prev[0], prev[1], curr[0], curr[1]] - ); + assert_array_eq(output.end.note_hashes, [prev[0], prev[1], curr[0], curr[1]]); // The extra counter won't be propagated. - assert_eq(output.end.new_note_hashes[4].nullifier_counter, 0); + assert_eq(output.end.note_hashes[4].nullifier_counter, 0); } #[test(should_fail_with="Invalid nullifier counter")] -fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_counters_less_than_fails() { +fn new_from_previous_kernel_with_private_call_note_hashes_with_nullifier_counters_less_than_fails() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_note_hashes(2); - let _ = builder.previous_kernel.new_note_hashes.storage; - builder.private_call.append_new_note_hashes(2); - let curr = builder.private_call.new_note_hashes.storage; + builder.previous_kernel.append_note_hashes(2); + let _ = builder.previous_kernel.note_hashes.storage; + builder.private_call.append_note_hashes(2); + let curr = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = curr[0].counter() + 10; // Tweak the nullifier counter to be less than the note hash counter. builder.note_hash_nullifier_counters[1] = curr[1].counter() - 1; @@ -227,34 +218,31 @@ fn new_from_previous_kernel_with_private_call_new_note_hashes_with_nullifier_cou } #[test] -fn new_from_previous_kernel_with_private_call_new_nullifiers_succeeds() { +fn new_from_previous_kernel_with_private_call_nullifiers_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_nullifiers(2); - let prev = builder.previous_kernel.new_nullifiers.storage; - builder.private_call.append_new_nullifiers(2); - let curr = builder.private_call.new_nullifiers.storage; + builder.previous_kernel.append_nullifiers(2); + let prev = builder.previous_kernel.nullifiers.storage; + builder.private_call.append_nullifiers(2); + let curr = builder.private_call.nullifiers.storage; let output = builder.compose_from_previous_kernel(); - assert_array_eq( - output.end.new_nullifiers, - [prev[0], prev[1], curr[0], curr[1]] - ); + assert_array_eq(output.end.nullifiers, [prev[0], prev[1], curr[0], curr[1]]); } #[test] -fn new_from_previous_kernel_with_private_call_new_l2_to_l1_msgs_succeeds() { +fn new_from_previous_kernel_with_private_call_l2_to_l1_msgs_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.previous_kernel.append_new_l2_to_l1_msgs(1); - let prev = builder.previous_kernel.new_l2_to_l1_msgs.storage; - builder.private_call.append_new_l2_to_l1_msgs(1); - let curr = builder.private_call.new_l2_to_l1_msgs.storage; + builder.previous_kernel.append_l2_to_l1_msgs(1); + let prev = builder.previous_kernel.l2_to_l1_msgs.storage; + builder.private_call.append_l2_to_l1_msgs(1); + let curr = builder.private_call.l2_to_l1_msgs.storage; let output = builder.compose_from_previous_kernel(); - assert_array_eq(output.end.new_l2_to_l1_msgs, [prev[0], curr[0]]); + assert_array_eq(output.end.l2_to_l1_msgs, [prev[0], curr[0]]); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr index b29457dee8ac..9fdca3bce25d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/new_from_tx_request.nr @@ -25,11 +25,11 @@ fn new_from_tx_request_succeeds() { assert(is_empty(output.constants.global_variables)); // Check first nullifier is set. - assert_eq(output.end.new_nullifiers[0], first_nullifier); + assert_eq(output.end.nullifiers[0], first_nullifier); let array_lengths = PrivateKernelCircuitPublicInputsArrayLengths::new(output); let mut expected_array_lengths = PrivateKernelCircuitPublicInputsArrayLengths::empty(); - expected_array_lengths.new_nullifiers = 1; + expected_array_lengths.nullifiers = 1; assert_eq(array_lengths, expected_array_lengths); // Check values default to empty. diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr index 613cd104cf16..af65939a7885 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/private_kernel_circuit_public_inputs_composer_builder/propagate_from_private_call.nr @@ -16,11 +16,11 @@ fn propagate_from_private_call_empty_data_succeeds() { let output = builder.compose_from_tx_request(); - assert_eq(output.end.new_nullifiers[0], first_nullifier); + assert_eq(output.end.nullifiers[0], first_nullifier); let array_lengths = PrivateKernelCircuitPublicInputsArrayLengths::new(output); let mut expected_array_lengths = PrivateKernelCircuitPublicInputsArrayLengths::empty(); - expected_array_lengths.new_nullifiers = 1; + expected_array_lengths.nullifiers = 1; assert_eq(array_lengths, expected_array_lengths); assert_eq(output.min_revertible_side_effect_counter, 0); @@ -98,23 +98,23 @@ fn propagate_from_private_call_key_validation_requests_succeeds() { } #[test] -fn propagate_from_private_call_new_note_hashes_succeeds() { +fn propagate_from_private_call_note_hashes_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let res = builder.private_call.new_note_hashes.storage; + builder.private_call.append_note_hashes(2); + let res = builder.private_call.note_hashes.storage; let output = builder.compose_from_tx_request(); - assert_array_eq(output.end.new_note_hashes, [res[0], res[1]]); + assert_array_eq(output.end.note_hashes, [res[0], res[1]]); } #[test] -fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_succeeds() { +fn propagate_from_private_call_note_hashes_with_nullifier_counters_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let mut res = builder.private_call.new_note_hashes.storage; + builder.private_call.append_note_hashes(2); + let mut res = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = res[0].counter() + 10; builder.note_hash_nullifier_counters[1] = res[1].counter() + 75; @@ -122,15 +122,15 @@ fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_succeeds( res[0].nullifier_counter = res[0].counter() + 10; res[1].nullifier_counter = res[1].counter() + 75; - assert_array_eq(output.end.new_note_hashes, [res[0], res[1]]); + assert_array_eq(output.end.note_hashes, [res[0], res[1]]); } #[test] -fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_more_hints_succeeds() { +fn propagate_from_private_call_note_hashes_with_nullifier_counters_more_hints_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let mut res = builder.private_call.new_note_hashes.storage; + builder.private_call.append_note_hashes(2); + let mut res = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = res[0].counter() + 10; builder.note_hash_nullifier_counters[1] = res[1].counter() + 75; // Add a random nullifier counter for a non-existent note hash to the hints. @@ -140,17 +140,17 @@ fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_more_hint res[0].nullifier_counter = res[0].counter() + 10; res[1].nullifier_counter = res[1].counter() + 75; - assert_array_eq(output.end.new_note_hashes, [res[0], res[1]]); + assert_array_eq(output.end.note_hashes, [res[0], res[1]]); // The extra counter won't be propagated. - assert_eq(output.end.new_note_hashes[2].nullifier_counter, 0); + assert_eq(output.end.note_hashes[2].nullifier_counter, 0); } #[test(should_fail_with="Invalid nullifier counter")] -fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_less_than_fails() { +fn propagate_from_private_call_note_hashes_with_nullifier_counters_less_than_fails() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_note_hashes(2); - let mut res = builder.private_call.new_note_hashes.storage; + builder.private_call.append_note_hashes(2); + let mut res = builder.private_call.note_hashes.storage; builder.note_hash_nullifier_counters[0] = res[0].counter() + 10; // Tweak the nullifier counter to be less than the note hash counter. builder.note_hash_nullifier_counters[1] = res[1].counter() - 1; @@ -159,30 +159,30 @@ fn propagate_from_private_call_new_note_hashes_with_nullifier_counters_less_than } #[test] -fn propagate_from_private_call_new_nullifiers_succeeds() { +fn propagate_from_private_call_nullifiers_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_nullifiers(2); - let res = builder.private_call.new_nullifiers.storage; + builder.private_call.append_nullifiers(2); + let res = builder.private_call.nullifiers.storage; let tx_request = builder.tx_request; let first_nullifier = create_first_nullifier(tx_request); let output = builder.compose_from_tx_request(); - assert_array_eq(output.end.new_nullifiers, [first_nullifier, res[0], res[1]]); + assert_array_eq(output.end.nullifiers, [first_nullifier, res[0], res[1]]); } #[test] -fn propagate_from_private_call_new_l2_to_l1_msgs_succeeds() { +fn propagate_from_private_call_l2_to_l1_msgs_succeeds() { let mut builder = PrivateKernelCircuitPublicInputsComposerBuilder::new(); - builder.private_call.append_new_l2_to_l1_msgs(2); - let res = builder.private_call.new_l2_to_l1_msgs.storage; + builder.private_call.append_l2_to_l1_msgs(2); + let res = builder.private_call.l2_to_l1_msgs.storage; let output = builder.compose_from_tx_request(); - assert_array_eq(output.end.new_l2_to_l1_msgs, [res[0], res[1]]); + assert_array_eq(output.end.l2_to_l1_msgs, [res[0], res[1]]); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr new file mode 100644 index 000000000000..b73651287517 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr @@ -0,0 +1,28 @@ +use crate::components::tail_output_composer::TailOutputComposer; +use dep::types::{abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, tests::fixture_builder::FixtureBuilder}; + +struct TailOutputComposerBuilder { + previous_kernel: FixtureBuilder, +} + +impl TailOutputComposerBuilder { + pub fn new() -> Self { + let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.set_first_nullifier(); // Need the first nullifier to silo note hashes. + TailOutputComposerBuilder { previous_kernel } + } + + pub fn with_siloed_data_builder(self) -> (Self, FixtureBuilder) { + let mut siloed_data_builder = FixtureBuilder::new(); + siloed_data_builder.set_first_nullifier(); + (self, siloed_data_builder) + } + + pub fn finish(self) -> KernelCircuitPublicInputs { + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + let composer = TailOutputComposer::new(previous_kernel); + composer.finish() + } +} + +// TODO: Add tests. \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr new file mode 100644 index 000000000000..6baadc391fbc --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr @@ -0,0 +1,28 @@ +mod validate_accumulated_values; +mod validate_empty_values; +mod validate_propagated_sorted_siloed_values; +mod validate_propagated_values; + +use crate::components::tail_output_validator::TailOutputValidator; +use dep::types::tests::fixture_builder::FixtureBuilder; + +struct TailOutputValidatorBuilder { + output: FixtureBuilder, + previous_kernel: FixtureBuilder +} + +impl TailOutputValidatorBuilder { + pub fn new() -> Self { + let mut output = FixtureBuilder::new(); + let mut previous_kernel = FixtureBuilder::new(); + output.set_first_nullifier(); + previous_kernel.set_first_nullifier(); + TailOutputValidatorBuilder { output, previous_kernel } + } + + pub fn validate(self) { + let output = self.output.to_kernel_circuit_public_inputs(); + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + TailOutputValidator::new(output, previous_kernel).validate(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_accumulated_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr similarity index 83% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_accumulated_values.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr index 8f50b622279b..cb2dedc44ab8 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_accumulated_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_accumulated_values.nr @@ -1,4 +1,5 @@ -use crate::tests::kernel_circuit_output_validator_builder::{KernelCircuitOutputValidatorBuilder, utils::swap_items}; +use crate::tests::tail_output_validator_builder::TailOutputValidatorBuilder; +use dep::types::tests::utils::swap_items; // TODO: Add tests that fail to validate with tweaked hints. @@ -8,7 +9,7 @@ use crate::tests::kernel_circuit_output_validator_builder::{KernelCircuitOutputV #[test] fn validate_accumulated_values_note_encrypted_log_hashes_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_note_encrypted_log_hashes(3); builder.output.append_note_encrypted_log_hashes(3); @@ -19,7 +20,7 @@ fn validate_accumulated_values_note_encrypted_log_hashes_succeeds() { #[test] fn validate_accumulated_values_note_encrypted_log_hashes_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_note_encrypted_log_hashes(3); // Swap the items at index 0 and 2. @@ -32,7 +33,7 @@ fn validate_accumulated_values_note_encrypted_log_hashes_unordered_succeeds() { #[test(should_fail_with="mismatch note_encrypted_logs_hash")] fn validate_accumulated_values_note_encrypted_log_hashes_wrong_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_note_encrypted_log_hashes(3); builder.output.append_note_encrypted_log_hashes(3); @@ -49,7 +50,7 @@ fn validate_accumulated_values_note_encrypted_log_hashes_wrong_hash_fails() { #[test] fn validate_accumulated_values_encrypted_log_hashes_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_encrypted_log_hashes(3); builder.output.append_encrypted_log_hashes(3); @@ -60,7 +61,7 @@ fn validate_accumulated_values_encrypted_log_hashes_succeeds() { #[test] fn validate_accumulated_values_encrypted_log_hashes_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_encrypted_log_hashes(3); // Swap the items at index 0 and 2. @@ -73,7 +74,7 @@ fn validate_accumulated_values_encrypted_log_hashes_unordered_succeeds() { #[test(should_fail_with="mismatch encrypted_logs_hash")] fn validate_accumulated_values_encrypted_log_hashes_wrong_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_encrypted_log_hashes(3); builder.output.append_encrypted_log_hashes(3); @@ -90,7 +91,7 @@ fn validate_accumulated_values_encrypted_log_hashes_wrong_hash_fails() { #[test] fn validate_accumulated_values_unencrypted_log_hashes_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_unencrypted_log_hashes(3); builder.output.append_unencrypted_log_hashes(3); @@ -101,7 +102,7 @@ fn validate_accumulated_values_unencrypted_log_hashes_succeeds() { #[test] fn validate_accumulated_values_unencrypted_log_hashes_unordered_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_unencrypted_log_hashes(3); // Swap the items at index 0 and 2. @@ -114,7 +115,7 @@ fn validate_accumulated_values_unencrypted_log_hashes_unordered_succeeds() { #[test(should_fail_with="mismatch unencrypted_logs_hash")] fn validate_accumulated_values_unencrypted_log_hashes_wrong_hash_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.append_unencrypted_log_hashes(3); builder.output.append_unencrypted_log_hashes(3); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_empty_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr similarity index 60% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_empty_values.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr index d68ec1bb7772..cc5020220794 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_empty_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_empty_values.nr @@ -1,14 +1,14 @@ -use crate::tests::kernel_circuit_output_validator_builder::KernelCircuitOutputValidatorBuilder; +use crate::tests::tail_output_validator_builder::TailOutputValidatorBuilder; #[test] fn validate_empty_values_succeeds() { - let builder = KernelCircuitOutputValidatorBuilder::new(); + let builder = TailOutputValidatorBuilder::new(); builder.validate(); } #[test(should_fail_with="start_state must be empty")] fn validate_empty_values_non_empty_start_state_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.output.start_state.public_data_tree.root = 123; @@ -17,7 +17,7 @@ fn validate_empty_values_non_empty_start_state_fails() { #[test(should_fail_with="revert_code must be empty")] fn validate_empty_values_non_empty_revert_code_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.output.revert_code = 1; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr new file mode 100644 index 000000000000..a1d68769169b --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_sorted_siloed_values.nr @@ -0,0 +1,117 @@ +use crate::tests::tail_output_validator_builder::TailOutputValidatorBuilder; +use dep::types::tests::utils::swap_items; + +/** + * note_hashes + */ + +#[test] +fn validate_propagated_sorted_siloed_values_note_hashes_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_note_hashes(3); + builder.output.append_siloed_note_hashes(3); + + builder.validate(); +} + +#[test] +fn validate_propagated_sorted_siloed_values_note_hashes_unordered_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_note_hashes(3); + swap_items(&mut builder.previous_kernel.note_hashes, 0, 2); + for i in 0..3 { + // Need to silo the note hashes in the right order to hash with the correct index. + builder.output.add_siloed_note_hash(builder.previous_kernel.note_hashes.storage[i].value()); + } + swap_items(&mut builder.output.note_hashes, 0, 2); + + builder.validate(); +} + +#[test(should_fail_with="mismatch sorted values")] +fn validate_propagated_sorted_siloed_values_note_hashes_mismatch_hash_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_note_hashes(2); + builder.output.append_siloed_note_hashes(2); + // Tweak the hash in the output. + builder.output.note_hashes.storage[0].note_hash.value += 1; + + builder.validate(); +} + +/** + * nullifiers + */ + +#[test] +fn validate_propagated_sorted_siloed_values_nullifiers_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_nullifiers(3); + builder.output.append_siloed_nullifiers(3); + + builder.validate(); +} + +#[test] +fn validate_propagated_sorted_siloed_values_nullifiers_unordered_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_nullifiers(3); + swap_items(&mut builder.previous_kernel.nullifiers, 0, 3); + builder.output.append_siloed_nullifiers(3); + + builder.validate(); +} + +#[test(should_fail_with="mismatch sorted values")] +fn validate_propagated_sorted_siloed_values_nullifiers_mismatch_hash_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_nullifiers(3); + builder.output.append_siloed_nullifiers(3); + // Tweak the hash in the output. + builder.output.nullifiers.storage[0].nullifier.value += 1; + + builder.validate(); +} + +/** + * l2_to_l1_msgs + */ + +#[test] +fn validate_propagated_sorted_siloed_values_l2_to_l1_msgs_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_l2_to_l1_msgs(2); + builder.output.append_siloed_l2_to_l1_msgs(2); + + builder.validate(); +} + +#[test] +fn validate_propagated_sorted_siloed_values_l2_to_l1_msgs_unordered_succeeds() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_l2_to_l1_msgs(2); + swap_items(&mut builder.previous_kernel.l2_to_l1_msgs, 0, 1); + builder.output.append_siloed_l2_to_l1_msgs(2); + + builder.validate(); +} + +#[test(should_fail_with="mismatch sorted values")] +fn validate_propagated_sorted_siloed_values_l2_to_l1_msgs_mismatch_hash_fails() { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_l2_to_l1_msgs(2); + builder.output.append_siloed_l2_to_l1_msgs(2); + // Tweak the content in the output. + builder.output.l2_to_l1_msgs.storage[0].message.content += 1; + + builder.validate(); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_values.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr similarity index 76% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_values.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr index 1217e37b223e..f5bea6db72fe 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/kernel_circuit_output_validator_builder/validate_propagated_values.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_propagated_values.nr @@ -1,9 +1,9 @@ -use crate::tests::kernel_circuit_output_validator_builder::KernelCircuitOutputValidatorBuilder; +use crate::tests::tail_output_validator_builder::TailOutputValidatorBuilder; use dep::types::address::AztecAddress; #[test] fn validate_propagated_values_constants_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.historical_header.total_fees = 123; builder.output.historical_header.total_fees = 123; @@ -13,7 +13,7 @@ fn validate_propagated_values_constants_succeeds() { #[test(should_fail_with="mismatch constants")] fn validate_propagated_values_constants_mismatch_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.historical_header.total_fees = 123; // Tweak the value in the output. @@ -24,7 +24,7 @@ fn validate_propagated_values_constants_mismatch_fails() { #[test] fn validate_propagated_values_max_block_number_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.set_max_block_number(123); builder.output.set_max_block_number(123); @@ -34,7 +34,7 @@ fn validate_propagated_values_max_block_number_succeeds() { #[test(should_fail_with="mismatch rollup_validation_requests")] fn validate_propagated_values_max_block_number_mismatch_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.set_max_block_number(123); // Tweak the value in the output. @@ -45,7 +45,7 @@ fn validate_propagated_values_max_block_number_mismatch_fails() { #[test] fn validate_propagated_values_fee_payer_succeeds() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.set_fee_payer(AztecAddress::from_field(123)); builder.output.set_fee_payer(AztecAddress::from_field(123)); @@ -55,7 +55,7 @@ fn validate_propagated_values_fee_payer_succeeds() { #[test(should_fail_with="mismatch fee_payer")] fn validate_propagated_values_fee_payer_mismatch_fails() { - let mut builder = KernelCircuitOutputValidatorBuilder::new(); + let mut builder = TailOutputValidatorBuilder::new(); builder.previous_kernel.set_fee_payer(AztecAddress::from_field(123)); // Tweak the value in the output. diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr new file mode 100644 index 000000000000..1d0042bf686d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr @@ -0,0 +1,33 @@ +mod meter_gas_used; +mod split_to_public; +mod tail_to_public_output_composer; + +use crate::components::tail_to_public_output_composer::TailToPublicOutputComposer; +use dep::types::{ + abis::kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + tests::fixture_builder::FixtureBuilder +}; + +struct TailToPublicOutputComposerBuilder { + previous_kernel: FixtureBuilder, +} + +impl TailToPublicOutputComposerBuilder { + pub fn new() -> Self { + let mut previous_kernel = FixtureBuilder::new(); + previous_kernel.set_first_nullifier(); // Need the first nullifier to silo note hashes. + TailToPublicOutputComposerBuilder { previous_kernel } + } + + pub fn with_siloed_data_builder(self) -> (Self, FixtureBuilder) { + let mut siloed_data_builder = FixtureBuilder::new(); + siloed_data_builder.set_first_nullifier(); + (self, siloed_data_builder) + } + + pub fn finish(self) -> PublicKernelCircuitPublicInputs { + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + let composer = TailToPublicOutputComposer::new(previous_kernel); + composer.finish() + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr new file mode 100644 index 000000000000..98b998134ee0 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr @@ -0,0 +1,79 @@ +use crate::components::tail_to_public_output_composer::meter_gas_used::{meter_gas_used_non_revertible, meter_gas_used_revertible}; +use dep::types::{ + abis::gas::Gas, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE}, + tests::fixture_builder::FixtureBuilder +}; + +#[test] +fn meter_gas_used_non_revertible_empty_succeeds() { + let builder = FixtureBuilder::new(); + let data = builder.to_public_accumulated_data_builder(); + let gas = meter_gas_used_non_revertible(data); + assert_eq(gas, Gas::tx_overhead()); +} + +#[test] +fn meter_gas_used_non_revertible_everything_succeeds() { + let mut builder = FixtureBuilder::new(); + + builder.append_note_hashes(4); + builder.append_nullifiers(3); + builder.append_l2_to_l1_msgs(1); + builder.add_note_encrypted_log_hash(1001, 12, 0); + builder.add_note_encrypted_log_hash(1002, 8, 0); + builder.add_note_encrypted_log_hash(1003, 20, 0); + builder.add_encrypted_log_hash(2001, 2); + builder.add_encrypted_log_hash(2002, 6); + builder.add_unencrypted_log_hash(3001, 51); + builder.append_public_call_requests(2); + builder.end_setup(); + + let data = builder.to_public_accumulated_data_builder(); + let gas = meter_gas_used_non_revertible(data); + + let total_num_side_effects = 4 + 3 + 1; + let total_log_length = 12 + 8 + 20 // note_encrypted_log_hash + + 2 + 6 // encrypted_log_hash + + 51; // unencrypted_log_hash + let computed_da_gas = (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; + + assert_eq(gas, Gas::new(computed_da_gas, 0) + Gas::tx_overhead()); +} + +#[test] +fn meter_gas_used_revertible_empty_succeeds() { + let builder = FixtureBuilder::new(); + let data = builder.to_public_accumulated_data_builder(); + let teardown_gas = Gas::new(42, 17); + let gas = meter_gas_used_revertible(data, teardown_gas); + assert_eq(gas, teardown_gas); +} + +#[test] +fn meter_gas_used_revertible_everything_succeeds() { + let mut builder = FixtureBuilder::new(); + + builder.append_note_hashes(4); + builder.append_nullifiers(3); + builder.append_l2_to_l1_msgs(1); + builder.add_note_encrypted_log_hash(1001, 12, 0); + builder.add_note_encrypted_log_hash(1002, 8, 0); + builder.add_note_encrypted_log_hash(1003, 20, 0); + builder.add_encrypted_log_hash(2001, 2); + builder.add_encrypted_log_hash(2002, 6); + builder.add_unencrypted_log_hash(3001, 51); + builder.append_public_call_requests(2); + builder.end_setup(); + + let data = builder.to_public_accumulated_data_builder(); + let teardown_gas = Gas::new(42, 17); + let gas = meter_gas_used_revertible(data, teardown_gas); + + let total_num_side_effects = 4 + 3 + 1; + let total_log_length = 12 + 8 + 20 // note_encrypted_log_hash + + 2 + 6 // encrypted_log_hash + + 51; // unencrypted_log_hash + let computed_da_gas = (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; + + assert_eq(gas, Gas::new(computed_da_gas, 0) + teardown_gas); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr new file mode 100644 index 000000000000..1cb4c9d081da --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr @@ -0,0 +1,108 @@ +use crate::components::tail_to_public_output_composer::split_to_public::split_to_public; +use dep::types::tests::{fixture_builder::FixtureBuilder, utils::assert_array_eq}; + +#[test] +fn split_to_public_succeeds() { + let mut builder = FixtureBuilder::new(); + + // Non-revertibles. + builder.append_note_hashes(2); + builder.append_nullifiers(2); + builder.append_l2_to_l1_msgs(1); + builder.append_note_encrypted_log_hashes(3); + builder.append_encrypted_log_hashes(2); + builder.append_unencrypted_log_hashes(1); + builder.append_public_call_requests(1); + builder.end_setup(); + // Revertibles. + builder.append_note_hashes(3); + builder.append_nullifiers(1); + builder.append_l2_to_l1_msgs(1); + builder.append_note_encrypted_log_hashes(1); + builder.append_encrypted_log_hashes(2); + builder.append_unencrypted_log_hashes(1); + builder.append_public_call_requests(2); + + let combined_data = builder.to_exposed_public_accumulated_data(); + let (non_revertible, revertible) = split_to_public( + builder.to_private_accumulated_data_builder(), + builder.min_revertible_side_effect_counter + ); + + // note_hashes + let expected = combined_data.note_hashes; + assert_array_eq( + non_revertible.note_hashes.storage, + [expected[0], expected[1]] + ); + assert_array_eq( + revertible.note_hashes.storage, + [expected[2], expected[3], expected[4]] + ); + + // nullifiers + let expected = combined_data.nullifiers; + assert_array_eq(non_revertible.nullifiers.storage, [expected[0], expected[1]]); + assert_array_eq(revertible.nullifiers.storage, [expected[2]]); + + // l2_to_l1_msgs + let expected = combined_data.l2_to_l1_msgs; + assert_array_eq(non_revertible.l2_to_l1_msgs.storage, [expected[0]]); + assert_array_eq(revertible.l2_to_l1_msgs.storage, [expected[1]]); + + // note_encrypted_logs_hashes + let expected = combined_data.note_encrypted_logs_hashes; + assert_array_eq( + non_revertible.note_encrypted_logs_hashes.storage, + [expected[0], expected[1], expected[2]] + ); + assert_array_eq(revertible.note_encrypted_logs_hashes.storage, [expected[3]]); + + // encrypted_logs_hashes + let expected = combined_data.encrypted_logs_hashes; + assert_array_eq( + non_revertible.encrypted_logs_hashes.storage, + [expected[0], expected[1]] + ); + assert_array_eq( + revertible.encrypted_logs_hashes.storage, + [expected[2], expected[3]] + ); + + // unencrypted_logs_hashes + let expected = combined_data.unencrypted_logs_hashes; + assert_array_eq(non_revertible.unencrypted_logs_hashes.storage, [expected[0]]); + assert_array_eq(revertible.unencrypted_logs_hashes.storage, [expected[1]]); + + // public_call_stack + let expected = combined_data.public_call_stack; + assert_array_eq(non_revertible.public_call_stack.storage, [expected[0]]); + assert_array_eq( + revertible.public_call_stack.storage, + [expected[1], expected[2]] + ); +} + +#[test] +fn split_to_public_zero_counter_succeeds() { + let mut builder = FixtureBuilder::new(); + + builder.append_note_hashes(2); + builder.set_first_nullifier(); + + let combined_data = builder.to_exposed_public_accumulated_data(); + let (non_revertible, revertible) = split_to_public( + builder.to_private_accumulated_data_builder(), + builder.min_revertible_side_effect_counter + ); + + // note_hashes + let expected = combined_data.note_hashes; + assert_array_eq(non_revertible.note_hashes.storage, []); + assert_array_eq(revertible.note_hashes.storage, [expected[0], expected[1]]); + + // nullifiers + let expected = combined_data.nullifiers; + assert_array_eq(non_revertible.nullifiers.storage, [expected[0]]); + assert_array_eq(revertible.nullifiers.storage, []); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr new file mode 100644 index 000000000000..8f9bb886ae40 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/tail_to_public_output_composer.nr @@ -0,0 +1,144 @@ +use crate::tests::tail_to_public_output_composer_builder::TailToPublicOutputComposerBuilder; +use dep::types::{ + abis::gas::Gas, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE}, + tests::utils::{assert_array_eq, swap_items} +}; + +#[test] +fn tail_to_public_output_composer_succeeds() { + let mut (builder, siloed_data_builder) = TailToPublicOutputComposerBuilder::new().with_siloed_data_builder(); + + let teardown_gas = Gas::new(789, 3254); + builder.previous_kernel.tx_context.gas_settings.teardown_gas_limits = teardown_gas; + + // Non-revertibles. + builder.previous_kernel.append_note_hashes(4); + siloed_data_builder.append_siloed_note_hashes(4); + + builder.previous_kernel.append_nullifiers(2); + siloed_data_builder.append_siloed_nullifiers(2); + + builder.previous_kernel.append_l2_to_l1_msgs(1); + siloed_data_builder.append_siloed_l2_to_l1_msgs(1); + + builder.previous_kernel.add_note_encrypted_log_hash(1001, 12, 0); + builder.previous_kernel.add_note_encrypted_log_hash(1002, 8, 0); + + builder.previous_kernel.add_encrypted_log_hash(2001, 2); + siloed_data_builder.add_siloed_encrypted_log_hash(2001, 2); + + builder.previous_kernel.add_unencrypted_log_hash(3001, 51); + siloed_data_builder.add_siloed_unencrypted_log_hash(3001, 51); + + builder.previous_kernel.append_public_call_requests(2); + + builder.previous_kernel.end_setup(); + + // Revertibles. + builder.previous_kernel.append_note_hashes(2); + siloed_data_builder.append_siloed_note_hashes(2); + + builder.previous_kernel.append_nullifiers(1); + siloed_data_builder.append_siloed_nullifiers(1); + + builder.previous_kernel.append_l2_to_l1_msgs(1); + siloed_data_builder.append_siloed_l2_to_l1_msgs(1); + + builder.previous_kernel.add_note_encrypted_log_hash(1003, 20, 0); + + builder.previous_kernel.add_encrypted_log_hash(2002, 6); + siloed_data_builder.add_siloed_encrypted_log_hash(2002, 6); + builder.previous_kernel.add_encrypted_log_hash(2003, 24); + siloed_data_builder.add_siloed_encrypted_log_hash(2003, 24); + + builder.previous_kernel.add_unencrypted_log_hash(3002, 4); + siloed_data_builder.add_siloed_unencrypted_log_hash(3002, 4); + + builder.previous_kernel.append_public_call_requests(3); + + // Get ordered items before shuffling for verifying with the output later. + let siloed_data = siloed_data_builder.to_exposed_public_accumulated_data(); + let unsiloed_data = builder.previous_kernel.to_exposed_public_accumulated_data(); + + // Shuffle ordered items. + swap_items(&mut builder.previous_kernel.note_hashes, 4, 0); + swap_items(&mut builder.previous_kernel.note_hashes, 3, 2); + swap_items(&mut builder.previous_kernel.nullifiers, 1, 3); + swap_items(&mut builder.previous_kernel.l2_to_l1_msgs, 0, 1); + swap_items(&mut builder.previous_kernel.note_encrypted_logs_hashes, 1, 2); + swap_items(&mut builder.previous_kernel.encrypted_logs_hashes, 1, 2); + swap_items(&mut builder.previous_kernel.public_call_requests, 1, 2); + + // Output. + let output = builder.finish(); + + // note_hashes + let siloed = siloed_data.note_hashes; + assert_array_eq( + output.end_non_revertible.note_hashes, + [siloed[0], siloed[1], siloed[2], siloed[3]] + ); + assert_array_eq(output.end.note_hashes, [siloed[4], siloed[5]]); + + // nullifiers + let siloed = siloed_data.nullifiers; + let unsiloed = unsiloed_data.nullifiers; + assert_array_eq( + output.end_non_revertible.nullifiers, + [unsiloed[0], siloed[1], siloed[2]] + ); + assert_array_eq(output.end.nullifiers, [siloed[3]]); + + // l2_to_l1_msgs + let siloed = siloed_data.l2_to_l1_msgs; + assert_array_eq(output.end_non_revertible.l2_to_l1_msgs, [siloed[0]]); + assert_array_eq(output.end.l2_to_l1_msgs, [siloed[1]]); + + // note_encrypted_logs_hashes + let unsiloed = unsiloed_data.note_encrypted_logs_hashes; + assert_array_eq( + output.end_non_revertible.note_encrypted_logs_hashes, + [unsiloed[0], unsiloed[1]] + ); + assert_array_eq(output.end.note_encrypted_logs_hashes, [unsiloed[2]]); + + // encrypted_logs_hashes + let siloed = siloed_data.encrypted_logs_hashes; + assert_array_eq(output.end_non_revertible.encrypted_logs_hashes, [siloed[0]]); + assert_array_eq(output.end.encrypted_logs_hashes, [siloed[1], siloed[2]]); + + // unencrypted_logs_hashes + let siloed = siloed_data.unencrypted_logs_hashes; + assert_array_eq( + output.end_non_revertible.unencrypted_logs_hashes, + [siloed[0]] + ); + assert_array_eq(output.end.unencrypted_logs_hashes, [siloed[1]]); + + // public_call_stack + let unsiloed = unsiloed_data.public_call_stack; + assert_array_eq( + output.end_non_revertible.public_call_stack, + [unsiloed[1], unsiloed[0]] + ); + assert_array_eq( + output.end.public_call_stack, + [unsiloed[4], unsiloed[3], unsiloed[2]] + ); + + // Gas: non-revertible + let total_num_side_effects = 4 + 3 + 1; + let total_log_length = 12 + 8 // note_encrypted_log_hash + + 2 // encrypted_log_hash + + 51; // unencrypted_log_hash + let computed_da_gas = (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; + assert_eq(output.end_non_revertible.gas_used, Gas::new(computed_da_gas, 0) + Gas::tx_overhead()); + + // Gas: revertible + let total_num_side_effects = 2 + 1 + 1; + let total_log_length = 20 // note_encrypted_log_hash + + 6 + 24 // encrypted_log_hash + + 4; // unencrypted_log_hash + let computed_da_gas = (total_num_side_effects * DA_BYTES_PER_FIELD + total_log_length) * DA_GAS_PER_BYTE; + assert_eq(output.end.gas_used, Gas::new(computed_da_gas, 0) + teardown_gas); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr new file mode 100644 index 000000000000..1a1f05e1893a --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_validator_builder.nr @@ -0,0 +1,27 @@ +use crate::components::tail_to_public_output_validator::TailToPublicOutputValidator; +use dep::types::tests::fixture_builder::FixtureBuilder; + +struct TailToPublicOutputValidatorBuilder { + output: FixtureBuilder, + previous_kernel: FixtureBuilder +} + +impl TailToPublicOutputValidatorBuilder { + pub fn new() -> Self { + let mut output = FixtureBuilder::new(); + let mut previous_kernel = FixtureBuilder::new(); + output.set_first_nullifier(); + previous_kernel.set_first_nullifier(); + TailToPublicOutputValidatorBuilder { output, previous_kernel } + } + + pub fn validate(self) { + // TODO: Split the data using min_revertible_side_effect_counter in FixtureBuilder. + let revertible = true; + let output = self.output.to_public_kernel_circuit_public_inputs(revertible); + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + TailToPublicOutputValidator::new(output, previous_kernel).validate(); + } +} + +// TODO: Add tests. \ No newline at end of file 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 7304e26463a5..4dfe96d6083c 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 @@ -10,7 +10,7 @@ use dep::types::{ address::AztecAddress, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, constants::{ - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, MAX_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_UNENCRYPTED_LOGS_PER_CALL @@ -73,9 +73,9 @@ pub fn initialize_end_values( circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder ) { let start = previous_kernel.public_inputs.end; - circuit_outputs.end.new_note_hashes = array_to_bounded_vec(start.new_note_hashes); - 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.note_hashes = array_to_bounded_vec(start.note_hashes); + circuit_outputs.end.nullifiers = array_to_bounded_vec(start.nullifiers); + circuit_outputs.end.l2_to_l1_msgs = array_to_bounded_vec(start.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_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); circuit_outputs.end.note_encrypted_logs_hashes = array_to_bounded_vec(start.note_encrypted_logs_hashes); @@ -97,9 +97,9 @@ pub fn initialize_non_revertible_values( circuit_outputs.end_non_revertible.gas_used = previous_kernel.public_inputs.end_non_revertible.gas_used; let start_non_revertible = previous_kernel.public_inputs.end_non_revertible; - circuit_outputs.end_non_revertible.new_note_hashes = array_to_bounded_vec(start_non_revertible.new_note_hashes); - 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.note_hashes = array_to_bounded_vec(start_non_revertible.note_hashes); + circuit_outputs.end_non_revertible.nullifiers = array_to_bounded_vec(start_non_revertible.nullifiers); + circuit_outputs.end_non_revertible.l2_to_l1_msgs = array_to_bounded_vec(start_non_revertible.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_hashes = array_to_bounded_vec(start_non_revertible.unencrypted_logs_hashes); circuit_outputs.end_non_revertible.note_encrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.note_encrypted_logs_hashes); @@ -117,19 +117,19 @@ fn perform_static_call_checks(public_call: PublicCallData) { let public_inputs = public_call.call_stack_item.public_inputs; if public_inputs.call_context.is_static_call { // No state changes are allowed for static calls: - let new_note_hashes_length = array_length(public_inputs.new_note_hashes); - assert(new_note_hashes_length == 0, "new_note_hashes must be empty for static calls"); + let note_hashes_length = array_length(public_inputs.note_hashes); + assert(note_hashes_length == 0, "note_hashes must be empty for static calls"); - let new_nullifiers_length = array_length(public_inputs.new_nullifiers); - assert(new_nullifiers_length == 0, "new_nullifiers must be empty for static calls"); + let nullifiers_length = array_length(public_inputs.nullifiers); + assert(nullifiers_length == 0, "nullifiers must be empty for static calls"); let update_requests_length = array_length(public_inputs.contract_storage_update_requests); assert( update_requests_length == 0, "No contract storage update requests are allowed for static calls" ); - let new_l2_to_l1_msgs_length = array_length(public_inputs.new_l2_to_l1_msgs); - assert(new_l2_to_l1_msgs_length == 0, "new_l2_to_l1_msgs must be empty for static calls"); + let l2_to_l1_msgs_length = array_length(public_inputs.l2_to_l1_msgs); + assert(l2_to_l1_msgs_length == 0, "l2_to_l1_msgs must be empty for static calls"); let new_unencrypted_logs_length = array_length(public_inputs.unencrypted_logs_hashes); assert(new_unencrypted_logs_length == 0, "No unencrypted logs are allowed for static calls"); @@ -279,8 +279,8 @@ pub fn update_public_end_non_revertible_values( // If this call is a static call, certain operations are disallowed, such as creating new state. perform_static_call_checks(public_call); - propagate_new_nullifiers_non_revertible(public_call, circuit_outputs); - propagate_new_note_hashes_non_revertible(public_call, circuit_outputs); + propagate_nullifiers_non_revertible(public_call, circuit_outputs); + propagate_note_hashes_non_revertible(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); @@ -292,8 +292,8 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m // If this call is a static call, certain operations are disallowed, such as creating new state. perform_static_call_checks(public_call); - propagate_new_nullifiers(public_call, circuit_outputs); - propagate_new_note_hashes(public_call, circuit_outputs); + propagate_nullifiers(public_call, circuit_outputs); + propagate_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); @@ -386,96 +386,79 @@ fn propagate_valid_public_data_reads(public_call: PublicCallData, circuit_output circuit_outputs.validation_requests.public_data_reads.extend_from_bounded_vec(public_data_reads); } -fn propagate_new_note_hashes_non_revertible( +fn propagate_note_hashes_non_revertible( public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder ) { let public_call_public_inputs = public_call.call_stack_item.public_inputs; - let new_note_hashes = public_call.call_stack_item.public_inputs.new_note_hashes; + let note_hashes = public_call.call_stack_item.public_inputs.note_hashes; let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; - let mut siloed_new_note_hashes : BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL { - let new_note_hash = new_note_hashes[i].value; + let mut siloed_note_hashes : BoundedVec = BoundedVec::new(); + for i in 0..MAX_NOTE_HASHES_PER_CALL { + let new_note_hash = note_hashes[i].value; if new_note_hash != 0 { let siloed_new_note_hash = compute_siloed_note_hash(storage_contract_address, new_note_hash); - siloed_new_note_hashes.push(NoteHash { value: siloed_new_note_hash, counter: new_note_hashes[i].counter }); + siloed_note_hashes.push(NoteHash { value: siloed_new_note_hash, counter: note_hashes[i].counter }); } } - circuit_outputs.end_non_revertible.new_note_hashes.extend_from_bounded_vec(siloed_new_note_hashes); + circuit_outputs.end_non_revertible.note_hashes.extend_from_bounded_vec(siloed_note_hashes); } -fn propagate_new_note_hashes( - public_call: PublicCallData, - circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder -) { +fn propagate_note_hashes(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { let public_call_public_inputs = public_call.call_stack_item.public_inputs; - let new_note_hashes = public_call.call_stack_item.public_inputs.new_note_hashes; + let note_hashes = public_call.call_stack_item.public_inputs.note_hashes; let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; - let mut siloed_new_note_hashes : BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL { - let new_note_hash = new_note_hashes[i].value; + let mut siloed_note_hashes : BoundedVec = BoundedVec::new(); + for i in 0..MAX_NOTE_HASHES_PER_CALL { + let new_note_hash = note_hashes[i].value; if new_note_hash != 0 { let siloed_new_note_hash = compute_siloed_note_hash(storage_contract_address, new_note_hash); - siloed_new_note_hashes.push(NoteHash { value: siloed_new_note_hash, counter: new_note_hashes[i].counter }); + siloed_note_hashes.push(NoteHash { value: siloed_new_note_hash, counter: note_hashes[i].counter }); } } - circuit_outputs.end.new_note_hashes.extend_from_bounded_vec(siloed_new_note_hashes); + circuit_outputs.end.note_hashes.extend_from_bounded_vec(siloed_note_hashes); } -fn propagate_new_nullifiers_non_revertible( - public_call: PublicCallData, - circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder -) { - let new_nullifiers = public_call.call_stack_item.public_inputs.new_nullifiers; +fn propagate_nullifiers_non_revertible(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { + let nullifiers = public_call.call_stack_item.public_inputs.nullifiers; let storage_contract_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; // Enhance commitments and nullifiers with domain separation whereby domain is the contract. - let mut siloed_new_nullifiers : BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NULLIFIERS_PER_CALL { - let new_nullifier = new_nullifiers[i].value; + let mut siloed_nullifiers : BoundedVec = BoundedVec::new(); + for i in 0..MAX_NULLIFIERS_PER_CALL { + let new_nullifier = nullifiers[i].value; if new_nullifier != 0 { let siloed_new_nullifier = compute_siloed_nullifier(storage_contract_address, new_nullifier); - siloed_new_nullifiers.push( - Nullifier { - value: siloed_new_nullifier, - counter: new_nullifiers[i].counter, - note_hash: new_nullifiers[i].note_hash - } + siloed_nullifiers.push( + Nullifier { value: siloed_new_nullifier, counter: nullifiers[i].counter, note_hash: nullifiers[i].note_hash } ); } } - circuit_outputs.end_non_revertible.new_nullifiers.extend_from_bounded_vec(siloed_new_nullifiers); + circuit_outputs.end_non_revertible.nullifiers.extend_from_bounded_vec(siloed_nullifiers); } -fn propagate_new_nullifiers( - public_call: PublicCallData, - circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder -) { - let new_nullifiers = public_call.call_stack_item.public_inputs.new_nullifiers; +fn propagate_nullifiers(public_call: PublicCallData, circuit_outputs: &mut PublicKernelCircuitPublicInputsBuilder) { + let nullifiers = public_call.call_stack_item.public_inputs.nullifiers; let storage_contract_address = public_call.call_stack_item.public_inputs.call_context.storage_contract_address; // Enhance commitments and nullifiers with domain separation whereby domain is the contract. - let mut siloed_new_nullifiers : BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NULLIFIERS_PER_CALL { - let new_nullifier = new_nullifiers[i].value; + let mut siloed_nullifiers : BoundedVec = BoundedVec::new(); + for i in 0..MAX_NULLIFIERS_PER_CALL { + let new_nullifier = nullifiers[i].value; if new_nullifier != 0 { let siloed_new_nullifier = compute_siloed_nullifier(storage_contract_address, new_nullifier); - siloed_new_nullifiers.push( - Nullifier { - value: siloed_new_nullifier, - counter: new_nullifiers[i].counter, - note_hash: new_nullifiers[i].note_hash - } + siloed_nullifiers.push( + Nullifier { value: siloed_new_nullifier, counter: nullifiers[i].counter, note_hash: nullifiers[i].note_hash } ); } } - circuit_outputs.end.new_nullifiers.extend_from_bounded_vec(siloed_new_nullifiers); + circuit_outputs.end.nullifiers.extend_from_bounded_vec(siloed_nullifiers); } fn propagate_new_l2_to_l1_messages_non_revertible( @@ -486,22 +469,22 @@ fn propagate_new_l2_to_l1_messages_non_revertible( 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]; + let l2_to_l1_msgs = public_call_public_inputs.l2_to_l1_msgs; + let mut l2_to_l1_msgs_to_insert : BoundedVec = BoundedVec::new(); + for i in 0..MAX_L2_TO_L1_MSGS_PER_CALL { + let msg = l2_to_l1_msgs[i]; if !is_empty(msg) { - let new_l2_to_l1_msgs = compute_l2_to_l1_hash( + let l2_to_l1_msgs = compute_l2_to_l1_hash( storage_contract_address, msg.recipient, msg.content, public_inputs.constants.tx_context.version, public_inputs.constants.tx_context.chain_id ); - new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) + l2_to_l1_msgs_to_insert.push(l2_to_l1_msgs) } } - public_inputs.end_non_revertible.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); + public_inputs.end_non_revertible.l2_to_l1_msgs.extend_from_bounded_vec(l2_to_l1_msgs_to_insert); } fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { @@ -509,22 +492,22 @@ fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: & 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]; + let l2_to_l1_msgs = public_call_public_inputs.l2_to_l1_msgs; + let mut l2_to_l1_msgs_to_insert : BoundedVec = BoundedVec::new(); + for i in 0..MAX_L2_TO_L1_MSGS_PER_CALL { + let msg = l2_to_l1_msgs[i]; if !is_empty(msg) { - let new_l2_to_l1_msgs = compute_l2_to_l1_hash( + let l2_to_l1_msgs = compute_l2_to_l1_hash( storage_contract_address, msg.recipient, msg.content, public_inputs.constants.tx_context.version, public_inputs.constants.tx_context.chain_id ); - new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) + l2_to_l1_msgs_to_insert.push(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.l2_to_l1_msgs.extend_from_bounded_vec(l2_to_l1_msgs_to_insert); } pub fn propagate_new_unencrypted_logs(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { 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 212a3e710c58..da8ea3554bf8 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 @@ -213,27 +213,28 @@ mod tests { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); let contract_address = builder.public_call.contract_address; // Setup 2 new note hashes and logs on the previous kernel. - builder.previous_kernel.append_new_note_hashes_with_logs(2); - let previous = builder.previous_kernel.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash); + builder.previous_kernel.append_note_hashes_with_logs(2); + let previous = builder.previous_kernel.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash); + let prev_data = builder.previous_kernel.to_public_accumulated_data(); + let prev_note_logs = prev_data.note_encrypted_logs_hashes; // Setup 2 new note hashes on the current public inputs. let current = [ NoteHash { value: previous[1].value + 1, counter: 5 }, NoteHash { value: previous[1].value + 2, counter: 6 } ]; - let note_logs = builder.previous_kernel.note_encrypted_logs_hashes.storage; - builder.public_call.public_inputs.new_note_hashes.extend_from_array(current); + builder.public_call.public_inputs.note_hashes.extend_from_array(current); let siloed = current.map(|c: NoteHash| compute_siloed_note_hash(contract_address, c.value)); - let new_note_hashes = [ + let note_hashes = [ previous[0], previous[1], NoteHash { value: siloed[0], counter: 5 }, NoteHash { value: siloed[1], counter: 6 } ]; let public_inputs = builder.execute(); - assert(array_eq(public_inputs.end.new_note_hashes, new_note_hashes)); + assert(array_eq(public_inputs.end.note_hashes, note_hashes)); assert( array_eq( public_inputs.end.note_encrypted_logs_hashes, - [note_logs[0].expose_to_public(), note_logs[1].expose_to_public()] + [prev_note_logs[0], prev_note_logs[1]] ) ); } @@ -281,14 +282,14 @@ mod tests { let contract_address = builder.public_call.contract_address; // Setup 2 new nullifiers on the previous kernel. - builder.previous_kernel.append_new_nullifiers(2); - let previous = builder.previous_kernel.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier); + builder.previous_kernel.append_nullifiers(2); + let previous = builder.previous_kernel.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier); // Setup 2 new note hashes on the current public inputs. let current = [ Nullifier { value: previous[1].value + 1, note_hash: 0, counter: 4 }, Nullifier { value: previous[1].value + 2, note_hash: 0, counter: 5 } ]; - builder.public_call.public_inputs.new_nullifiers.extend_from_array(current); + builder.public_call.public_inputs.nullifiers.extend_from_array(current); let siloed = current.map( |current: Nullifier| @@ -297,11 +298,11 @@ mod tests { // There are 2 revertible nullifiers in the previous kernel. // The tx nullifier is part of the non-revertible nullifiers. - let new_nullifiers = [previous[0], previous[1], siloed[0], siloed[1]]; + let nullifiers = [previous[0], previous[1], siloed[0], siloed[1]]; let public_inputs = builder.execute(); - assert(array_eq(public_inputs.end.new_nullifiers, new_nullifiers)); + assert(array_eq(public_inputs.end.nullifiers, nullifiers)); } #[test] @@ -316,17 +317,17 @@ mod tests { builder.previous_kernel.add_l2_to_l1_message(previous[0], portal_contract_address); // Setup 1 new l2 to l1 message on the current public inputs. let current = [L2ToL1Message { recipient: portal_contract_address, content: 67890, counter: 0 }]; - builder.public_call.public_inputs.new_l2_to_l1_msgs.extend_from_array(current); + builder.public_call.public_inputs.l2_to_l1_msgs.extend_from_array(current); let tx_context = builder.previous_kernel.tx_context; let version = tx_context.version; let chain_id = tx_context.chain_id; let siloed = current.map( |c: L2ToL1Message| compute_l2_to_l1_hash(contract_address, c.recipient, c.content, version, chain_id) ); - let new_l2_to_l1_msgs = [previous[0], siloed[0]]; + let l2_to_l1_msgs = [previous[0], siloed[0]]; let public_inputs = builder.execute(); - assert(array_eq(public_inputs.end.new_l2_to_l1_msgs, new_l2_to_l1_msgs)); + assert(array_eq(public_inputs.end.l2_to_l1_msgs, l2_to_l1_msgs)); } // TODO: Break up this test into smaller tests. #[test] @@ -347,14 +348,15 @@ mod tests { prev_unencrypted_logs_hash, prev_unencrypted_log_preimages_length ); + let prev_data = builder.previous_kernel.to_public_accumulated_data(); let mut expected_unencrypted_logs = [ - builder.previous_kernel.unencrypted_logs_hashes.storage[0].log_hash, builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] ]; // silo the new log hash expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels - let expected_encrypted_logs = [builder.previous_kernel.encrypted_logs_hashes.storage[0].expose_to_public()]; + let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; let public_inputs = builder.execute(); @@ -390,20 +392,20 @@ mod tests { builder.failed(); } - #[test(should_fail_with="new_note_hashes must be empty for static calls")] - fn public_kernel_fails_creating_new_note_hashes_on_static_call() { + #[test(should_fail_with="note_hashes must be empty for static calls")] + fn public_kernel_fails_creating_note_hashes_on_static_call() { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.call_context.is_static_call = true; - builder.public_call.public_inputs.new_note_hashes.push(NoteHash { value: 1, counter: 0 }); + builder.public_call.public_inputs.note_hashes.push(NoteHash { value: 1, counter: 0 }); builder.failed(); } - #[test(should_fail_with="new_nullifiers must be empty for static calls")] - fn public_kernel_fails_creating_new_nullifiers_on_static_call() { + #[test(should_fail_with="nullifiers must be empty for static calls")] + fn public_kernel_fails_creating_nullifiers_on_static_call() { let mut builder = PublicKernelAppLogicCircuitPrivateInputsBuilder::new(); builder.public_call.public_inputs.call_context.is_static_call = true; - builder.public_call.public_inputs.new_nullifiers.push(Nullifier { value: 1, note_hash: 0, counter: 0 }); + builder.public_call.public_inputs.nullifiers.push(Nullifier { value: 1, note_hash: 0, counter: 0 }); builder.failed(); } 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 648606d1a4cf..a041fc2a56f7 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 @@ -448,14 +448,15 @@ mod tests { prev_unencrypted_logs_hash, prev_unencrypted_log_preimages_length ); + let prev_data = builder.previous_kernel.to_public_accumulated_data(); let mut expected_unencrypted_logs = [ - builder.previous_kernel.unencrypted_logs_hashes.storage[0].log_hash, builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] ]; // silo the new log hash expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels - let expected_encrypted_logs = [builder.previous_kernel.encrypted_logs_hashes.storage[0].expose_to_public()]; + let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; let public_inputs = builder.execute(); 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 f87434c241cc..bcb64d69486d 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 @@ -9,10 +9,7 @@ use dep::types::{ kernel_circuit_public_inputs::KernelCircuitPublicInputs, public_kernel_data::PublicKernelData, public_data_update_request::PublicDataUpdateRequest, side_effect::Ordered }, - constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX -}, + constants::{MAX_PUBLIC_DATA_HINTS, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX}, data::public_data_hint::PublicDataHint, merkle_tree::{conditionally_assert_check_membership, MembershipWitness}, partial_state_reference::PartialStateReference, utils::{arrays::array_length}, address::AztecAddress @@ -109,7 +106,7 @@ mod tests { }, address::AztecAddress, constants::{ - MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, + MAX_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, MAX_ENCRYPTED_LOGS_PER_TX, @@ -117,13 +114,14 @@ mod tests { }, hash::{compute_siloed_nullifier, sha256_to_field}, public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, - tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree, sort::sort_get_sorted_hints}, + tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree}, traits::is_empty, partial_state_reference::PartialStateReference, - utils::arrays::{array_length, array_merge}, merkle_tree::MembershipWitness + utils::arrays::{array_length, array_merge, sort_get_sorted_hints}, + merkle_tree::MembershipWitness }; - fn build_nullifier_tree() -> NonEmptyMerkleTree { - let mut pre_existing_nullifiers = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX]; + fn build_nullifier_tree() -> NonEmptyMerkleTree { + let mut pre_existing_nullifiers = [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX]; pre_existing_nullifiers[0] = NullifierLeafPreimage { nullifier: 0, next_nullifier: 100, next_index: 1 }; pre_existing_nullifiers[1] = NullifierLeafPreimage { nullifier: 100, next_nullifier: 0, next_index: 0 }; NonEmptyMerkleTree::new( @@ -219,8 +217,8 @@ mod tests { fn set_nullifiers_for_non_existent_read_request_hints(&mut self) { let nullifiers = array_merge( - self.previous_kernel.new_nullifiers.storage, - self.previous_revertible.new_nullifiers.storage + self.previous_kernel.nullifiers.storage, + self.previous_revertible.nullifiers.storage ).map(|n: ScopedNullifier| n.nullifier); self.nullifier_non_existent_read_request_hints_builder.set_nullifiers(nullifiers); } @@ -229,7 +227,7 @@ mod tests { let read_request_index = self.previous_kernel.add_read_request_for_pending_nullifier(nullifier_index); self.sync_counters(); let hint_index = self.nullifier_read_request_hints_builder.pending_read_hints.len(); - let pending_value_index = nullifier_index + self.previous_kernel.new_nullifiers.len(); + let pending_value_index = nullifier_index + self.previous_kernel.nullifiers.len(); let hint = PendingReadHint { read_request_index, pending_value_index }; self.nullifier_read_request_hints_builder.pending_read_hints.push(hint); self.nullifier_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; @@ -302,8 +300,8 @@ mod tests { // Note: note hashes are a bit odd here: whereas we'd like to use `combined` and then // sort the result, we cannot because we lose the side effect counters when we combine. let merged = array_merge( - previous_kernel.public_inputs.end_non_revertible.new_note_hashes, - previous_kernel.public_inputs.end.new_note_hashes + previous_kernel.public_inputs.end_non_revertible.note_hashes, + previous_kernel.public_inputs.end.note_hashes ); let sorted = sort_get_sorted_hints(merged, |a: NoteHash, b: NoteHash| a.counter() < b.counter()); let sorted_note_hashes = sorted.sorted_array; @@ -454,7 +452,7 @@ mod tests { builder.append_nullifiers_revertible(3); builder.add_pending_revertible_nullifier_read_request(1); - let nullifier_being_read = builder.previous_revertible.new_nullifiers.get(1); + let nullifier_being_read = builder.previous_revertible.nullifiers.get(1); let mut read_request = builder.previous_kernel.nullifier_read_requests.pop(); read_request.read_request.counter = nullifier_being_read.counter() - 1; builder.previous_kernel.nullifier_read_requests.push(read_request); 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 a9c104a3ce77..1063374ec22e 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 @@ -432,14 +432,15 @@ mod tests { prev_unencrypted_logs_hash, prev_unencrypted_log_preimages_length ); + let prev_data = builder.previous_kernel.to_public_accumulated_data(); let mut expected_unencrypted_logs = [ - builder.previous_kernel.unencrypted_logs_hashes.storage[0].log_hash, builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] + prev_data.unencrypted_logs_hashes[0], builder.public_call.public_inputs.unencrypted_logs_hashes.storage[0] ]; // silo the new log hash expected_unencrypted_logs[1].value = compute_siloed_unencrypted_log_hash(builder.public_call.contract_address, expected_unencrypted_logs[1].value); // we assume the encrypted log is already siloed from private kernels - let expected_encrypted_logs = [builder.previous_kernel.encrypted_logs_hashes.storage[0].expose_to_public()]; + let expected_encrypted_logs = [prev_data.encrypted_logs_hashes[0]]; let public_inputs = builder.execute(); 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 b9c8b19879c7..fef20b6eeb99 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 @@ -2,7 +2,7 @@ use crate::reset::non_existent_read_request::NonMembershipHint; use dep::types::{ abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage}, merkle_tree::MembershipWitness, - constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT} + constants::{MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT} }; struct NullifierNonMembershipHint { @@ -22,7 +22,7 @@ impl NonMembershipHint for Nullifi struct NullifierNonExistentReadRequestHints { non_membership_hints: [NullifierNonMembershipHint; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], - sorted_pending_values: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], - sorted_pending_value_index_hints: [u32; MAX_NEW_NULLIFIERS_PER_TX], + sorted_pending_values: [Nullifier; MAX_NULLIFIERS_PER_TX], + sorted_pending_value_index_hints: [u32; MAX_NULLIFIERS_PER_TX], next_pending_value_indices: [u32; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX], } 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 ca1fcea8f668..94500890172d 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 @@ -10,7 +10,7 @@ use dep::types::{ read_request::ScopedReadRequest }, constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, GENERATOR_INDEX__NSK_M, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, hash::poseidon2_hash, traits::is_empty, @@ -20,10 +20,10 @@ use dep::types::{ struct PrivateValidationRequestProcessor { validation_requests: ValidationRequests, note_hash_read_request_hints: NoteHashReadRequestHints, - pending_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], + pending_note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], note_hash_tree_root: Field, nullifier_read_request_hints: NullifierReadRequestHints, - pending_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], + pending_nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], nullifier_tree_root: Field, key_validation_hints: [KeyValidationHint; KEY_VALIDATION_REQUESTS], } 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 index fc72928b3858..c0d9adf33139 100644 --- 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 @@ -13,14 +13,14 @@ use dep::types::{ public_data_update_request::PublicDataUpdateRequest, validation_requests::ValidationRequests }, data::public_data_hint::PublicDataHint, - constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, + constants::{MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX}, hash::compute_siloed_nullifier, traits::is_empty, utils::arrays::{array_merge, array_to_bounded_vec, assert_sorted_array} }; struct PublicValidationRequestProcessor { validation_requests: ValidationRequests, - pending_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + pending_nullifiers: [Nullifier; MAX_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, @@ -41,7 +41,7 @@ impl PublicValidationRequestProcessor { 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_nullifiers = array_merge(end_non_revertible.nullifiers, end.nullifiers); let pending_public_data_writes = array_merge( end_non_revertible.public_data_update_requests, 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/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr rename to noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests.nr rename to noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr index 7d05daec74a0..1d9a3e601658 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/tests/nullifier_non_existent_read_request_hints_builder.nr @@ -2,19 +2,18 @@ use crate::nullifier_non_existent_read_request_reset::{NullifierNonMembershipHin use dep::types::{ abis::{nullifier::Nullifier, nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ - MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT }, - merkle_tree::MembershipWitness, - tests::{merkle_tree_utils::NonEmptyMerkleTree, sort::sort_get_sorted_hints}, - utils::{arrays::find_index, field::full_field_greater_than} + merkle_tree::MembershipWitness, tests::{merkle_tree_utils::NonEmptyMerkleTree}, + utils::{arrays::{find_index, sort_get_sorted_hints}, field::full_field_greater_than} }; struct NullifierNonExistentReadRequestHintsBuilder { - nullifier_tree: NonEmptyMerkleTree, + nullifier_tree: NonEmptyMerkleTree, non_membership_hints: BoundedVec, read_values: BoundedVec, - pending_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], + pending_nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], } impl NullifierNonExistentReadRequestHintsBuilder { @@ -23,18 +22,18 @@ impl NullifierNonExistentReadRequestHintsBuilder { nullifier_tree: NonEmptyMerkleTree::empty(), non_membership_hints: BoundedVec::new(), read_values: BoundedVec::new(), - pending_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX] + pending_nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_TX] } } pub fn set_nullifier_tree( &mut self, - tree: NonEmptyMerkleTree + tree: NonEmptyMerkleTree ) { self.nullifier_tree = tree; } - pub fn set_nullifiers(&mut self, nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX]) { + pub fn set_nullifiers(&mut self, nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX]) { self.pending_nullifiers = nullifiers; } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr index 0b643692f67f..cbe1a5cb28b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/base_or_merge_rollup_public_inputs.nr @@ -12,9 +12,7 @@ struct BaseOrMergeRollupPublicInputs { // rollup_type is either 0 (base) or 1 (merge) // TODO(Kev): Why is this a u32 instead of a u8/u16? rollup_type : u32, - // subtree height is always 0 for base. - // so that we always pass-in two base/merge circuits of the same height into the next level of recursion - height_in_block_tree : Field, + num_txs : u32, constants : ConstantRollupData, start: PartialStateReference, @@ -35,7 +33,7 @@ impl Empty for BaseOrMergeRollupPublicInputs { fn empty() -> Self { BaseOrMergeRollupPublicInputs { rollup_type : 0 as u32, - height_in_block_tree : 0, + num_txs : 0 as u32, constants : ConstantRollupData::empty(), start: PartialStateReference::empty(), end: PartialStateReference::empty(), @@ -49,7 +47,7 @@ impl Empty for BaseOrMergeRollupPublicInputs { impl Eq for BaseOrMergeRollupPublicInputs { fn eq(self, other: Self) -> bool { (self.rollup_type == other.rollup_type) & - (self.height_in_block_tree == other.height_in_block_tree) & + (self.num_txs == other.num_txs) & (self.constants.eq(other.constants)) & (self.start.eq(other.start)) & (self.end.eq(other.end)) & @@ -64,7 +62,7 @@ impl Serialize for BaseOrMergeRollupPublicIn let mut fields: BoundedVec = BoundedVec::new(); fields.push(self.rollup_type as Field); - fields.push(self.height_in_block_tree as Field); + fields.push(self.num_txs as Field); fields.extend_from_array(self.constants.serialize()); fields.extend_from_array(self.start.serialize()); fields.extend_from_array(self.end.serialize()); @@ -83,7 +81,7 @@ impl Deserialize for BaseOrMergeRollupPublic let mut reader = Reader::new(fields); let item = Self { rollup_type: reader.read() as u32, - height_in_block_tree: reader.read(), + num_txs: reader.read() as u32, constants: reader.read_struct(ConstantRollupData::deserialize), start: reader.read_struct(PartialStateReference::deserialize), end: reader.read_struct(PartialStateReference::deserialize), diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/constant_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/constant_rollup_data.nr index 6bfb8ffe1118..ef4065bb9ee0 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/constant_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/constant_rollup_data.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use dep::types::{ abis::{global_variables::GlobalVariables, append_only_tree_snapshot::AppendOnlyTreeSnapshot}, traits::{Empty, Serialize, Deserialize}, constants::CONSTANT_ROLLUP_DATA_LENGTH, diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis.nr rename to noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr index cf68a864de9e..a0faee5bfeaa 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/previous_rollup_data.nr @@ -16,7 +16,7 @@ struct PreviousRollupData{ impl Verifiable for PreviousRollupData { fn verify(self) { let inputs = BaseOrMergeRollupPublicInputs::serialize(self.base_or_merge_rollup_public_inputs); - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), 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 d7d42d779cef..0c2d7e31d487 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 @@ -20,10 +20,10 @@ use dep::types::{ }, constants::{ NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, - PUBLIC_DATA_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, MAX_NEW_NOTE_HASHES_PER_TX, - MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, - NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_HEIGHT, + PUBLIC_DATA_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NULLIFIER_TREE_HEIGHT, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_HEIGHT, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ARCHIVE_HEIGHT, GAS_TOKEN_ADDRESS, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }, @@ -128,7 +128,7 @@ impl BaseRollupInputs { BaseOrMergeRollupPublicInputs { rollup_type: BASE_ROLLUP_TYPE, - height_in_block_tree: 0, + num_txs: 1, constants: self.constants, start: self.start, end: PartialStateReference { @@ -145,13 +145,13 @@ impl BaseRollupInputs { // TODO(Kev): This should say calculate_commitments_subtree_root // Cpp code says calculate_commitments_subtree, so I'm leaving it as is for now fn calculate_commitments_subtree(self) -> Field { - calculate_subtree_root(self.kernel_data.public_inputs.end.new_note_hashes) + calculate_subtree_root(self.kernel_data.public_inputs.end.note_hashes) } fn check_nullifier_tree_non_membership_and_insert_to_tree(self) -> AppendOnlyTreeSnapshot { indexed_tree::batch_insert( self.start.nullifier_tree, - self.kernel_data.public_inputs.end.new_nullifiers, + self.kernel_data.public_inputs.end.nullifiers, self.state_diff_hints.sorted_nullifiers, self.state_diff_hints.sorted_nullifier_indexes, self.state_diff_hints.nullifier_subtree_sibling_path, @@ -410,7 +410,7 @@ fn compute_fee_payer_gas_token_balance_leaf_slot(fee_payer: AztecAddress) -> Fie #[test] fn consistent_not_hash_subtree_width() { assert_eq( - MAX_NEW_NOTE_HASHES_PER_TX as Field, 2.pow_32(NOTE_HASH_SUBTREE_HEIGHT as Field), "note hash subtree width is incorrect" + MAX_NOTE_HASHES_PER_TX as Field, 2.pow_32(NOTE_HASH_SUBTREE_HEIGHT as Field), "note hash subtree width is incorrect" ); } @@ -455,12 +455,11 @@ mod tests { address::{AztecAddress, EthAddress}, constants::{ ARCHIVE_HEIGHT, MAX_PUBLIC_DATA_READS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NOTE_HASH_TREE_HEIGHT, NOTE_HASH_SUBTREE_HEIGHT, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, - PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, MAX_L2_TO_L1_MSGS_PER_TX, + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }, contract_class_id::ContractClassId, partial_state_reference::PartialStateReference, public_data_tree_leaf::PublicDataTreeLeaf, @@ -478,7 +477,7 @@ mod tests { value: Field, } - global MAX_NEW_NULLIFIERS_PER_TEST = 4; + global MAX_nullifiers_PER_TEST = 4; global MAX_PUBLIC_DATA_READS_PER_TEST = 2; fn update_public_data_tree( @@ -571,8 +570,8 @@ mod tests { struct BaseRollupInputsBuilder { kernel_data: FixtureBuilder, - pre_existing_notes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], - pre_existing_nullifiers: [NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], + pre_existing_notes: [Field; MAX_NOTE_HASHES_PER_TX], + pre_existing_nullifiers: [NullifierLeafPreimage; MAX_NULLIFIERS_PER_TX], pre_existing_contracts: [Field; 2], pre_existing_public_data: [PublicDataTreeLeafPreimage; MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], pre_existing_blocks: [Field; 2], @@ -583,7 +582,7 @@ mod tests { protocol_public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>, // Public data writes after processing by the base rollup circuit (defaults to public_data_writes ++ protocol_public_data_writes if empty) final_public_data_writes: BoundedVec<(u32, PublicDataTreeLeaf), MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX>, - new_nullifiers: BoundedVec, + nullifiers: BoundedVec, constants: ConstantRollupData, // Index of the item in the pre_existing_public_data array that contains the fee payer's gas token balance. // Used for building the public data hint read for the payment update request. If set to none, no hint is built. @@ -640,23 +639,23 @@ mod tests { fn update_nullifier_tree_with_new_leaves( mut self, - nullifier_tree: &mut NonEmptyMerkleTree, + nullifier_tree: &mut NonEmptyMerkleTree, kernel_data: &mut KernelData, start_nullifier_tree_snapshot: AppendOnlyTreeSnapshot - ) -> ([NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], [MembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], [Field; MAX_NEW_NULLIFIERS_PER_TX], [u32; MAX_NEW_NULLIFIERS_PER_TX]) { - let mut nullifier_predecessor_preimages = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX]; - let mut low_nullifier_membership_witness = [MembershipWitness::empty(); MAX_NEW_NULLIFIERS_PER_TX]; + ) -> ([NullifierLeafPreimage; MAX_NULLIFIERS_PER_TX], [MembershipWitness; MAX_NULLIFIERS_PER_TX], [Field; MAX_NULLIFIERS_PER_TX], [u32; MAX_NULLIFIERS_PER_TX]) { + let mut nullifier_predecessor_preimages = [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX]; + let mut low_nullifier_membership_witness = [MembershipWitness::empty(); MAX_NULLIFIERS_PER_TX]; let sorted_new_nullifier_tuples = sort_high_to_low( - self.new_nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), + self.nullifiers.storage.map(|insertion: NullifierInsertion| insertion.value), full_field_less_than ); - let mut sorted_nullifiers = [0; MAX_NEW_NULLIFIERS_PER_TX]; - let mut sorted_nullifiers_indexes = [0; MAX_NEW_NULLIFIERS_PER_TX]; + let mut sorted_nullifiers = [0; MAX_NULLIFIERS_PER_TX]; + let mut sorted_nullifiers_indexes = [0; MAX_NULLIFIERS_PER_TX]; - for i in 0..MAX_NEW_NULLIFIERS_PER_TX { - if (i as u32) < (MAX_NEW_NULLIFIERS_PER_TEST as u32) { + for i in 0..MAX_NULLIFIERS_PER_TX { + if (i as u32) < (MAX_nullifiers_PER_TEST as u32) { sorted_nullifiers[i] = sorted_new_nullifier_tuples[i].value; sorted_nullifiers_indexes[i] = sorted_new_nullifier_tuples[i].original_index; } else { @@ -667,15 +666,15 @@ mod tests { let mut pre_existing_nullifiers = self.pre_existing_nullifiers; - for i in 0..MAX_NEW_NULLIFIERS_PER_TEST { - if i < self.new_nullifiers.len() { + for i in 0..MAX_nullifiers_PER_TEST { + if i < self.nullifiers.len() { let sorted_tuple = sorted_new_nullifier_tuples[i]; let new_nullifier = sorted_tuple.value; let original_index = sorted_tuple.original_index; - let low_index = self.new_nullifiers.get_unchecked(original_index).existing_index; + let low_index = self.nullifiers.get_unchecked(original_index).existing_index; - kernel_data.public_inputs.end.new_nullifiers[original_index] = new_nullifier; + kernel_data.public_inputs.end.nullifiers[original_index] = new_nullifier; let mut low_preimage = pre_existing_nullifiers[low_index]; nullifier_predecessor_preimages[i] = low_preimage; @@ -831,8 +830,8 @@ mod tests { fn empty() -> Self { BaseRollupInputsBuilder { kernel_data: FixtureBuilder::new(), - pre_existing_notes: [0; MAX_NEW_NOTE_HASHES_PER_TX], - pre_existing_nullifiers: [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX], + pre_existing_notes: [0; MAX_NOTE_HASHES_PER_TX], + pre_existing_nullifiers: [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX], pre_existing_contracts: [0; 2], pre_existing_public_data: [PublicDataTreeLeafPreimage::empty(); MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], pre_existing_blocks: [0; 2], @@ -840,7 +839,7 @@ mod tests { public_data_writes: BoundedVec::new(), protocol_public_data_writes: BoundedVec::new(), final_public_data_writes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), + nullifiers: BoundedVec::new(), constants: ConstantRollupData::empty(), fee_payer_gas_token_balance_pre_existing_public_data_index: Option::none() } @@ -848,33 +847,30 @@ mod tests { } #[test] - unconstrained fn new_note_hashes_tree() { + unconstrained fn note_hashes_tree() { let mut builder = BaseRollupInputsBuilder::new(); - let new_note_hashes = [27, 28, 29, 30, 31, 32]; - for i in 0..new_note_hashes.len() { - builder.kernel_data.add_new_note_hash(new_note_hashes[i], 0); + let note_hashes = [27, 28, 29, 30, 31, 32]; + for i in 0..note_hashes.len() { + builder.kernel_data.add_new_note_hash(note_hashes[i], 0); } let mut expected_commitments_tree = NonEmptyMerkleTree::new( - [0; MAX_NEW_NOTE_HASHES_PER_TX * 2], + [0; MAX_NOTE_HASHES_PER_TX * 2], [0; NOTE_HASH_TREE_HEIGHT], [0; NOTE_HASH_TREE_HEIGHT - NOTE_HASH_SUBTREE_HEIGHT - 1], [0; NOTE_HASH_SUBTREE_HEIGHT + 1] ); let outputs = builder.execute(); - let expected_start_note_hash_tree_snapshot = AppendOnlyTreeSnapshot { - root: expected_commitments_tree.get_root(), - next_available_leaf_index: MAX_NEW_NOTE_HASHES_PER_TX as u32 - }; + let expected_start_note_hash_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_commitments_tree.get_root(), next_available_leaf_index: MAX_NOTE_HASHES_PER_TX as u32 }; assert(outputs.start.note_hash_tree.eq(expected_start_note_hash_tree_snapshot)); - for i in 0..new_note_hashes.len() { - expected_commitments_tree.update_leaf(i + MAX_NEW_NOTE_HASHES_PER_TX, new_note_hashes[i]); + for i in 0..note_hashes.len() { + expected_commitments_tree.update_leaf(i + MAX_NOTE_HASHES_PER_TX, note_hashes[i]); } let expected_end_note_hash_tree_snapshot = AppendOnlyTreeSnapshot { root: expected_commitments_tree.get_root(), - next_available_leaf_index: (MAX_NEW_NOTE_HASHES_PER_TX * 2) as u32 + next_available_leaf_index: (MAX_NOTE_HASHES_PER_TX * 2) as u32 }; assert(outputs.end.note_hash_tree.eq(expected_end_note_hash_tree_snapshot)); } @@ -921,15 +917,15 @@ mod tests { next_index : 0, }; - builder.new_nullifiers.push(NullifierInsertion { existing_index: 0, value: 1 }); - let mut tree_nullifiers = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX * 2]; + builder.nullifiers.push(NullifierInsertion { existing_index: 0, value: 1 }); + let mut tree_nullifiers = [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX * 2]; tree_nullifiers[0] = NullifierLeafPreimage { nullifier : 0, next_nullifier : 1, - next_index : MAX_NEW_NULLIFIERS_PER_TX, + next_index : MAX_NULLIFIERS_PER_TX, }; tree_nullifiers[1] = builder.pre_existing_nullifiers[1]; - tree_nullifiers[MAX_NEW_NULLIFIERS_PER_TX] = NullifierLeafPreimage { + tree_nullifiers[MAX_NULLIFIERS_PER_TX] = NullifierLeafPreimage { nullifier : 1, next_nullifier : 7, next_index : 1, @@ -946,7 +942,7 @@ mod tests { assert( output.end.nullifier_tree.eq( - AppendOnlyTreeSnapshot { root: end_nullifier_tree.get_root(), next_available_leaf_index: 2 * MAX_NEW_NULLIFIERS_PER_TX as u32 } + AppendOnlyTreeSnapshot { root: end_nullifier_tree.get_root(), next_available_leaf_index: 2 * MAX_NULLIFIERS_PER_TX as u32 } ) ); } @@ -966,30 +962,30 @@ mod tests { next_index : 0, }; - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); - for i in 1..builder.new_nullifiers.max_len() { - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: (8 + i) as Field }); + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); + for i in 1..builder.nullifiers.max_len() { + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: (8 + i) as Field }); } let output = builder.execute(); - let mut tree_nullifiers = [NullifierLeafPreimage::empty(); MAX_NEW_NULLIFIERS_PER_TX * 2]; + let mut tree_nullifiers = [NullifierLeafPreimage::empty(); MAX_NULLIFIERS_PER_TX * 2]; tree_nullifiers[0] = builder.pre_existing_nullifiers[0]; tree_nullifiers[1] = NullifierLeafPreimage { nullifier : 7, next_nullifier : 8, - next_index : MAX_NEW_NULLIFIERS_PER_TX, + next_index : MAX_NULLIFIERS_PER_TX, }; - let last_index = builder.new_nullifiers.max_len() - 1; + let last_index = builder.nullifiers.max_len() - 1; for i in 0..last_index { - tree_nullifiers[MAX_NEW_NULLIFIERS_PER_TX + i] = NullifierLeafPreimage { + tree_nullifiers[MAX_NULLIFIERS_PER_TX + i] = NullifierLeafPreimage { nullifier : (8 + i) as Field, next_nullifier : (8 + i + 1) as Field, - next_index : MAX_NEW_NULLIFIERS_PER_TX + i + 1, + next_index : MAX_NULLIFIERS_PER_TX + i + 1, }; } - tree_nullifiers[MAX_NEW_NULLIFIERS_PER_TX+last_index] = NullifierLeafPreimage { + tree_nullifiers[MAX_NULLIFIERS_PER_TX+last_index] = NullifierLeafPreimage { nullifier : (8 + last_index) as Field, next_nullifier : 0, next_index : 0, @@ -1004,7 +1000,7 @@ mod tests { assert( output.end.nullifier_tree.eq( - AppendOnlyTreeSnapshot { root: end_nullifier_tree.get_root(), next_available_leaf_index: 2 * MAX_NEW_NULLIFIERS_PER_TX as u32 } + AppendOnlyTreeSnapshot { root: end_nullifier_tree.get_root(), next_available_leaf_index: 2 * MAX_NULLIFIERS_PER_TX as u32 } ) ); } @@ -1024,8 +1020,8 @@ mod tests { next_index : 0, }; - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); builder.fails(); } @@ -1045,8 +1041,8 @@ mod tests { next_index : 0, }; - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); - builder.new_nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); + builder.nullifiers.push(NullifierInsertion { existing_index: 1, value: 8 }); builder.fails(); } @@ -1056,7 +1052,7 @@ mod tests { let outputs = BaseRollupInputsBuilder::new().execute(); let hash_input_flattened = [0; TX_EFFECTS_HASH_INPUT_FIELDS * 32]; - let sha_digest = dep::std::hash::sha256(hash_input_flattened); + let sha_digest = std::hash::sha256(hash_input_flattened); let expected_tx_effects_hash = field_from_bytes_32_trunc(sha_digest); assert_eq(outputs.txs_effects_hash, expected_tx_effects_hash); } @@ -1067,7 +1063,7 @@ mod tests { // For now setting an empty out hash to be H(0,0) to keep consistent // with prev work. let hash_input_flattened = [0; 64]; - let sha_digest = dep::std::hash::sha256(hash_input_flattened); + let sha_digest = std::hash::sha256(hash_input_flattened); let expected_out_hash = field_from_bytes_32_trunc(sha_digest); assert_eq(outputs.out_hash, expected_out_hash); } @@ -1075,13 +1071,13 @@ mod tests { #[test] unconstrained fn nonempty_block_out_hash() { let mut end = CombinedAccumulatedData::empty(); - for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - end.new_l2_to_l1_msgs[i] = 10 + i as Field; + for i in 0..MAX_L2_TO_L1_MSGS_PER_TX { + end.l2_to_l1_msgs[i] = 10 + i as Field; } let out_hash = compute_kernel_out_hash(end); // Since we fill the tree completely, we know to expect a full tree as below - let expected_tree = dep::types::merkle_tree::variable_merkle_tree::tests::generate_full_sha_tree(end.new_l2_to_l1_msgs); + let expected_tree = dep::types::merkle_tree::variable_merkle_tree::tests::generate_full_sha_tree(end.l2_to_l1_msgs); assert_eq(out_hash, expected_tree.get_root()); } @@ -1147,10 +1143,10 @@ mod tests { } #[test] - unconstrained fn subtree_height_is_0() { + unconstrained fn num_txs_is_1() { let outputs = BaseRollupInputsBuilder::new().execute(); - assert_eq(outputs.height_in_block_tree, 0); + assert_eq(outputs.num_txs, 1); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base.nr rename to noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr index a4479a8b9170..91f2cc0a31bb 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/state_diff_hints.nr @@ -1,19 +1,18 @@ use dep::types::{ abis::{nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ - MAX_NEW_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, - NULLIFIER_TREE_HEIGHT + MAX_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT }, merkle_tree::MembershipWitness }; struct StateDiffHints { - nullifier_predecessor_preimages: [NullifierLeafPreimage; MAX_NEW_NULLIFIERS_PER_TX], - nullifier_predecessor_membership_witnesses: [MembershipWitness; MAX_NEW_NULLIFIERS_PER_TX], + nullifier_predecessor_preimages: [NullifierLeafPreimage; MAX_NULLIFIERS_PER_TX], + nullifier_predecessor_membership_witnesses: [MembershipWitness; MAX_NULLIFIERS_PER_TX], - sorted_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], - sorted_nullifier_indexes: [u32; MAX_NEW_NULLIFIERS_PER_TX], + sorted_nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + sorted_nullifier_indexes: [u32; MAX_NULLIFIERS_PER_TX], // For inserting the new subtrees into their respective trees: // Note: the insertion leaf index can be derived from the snapshots' `next_available_leaf_index` values (tree diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index e74c8398eaff..78a138dd4f3c 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -3,7 +3,7 @@ use crate::abis::previous_rollup_data::PreviousRollupData; use dep::types::{ hash::accumulate_sha256, merkle_tree::VariableMerkleTree, constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX }, @@ -15,28 +15,29 @@ use dep::types::{ }; /** - * Asserts that the rollup types are the same. - * Either both merge or both base + * Asserts that the tree formed by rollup circuits is filled greedily from L to R + * */ -pub fn assert_both_input_proofs_of_same_rollup_type( +pub fn assert_txs_filled_from_left( left: BaseOrMergeRollupPublicInputs, right: BaseOrMergeRollupPublicInputs ) { - assert(left.rollup_type == right.rollup_type, "input proofs are of different rollup types"); -} - -/** - * Asserts that the rollup subtree heights are the same and returns the height - * Returns the height of the rollup subtrees - */ -pub fn assert_both_input_proofs_of_same_height_and_return( - left: BaseOrMergeRollupPublicInputs, - right: BaseOrMergeRollupPublicInputs -) -> Field { - assert( - left.height_in_block_tree == right.height_in_block_tree, "input proofs are of different rollup heights" - ); - left.height_in_block_tree + // assert that the left rollup is either a base (1 tx) or a balanced tree (num txs = power of 2) + if (left.rollup_type == 1) { + let left_txs = left.num_txs; + let right_txs = right.num_txs; + // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 + assert( + (left_txs) & (left_txs - 1) == 0, "The rollup should be filled greedily from L to R, but received an unbalanced left subtree" + ); + assert( + right_txs <= left_txs, "The rollup should be filled greedily from L to R, but received a L txs < R txs" + ); + } else { + assert( + right.rollup_type == 0, "The rollup should be filled greedily from L to R, but received a L base and R merge" + ); + } } /** @@ -90,8 +91,8 @@ pub fn compute_out_hash(previous_rollup_data: [PreviousRollupData; 2]) -> Field } pub fn compute_kernel_out_hash(combined: CombinedAccumulatedData) -> Field { - let non_empty_items = array_length(combined.new_l2_to_l1_msgs); - let merkle_tree = VariableMerkleTree::new_sha(combined.new_l2_to_l1_msgs, non_empty_items); + let non_empty_items = array_length(combined.l2_to_l1_msgs); + let merkle_tree = VariableMerkleTree::new_sha(combined.l2_to_l1_msgs, non_empty_items); merkle_tree.get_root() } @@ -113,9 +114,9 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - // Tx effects hash consists of // 1 field for revert code // 1 field for transaction fee -// MAX_NEW_NOTE_HASHES_PER_TX fields for note hashes -// MAX_NEW_NULLIFIERS_PER_TX fields for nullifiers -// MAX_NEW_L2_TO_L1_MSGS_PER_TX fields for L2 to L1 messages +// MAX_NOTE_HASHES_PER_TX fields for note hashes +// MAX_NULLIFIERS_PER_TX fields for nullifiers +// MAX_L2_TO_L1_MSGS_PER_TX fields for L2 to L1 messages // MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX public data update requests -> MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 fields // __ // 1 note encrypted logs length --> 1 field | @@ -125,7 +126,7 @@ pub fn compute_txs_effects_hash(previous_rollup_data: [PreviousRollupData; 2]) - // 1 note encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | // 1 encrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! | -> 3 types of logs - 3 fields for its hashes // 1 unencrypted logs hash --> 1 sha256 hash -> 31 bytes -> 1 fields | Beware when populating bytes that we fill (prepend) to 32! __| -global TX_EFFECTS_HASH_INPUT_FIELDS = 1 + 1 + MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + 3 + 3; +global TX_EFFECTS_HASH_INPUT_FIELDS = 1 + 1 + MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 + 3 + 3; // Computes the tx effects hash for a base rollup (a single transaction) // TODO(Alvaro): This is too slow for brillig without the array optimization @@ -137,9 +138,9 @@ pub fn compute_tx_effects_hash( ) -> Field { let mut tx_effects_hash_input = [0; TX_EFFECTS_HASH_INPUT_FIELDS]; - let new_note_hashes = combined.new_note_hashes; - let new_nullifiers = combined.new_nullifiers; - let new_l2_to_l1_msgs = combined.new_l2_to_l1_msgs; + let note_hashes = combined.note_hashes; + let nullifiers = combined.nullifiers; + let l2_to_l1_msgs = combined.l2_to_l1_msgs; // Public writes are the concatenation of all non-empty user update requests and protocol update requests, then padded with zeroes. // The incoming all_public_data_update_requests may have empty update requests in the middle, so we move those to the end of the array. @@ -163,22 +164,22 @@ pub fn compute_tx_effects_hash( offset += 1; // NOTE HASHES - for j in 0..MAX_NEW_NOTE_HASHES_PER_TX { - tx_effects_hash_input[offset + j] = new_note_hashes[j]; + for j in 0..MAX_NOTE_HASHES_PER_TX { + tx_effects_hash_input[offset + j] = note_hashes[j]; } - offset += MAX_NEW_NOTE_HASHES_PER_TX ; + offset += MAX_NOTE_HASHES_PER_TX ; // NULLIFIERS - for j in 0..MAX_NEW_NULLIFIERS_PER_TX { - tx_effects_hash_input[offset + j] = new_nullifiers[j]; + for j in 0..MAX_NULLIFIERS_PER_TX { + tx_effects_hash_input[offset + j] = nullifiers[j]; } - offset += MAX_NEW_NULLIFIERS_PER_TX ; + offset += MAX_NULLIFIERS_PER_TX ; // L2 TO L1 MESSAGES - for j in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - tx_effects_hash_input[offset + j] = new_l2_to_l1_msgs[j]; + for j in 0..MAX_L2_TO_L1_MSGS_PER_TX { + tx_effects_hash_input[offset + j] = l2_to_l1_msgs[j]; } - offset += MAX_NEW_L2_TO_L1_MSGS_PER_TX; + offset += MAX_L2_TO_L1_MSGS_PER_TX; // PUBLIC DATA UPDATE REQUESTS for j in 0..MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { @@ -241,10 +242,10 @@ fn get_all_update_requests_for_tx_effects(all_public_data_update_requests: [Publ fn consistent_TX_EFFECTS_HASH_INPUT_FIELDS() { let expected_size = 1 // revert code + 1 // transaction fee - + MAX_NEW_NOTE_HASHES_PER_TX - + MAX_NEW_NULLIFIERS_PER_TX + + MAX_NOTE_HASHES_PER_TX + + MAX_NULLIFIERS_PER_TX + MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2 - + MAX_NEW_L2_TO_L1_MSGS_PER_TX + + MAX_L2_TO_L1_MSGS_PER_TX + 3 // logs lengths + 3; // logs hashes assert(TX_EFFECTS_HASH_INPUT_FIELDS == expected_size, "tx effects hash input size is incorrect"); diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr index daa66bfff13d..0fbdc3d22d48 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/merge_rollup_inputs.nr @@ -28,10 +28,7 @@ impl MergeRollupInputs { let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; let right = self.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - // check that both input proofs are either both "BASE" or "MERGE" and not a mix! - // this prevents having wonky commitment, nullifier and contract subtrees. - components::assert_both_input_proofs_of_same_rollup_type(left, right); - let current_height = components::assert_both_input_proofs_of_same_height_and_return(left, right); + components::assert_txs_filled_from_left(left, right); components::assert_equal_constants(left, right); components::assert_prev_rollups_follow_on_from_each_other(left, right); @@ -43,7 +40,7 @@ impl MergeRollupInputs { let public_inputs = BaseOrMergeRollupPublicInputs { rollup_type: MERGE_ROLLUP_TYPE, - height_in_block_tree: current_height + 1, + num_txs: left.num_txs + right.num_txs, constants: left.constants, start: left.start, end: right.end, @@ -63,7 +60,7 @@ mod tests { }; use dep::types::hash::accumulate_sha256; - #[test(should_fail_with="input proofs are of different rollup types")] + #[test(should_fail_with="The rollup should be filled greedily from L to R, but received a L base and R merge")] fn different_rollup_type_fails() { let mut inputs = default_merge_rollup_inputs(); inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 0; @@ -71,14 +68,6 @@ mod tests { let _output = inputs.merge_rollup_circuit(); } - #[test(should_fail_with="input proofs are of different rollup heights")] - fn different_height_fails() { - let mut inputs = default_merge_rollup_inputs(); - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 0; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; - let _output = inputs.merge_rollup_circuit(); - } - #[test(should_fail_with="input proofs have different constants")] fn constants_different_fails() { let mut inputs = default_merge_rollup_inputs(); @@ -116,20 +105,44 @@ mod tests { let mut inputs = default_merge_rollup_inputs(); let mut outputs = inputs.merge_rollup_circuit(); assert_eq(outputs.rollup_type, 1); - assert_eq( - outputs.height_in_block_tree, inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree + 1 - ); + assert_eq(outputs.num_txs, 2); // set inputs to have a merge rollup type and set the rollup height and test again. inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 2; inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; - inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 2; outputs = inputs.merge_rollup_circuit(); assert_eq(outputs.rollup_type, 1); - assert_eq(outputs.height_in_block_tree, 2); + assert_eq(outputs.num_txs, 4); + } + + #[test] + fn tx_subtrees_are_set_correctly() { + let mut inputs = default_merge_rollup_inputs(); + let mut outputs = inputs.merge_rollup_circuit(); + // Start with two bases => two single txs + assert_eq(outputs.num_txs, 2); + // Test one merge of 2 merged with one base + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 2; + outputs = inputs.merge_rollup_circuit(); + // Should have one subtree of size 2, and one of size 1 + assert_eq(outputs.num_txs, 3); + // Test two merges, each with a subtree of 2 + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = 1; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 2; + outputs = inputs.merge_rollup_circuit(); + // Should have one subtree of size 4 + assert_eq(outputs.num_txs, 4); + + // Test two merges, one with a subtree of 16, one with subtrees of 4 and 1 + inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 16; + inputs.previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 5; + outputs = inputs.merge_rollup_circuit(); + assert_eq(outputs.num_txs, 21); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge.nr rename to noir-projects/noir-protocol-circuits/crates/rollup-lib/src/merge/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root.nr rename to noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index e1742efb8abc..365d288359c4 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -2,9 +2,8 @@ use crate::{ abis::{previous_rollup_data::PreviousRollupData, constant_rollup_data::ConstantRollupData}, components, root::{root_rollup_public_inputs::RootRollupPublicInputs} }; -use dep::{ - std, parity_lib::{root::root_rollup_parity_input::RootRollupParityInput, ParityPublicInputs}, - types::{ +use parity_lib::{root::root_rollup_parity_input::RootRollupParityInput, ParityPublicInputs}; +use types::{ abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, L1_TO_L2_MSG_SUBTREE_HEIGHT, @@ -13,7 +12,6 @@ use dep::{ header::Header, content_commitment::ContentCommitment, merkle_tree::{append_only_tree, calculate_subtree_root, calculate_empty_tree_root}, state_reference::StateReference, traits::Empty -} }; struct RootRollupInputs { @@ -23,8 +21,8 @@ struct RootRollupInputs { l1_to_l2_roots: RootRollupParityInput, // inputs required to process l1 to l2 messages - new_l1_to_l2_messages : [Field; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP], - new_l1_to_l2_message_tree_root_sibling_path : [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH], + l1_to_l2_messages : [Field; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP], + l1_to_l2_message_subtree_sibling_path : [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH], start_l1_to_l2_message_tree_snapshot : AppendOnlyTreeSnapshot, @@ -45,8 +43,7 @@ impl RootRollupInputs { let left = self.previous_rollup_data[0].base_or_merge_rollup_public_inputs; let right = self.previous_rollup_data[1].base_or_merge_rollup_public_inputs; - components::assert_both_input_proofs_of_same_rollup_type(left, right); - let _ = components::assert_both_input_proofs_of_same_height_and_return(left, right); + components::assert_txs_filled_from_left(left, right); components::assert_equal_constants(left, right); components::assert_prev_rollups_follow_on_from_each_other(left, right); @@ -54,7 +51,7 @@ impl RootRollupInputs { let empty_l1_to_l2_subtree_root = calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_HEIGHT); let new_l1_to_l2_message_tree_snapshot = append_only_tree::insert_subtree_to_snapshot_tree( self.start_l1_to_l2_message_tree_snapshot, - self.new_l1_to_l2_message_tree_root_sibling_path, + self.l1_to_l2_message_subtree_sibling_path, empty_l1_to_l2_subtree_root, self.l1_to_l2_roots.public_inputs.converted_root, // TODO(Kev): For now we can add a test that this fits inside of @@ -65,7 +62,7 @@ impl RootRollupInputs { let state = StateReference { l1_to_l2_message_tree: new_l1_to_l2_message_tree_snapshot, partial: right.end }; let content_commitment = ContentCommitment { - tx_tree_height: right.height_in_block_tree + 1, + num_txs: (left.num_txs + right.num_txs) as Field, txs_effects_hash: components::compute_txs_effects_hash(self.previous_rollup_data), in_hash: self.l1_to_l2_roots.public_inputs.sha_root, out_hash: components::compute_out_hash(self.previous_rollup_data) @@ -102,8 +99,8 @@ impl Empty for RootRollupInputs { RootRollupInputs { previous_rollup_data : [PreviousRollupData::empty(); 2], l1_to_l2_roots: RootRollupParityInput::empty(), - new_l1_to_l2_messages : [0; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP], - new_l1_to_l2_message_tree_root_sibling_path : [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH], + l1_to_l2_messages : [0; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP], + l1_to_l2_message_subtree_sibling_path : [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH], start_l1_to_l2_message_tree_snapshot : AppendOnlyTreeSnapshot::zero(), start_archive_snapshot : AppendOnlyTreeSnapshot::zero(), new_archive_sibling_path : [0; ARCHIVE_HEIGHT], diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests.nr rename to noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr index df34d71d8668..52edabc33e68 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_data.nr @@ -59,8 +59,8 @@ pub fn default_previous_rollup_data() -> [PreviousRollupData; 2] { previous_rollup_data[0].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE; previous_rollup_data[1].base_or_merge_rollup_public_inputs.rollup_type = BASE_ROLLUP_TYPE; - previous_rollup_data[0].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; - previous_rollup_data[1].base_or_merge_rollup_public_inputs.height_in_block_tree = 1; + previous_rollup_data[0].base_or_merge_rollup_public_inputs.num_txs = 1; + previous_rollup_data[1].base_or_merge_rollup_public_inputs.num_txs = 1; previous_rollup_data[0].base_or_merge_rollup_public_inputs.txs_effects_hash = 1; previous_rollup_data[1].base_or_merge_rollup_public_inputs.txs_effects_hash = 2; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/root_rollup_inputs.nr index 03ac395b32d5..fec7e28ec225 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/root_rollup_inputs.nr @@ -11,15 +11,15 @@ use crate::tests::previous_rollup_data::default_previous_rollup_data; pub fn compute_l1_l2_empty_snapshot() -> (AppendOnlyTreeSnapshot, [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH]) { let zero_hashes = compute_zero_hashes([0; L1_TO_L2_MSG_TREE_HEIGHT]); - let mut new_l1_to_l2_message_tree_root_sibling_path = [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH]; + let mut l1_to_l2_message_subtree_sibling_path = [0; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH]; for i in 0..L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH { let index = L1_TO_L2_MSG_SUBTREE_HEIGHT + i - 1; - new_l1_to_l2_message_tree_root_sibling_path[i] = zero_hashes[index]; + l1_to_l2_message_subtree_sibling_path[i] = zero_hashes[index]; } ( - AppendOnlyTreeSnapshot { root: zero_hashes[zero_hashes.len() - 1], next_available_leaf_index: 0 }, new_l1_to_l2_message_tree_root_sibling_path + AppendOnlyTreeSnapshot { root: zero_hashes[zero_hashes.len() - 1], next_available_leaf_index: 0 }, l1_to_l2_message_subtree_sibling_path ) } @@ -38,7 +38,7 @@ pub fn default_root_rollup_inputs() -> RootRollupInputs { let mut inputs = RootRollupInputs::empty(); let (l1_l2_empty_snapshot, l1_l2_empty_sibling_path) = compute_l1_l2_empty_snapshot(); - inputs.new_l1_to_l2_message_tree_root_sibling_path = l1_l2_empty_sibling_path; + inputs.l1_to_l2_message_subtree_sibling_path = l1_l2_empty_sibling_path; inputs.start_l1_to_l2_message_tree_snapshot = l1_l2_empty_snapshot; let (blocks_snapshot, blocks_sibling_path) = compute_archive_snapshot(); 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 f23ee1363c4d..9f0cbf36b2dd 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 @@ -6,7 +6,7 @@ use crate::{ log_hash::{LogHash, NoteLogHash}, gas::Gas, side_effect::{Ordered, Positioned} }, constants::{ - MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, COMBINED_ACCUMULATED_DATA_LENGTH, MAX_UNENCRYPTED_LOGS_PER_TX }, @@ -15,8 +15,8 @@ use crate::{ }; struct CombineHints { - sorted_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - sorted_note_hashes_indexes: [u32; MAX_NEW_NOTE_HASHES_PER_TX], + sorted_note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_TX], + sorted_note_hashes_indexes: [u32; MAX_NOTE_HASHES_PER_TX], sorted_unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_TX], sorted_unencrypted_logs_hashes_indexes: [u32; MAX_UNENCRYPTED_LOGS_PER_TX], // the public data update requests are sorted by their leaf index AND counter @@ -28,9 +28,9 @@ struct CombineHints { } struct CombinedAccumulatedData { - new_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + nullifiers: [Field; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hash: Field, encrypted_logs_hash: Field, @@ -57,7 +57,7 @@ impl CombinedAccumulatedData { revertible: PublicAccumulatedData, combine_hints: CombineHints ) -> Self { - let merged_note_hashes = array_merge(non_revertible.new_note_hashes, revertible.new_note_hashes); + let merged_note_hashes = array_merge(non_revertible.note_hashes, revertible.note_hashes); assert_sorted_array( merged_note_hashes, combine_hints.sorted_note_hashes, @@ -116,12 +116,9 @@ impl CombinedAccumulatedData { let unencrypted_log_preimages_length = non_revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length) + revertible.unencrypted_logs_hashes.fold(0, |a, b: LogHash| a + b.length); CombinedAccumulatedData { - new_note_hashes: combine_hints.sorted_note_hashes.map(|n: NoteHash| n.value), - new_nullifiers: array_merge(non_revertible.new_nullifiers, revertible.new_nullifiers).map(|n: Nullifier| n.value), - new_l2_to_l1_msgs: array_merge( - non_revertible.new_l2_to_l1_msgs, - revertible.new_l2_to_l1_msgs - ), + note_hashes: combine_hints.sorted_note_hashes.map(|n: NoteHash| n.value), + nullifiers: array_merge(non_revertible.nullifiers, revertible.nullifiers).map(|n: Nullifier| n.value), + l2_to_l1_msgs: array_merge(non_revertible.l2_to_l1_msgs, revertible.l2_to_l1_msgs), note_encrypted_logs_hash, encrypted_logs_hash, unencrypted_logs_hash, @@ -137,9 +134,9 @@ impl CombinedAccumulatedData { impl Empty for CombinedAccumulatedData { fn empty() -> Self { CombinedAccumulatedData { - new_note_hashes: [0; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [0; MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [0; MAX_NOTE_HASHES_PER_TX], + nullifiers: [0; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [0; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hash: 0, encrypted_logs_hash: 0, unencrypted_logs_hash: 0, @@ -156,9 +153,9 @@ impl Serialize for CombinedAccumulatedData { fn serialize(self) -> [Field; COMBINED_ACCUMULATED_DATA_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - fields.extend_from_array(self.new_note_hashes); - fields.extend_from_array(self.new_nullifiers); - fields.extend_from_array(self.new_l2_to_l1_msgs); + fields.extend_from_array(self.note_hashes); + fields.extend_from_array(self.nullifiers); + fields.extend_from_array(self.l2_to_l1_msgs); fields.push(self.note_encrypted_logs_hash); fields.push(self.encrypted_logs_hash); fields.push(self.unencrypted_logs_hash); @@ -183,9 +180,9 @@ impl Deserialize for CombinedAccumulatedData { let mut reader = Reader::new(fields); let item = CombinedAccumulatedData { - new_note_hashes: reader.read_array([0; MAX_NEW_NOTE_HASHES_PER_TX]), - new_nullifiers: reader.read_array([0; MAX_NEW_NULLIFIERS_PER_TX]), - new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_TX]), + note_hashes: reader.read_array([0; MAX_NOTE_HASHES_PER_TX]), + nullifiers: reader.read_array([0; MAX_NULLIFIERS_PER_TX]), + l2_to_l1_msgs: reader.read_array([0; MAX_L2_TO_L1_MSGS_PER_TX]), note_encrypted_logs_hash: reader.read(), encrypted_logs_hash: reader.read(), unencrypted_logs_hash: reader.read(), @@ -202,9 +199,9 @@ impl Deserialize for CombinedAccumulatedData { impl Eq for CombinedAccumulatedData { fn eq(self, other: Self) -> bool { - (self.new_note_hashes == other.new_note_hashes) & - (self.new_nullifiers == other.new_nullifiers) & - (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_hashes == other.note_hashes) & + (self.nullifiers == other.nullifiers) & + (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hash == other.note_encrypted_logs_hash) & (self.encrypted_logs_hash == other.encrypted_logs_hash) & (self.unencrypted_logs_hash == other.unencrypted_logs_hash) & 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 7e1eda7a5721..fe8491707574 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 @@ -8,15 +8,15 @@ use crate::{ utils::reader::Reader }; 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_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, PRIVATE_ACCUMULATED_DATA_LENGTH }; struct PrivateAccumulatedData { - new_note_hashes: [ScopedNoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [ScopedNullifier; MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [ScopedNoteHash; MAX_NOTE_HASHES_PER_TX], + nullifiers: [ScopedNullifier; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedEncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_TX], @@ -30,16 +30,16 @@ impl Serialize for PrivateAccumulatedData { fn serialize(self) -> [Field; PRIVATE_ACCUMULATED_DATA_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { - fields.extend_from_array(self.new_note_hashes[i].serialize()); + for i in 0..MAX_NOTE_HASHES_PER_TX { + fields.extend_from_array(self.note_hashes[i].serialize()); } - for i in 0..MAX_NEW_NULLIFIERS_PER_TX { - fields.extend_from_array(self.new_nullifiers[i].serialize()); + for i in 0..MAX_NULLIFIERS_PER_TX { + fields.extend_from_array(self.nullifiers[i].serialize()); } - for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); + for i in 0..MAX_L2_TO_L1_MSGS_PER_TX { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); } for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { @@ -73,9 +73,9 @@ impl Deserialize for PrivateAccumulatedData { let mut reader = Reader::new(fields); let item = PrivateAccumulatedData { - new_note_hashes: reader.read_struct_array(ScopedNoteHash::deserialize, [ScopedNoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX]), - new_nullifiers: reader.read_struct_array(ScopedNullifier::deserialize, [ScopedNullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX]), - new_l2_to_l1_msgs: reader.read_struct_array(ScopedL2ToL1Message::deserialize, [ScopedL2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_TX]), + note_hashes: reader.read_struct_array(ScopedNoteHash::deserialize, [ScopedNoteHash::empty(); MAX_NOTE_HASHES_PER_TX]), + nullifiers: reader.read_struct_array(ScopedNullifier::deserialize, [ScopedNullifier::empty(); MAX_NULLIFIERS_PER_TX]), + l2_to_l1_msgs: reader.read_struct_array(ScopedL2ToL1Message::deserialize, [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX]), note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX]), encrypted_logs_hashes: reader.read_struct_array(ScopedEncryptedLogHash::deserialize, [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), unencrypted_logs_hashes: reader.read_struct_array(ScopedLogHash::deserialize, [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), @@ -89,9 +89,9 @@ impl Deserialize for PrivateAccumulatedData { impl Eq for PrivateAccumulatedData { fn eq(self, other: Self) -> bool { - (self.new_note_hashes == other.new_note_hashes) & - (self.new_nullifiers == other.new_nullifiers) & - (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_hashes == other.note_hashes) & + (self.nullifiers == other.nullifiers) & + (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & @@ -103,9 +103,9 @@ impl Eq for PrivateAccumulatedData { impl Empty for PrivateAccumulatedData { fn empty() -> Self { PrivateAccumulatedData { - new_note_hashes: [ScopedNoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [ScopedNullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [ScopedNoteHash::empty(); MAX_NOTE_HASHES_PER_TX], + nullifiers: [ScopedNullifier::empty(); MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [ScopedL2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [ScopedEncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [ScopedLogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], 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 98c5be1191ef..5b90203eed5a 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,33 +1,22 @@ use crate::{ - address::AztecAddress, hash::{compute_tx_logs_hash, compute_tx_note_logs_hash}, abis::{ - gas::Gas, - accumulated_data::{ - combined_accumulated_data::CombinedAccumulatedData, - private_accumulated_data::PrivateAccumulatedData, public_accumulated_data::PublicAccumulatedData, - public_accumulated_data_builder::PublicAccumulatedDataBuilder -}, - call_request::CallRequest, note_hash::{NoteHash, ScopedNoteHash}, nullifier::ScopedNullifier, - private_call_request::ScopedPrivateCallRequest, public_data_update_request::PublicDataUpdateRequest, + accumulated_data::{private_accumulated_data::PrivateAccumulatedData}, call_request::CallRequest, + note_hash::ScopedNoteHash, nullifier::ScopedNullifier, + private_call_request::ScopedPrivateCallRequest, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash} }, 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_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, - messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::{Empty, is_empty} + messaging::l2_to_l1_message::ScopedL2ToL1Message, traits::Empty }; -// Builds via PrivateKernelCircuitPublicInputsBuilder: -// .finish: PrivateKernelCircuitPublicInputs.end -// .to_combined: KernelCircuitPublicInputs.end -// .split_to_public: PublicKernelCircuitPublicInputs.(end,end_non_revertible) struct PrivateAccumulatedDataBuilder { - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + note_hashes: BoundedVec, + nullifiers: BoundedVec, + l2_to_l1_msgs: BoundedVec, note_encrypted_logs_hashes: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -41,9 +30,9 @@ struct PrivateAccumulatedDataBuilder { impl PrivateAccumulatedDataBuilder { pub fn finish(self) -> PrivateAccumulatedData { PrivateAccumulatedData { - 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, + note_hashes: self.note_hashes.storage, + nullifiers: self.nullifiers.storage, + l2_to_l1_msgs: self.l2_to_l1_msgs.storage, note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, @@ -51,188 +40,14 @@ impl PrivateAccumulatedDataBuilder { public_call_stack: self.public_call_stack.storage } } - - pub fn to_combined(self, teardown_gas: Gas) -> CombinedAccumulatedData { - // TODO(Miranda): Hash here or elsewhere? - let note_encrypted_logs_hash = compute_tx_note_logs_hash(self.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| l.expose_to_public())); - let encrypted_logs_hash = compute_tx_logs_hash(self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.expose_to_public())); - let unencrypted_logs_hash = compute_tx_logs_hash(self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.log_hash)); - let gas_used = self.to_metered_gas_used() + Gas::tx_overhead() + teardown_gas; - let note_encrypted_log_preimages_length = self.note_encrypted_logs_hashes.storage.fold(0, |a, b: NoteLogHash| a + b.length); - let encrypted_log_preimages_length = self.encrypted_logs_hashes.storage.fold(0, |a, b: ScopedEncryptedLogHash| a + b.log_hash.length); - let unencrypted_log_preimages_length = self.unencrypted_logs_hashes.storage.fold(0, |a, b: ScopedLogHash| a + b.log_hash.length); - - CombinedAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), - note_encrypted_logs_hash, - encrypted_logs_hash, - unencrypted_logs_hash, - note_encrypted_log_preimages_length, - encrypted_log_preimages_length, - unencrypted_log_preimages_length, - public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - gas_used - } - } - - pub fn to_metered_gas_used(self) -> Gas { - let mut metered_bytes = 0; - - // note_hash_gas - for i in 0..self.new_note_hashes.storage.len() { - if !is_empty(self.new_note_hashes.get_unchecked(i)) { - metered_bytes += DA_BYTES_PER_FIELD; - } - } - - // nullifier_gas - for i in 0..self.new_nullifiers.storage.len() { - if !is_empty(self.new_nullifiers.get_unchecked(i)) { - metered_bytes += DA_BYTES_PER_FIELD; - } - } - - // l2_to_l1_msg_gas - for i in 0..self.new_l2_to_l1_msgs.storage.len() { - if !is_empty(self.new_l2_to_l1_msgs.get_unchecked(i)) { - metered_bytes += DA_BYTES_PER_FIELD; - } - } - - // note_encrypted_logs_hash_gas - for i in 0..self.note_encrypted_logs_hashes.storage.len() { - let log = self.note_encrypted_logs_hashes.get_unchecked(i); - metered_bytes += log.length as u32; - } - - // encrypted_logs_hash_gas - for i in 0..self.encrypted_logs_hashes.storage.len() { - let log = self.encrypted_logs_hashes.get_unchecked(i); - metered_bytes += log.log_hash.length as u32; - } - - // unencrypted_logs_hash_gas - for i in 0..self.unencrypted_logs_hashes.storage.len() { - let log = self.unencrypted_logs_hashes.get_unchecked(i); - metered_bytes += log.log_hash.length as u32; - } - - Gas::new(DA_GAS_PER_BYTE * metered_bytes, 0) - } - - pub fn split_to_public( - self, - min_revertible_side_effect_counter: u32, - teardown_gas: Gas - ) -> (PublicAccumulatedData, PublicAccumulatedData) { - let mut non_revertible_builder = PublicAccumulatedDataBuilder::empty(); - let mut revertible_builder = PublicAccumulatedDataBuilder::empty(); - let mut non_revertible_da_gas_used = 0; - let mut non_revertible_l2_gas_used = 0; - let mut revertible_da_gas_used = teardown_gas.da_gas; // pre-pay for teardown gas - let mut revertible_l2_gas_used = teardown_gas.l2_gas; - let DA_GAS_PER_FIELD = DA_BYTES_PER_FIELD * DA_GAS_PER_BYTE; - - for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { - let note_hash = self.new_note_hashes.storage[i]; - let public_note_hash = note_hash.expose_to_public(); - if note_hash.counter() < min_revertible_side_effect_counter { - non_revertible_builder.new_note_hashes.push(public_note_hash); - if !is_empty(public_note_hash) { - non_revertible_da_gas_used += DA_GAS_PER_FIELD ; - } - } else { - revertible_builder.new_note_hashes.push(public_note_hash); - if !is_empty(public_note_hash) { - revertible_da_gas_used += DA_GAS_PER_FIELD; - } - } - } - - for i in 0..MAX_NEW_NULLIFIERS_PER_TX { - let nullifier = self.new_nullifiers.storage[i]; - let public_nullifier = nullifier.expose_to_public(); - if nullifier.counter() < min_revertible_side_effect_counter { - non_revertible_builder.new_nullifiers.push(public_nullifier); - if !is_empty(public_nullifier) { - non_revertible_da_gas_used += DA_GAS_PER_FIELD; - } - } else { - revertible_builder.new_nullifiers.push(public_nullifier); - if !is_empty(public_nullifier) { - revertible_da_gas_used += DA_GAS_PER_FIELD; - } - } - } - - for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - let msg = self.new_l2_to_l1_msgs.storage[i]; - if msg.counter() < min_revertible_side_effect_counter { - non_revertible_builder.new_l2_to_l1_msgs.push(msg.message.content); - } else { - revertible_builder.new_l2_to_l1_msgs.push(msg.message.content); - } - } - - // TODO(gas): add AVM_STARTUP_L2_GAS here - for i in 0..MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX { - let call_stack_item = self.public_call_stack.storage[i]; - if call_stack_item.start_side_effect_counter < min_revertible_side_effect_counter { - non_revertible_builder.public_call_stack.push(call_stack_item); - } else { - revertible_builder.public_call_stack.push(call_stack_item); - } - } - - for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { - let note_encrypted_logs_hash = self.note_encrypted_logs_hashes.storage[i]; - let note_encrypted_logs_hash_public = note_encrypted_logs_hash.expose_to_public(); - if note_encrypted_logs_hash.counter < min_revertible_side_effect_counter { - non_revertible_builder.note_encrypted_logs_hashes.push(note_encrypted_logs_hash_public); - non_revertible_da_gas_used += note_encrypted_logs_hash_public.length as u32 * DA_GAS_PER_BYTE; - } else { - revertible_builder.note_encrypted_logs_hashes.push(note_encrypted_logs_hash_public); - revertible_da_gas_used += note_encrypted_logs_hash_public.length as u32 * DA_GAS_PER_BYTE; - } - } - - for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { - let encrypted_logs_hash = self.encrypted_logs_hashes.storage[i]; - let encrypted_logs_hash_public = encrypted_logs_hash.expose_to_public(); - if encrypted_logs_hash.counter() < min_revertible_side_effect_counter { - non_revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash_public); - non_revertible_da_gas_used += encrypted_logs_hash_public.length as u32 * DA_GAS_PER_BYTE; - } else { - revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash_public); - revertible_da_gas_used += encrypted_logs_hash_public.length as u32 * DA_GAS_PER_BYTE; - } - } - - for i in 0..MAX_UNENCRYPTED_LOGS_PER_TX { - let unencrypted_logs_hash = self.unencrypted_logs_hashes.storage[i].log_hash; - if unencrypted_logs_hash.counter < min_revertible_side_effect_counter { - non_revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); - non_revertible_da_gas_used += unencrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; - } else { - revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); - revertible_da_gas_used += unencrypted_logs_hash.length as u32 * DA_GAS_PER_BYTE; - } - } - - revertible_builder.gas_used = Gas::new(revertible_da_gas_used, revertible_l2_gas_used); - non_revertible_builder.gas_used = Gas::tx_overhead() + Gas::new(non_revertible_da_gas_used, non_revertible_l2_gas_used); - (non_revertible_builder.finish(), revertible_builder.finish()) - } } impl Empty for PrivateAccumulatedDataBuilder { fn empty() -> Self { PrivateAccumulatedDataBuilder { - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), @@ -241,233 +56,3 @@ impl Empty for PrivateAccumulatedDataBuilder { } } } - -mod tests { - use crate::{ - abis::{ - accumulated_data::private_accumulated_data_builder::PrivateAccumulatedDataBuilder, gas::Gas, - call_request::CallRequest, caller_context::CallerContext, note_hash::NoteHash, - nullifier::Nullifier, public_data_update_request::PublicDataUpdateRequest, - log_hash::{LogHash, NoteLogHash, ScopedLogHash, EncryptedLogHash, ScopedEncryptedLogHash} - }, - address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, - utils::arrays::array_eq, constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE} - }; - - #[test] - unconstrained fn splits_revertible_and_non_revertible() { - let mut builder = PrivateAccumulatedDataBuilder::empty(); - let contract_address = AztecAddress::from_field(8989); - - let min_revertible_side_effect_counter = 13; - - // Non revertible: counter < 13 - - let non_revertible_note_hashes = [ - NoteHash { value: 1, counter: 1 }.scope(20, contract_address), - NoteHash { value: 2, counter: 4 }.scope(5, contract_address) - ]; - - let non_revertible_note_logs = [NoteLogHash { value: 11, counter: 2, length: 2, note_hash_counter: 1 }]; - - let non_revertible_nullifiers = [ - Nullifier { value: 10, note_hash: 1, counter: 3 }.scope(contract_address), - Nullifier { value: 20, note_hash: 2, counter: 5 }.scope(contract_address) - ]; - - let non_revertible_l2_to_l1_messages = [ - L2ToL1Message { recipient: EthAddress::from_field(3030), content: 333333, counter: 6 }.scope(AztecAddress::from_field(9900)) - ]; - - let non_revertible_public_stack = [ - CallRequest { - hash: 1, - caller_contract_address: AztecAddress::from_field(1), - caller_context: CallerContext::empty(), - start_side_effect_counter: 6, - end_side_effect_counter: 0 - }, - CallRequest { - hash: 2, - caller_contract_address: AztecAddress::from_field(1), - caller_context: CallerContext::empty(), - start_side_effect_counter: 7, - end_side_effect_counter: 0 - } - ]; - - let non_revertible_enc_log_hashes = [ - EncryptedLogHash { value: 11, counter: 9, length: 2, randomness: 4 }.scope(contract_address), - EncryptedLogHash { value: 22, counter: 10, length: 2, randomness: 4 }.scope(contract_address) - ]; - - let non_revertible_unenc_log_hashes = [ - LogHash { value: 33, counter: 11, length: 5 }.scope(contract_address), - LogHash { value: 44, counter: 12, length: 5 }.scope(contract_address) - ]; - - // Revertible: counter >= 13 - - let revertible_note_hashes = [ - NoteHash { value: 3, counter: 13 }.scope(15, contract_address), - NoteHash { value: 4, counter: 16 }.scope(0, contract_address) - ]; - - let revertible_note_logs = [NoteLogHash { value: 33, counter: 14, length: 2, note_hash_counter: 13 }]; - - let revertible_nullifiers = [ - Nullifier { value: 30, note_hash: 3, counter: 15 }.scope(contract_address), - Nullifier { value: 40, note_hash: 4, counter: 18 }.scope(contract_address) - ]; - - let revertible_l2_to_l1_messages = [ - L2ToL1Message { recipient: EthAddress::from_field(3030), content: 444444, counter: 19 }.scope(AztecAddress::from_field(7788)) - ]; - - let revertible_public_call_stack = [ - CallRequest { - hash: 3, - caller_contract_address: AztecAddress::from_field(3), - caller_context: CallerContext::empty(), - start_side_effect_counter: 17, - end_side_effect_counter: 0 - } - ]; - - let revertible_enc_log_hashes = [ - EncryptedLogHash { value: 55, counter: 20, length: 2, randomness: 4 }.scope(contract_address), - EncryptedLogHash { value: 66, counter: 21, length: 2, randomness: 4 }.scope(contract_address) - ]; - - let revertible_unenc_log_hashes = [ - LogHash { value: 77, counter: 22, length: 5 }.scope(contract_address), - LogHash { value: 88, counter: 23, length: 5 }.scope(contract_address) - ]; - - builder.new_note_hashes.extend_from_array(non_revertible_note_hashes); - builder.new_note_hashes.extend_from_array(revertible_note_hashes); - - builder.new_nullifiers.extend_from_array(non_revertible_nullifiers); - builder.new_nullifiers.extend_from_array(revertible_nullifiers); - - builder.new_l2_to_l1_msgs.extend_from_array(non_revertible_l2_to_l1_messages); - builder.new_l2_to_l1_msgs.extend_from_array(revertible_l2_to_l1_messages); - - builder.public_call_stack.extend_from_array(non_revertible_public_stack); - builder.public_call_stack.extend_from_array(revertible_public_call_stack); - - builder.note_encrypted_logs_hashes.extend_from_array(non_revertible_note_logs); - builder.note_encrypted_logs_hashes.extend_from_array(revertible_note_logs); - - builder.encrypted_logs_hashes.extend_from_array(non_revertible_enc_log_hashes); - builder.encrypted_logs_hashes.extend_from_array(revertible_enc_log_hashes); - - builder.unencrypted_logs_hashes.extend_from_array(non_revertible_unenc_log_hashes); - builder.unencrypted_logs_hashes.extend_from_array(revertible_unenc_log_hashes); - - let public_non_revertible_note_logs = non_revertible_note_logs.map(|n: NoteLogHash| n.expose_to_public()); - let public_revertible_note_logs = revertible_note_logs.map(|n: NoteLogHash| n.expose_to_public()); - - let (non_revertible, revertible) = builder.split_to_public(min_revertible_side_effect_counter, Gas::new(42, 17)); - - assert( - array_eq( - non_revertible.new_note_hashes, - [ - NoteHash { value: 1, counter: 0 }, - NoteHash { value: 2, counter: 0 } - ] - ) - ); - assert( - array_eq( - non_revertible.new_nullifiers, - [ - Nullifier { value: 10, note_hash: 0, counter: 0 }, - Nullifier { value: 20, note_hash: 0, counter: 0 } - ] - ) - ); - assert(array_eq(non_revertible.new_l2_to_l1_msgs, [333333])); - assert(array_eq(non_revertible.public_call_stack, non_revertible_public_stack)); - assert( - array_eq( - non_revertible.note_encrypted_logs_hashes, - public_non_revertible_note_logs - ) - ); - assert( - array_eq( - non_revertible.encrypted_logs_hashes, - non_revertible_enc_log_hashes.map(|h: ScopedEncryptedLogHash| h.expose_to_public()) - ) - ); - assert( - array_eq( - non_revertible.unencrypted_logs_hashes, - non_revertible_unenc_log_hashes.map(|h: ScopedLogHash| h.log_hash) - ) - ); - - assert( - array_eq( - revertible.new_note_hashes, - [ - NoteHash { value: 3, counter: 0 }, - NoteHash { value: 4, counter: 0 } - ] - ) - ); - assert( - array_eq( - revertible.new_nullifiers, - [ - Nullifier { value: 30, note_hash: 0, counter: 0 }, - Nullifier { value: 40, note_hash: 0, counter: 0 } - ] - ) - ); - assert(array_eq(revertible.new_l2_to_l1_msgs, [444444])); - assert(array_eq(revertible.public_call_stack, revertible_public_call_stack)); - assert( - array_eq( - revertible.note_encrypted_logs_hashes, - public_revertible_note_logs - ) - ); - assert( - array_eq( - revertible.encrypted_logs_hashes, - revertible_enc_log_hashes.map(|h: ScopedEncryptedLogHash| h.expose_to_public()) - ) - ); - assert( - array_eq( - revertible.unencrypted_logs_hashes, - revertible_unenc_log_hashes.map(|h: ScopedLogHash| h.log_hash) - ) - ); - - assert_eq( - revertible.gas_used, Gas::new( - (4 * DA_BYTES_PER_FIELD - + 6 // revertible encrypted logs len - + 10) // revertible unencrypted logs len - * DA_GAS_PER_BYTE, - 0 - ) - + Gas::new(42, 17) - ); - - assert_eq( - non_revertible.gas_used, Gas::new( - (4 * DA_BYTES_PER_FIELD - + 6 // non-revertible encrypted logs len - + 10) // non-revertible unencrypted logs len - * DA_GAS_PER_BYTE, - 0 - ) - + Gas::tx_overhead() - ); - } -} 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 7bdc889c3e43..ae6392b23865 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 @@ -4,17 +4,17 @@ use crate::{ note_hash::NoteHash, nullifier::Nullifier, log_hash::{LogHash, NoteLogHash} }, 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_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, PUBLIC_ACCUMULATED_DATA_LENGTH }, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader }; struct PublicAccumulatedData { - new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_TX], + nullifiers: [Nullifier; MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX], @@ -30,9 +30,9 @@ struct PublicAccumulatedData { impl Empty for PublicAccumulatedData { fn empty() -> Self { PublicAccumulatedData { - new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX], - new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_TX], + nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_TX], + l2_to_l1_msgs: [0; MAX_L2_TO_L1_MSGS_PER_TX], note_encrypted_logs_hashes: [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX], encrypted_logs_hashes: [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX], unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], @@ -47,15 +47,15 @@ impl Serialize for PublicAccumulatedData { fn serialize(self) -> [Field; PUBLIC_ACCUMULATED_DATA_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - for i in 0..MAX_NEW_NOTE_HASHES_PER_TX { - fields.extend_from_array(self.new_note_hashes[i].serialize()); + for i in 0..MAX_NOTE_HASHES_PER_TX { + fields.extend_from_array(self.note_hashes[i].serialize()); } - for i in 0..MAX_NEW_NULLIFIERS_PER_TX { - fields.extend_from_array(self.new_nullifiers[i].serialize()); + for i in 0..MAX_NULLIFIERS_PER_TX { + fields.extend_from_array(self.nullifiers[i].serialize()); } - fields.extend_from_array(self.new_l2_to_l1_msgs); + fields.extend_from_array(self.l2_to_l1_msgs); for i in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX { fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize()); @@ -90,9 +90,9 @@ impl Deserialize for PublicAccumulatedData { let mut reader = Reader::new(fields); let item = PublicAccumulatedData { - new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_TX]), - new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_TX]), - new_l2_to_l1_msgs: reader.read_array([0; MAX_NEW_L2_TO_L1_MSGS_PER_TX]), + note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NOTE_HASHES_PER_TX]), + nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NULLIFIERS_PER_TX]), + l2_to_l1_msgs: reader.read_array([0; MAX_L2_TO_L1_MSGS_PER_TX]), note_encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_TX]), encrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_ENCRYPTED_LOGS_PER_TX]), unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_TX]), @@ -107,9 +107,9 @@ impl Deserialize for PublicAccumulatedData { impl Eq for PublicAccumulatedData { fn eq(self, other: Self) -> bool { - (self.new_note_hashes == other.new_note_hashes) & - (self.new_nullifiers == other.new_nullifiers) & - (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_hashes == other.note_hashes) & + (self.nullifiers == other.nullifiers) & + (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & 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 02146a8e4522..7d8237922d47 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 @@ -5,17 +5,17 @@ use crate::{ public_data_update_request::PublicDataUpdateRequest, log_hash::{LogHash, NoteLogHash} }, 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_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, traits::Empty }; struct PublicAccumulatedDataBuilder { - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + note_hashes: BoundedVec, + nullifiers: BoundedVec, + l2_to_l1_msgs: BoundedVec, note_encrypted_logs_hashes: BoundedVec, encrypted_logs_hashes: BoundedVec, @@ -31,9 +31,9 @@ struct PublicAccumulatedDataBuilder { impl PublicAccumulatedDataBuilder { pub fn finish(self) -> PublicAccumulatedData { PublicAccumulatedData { - 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, + note_hashes: self.note_hashes.storage, + nullifiers: self.nullifiers.storage, + l2_to_l1_msgs: self.l2_to_l1_msgs.storage, note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage, encrypted_logs_hashes: self.encrypted_logs_hashes.storage, unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, @@ -47,9 +47,9 @@ impl PublicAccumulatedDataBuilder { impl Empty for PublicAccumulatedDataBuilder { fn empty() -> Self { PublicAccumulatedDataBuilder { - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr index 45f578d98da2..05dac0f9af0d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr @@ -1,5 +1,3 @@ -use dep::std::cmp::Eq; - struct AppendOnlyTreeSnapshot { root : Field, // TODO(Alvaro) change this to a u64 diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr index 32e56c9511c0..2f2ee96ba7d7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_request.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ abis::{caller_context::CallerContext, side_effect::Ordered}, address::AztecAddress, constants::CALL_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize}, utils::reader::Reader @@ -40,6 +39,18 @@ impl Empty for CallRequest { } } +impl CallRequest { + pub fn expose_to_public(self) -> Self { + CallRequest { + hash: self.hash, + caller_contract_address: self.caller_contract_address, + caller_context: self.caller_context, + start_side_effect_counter: 0, + end_side_effect_counter: 0 + } + } +} + impl Serialize for CallRequest { fn serialize(self) -> [Field; CALL_REQUEST_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr index 0594718a73fb..aad2461105f6 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr @@ -1,5 +1,4 @@ use crate::address::AztecAddress; -use dep::std::cmp::Eq; use crate::traits::{Empty, Serialize, Deserialize}; use crate::constants::CALLER_CONTEXT_LENGTH; use crate::utils::reader::Reader; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr index 3a94d6cd2417..30bce550183e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/contract_class_function_leaf_preimage.nr @@ -9,7 +9,7 @@ struct ContractClassFunctionLeafPreimage { impl Hash for ContractClassFunctionLeafPreimage { fn hash(self) -> Field { - dep::std::hash::pedersen_hash_with_separator([ + std::hash::pedersen_hash_with_separator([ self.selector.to_field(), self.vk_hash, ], GENERATOR_INDEX__FUNCTION_LEAF) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr index b03a9dfba1c1..eca5867114b3 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/event_selector.nr @@ -1,5 +1,4 @@ use crate::utils::field::field_from_bytes; -use dep::std::cmp::Eq; use crate::traits::{Serialize, Deserialize, FromField, ToField, Empty}; global SELECTOR_SIZE = 4; @@ -54,7 +53,7 @@ impl EventSelector { pub fn from_signature(signature: str) -> Self { let bytes = signature.as_bytes(); - let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32); + let hash = std::hash::keccak256(bytes, bytes.len() as u32); let mut selector_be_bytes = [0; SELECTOR_SIZE]; for i in 0..SELECTOR_SIZE { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr index 4dc4e0c0b00a..57be8ba02789 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr @@ -1,5 +1,4 @@ use crate::utils::field::field_from_bytes; -use dep::std::cmp::Eq; use crate::traits::{Serialize, Deserialize, FromField, ToField, Empty}; global SELECTOR_SIZE = 4; @@ -54,7 +53,7 @@ impl FunctionSelector { pub fn from_signature(signature: str) -> Self { let bytes = signature.as_bytes(); - let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32); + let hash = std::hash::keccak256(bytes, bytes.len() as u32); let mut selector_be_bytes = [0; SELECTOR_SIZE]; for i in 0..SELECTOR_SIZE { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr index cd5f87f3cfa5..cf2652e7fed2 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr @@ -4,7 +4,7 @@ use crate::{ traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader, abis::gas_fees::GasFees }; -use dep::std::ops::{Add, Sub}; +use std::ops::{Add, Sub}; struct Gas { da_gas: u32, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr index f08db75bb735..fb205e79e776 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees, constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH}, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr index be8ad0c72dd2..8d8ffb850074 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs.nr @@ -11,9 +11,9 @@ struct PrivateKernelCircuitPublicInputsArrayLengths { note_hash_read_requests: u32, nullifier_read_requests: u32, scoped_key_validation_requests_and_generators: u32, - new_note_hashes: u32, - new_nullifiers: u32, - new_l2_to_l1_msgs: u32, + note_hashes: u32, + nullifiers: u32, + l2_to_l1_msgs: u32, note_encrypted_logs_hashes: u32, encrypted_logs_hashes: u32, unencrypted_logs_hashes: u32, @@ -27,9 +27,9 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { note_hash_read_requests: array_length(public_inputs.validation_requests.note_hash_read_requests), nullifier_read_requests: array_length(public_inputs.validation_requests.nullifier_read_requests), scoped_key_validation_requests_and_generators: array_length(public_inputs.validation_requests.scoped_key_validation_requests_and_generators), - new_note_hashes: array_length(public_inputs.end.new_note_hashes), - new_nullifiers: array_length(public_inputs.end.new_nullifiers), - new_l2_to_l1_msgs: array_length(public_inputs.end.new_l2_to_l1_msgs), + note_hashes: array_length(public_inputs.end.note_hashes), + nullifiers: array_length(public_inputs.end.nullifiers), + l2_to_l1_msgs: array_length(public_inputs.end.l2_to_l1_msgs), note_encrypted_logs_hashes: array_length(public_inputs.end.note_encrypted_logs_hashes), encrypted_logs_hashes: array_length(public_inputs.end.encrypted_logs_hashes), unencrypted_logs_hashes: array_length(public_inputs.end.unencrypted_logs_hashes), @@ -43,9 +43,9 @@ impl PrivateKernelCircuitPublicInputsArrayLengths { note_hash_read_requests: 0, nullifier_read_requests: 0, scoped_key_validation_requests_and_generators: 0, - new_note_hashes: 0, - new_nullifiers: 0, - new_l2_to_l1_msgs: 0, + note_hashes: 0, + nullifiers: 0, + l2_to_l1_msgs: 0, note_encrypted_logs_hashes: 0, encrypted_logs_hashes: 0, unencrypted_logs_hashes: 0, @@ -60,9 +60,9 @@ impl Eq for PrivateKernelCircuitPublicInputsArrayLengths { (self.note_hash_read_requests == other.note_hash_read_requests) & (self.nullifier_read_requests == other.nullifier_read_requests) & (self.scoped_key_validation_requests_and_generators == other.scoped_key_validation_requests_and_generators) & - (self.new_note_hashes == other.new_note_hashes) & - (self.new_nullifiers == other.new_nullifiers) & - (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.note_hashes == other.note_hashes) & + (self.nullifiers == other.nullifiers) & + (self.l2_to_l1_msgs == other.l2_to_l1_msgs) & (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & 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 d0583d1661e7..c718b02430ff 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 @@ -1,22 +1,13 @@ use crate::{ abis::{ accumulated_data::PrivateAccumulatedDataBuilder, combined_constant_data::CombinedConstantData, - kernel_circuit_public_inputs::{ - kernel_circuit_public_inputs::KernelCircuitPublicInputs, - private_kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, - public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs -}, - gas::Gas, validation_requests::validation_requests_builder::ValidationRequestsBuilder, + kernel_circuit_public_inputs::private_kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, + validation_requests::validation_requests_builder::ValidationRequestsBuilder, call_request::CallRequest }, - address::AztecAddress, constants::MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - partial_state_reference::PartialStateReference, traits::{Empty, is_empty} + address::AztecAddress, traits::Empty }; -// Builds: -// .finish: PrivateKernelCircuitPublicInputs -// .finish_tail: KernelCircuitPublicInputs (from KernelCircuitPublicInputsComposer) -// .finish_to_public: PublicKernelCircuitPublicInputs (from KernelCircuitPublicInputsComposer) struct PrivateKernelCircuitPublicInputsBuilder { min_revertible_side_effect_counter: u32, validation_requests: ValidationRequestsBuilder, @@ -37,45 +28,12 @@ impl PrivateKernelCircuitPublicInputsBuilder { fee_payer: self.fee_payer } } - - pub fn finish_tail(self, teardown_gas: Gas) -> KernelCircuitPublicInputs { - KernelCircuitPublicInputs { - rollup_validation_requests: self.validation_requests.to_rollup(), - end: self.end.to_combined(teardown_gas), - constants: self.constants, - start_state: PartialStateReference::empty(), - revert_code: 0, - fee_payer: self.fee_payer - } - } - - pub fn finish_to_public( - self, - teardown_gas: Gas, - min_revertible_side_effect_counter: u32 - ) -> PublicKernelCircuitPublicInputs { - let (end_non_revertible, end) = self.end.split_to_public(min_revertible_side_effect_counter, teardown_gas); - let mut public_teardown_call_stack: BoundedVec = BoundedVec::new(); - if (!is_empty(self.public_teardown_call_request)) { - public_teardown_call_stack.push(self.public_teardown_call_request); - } - - PublicKernelCircuitPublicInputs { - validation_requests: self.validation_requests.finish(), - end_non_revertible, - end, - constants: self.constants, - revert_code: 0, - public_teardown_call_stack: public_teardown_call_stack.storage, - fee_payer: self.fee_payer - } - } } impl Empty for PrivateKernelCircuitPublicInputsBuilder { fn empty() -> Self { PrivateKernelCircuitPublicInputsBuilder { - min_revertible_side_effect_counter: 0 as u32, + min_revertible_side_effect_counter: 0, validation_requests: ValidationRequestsBuilder::empty(), end: PrivateAccumulatedDataBuilder::empty(), constants: CombinedConstantData::empty(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr index 67d9358ae376..5ec42ae4b060 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_data.nr @@ -13,7 +13,7 @@ struct KernelData { impl Verifiable for KernelData { fn verify(self) { let inputs = KernelCircuitPublicInputs::serialize(self.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr index c212bd063854..6d5ad39702f1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr @@ -131,6 +131,14 @@ impl Deserialize for ScopedLogHash { } } +impl ScopedLogHash { + pub fn expose_to_public(self) -> LogHash { + // Hide the counter when exposing to public. + // The log hash must already be siloed when we call this. + LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length } + } +} + struct EncryptedLogHash { value: Field, counter: u32, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/abis.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/abis/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr index fbbe653de97d..4ac04a4f2eec 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr @@ -4,7 +4,6 @@ use crate::{ constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader} }; -use dep::std::cmp::Eq; struct NoteHash { value: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr index 904068ff4b25..053f3a552f14 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr @@ -26,7 +26,7 @@ impl Hash for NullifierLeafPreimage { if self.is_empty() { 0 } else { - dep::std::hash::pedersen_hash(self.serialize()) + std::hash::pedersen_hash(self.serialize()) } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr index 02d4de6e4903..7b97099d8f4f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}}, address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH}, 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 80ef09922600..bf322ef6adbe 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 = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf; + let test_data_empty_hash = 0x157022d579f892f06461fb895cdf5550b24329e15e7a41df14f9dad582fa1bc5; 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 b8871423e59e..7848088a9448 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 @@ -7,9 +7,9 @@ use crate::{ }, constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NOTE_HASHES_PER_CALL, MAX_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, + MAX_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL }, @@ -22,9 +22,9 @@ struct PrivateCircuitPublicInputsArrayLengths { note_hash_read_requests: u32, nullifier_read_requests: u32, key_validation_requests_and_generators: u32, - new_note_hashes: u32, - new_nullifiers: u32, - new_l2_to_l1_msgs: u32, + note_hashes: u32, + nullifiers: u32, + l2_to_l1_msgs: u32, private_call_requests: u32, public_call_stack_hashes: u32, note_encrypted_logs_hashes: u32, @@ -38,9 +38,9 @@ impl PrivateCircuitPublicInputsArrayLengths { note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests), nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests), key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators), - new_note_hashes: validate_array(public_inputs.new_note_hashes), - new_nullifiers: validate_array(public_inputs.new_nullifiers), - new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs), + note_hashes: validate_array(public_inputs.note_hashes), + nullifiers: validate_array(public_inputs.nullifiers), + l2_to_l1_msgs: validate_array(public_inputs.l2_to_l1_msgs), private_call_requests: validate_array(public_inputs.private_call_requests), public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes), note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes), @@ -65,12 +65,12 @@ struct PrivateCircuitPublicInputs { nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL], key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL], - new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL], + note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_function_hash: Field, - new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : u32, end_side_effect_counter : u32, @@ -98,11 +98,11 @@ impl Eq for PrivateCircuitPublicInputs { (self.note_hash_read_requests == other.note_hash_read_requests) & (self.nullifier_read_requests == other.nullifier_read_requests) & (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) & - (self.new_note_hashes == other.new_note_hashes) & - (self.new_nullifiers == other.new_nullifiers) & + (self.note_hashes == other.note_hashes) & + (self.nullifiers == other.nullifiers) & (self.private_call_requests == other.private_call_requests) & (self.public_call_stack_hashes == other.public_call_stack_hashes) & - (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & + (self.l2_to_l1_msgs == other.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.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) & @@ -134,19 +134,19 @@ impl Serialize for PrivateCircuitPublicInp for i in 0..self.key_validation_requests_and_generators.len() { fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize()); } - for i in 0..self.new_note_hashes.len() { - fields.extend_from_array(self.new_note_hashes[i].serialize()); + for i in 0..self.note_hashes.len() { + fields.extend_from_array(self.note_hashes[i].serialize()); } - for i in 0..self.new_nullifiers.len() { - fields.extend_from_array(self.new_nullifiers[i].serialize()); + for i in 0..self.nullifiers.len() { + fields.extend_from_array(self.nullifiers[i].serialize()); } for i in 0..self.private_call_requests.len() { fields.extend_from_array(self.private_call_requests[i].serialize()); } fields.extend_from_array(self.public_call_stack_hashes); fields.push(self.public_teardown_function_hash); - for i in 0..self.new_l2_to_l1_msgs.len() { - fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); + for i in 0..self.l2_to_l1_msgs.len() { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); } fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); @@ -182,12 +182,12 @@ impl Deserialize for PrivateCircuitPublicI note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]), nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]), key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]), - new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]), - new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]), + note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL]), + nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL]), private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]), public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), public_teardown_function_hash: reader.read(), - new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), + l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]), @@ -220,12 +220,12 @@ impl Empty for PrivateCircuitPublicInputs { note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL], nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL], key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL], - new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], + note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL], public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], public_teardown_function_hash: 0, - new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : 0 as u32, end_side_effect_counter : 0 as u32, note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL], @@ -250,6 +250,6 @@ 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 = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622; + let test_data_empty_hash = 0x1eb5048b5bdcea5ba66519ecd1cbdb9e18fd957d52830b2bcb309f4ce9bcfbd3; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr index b6cbe427fac6..bf3868946025 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel/private_call_data.nr @@ -29,7 +29,7 @@ struct PrivateCallData { impl Verifiable for PrivateCallData { fn verify(self) { let inputs = PrivateCircuitPublicInputs::serialize(self.call_stack_item.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr index f4e149143ccc..2493aaba90a9 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_kernel_data.nr @@ -26,7 +26,7 @@ struct PrivateKernelData { impl Verifiable for PrivateKernelData { fn verify(self) { let inputs = PrivateKernelCircuitPublicInputs::serialize(self.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), 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 9572f179dd1b..4c12a77d0d3b 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 @@ -20,7 +20,7 @@ impl Hash for PublicCallStackItem { self }; - dep::std::hash::pedersen_hash_with_separator([ + std::hash::pedersen_hash_with_separator([ item.contract_address.to_field(), item.function_data.hash(), item.public_inputs.hash(), @@ -62,7 +62,7 @@ mod tests { let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false }; let mut public_inputs = PublicCircuitPublicInputs::empty(); - public_inputs.new_note_hashes[0] = NoteHash { + public_inputs.note_hashes[0] = NoteHash { value: 1, counter: 0, }; @@ -70,7 +70,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 = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102; + let test_data_call_stack_item_request_hash = 0x022a2b82af83606ae5a8d4955ef6215e54025193356318aefbde3b5026952953; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -80,7 +80,7 @@ mod tests { let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false }; let mut public_inputs = PublicCircuitPublicInputs::empty(); - public_inputs.new_note_hashes[0] = NoteHash { + public_inputs.note_hashes[0] = NoteHash { value: 1, counter: 0, }; @@ -88,7 +88,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 = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a; + let test_data_call_stack_item_hash = 0x23a1d22e7bf37df7d68e8fcbfb7e016c060194b7915e3771e2dcd72cea26e427; 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 cd76145a67eb..555ab222440e 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 @@ -5,8 +5,8 @@ use crate::{ }, address::AztecAddress, constants::{ - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NULLIFIERS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_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, @@ -32,9 +32,9 @@ struct PublicCircuitPublicInputs { // todo: add sideeffect ranges for the input to these hashes public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL], - new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + note_hashes: [NoteHash; MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier; MAX_NULLIFIERS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message; MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: u32, end_side_effect_counter: u32, @@ -89,14 +89,14 @@ impl Serialize for PublicCircuitPublicInput } fields.extend_from_array(self.public_call_stack_hashes); - for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL { - fields.extend_from_array(self.new_note_hashes[i].serialize()); + for i in 0..MAX_NOTE_HASHES_PER_CALL { + fields.extend_from_array(self.note_hashes[i].serialize()); } - for i in 0..MAX_NEW_NULLIFIERS_PER_CALL { - fields.extend_from_array(self.new_nullifiers[i].serialize()); + for i in 0..MAX_NULLIFIERS_PER_CALL { + fields.extend_from_array(self.nullifiers[i].serialize()); } - for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL { - fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize()); + for i in 0..MAX_L2_TO_L1_MSGS_PER_CALL { + fields.extend_from_array(self.l2_to_l1_msgs[i].serialize()); } fields.push(self.start_side_effect_counter as Field); @@ -131,9 +131,9 @@ impl Deserialize for PublicCircuitPublicInp contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]), contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]), public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]), - new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]), - new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]), - new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), + note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL]), + nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL]), + l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), @@ -170,9 +170,9 @@ impl Empty for PublicCircuitPublicInputs { contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL], contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL], public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL], - new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL], - new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL], - new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], + note_hashes: [NoteHash::empty(); MAX_NOTE_HASHES_PER_CALL], + nullifiers: [Nullifier::empty(); MAX_NULLIFIERS_PER_CALL], + l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0 as u32, end_side_effect_counter: 0 as u32, unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], @@ -201,6 +201,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 = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125; + let test_data_empty_hash = 0x2e08158f3f0d9a94e3f17338aadc3733a15bf5d163f94cef1afd8a47b446d789; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr index 14482ab515ee..550669fc8e0a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_read.nr @@ -1,5 +1,4 @@ use crate::constants::{GENERATOR_INDEX__PUBLIC_DATA_READ, PUBLIC_DATA_READ_LENGTH}; -use dep::std::cmp::Eq; use crate::traits::{Empty, Hash, Serialize, Deserialize}; use crate::contrakt::storage_read::StorageRead; use crate::data::hash::{compute_public_data_tree_value, compute_public_data_tree_index}; @@ -39,7 +38,7 @@ impl Empty for PublicDataRead { impl Hash for PublicDataRead { fn hash(self) -> Field { - dep::std::hash::pedersen_hash_with_separator([ + std::hash::pedersen_hash_with_separator([ self.leaf_slot, self.value, ], GENERATOR_INDEX__PUBLIC_DATA_READ) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr index 9041de2cbfb7..4c60e388284d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_data_update_request.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::constants::{PUBLIC_DATA_UPDATE_REQUEST_LENGTH, GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST}; use crate::traits::{Empty, Hash, Serialize, Deserialize}; use crate::public_data_tree_leaf::PublicDataTreeLeaf; @@ -57,7 +56,7 @@ impl Empty for PublicDataUpdateRequest { impl Hash for PublicDataUpdateRequest { fn hash(self) -> Field { - dep::std::hash::pedersen_hash_with_separator([ + std::hash::pedersen_hash_with_separator([ self.leaf_slot, self.new_value ], GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr index f0073faffaea..fc6246a321d5 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_kernel_data.nr @@ -13,7 +13,7 @@ struct PublicKernelData { impl Verifiable for PublicKernelData { fn verify(self) { let inputs = PublicKernelCircuitPublicInputs::serialize(self.public_inputs); - dep::std::verify_proof( + std::verify_proof( self.vk.key.as_slice(), self.proof.fields.as_slice(), inputs.as_slice(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr index fa5682ca079b..fce87307f01a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr @@ -3,7 +3,6 @@ use crate::{ address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN}, utils::{arrays::array_concat, reader::Reader} }; -use dep::std::cmp::Eq; struct ReadRequest { value: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr index 8a8e2691b8b0..e888e6a3fbd1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/side_effect.nr @@ -1,5 +1,4 @@ use crate::{abis::read_request::ScopedReadRequest, address::AztecAddress}; -use dep::std::cmp::Eq; trait Ordered { fn counter(self) -> u32; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr index 56baf77a1c3e..a54a78a2f795 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize}, grumpkin_point::GrumpkinPoint diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr index c34345bf3d85..d319ee190c9f 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ address::AztecAddress, abis::validation_requests::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr index a914dfde77c6..e8eebb0e5756 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/scoped_key_validation_request_and_generator.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::{ address::AztecAddress, constants::SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/address.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/address/mod.nr 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 8d450bce84d7..b830d210c515 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -7,32 +7,31 @@ global ARGS_LENGTH: u32 = 16; * * Agreed convention is to use MAX_XXX_PER_CALL resp. MAX_XXX_PER_TX, where XXX denotes a type of element such as * commitment, or nullifier, e.g.,: - * - MAX_NEW_NULLIFIERS_PER_CALL - * - MAX_NEW_NOTE_HASHES_PER_TX + * - MAX_NULLIFIERS_PER_CALL + * - MAX_NOTE_HASHES_PER_TX * * In the kernel circuits, we accumulate elements such as note hashes and the nullifiers from all functions calls in a * transaction. Therefore, we always must have: * MAX_XXX_PER_TX ≥ MAX_XXX_PER_CALL * * For instance: - * MAX_NEW_NOTE_HASHES_PER_TX ≥ MAX_NEW_NOTE_HASHES_PER_CALL - * MAX_NEW_NULLIFIERS_PER_TX ≥ MAX_NEW_NULLIFIERS_PER_CALL + * MAX_NOTE_HASHES_PER_TX ≥ MAX_NOTE_HASHES_PER_CALL + * MAX_NULLIFIERS_PER_TX ≥ MAX_NULLIFIERS_PER_CALL * */ // docs:start:constants // "PER CALL" CONSTANTS -// If modifiying, update avm_kernel.pil / constants.pil offset values (our pil does not yet support constant evaluation so values are hardcoded) -global MAX_NEW_NOTE_HASHES_PER_CALL: u32 = 16; -global MAX_NEW_NULLIFIERS_PER_CALL: u32 = 16; +global MAX_NOTE_HASHES_PER_CALL: u32 = 16; +global MAX_NULLIFIERS_PER_CALL: u32 = 16; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL: u32 = 4; global MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL: u32 = 16; -global MAX_NEW_L2_TO_L1_MSGS_PER_CALL: u32 = 2; +global MAX_L2_TO_L1_MSGS_PER_CALL: u32 = 2; global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL: u32 = 32; global MAX_PUBLIC_DATA_READS_PER_CALL: u32 = 32; -global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u32 = 32; -global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u32 = 32; -global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u32 = 32; +global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u32 = 16; +global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u32 = 16; +global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u32 = 16; global MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL: u32 = 16; global MAX_KEY_VALIDATION_REQUESTS_PER_CALL: u32 = 16; global MAX_NOTE_ENCRYPTED_LOGS_PER_CALL: u32 = 16; @@ -40,8 +39,8 @@ global MAX_ENCRYPTED_LOGS_PER_CALL: u32 = 4; // If modifying, update DEPLOYER_CO global MAX_UNENCRYPTED_LOGS_PER_CALL: u32 = 4; // If modifying, update DEPLOYER_CONTRACT_ADDRESS. // "PER TRANSACTION" CONSTANTS -global MAX_NEW_NOTE_HASHES_PER_TX: u32 = 64; -global MAX_NEW_NULLIFIERS_PER_TX: u32 = 64; +global MAX_NOTE_HASHES_PER_TX: u32 = 64; +global MAX_NULLIFIERS_PER_TX: u32 = 64; global MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX: u32 = 8; global MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX: u32 = 32; // If you touch any of the constants below don't forget to update MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX. @@ -52,10 +51,10 @@ global PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 1; // Pain. global MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u32 = 64; // MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; global MAX_PUBLIC_DATA_READS_PER_TX: u32 = 64; -global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u32 = 8; -global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u32 = 128; -global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u32 = 128; -global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u32 = 128; +global MAX_L2_TO_L1_MSGS_PER_TX: u32 = 8; +global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u32 = 64; +global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u32 = 64; +global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u32 = 64; global MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX: u32 = 64; // TODO: for large multisends we might run out of key validation requests here but not dealing with this now as // databus will hopefully make the issue go away. @@ -66,7 +65,7 @@ global MAX_UNENCRYPTED_LOGS_PER_TX: u32 = 8; // docs:end:constants // KERNEL CIRCUIT PRIVATE INPUTS CONSTANTS -// global MAX_PUBLIC_DATA_HINTS: u32 = MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_READS_PER_TX; +// global MAX_PUBLIC_DATA_HINTS: u32 = MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_READS_PER_TX; // FIX: Sadly, writing this as above causes a type error in type_conversion.ts. global MAX_PUBLIC_DATA_HINTS: u32 = 128; @@ -194,8 +193,8 @@ global TX_CONTEXT_LENGTH: u32 = 2 + GAS_SETTINGS_LENGTH; global TX_REQUEST_LENGTH: u32 = 2 + TX_CONTEXT_LENGTH + FUNCTION_DATA_LENGTH; global TOTAL_FEES_LENGTH = 1; global HEADER_LENGTH: u32 = APPEND_ONLY_TREE_SNAPSHOT_LENGTH + CONTENT_COMMITMENT_LENGTH + STATE_REFERENCE_LENGTH + GLOBAL_VARIABLES_LENGTH + TOTAL_FEES_LENGTH; -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + TX_CONTEXT_LENGTH; -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + /*argsHash + returnsHash*/ 2 + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_NEW_L2_TO_L1_MSGS_PER_CALL) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + 4 + MAX_BLOCK_NUMBER_LENGTH + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_CALL) + (NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_CALL) + (PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + 1 + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_CALL) + (ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_CALL) + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + TX_CONTEXT_LENGTH; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + /*argsHash + returnsHash*/ 2 + (READ_REQUEST_LENGTH * MAX_NOTE_HASH_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL) + (READ_REQUEST_LENGTH * MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH * MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL) + (CONTRACT_STORAGE_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_CALL) + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL + (NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_CALL) + (NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_CALL) + (L2_TO_L1_MESSAGE_LENGTH * MAX_L2_TO_L1_MSGS_PER_CALL) + 2 + (LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_CALL) + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + AZTEC_ADDRESS_LENGTH + /* revert_code */ 1 + 2 * GAS_LENGTH + /* transaction_fee */ 1; global PRIVATE_CALL_STACK_ITEM_LENGTH: u32 = AZTEC_ADDRESS_LENGTH + FUNCTION_DATA_LENGTH + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH; global PUBLIC_CONTEXT_INPUTS_LENGTH: u32 = CALL_CONTEXT_LENGTH + HEADER_LENGTH + GLOBAL_VARIABLES_LENGTH + GAS_LENGTH + 2; @@ -206,14 +205,14 @@ global PUBLIC_DATA_READ_LENGTH = 2; global VALIDATION_REQUESTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + (SCOPED_READ_REQUEST_LEN * MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_READ_REQUESTS_PER_TX) + (SCOPED_READ_REQUEST_LEN * MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) + (SCOPED_KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH * MAX_KEY_VALIDATION_REQUESTS_PER_TX) + (PUBLIC_DATA_READ_LENGTH * MAX_PUBLIC_DATA_READS_PER_TX); global PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; -global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NEW_NOTE_HASHES_PER_TX + MAX_NEW_NULLIFIERS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; +global COMBINED_ACCUMULATED_DATA_LENGTH = MAX_NOTE_HASHES_PER_TX + MAX_NULLIFIERS_PER_TX + MAX_L2_TO_L1_MSGS_PER_TX + 6 + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + GAS_LENGTH; global COMBINED_CONSTANT_DATA_LENGTH = HEADER_LENGTH + TX_CONTEXT_LENGTH + GLOBAL_VARIABLES_LENGTH; global CALL_REQUEST_LENGTH = 1 + AZTEC_ADDRESS_LENGTH + CALLER_CONTEXT_LENGTH + 2; -global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NEW_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NEW_NULLIFIERS_PER_TX) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (SCOPED_PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); +global PRIVATE_ACCUMULATED_DATA_LENGTH = (SCOPED_NOTE_HASH_LENGTH * MAX_NOTE_HASHES_PER_TX) + (SCOPED_NULLIFIER_LENGTH * MAX_NULLIFIERS_PER_TX) + (MAX_L2_TO_L1_MSGS_PER_TX * SCOPED_L2_TO_L1_MESSAGE_LENGTH) + (NOTE_LOG_HASH_LENGTH * MAX_NOTE_ENCRYPTED_LOGS_PER_TX) + (SCOPED_ENCRYPTED_LOG_HASH_LENGTH * MAX_ENCRYPTED_LOGS_PER_TX) + (SCOPED_LOG_HASH_LENGTH * MAX_UNENCRYPTED_LOGS_PER_TX) + (SCOPED_PRIVATE_CALL_REQUEST_LENGTH * MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX) + (CALL_REQUEST_LENGTH * MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX); global PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1 + VALIDATION_REQUESTS_LENGTH + PRIVATE_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + CALL_REQUEST_LENGTH + AZTEC_ADDRESS_LENGTH; -global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NEW_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NEW_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_NEW_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; +global PUBLIC_ACCUMULATED_DATA_LENGTH = (MAX_NOTE_HASHES_PER_TX * NOTE_HASH_LENGTH) + (MAX_NULLIFIERS_PER_TX * NULLIFIER_LENGTH) + (MAX_L2_TO_L1_MSGS_PER_TX * 1) + (MAX_NOTE_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_ENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_UNENCRYPTED_LOGS_PER_TX * LOG_HASH_LENGTH) + (MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * PUBLIC_DATA_UPDATE_REQUEST_LENGTH) + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + GAS_LENGTH; global PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = VALIDATION_REQUESTS_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + PUBLIC_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + 1 + (MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX * CALL_REQUEST_LENGTH) + AZTEC_ADDRESS_LENGTH; global KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = ROLLUP_VALIDATION_REQUESTS_LENGTH + COMBINED_ACCUMULATED_DATA_LENGTH + COMBINED_CONSTANT_DATA_LENGTH + PARTIAL_STATE_REFERENCE_LENGTH + 1 + AZTEC_ADDRESS_LENGTH; @@ -225,8 +224,8 @@ global BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = CONSTANT_ROLLUP_DATA_LENGTH + PARTIA global ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH: u32 = 3 + CALL_CONTEXT_LENGTH; global GET_NOTES_ORACLE_RETURN_LENGTH: u32 = 674; -global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NEW_NOTE_HASHES_PER_TX; -global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NEW_NULLIFIERS_PER_TX; +global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NOTE_HASHES_PER_TX; +global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NULLIFIERS_PER_TX; global PUBLIC_DATA_WRITES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 64 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; // 1 write is 64 bytes global CONTRACTS_NUM_BYTES_PER_BASE_ROLLUP: Field = 32; global CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; @@ -310,3 +309,36 @@ global GENERATOR_INDEX__NOTE_NULLIFIER = 53; global GENERATOR_INDEX__INNER_NOTE_HASH = 54; global GENERATOR_INDEX__NOTE_CONTENT_HASH = 55; global GENERATOR_INDEX__SYMMETRIC_KEY: u8 = 56; + +global SENDER_SELECTOR: u32 = 0; +// "address" actually does not exist in PublicCircuitPublicInputs, +// so this is just an alias to "storage address" for now +global ADDRESS_SELECTOR: u32 = SENDER_SELECTOR + 1; +global STORAGE_ADDRESS_SELECTOR: u32 = ADDRESS_SELECTOR; +global FUNCTION_SELECTOR_SELECTOR: u32 = ADDRESS_SELECTOR + 1; +// Global Variables +global START_GLOBAL_VARIABLES: u32 = CALL_CONTEXT_LENGTH + HEADER_LENGTH; +global CHAIN_ID_SELECTOR: u32 = START_GLOBAL_VARIABLES; +global VERSION_SELECTOR: u32 = CHAIN_ID_SELECTOR + 1; +global BLOCK_NUMBER_SELECTOR: u32 = VERSION_SELECTOR + 1; +global TIMESTAMP_SELECTOR: u32 = BLOCK_NUMBER_SELECTOR + 1; +global COINBASE_SELECTOR: u32 = TIMESTAMP_SELECTOR + 1; +global UNUSED_FEE_RECIPIENT_SELECTOR: u32 = COINBASE_SELECTOR + 1; +// Global Variables - fees +global FEE_PER_DA_GAS_SELECTOR: u32 = UNUSED_FEE_RECIPIENT_SELECTOR + 1; +global FEE_PER_L2_GAS_SELECTOR: u32 = FEE_PER_DA_GAS_SELECTOR + 1; +global END_GLOBAL_VARIABLES: u32 = START_GLOBAL_VARIABLES + GLOBAL_VARIABLES_LENGTH; +// Top-level members +global START_SIDE_EFFECT_COUNTER: u32 = END_GLOBAL_VARIABLES; +global TRANSACTION_FEE_SELECTOR: u32 = PUBLIC_CONTEXT_INPUTS_LENGTH - 1; +// Side effects +global START_NOTE_HASH_EXISTS_WRITE_OFFSET: u32 = 0; +global START_NULLIFIER_EXISTS_OFFSET: u32 = START_NOTE_HASH_EXISTS_WRITE_OFFSET + MAX_NOTE_HASH_READ_REQUESTS_PER_CALL; +global START_NULLIFIER_NON_EXISTS_OFFSET: u32 = START_NULLIFIER_EXISTS_OFFSET + MAX_NULLIFIER_READ_REQUESTS_PER_CALL; +global START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET: u32 = START_NULLIFIER_NON_EXISTS_OFFSET + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL; +global START_SSTORE_WRITE_OFFSET: u32 = START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET + MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL; +global START_SLOAD_WRITE_OFFSET: u32 = START_SSTORE_WRITE_OFFSET + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL; +global START_EMIT_NOTE_HASH_WRITE_OFFSET: u32 = START_SLOAD_WRITE_OFFSET + MAX_PUBLIC_DATA_READS_PER_CALL; +global START_EMIT_NULLIFIER_WRITE_OFFSET: u32 = START_EMIT_NOTE_HASH_WRITE_OFFSET + MAX_NOTE_HASHES_PER_CALL; +global START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET: u32 = START_EMIT_NULLIFIER_WRITE_OFFSET + MAX_NULLIFIERS_PER_CALL; +global START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET: u32 = START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET + MAX_L2_TO_L1_MSGS_PER_CALL; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr index 3279b6ab9f2d..bc1b421134ce 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr @@ -4,7 +4,7 @@ use crate::{ }; struct ContentCommitment { - tx_tree_height: Field, + num_txs: Field, txs_effects_hash: Field, in_hash: Field, out_hash: Field, @@ -14,7 +14,7 @@ impl Serialize for ContentCommitment { fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] { let mut fields: BoundedVec = BoundedVec::new(); - fields.push(self.tx_tree_height); + fields.push(self.num_txs); fields.push(self.txs_effects_hash); fields.push(self.in_hash); fields.push(self.out_hash); @@ -25,7 +25,7 @@ impl Serialize for ContentCommitment { impl Deserialize for ContentCommitment { fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self { - let tx_tree_height = serialized[0]; + let num_txs = serialized[0]; let txs_effects_hash = serialized[1]; @@ -34,7 +34,7 @@ impl Deserialize for ContentCommitment { let out_hash = serialized[3]; Self { - tx_tree_height, + num_txs, txs_effects_hash, in_hash, out_hash, @@ -45,7 +45,7 @@ impl Deserialize for ContentCommitment { impl Empty for ContentCommitment { fn empty() -> Self { Self { - tx_tree_height: 0, + num_txs: 0, txs_effects_hash: 0, in_hash: 0, out_hash: 0, @@ -55,7 +55,7 @@ impl Empty for ContentCommitment { impl Eq for ContentCommitment { fn eq(self, other: Self) -> bool { - (self.tx_tree_height == other.tx_tree_height) + (self.num_txs == other.num_txs) & (self.txs_effects_hash == other.txs_effects_hash) & (self.in_hash == other.in_hash) & (self.out_hash == other.out_hash) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr index 1d16de258a7d..7ae3a07f3d2a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr @@ -41,7 +41,7 @@ impl ContractClassId { private_functions_root: Field, public_bytecode_commitment: Field ) -> Self { - let hash = dep::std::hash::pedersen_hash_with_separator( + let hash = std::hash::pedersen_hash_with_separator( [ artifact_hash, private_functions_root, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/contrakt.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/contrakt/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr index 01f0acf1eb10..5f5cc1ae1464 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/contrakt/storage_update_request.nr @@ -2,7 +2,6 @@ use crate::{ constants::{CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH, GENERATOR_INDEX__PUBLIC_DATA_UPDATE_REQUEST}, hash::pedersen_hash, traits::{Deserialize, Hash, Empty, Serialize} }; -use dep::std::cmp::Eq; struct StorageUpdateRequest { storage_slot : Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/hash.nr index 250ed76f1418..c10db9c20098 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/data/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/data/hash.nr @@ -1,7 +1,7 @@ use crate::{address::AztecAddress, constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX}; pub fn compute_public_data_tree_index(contract_address: AztecAddress, storage_slot: Field) -> Field { - dep::std::hash::pedersen_hash_with_separator( + std::hash::pedersen_hash_with_separator( [ contract_address.to_field(), storage_slot diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/data.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/data/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr index a7caaa397512..a996a0df6fee 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr @@ -1,5 +1,4 @@ -use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash}; -use dep::std::cmp::Eq; +use crate::{traits::{Serialize, Deserialize, Hash, Empty}, hash::poseidon2_hash}; global GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2; @@ -36,6 +35,15 @@ impl Hash for GrumpkinPoint { } } +impl Empty for GrumpkinPoint { + fn empty() -> Self { + GrumpkinPoint { + x: 0, + y: 0 + } + } +} + impl GrumpkinPoint { pub fn new(x: Field, y: Field) -> Self { Self { x, y } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr index f9d8526ddb89..f00d3d8ddf1a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr @@ -1,4 +1,4 @@ -use dep::std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul}; +use std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul}; use crate::{grumpkin_point::GrumpkinPoint, traits::Empty}; global GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN: Field = 2; 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 561c3d1029be..bf2afcf5da84 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -10,12 +10,11 @@ use crate::{ GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH, MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX }, - contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path, - messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message}, - recursion::verification_key::VerificationKey, traits::{Hash, is_empty}, - utils::{uint256::U256, field::field_from_bytes_32_trunc} + merkle_tree::root::root_from_sibling_path, messaging::l2_to_l1_message::ScopedL2ToL1Message, + recursion::verification_key::VerificationKey, traits::is_empty, + utils::field::field_from_bytes_32_trunc }; -use dep::std::hash::{pedersen_hash_with_separator, sha256}; +use std::hash::{pedersen_hash_with_separator, sha256}; pub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field { let sha256_hashed = sha256(bytes_to_hash); @@ -35,11 +34,12 @@ pub fn private_functions_root_from_siblings( root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path) } -pub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field { +fn compute_note_hash_nonce(tx_hash: Field, note_index_in_tx: u32) -> Field { + // Hashing tx hash with note index in tx is guaranteed to be unique pedersen_hash( [ - first_nullifier, - note_hash_index as Field + tx_hash, + note_index_in_tx as Field ], GENERATOR_INDEX__NOTE_HASH_NONCE ) @@ -60,11 +60,11 @@ pub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> F ) } -pub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field { +pub fn silo_note_hash(note_hash: ScopedNoteHash, tx_hash: Field, note_index_in_tx: u32) -> Field { if note_hash.contract_address.is_zero() { 0 } else { - let nonce = compute_note_hash_nonce(first_nullifier, index); + let nonce = compute_note_hash_nonce(tx_hash, note_index_in_tx); let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value()); compute_siloed_note_hash(note_hash.contract_address, unique_note_hash) } @@ -249,11 +249,11 @@ pub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX] } pub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field { - dep::std::hash::pedersen_hash_with_separator(inputs, hash_index) + std::hash::pedersen_hash_with_separator(inputs, hash_index) } pub fn poseidon2_hash(inputs: [Field; N]) -> Field { - dep::std::hash::poseidon2::Poseidon2::hash(inputs, N) + std::hash::poseidon2::Poseidon2::hash(inputs, N) } #[test] 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 6de1fb6fe6a9..14bd01ef8f2a 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 @@ -82,7 +82,7 @@ mod tests { }, tests::merkle_tree_utils::NonEmptyMerkleTree }; - use dep::std::hash::pedersen_hash; + use std::hash::pedersen_hash; struct TestLeafPreimage { value: Field, diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr index 939301a768dc..88e497089a0d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/merkle_tree.nr @@ -24,12 +24,12 @@ impl MerkleTree { // hash base layer for i in 0..half_size { - nodes[i] = dep::std::hash::pedersen_hash([leaves[2*i], leaves[2*i+1]]); + nodes[i] = std::hash::pedersen_hash([leaves[2*i], leaves[2*i+1]]); } // hash the other layers for i in 0..(total_nodes - half_size) { - nodes[half_size+i] = dep::std::hash::pedersen_hash([nodes[2*i], nodes[2*i+1]]); + nodes[half_size+i] = std::hash::pedersen_hash([nodes[2*i], nodes[2*i+1]]); } MerkleTree { leaves, nodes } 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/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/messaging.nr b/noir-projects/noir-protocol-circuits/crates/types/src/messaging/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/messaging.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/messaging/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr b/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr index 57eb1945a3ac..79f21b9734ad 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf.nr @@ -1,5 +1,4 @@ use crate::traits::Empty; -use dep::std::cmp::Eq; struct PublicDataTreeLeaf { slot: Field, 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 c7f5521b968b..476562690c8f 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 @@ -23,7 +23,7 @@ impl Hash for PublicDataTreeLeafPreimage { if self.is_empty() { 0 } else { - dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot]) + std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot]) } } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/recursion.nr b/noir-projects/noir-protocol-circuits/crates/types/src/recursion/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/recursion.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/recursion/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/storage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/storage.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/storage/mod.nr 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 a0fbb0dacecf..85a039642cf7 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 @@ -2,7 +2,10 @@ use crate::{ abis::{ gas::Gas, gas_settings::GasSettings, call_context::CallContext, call_request::{CallerContext, CallRequest}, - accumulated_data::{CombinedAccumulatedData, PrivateAccumulatedData, PrivateAccumulatedDataBuilder, PublicAccumulatedData}, + accumulated_data::{ + CombinedAccumulatedData, PrivateAccumulatedData, PrivateAccumulatedDataBuilder, + PublicAccumulatedData, PublicAccumulatedDataBuilder +}, function_data::FunctionData, global_variables::GlobalVariables, combined_constant_data::CombinedConstantData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs, PublicKernelCircuitPublicInputs}, @@ -22,8 +25,8 @@ use crate::{ }, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, constants::{ - FUNCTION_TREE_HEIGHT, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + FUNCTION_TREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_L2_TO_L1_MSGS_PER_TX, + MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, 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_KEY_VALIDATION_REQUESTS_PER_TX, VK_TREE_HEIGHT, @@ -79,9 +82,9 @@ struct FixtureBuilder { global_variables: GlobalVariables, // Accumulated data. - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + note_hashes: BoundedVec, + nullifiers: BoundedVec, + l2_to_l1_msgs: BoundedVec, note_encrypted_logs_hashes: BoundedVec, encrypted_logs_hashes: BoundedVec, unencrypted_logs_hashes: BoundedVec, @@ -243,12 +246,12 @@ impl FixtureBuilder { key_validation_requests_and_generators: subarray( self.scoped_key_validation_requests_and_generators.storage.map(|r: ScopedKeyValidationRequestAndGenerator| r.request) ), - new_note_hashes: subarray(self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash)), - new_nullifiers: subarray(self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier)), + note_hashes: subarray(self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash)), + nullifiers: subarray(self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier)), private_call_requests: subarray(self.private_call_requests.storage.map(|r: ScopedPrivateCallRequest| r.call_request)), public_call_stack_hashes: subarray(self.public_call_requests.storage.map(|c: CallRequest| c.hash)), public_teardown_function_hash: self.public_teardown_call_stack.storage[0].hash, - new_l2_to_l1_msgs: subarray(self.new_l2_to_l1_msgs.storage.map(|r: ScopedL2ToL1Message| r.message)), + l2_to_l1_msgs: subarray(self.l2_to_l1_msgs.storage.map(|r: ScopedL2ToL1Message| r.message)), start_side_effect_counter: self.counter_start, end_side_effect_counter: self.counter, note_encrypted_logs_hashes: subarray(self.note_encrypted_logs_hashes.storage), @@ -283,29 +286,71 @@ impl FixtureBuilder { } } - pub fn to_private_accumulated_data(self) -> PrivateAccumulatedData { - let public_inputs = PrivateAccumulatedDataBuilder { - new_note_hashes: self.new_note_hashes, - new_nullifiers: self.new_nullifiers, - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs, + pub fn to_private_accumulated_data_builder(self) -> PrivateAccumulatedDataBuilder { + PrivateAccumulatedDataBuilder { + note_hashes: self.note_hashes, + nullifiers: self.nullifiers, + l2_to_l1_msgs: self.l2_to_l1_msgs, note_encrypted_logs_hashes: self.note_encrypted_logs_hashes, encrypted_logs_hashes: self.encrypted_logs_hashes, unencrypted_logs_hashes: self.unencrypted_logs_hashes, private_call_stack: vec_reverse(self.private_call_requests), public_call_stack: self.public_call_requests + } + } + + pub fn to_private_accumulated_data(self) -> PrivateAccumulatedData { + self.to_private_accumulated_data_builder().finish() + } + + pub fn to_public_accumulated_data_builder(self) -> PublicAccumulatedDataBuilder { + let note_hashes = BoundedVec { storage: self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), len: self.note_hashes.len() }; + let nullifiers = BoundedVec { storage: self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), len: self.nullifiers.len() }; + let l2_to_l1_msgs = BoundedVec { + storage: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), + len: self.l2_to_l1_msgs.len() + }; + let note_encrypted_logs_hashes = BoundedVec { + storage: self.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| LogHash { value: l.value, counter: l.counter, length: l.length }), + len: self.note_encrypted_logs_hashes.len() }; - public_inputs.finish() + let encrypted_logs_hashes = BoundedVec { + storage: self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.log_hash).map(|l: EncryptedLogHash| LogHash { value: l.value, counter: l.counter, length: l.length }), + len: self.encrypted_logs_hashes.len() + }; + let unencrypted_logs_hashes = BoundedVec { + storage: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.log_hash), + len: self.unencrypted_logs_hashes.len() + }; + + PublicAccumulatedDataBuilder { + note_hashes, + nullifiers, + l2_to_l1_msgs, + note_encrypted_logs_hashes, + encrypted_logs_hashes, + unencrypted_logs_hashes, + public_data_update_requests: self.public_data_update_requests, + public_call_stack: self.public_call_requests, + gas_used: self.gas_used + } } pub fn to_public_accumulated_data(self) -> PublicAccumulatedData { + self.to_public_accumulated_data_builder().finish() + } + + pub fn to_exposed_public_accumulated_data(self) -> PublicAccumulatedData { PublicAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash), - new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), + note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.expose_to_public()), + nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.expose_to_public()), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage.map(|l: NoteLogHash| l.expose_to_public()), encrypted_logs_hashes: self.encrypted_logs_hashes.storage.map(|l: ScopedEncryptedLogHash| l.expose_to_public()), - unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.log_hash), + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage.map(|l: ScopedLogHash| l.expose_to_public()), public_data_update_requests: self.public_data_update_requests.storage, + // TODO: Hide the counter of a public call request. + // public_call_stack: self.public_call_requests.storage.map(|cr: CallRequest| cr.expose_to_public()), public_call_stack: self.public_call_requests.storage, gas_used: self.gas_used } @@ -313,9 +358,9 @@ impl FixtureBuilder { pub fn to_combined_accumulated_data(self) -> CombinedAccumulatedData { CombinedAccumulatedData { - new_note_hashes: self.new_note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), - new_nullifiers: self.new_nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), - new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), + note_hashes: self.note_hashes.storage.map(|n: ScopedNoteHash| n.note_hash.value), + nullifiers: self.nullifiers.storage.map(|n: ScopedNullifier| n.nullifier.value), + l2_to_l1_msgs: self.l2_to_l1_msgs.storage.map(|m: ScopedL2ToL1Message| m.message.content), note_encrypted_logs_hash: self.note_encrypted_logs_hash, encrypted_logs_hash: self.encrypted_logs_hash, unencrypted_logs_hash: self.unencrypted_logs_hash, @@ -361,6 +406,7 @@ impl FixtureBuilder { } pub fn to_public_kernel_circuit_public_inputs(self, revertible: bool) -> PublicKernelCircuitPublicInputs { + // TODO: Split the data using self.min_revertible_side_effect_counter. let accumulated_data = self.to_public_accumulated_data(); let end_non_revertible = if revertible { PublicAccumulatedData::empty() @@ -424,43 +470,44 @@ impl FixtureBuilder { } pub fn add_new_note_hash(&mut self, value: Field, nullifier_counter: u32) { - self.new_note_hashes.push( + self.note_hashes.push( NoteHash { value, counter: self.next_counter() }.scope(nullifier_counter, self.storage_contract_address) ); } pub fn add_siloed_note_hash(&mut self, value: Field) { - let first_nullifier = self.new_nullifiers.get(0).value(); - let index = self.new_note_hashes.len(); + // First nullifier is tx hash. + let tx_hash = self.nullifiers.get(0).value(); + let index = self.note_hashes.len(); let note_hash = NoteHash { value, counter: 0 }.scope(0, self.storage_contract_address); - let siloed_value = silo_note_hash(note_hash, first_nullifier, index); + let siloed_value = silo_note_hash(note_hash, tx_hash, index); self.add_new_note_hash(siloed_value, 0); } - pub fn append_new_note_hashes(&mut self, num_new_note_hashes: u32) { - let index_offset = self.new_note_hashes.len(); - for i in 0..self.new_note_hashes.max_len() { - if i < num_new_note_hashes { + pub fn append_note_hashes(&mut self, num_note_hashes: u32) { + let index_offset = self.note_hashes.len(); + for i in 0..self.note_hashes.max_len() { + if i < num_note_hashes { let value = self.mock_note_hash_value(index_offset + i); self.add_new_note_hash(value, 0); } } } - pub fn append_siloed_note_hashes(&mut self, num_new_note_hashes: u32) { - let index_offset = self.new_note_hashes.len(); - for i in 0..self.new_note_hashes.max_len() { - if i < num_new_note_hashes { + pub fn append_siloed_note_hashes(&mut self, num_note_hashes: u32) { + let index_offset = self.note_hashes.len(); + for i in 0..self.note_hashes.max_len() { + if i < num_note_hashes { let value = self.mock_note_hash_value(index_offset + i); self.add_siloed_note_hash(value); } } } - pub fn append_new_note_hashes_with_logs(&mut self, num_new_note_hashes: u32) { - let index_offset = self.new_note_hashes.len(); - for i in 0..self.new_note_hashes.max_len() { - if i < num_new_note_hashes { + pub fn append_note_hashes_with_logs(&mut self, num_note_hashes: u32) { + let index_offset = self.note_hashes.len(); + for i in 0..self.note_hashes.max_len() { + if i < num_note_hashes { let value = self.mock_note_hash_value(index_offset + i); self.add_new_note_hash(value, 0); let (log_hash, length) = self.mock_note_encrypted_log(index_offset + i); @@ -469,8 +516,15 @@ impl FixtureBuilder { } } + pub fn set_first_nullifier(&mut self) { + assert_eq(self.nullifiers.len(), 0, "first nullifier already set"); + let value = self.mock_nullifier_value(0); + let first_nullifier = Nullifier { value, counter: 0, note_hash: 0 }.scope(AztecAddress::zero()); + self.nullifiers.push(first_nullifier); + } + pub fn add_nullifier(&mut self, value: Field) { - self.new_nullifiers.push( + self.nullifiers.push( Nullifier { value, counter: self.next_counter(), note_hash: 0 }.scope(self.storage_contract_address) ); } @@ -480,9 +534,9 @@ impl FixtureBuilder { self.add_nullifier(siloed_value); } - pub fn append_new_nullifiers(&mut self, num_extra_nullifier: u32) { - let index_offset = self.new_nullifiers.len(); - for i in 0..self.new_nullifiers.max_len() { + pub fn append_nullifiers(&mut self, num_extra_nullifier: u32) { + let index_offset = self.nullifiers.len(); + for i in 0..self.nullifiers.max_len() { if i < num_extra_nullifier { let value = self.mock_nullifier_value(index_offset + i); self.add_nullifier(value); @@ -491,8 +545,8 @@ impl FixtureBuilder { } pub fn append_siloed_nullifiers(&mut self, num_extra_nullifier: u32) { - let index_offset = self.new_nullifiers.len(); - for i in 0..self.new_nullifiers.max_len() { + let index_offset = self.nullifiers.len(); + for i in 0..self.nullifiers.max_len() { if i < num_extra_nullifier { let value = self.mock_nullifier_value(index_offset + i); self.add_siloed_nullifier(value); @@ -501,7 +555,7 @@ impl FixtureBuilder { } pub fn add_l2_to_l1_message(&mut self, content: Field, recipient: EthAddress) { - self.new_l2_to_l1_msgs.push( + self.l2_to_l1_msgs.push( L2ToL1Message { recipient, content, counter: self.next_counter() }.scope(self.storage_contract_address) ); } @@ -517,9 +571,9 @@ impl FixtureBuilder { self.add_l2_to_l1_message(siloed_content, recipient); } - pub fn append_new_l2_to_l1_msgs(&mut self, num: u32) { - let index_offset = self.new_l2_to_l1_msgs.len(); - for i in 0..self.new_l2_to_l1_msgs.max_len() { + pub fn append_l2_to_l1_msgs(&mut self, num: u32) { + let index_offset = self.l2_to_l1_msgs.len(); + for i in 0..self.l2_to_l1_msgs.max_len() { if i < num { let (content, recipient) = self.mock_l2_to_l1_msg(index_offset + i); self.add_l2_to_l1_message(content, recipient); @@ -528,8 +582,8 @@ impl FixtureBuilder { } pub fn append_siloed_l2_to_l1_msgs(&mut self, num: u32) { - let index_offset = self.new_l2_to_l1_msgs.len(); - for i in 0..self.new_l2_to_l1_msgs.max_len() { + let index_offset = self.l2_to_l1_msgs.len(); + for i in 0..self.l2_to_l1_msgs.max_len() { if i < num { let (content, recipient) = self.mock_l2_to_l1_msg(index_offset + i); self.add_siloed_l2_to_l1_message(content, recipient); @@ -660,6 +714,13 @@ impl FixtureBuilder { self.encrypted_log_preimages_length += length; } + pub fn add_siloed_encrypted_log_hash(&mut self, hash: Field, length: Field) { + let mut log_hash = EncryptedLogHash { value: hash, counter: self.next_counter(), length, randomness: 2 }.scope(self.storage_contract_address); + log_hash.log_hash.value = silo_encrypted_log_hash(log_hash); + self.encrypted_logs_hashes.push(log_hash); + self.encrypted_log_preimages_length += length; + } + pub fn append_encrypted_log_hashes(&mut self, num: u32) { let index_offset = self.encrypted_logs_hashes.len(); for i in 0..self.encrypted_logs_hashes.max_len() { @@ -687,6 +748,13 @@ impl FixtureBuilder { self.unencrypted_log_preimages_length += length; } + pub fn add_siloed_unencrypted_log_hash(&mut self, hash: Field, length: Field) { + let mut log_hash = LogHash { value: hash, counter: self.next_counter(), length }.scope(self.storage_contract_address); + log_hash.log_hash.value = silo_unencrypted_log_hash(log_hash); + self.unencrypted_logs_hashes.push(log_hash); + self.unencrypted_log_preimages_length += length; + } + pub fn append_unencrypted_log_hashes(&mut self, num: u32) { let index_offset = self.unencrypted_logs_hashes.len(); for i in 0..self.unencrypted_logs_hashes.max_len() { @@ -924,9 +992,9 @@ impl Empty for FixtureBuilder { historical_header: Header::empty(), tx_context: TxContext::empty(), global_variables: GlobalVariables::empty(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), note_encrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_hashes: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr index 3c5ca634f791..5818fb22ace4 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/merkle_tree_utils.nr @@ -1,10 +1,10 @@ use crate::{merkle_tree::{MerkleTree, calculate_empty_tree_root}, traits::Empty}; pub fn compute_zero_hashes(mut hashes: [Field; N]) -> [Field; N] { - hashes[0] = dep::std::hash::pedersen_hash([0, 0]); + hashes[0] = std::hash::pedersen_hash([0, 0]); for i in 1..N { - hashes[i] = dep::std::hash::pedersen_hash([hashes[i-1], hashes[i-1]]); + hashes[i] = std::hash::pedersen_hash([hashes[i-1], hashes[i-1]]); } hashes @@ -25,7 +25,7 @@ impl MerkleTree { let mut layer_offset: u32 = 0; let mut node_index: u32 = index / 2 + layer_offset; for _ in 0..K { - self.nodes[node_index] = dep::std::hash::pedersen_hash([left_node, right_node]); + self.nodes[node_index] = std::hash::pedersen_hash([left_node, right_node]); sibling_index = MerkleTree::sibling_index(node_index); let nodes = if node_index % 2 == 0 { (self.nodes[node_index], self.nodes[sibling_index]) @@ -51,11 +51,11 @@ impl MerkleTree { #[test] fn test_merkle_tree_update_leaf() { let mut tree = MerkleTree::new([1, 2]); - assert_eq(tree.get_root(), dep::std::hash::pedersen_hash([1, 2])); + assert_eq(tree.get_root(), std::hash::pedersen_hash([1, 2])); tree.update_leaf(1, 0, [0; 1]); - assert_eq(tree.get_root(), dep::std::hash::pedersen_hash([1, 0])); + assert_eq(tree.get_root(), std::hash::pedersen_hash([1, 0])); tree.update_leaf(0, 0, [0; 1]); - assert_eq(tree.get_root(), dep::std::hash::pedersen_hash([0, 0])); + assert_eq(tree.get_root(), std::hash::pedersen_hash([0, 0])); } #[test] @@ -105,10 +105,10 @@ impl NonEmptyMerkl let zero_hashes = compute_zero_hashes(_tree_height); let mut left_supertree_branch = [0; SUPERTREE_HEIGHT]; - left_supertree_branch[0] = dep::std::hash::pedersen_hash([subtree.get_root(), zero_hashes[SUBTREE_HEIGHT-1]]); + left_supertree_branch[0] = std::hash::pedersen_hash([subtree.get_root(), zero_hashes[SUBTREE_HEIGHT-1]]); for i in 1..left_supertree_branch.len() { // TODO(md): far right of this yuck - left_supertree_branch[i] = dep::std::hash::pedersen_hash([left_supertree_branch[i-1], zero_hashes[(SUBTREE_HEIGHT as u64 -1) + i as u64]]); + left_supertree_branch[i] = std::hash::pedersen_hash([left_supertree_branch[i-1], zero_hashes[(SUBTREE_HEIGHT as u64 -1) + i as u64]]); } NonEmptyMerkleTree { subtree, zero_hashes, left_supertree_branch, _phantom_subtree_height: _subtree_height } @@ -154,9 +154,9 @@ impl NonEmptyMerkl self.subtree.update_leaf(index, value, [0; SUBTREE_HEIGHT]); - self.left_supertree_branch[0] = dep::std::hash::pedersen_hash([self.subtree.get_root(), self.zero_hashes[SUBTREE_HEIGHT-1]]); + self.left_supertree_branch[0] = std::hash::pedersen_hash([self.subtree.get_root(), self.zero_hashes[SUBTREE_HEIGHT-1]]); for i in 1..self.left_supertree_branch.len() { - self.left_supertree_branch[i] = dep::std::hash::pedersen_hash([self.left_supertree_branch[i-1], self.zero_hashes[SUBTREE_HEIGHT-1+i]]); + self.left_supertree_branch[i] = std::hash::pedersen_hash([self.left_supertree_branch[i-1], self.zero_hashes[SUBTREE_HEIGHT-1+i]]); } } @@ -177,7 +177,7 @@ fn test_merkle_tree_empty_subtree() { assert_eq(tree.zero_hashes.len(), 2); let path = tree.get_sibling_path(3); assert_eq(path[0], 0); - assert_eq(path[1], dep::std::hash::pedersen_hash([0, 0])); + assert_eq(path[1], std::hash::pedersen_hash([0, 0])); assert_eq(tree.get_root(), calculate_empty_tree_root(2)); } @@ -200,7 +200,7 @@ fn test_merkle_tree_non_empty_subtree() { assert_eq(tree.zero_hashes.len(), 2); let path = tree.get_sibling_path(3); assert_eq(path[0], 0); - assert_eq(path[1], dep::std::hash::pedersen_hash([1, 1])); + assert_eq(path[1], std::hash::pedersen_hash([1, 1])); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/tests.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/tests/mod.nr 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 e2a97cf3397f..50aa8e0aa9d5 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 @@ -11,7 +11,7 @@ use crate::{ use crate::{ constants::{ MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_L2_TO_L1_MSGS_PER_CALL, MAX_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_UNENCRYPTED_LOGS_PER_CALL @@ -30,9 +30,9 @@ struct PublicCircuitPublicInputsBuilder { contract_storage_update_requests: BoundedVec, contract_storage_reads: BoundedVec, public_call_stack_hashes: BoundedVec, - new_note_hashes: BoundedVec, - new_nullifiers: BoundedVec, - new_l2_to_l1_msgs: BoundedVec, + note_hashes: BoundedVec, + nullifiers: BoundedVec, + l2_to_l1_msgs: BoundedVec, start_side_effect_counter: u32, end_side_effect_counter: u32, unencrypted_logs_hashes: BoundedVec, @@ -64,9 +64,9 @@ impl PublicCircuitPublicInputsBuilder { contract_storage_update_requests: self.contract_storage_update_requests.storage, contract_storage_reads: self.contract_storage_reads.storage, public_call_stack_hashes: self.public_call_stack_hashes.storage, - 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, + note_hashes: self.note_hashes.storage, + nullifiers: self.nullifiers.storage, + l2_to_l1_msgs: self.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_hashes: self.unencrypted_logs_hashes.storage, @@ -94,9 +94,9 @@ impl Empty for PublicCircuitPublicInputsBuilder { contract_storage_update_requests: BoundedVec::new(), contract_storage_reads: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), - new_note_hashes: BoundedVec::new(), - new_nullifiers: BoundedVec::new(), - new_l2_to_l1_msgs: BoundedVec::new(), + note_hashes: BoundedVec::new(), + nullifiers: BoundedVec::new(), + l2_to_l1_msgs: BoundedVec::new(), start_side_effect_counter: 0 as u32, end_side_effect_counter: 0 as u32, unencrypted_logs_hashes: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr index 506bacf0bbe3..e3cbe0c49180 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/sort.nr @@ -1,14 +1,9 @@ -use crate::traits::{Empty, is_empty}; - struct SortedTuple { value: T, original_index: u32, } -pub fn sort_high_to_low( - values: [T; N], - is_less_than: fn(T, T) -> bool -) -> [SortedTuple; N] where T: Eq { +pub fn sort_high_to_low(values: [T; N], is_less_than: fn(T, T) -> bool) -> [SortedTuple; N] where T: Eq { let mut sorted_tuples = [SortedTuple { value: values[0], original_index: 0 }; N]; for i in 0..N { @@ -20,68 +15,3 @@ pub fn sort_high_to_low( sorted_tuples.sort_via(|a: SortedTuple, b: SortedTuple| (b.value == a.value) | is_less_than(b.value, a.value)) } - -struct SortedResult { - sorted_array: [T; N], - sorted_index_hints: [u32; N], -} - -pub fn sort_get_sorted_hints( - values: [T; N], - ordering: fn(T, T) -> bool -) -> SortedResult where T: Eq + Empty { - let mut tuples = [SortedTuple { value: values[0], original_index: 0 }; N]; - for i in 0..N { - tuples[i] = SortedTuple { - value: values[i], - original_index: i, - }; - } - - let sorted_tuples = tuples.sort_via( - |a: SortedTuple, b: SortedTuple| is_empty(b.value) | (!is_empty(a.value) & !is_empty(b.value) & ordering(a.value, b.value)) - ); - - let sorted_array = sorted_tuples.map(|t: SortedTuple| t.value); - let mut sorted_index_hints = [0; N]; - for i in 0..N { - if !is_empty(sorted_tuples[i].value) { - let original_index = sorted_tuples[i].original_index; - sorted_index_hints[original_index] = i; - } - } - - SortedResult { sorted_array, sorted_index_hints } -} - -#[test] -fn sort_get_sorted_hints_asc_non_padded() { - let values = [40, 60, 20, 50]; - let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); - assert_eq(res.sorted_array, [20, 40, 50, 60]); - assert_eq(res.sorted_index_hints, [1, 3, 0, 2]); -} - -#[test] -fn sort_get_sorted_hints_desc_non_padded() { - let values = [40, 20, 60, 50]; - let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); - assert_eq(res.sorted_array, [60, 50, 40, 20]); - assert_eq(res.sorted_index_hints, [2, 3, 0, 1]); -} - -#[test] -fn sort_get_sorted_hints_asc_padded() { - let values = [40, 60, 20, 50, 0, 0]; - let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); - assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]); - assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 0, 0]); -} - -#[test] -fn sort_get_sorted_hints_desc_padded() { - let values = [40, 20, 60, 50, 0, 0]; - let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); - assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]); - assert_eq(res.sorted_index_hints, [2, 3, 0, 1, 0, 0]); -} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr index 8b4fc27bbd25..bc95d59c4cba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/utils.nr @@ -1,4 +1,3 @@ -use dep::std::cmp::Eq; use crate::traits::{Empty, is_empty}; fn count_non_empty_elements(array: [T; N]) -> u64 where T: Empty + Eq { @@ -18,3 +17,11 @@ pub fn assert_array_eq(array: [T; N], expected: [T; S]) where T: Empty assert_eq(array[i], expected[i], "mismatch array elements"); } } + +// Swap two items in a BoundedVec. +// Useful when we want to shuffle side effects, which by default are ordered by counters when we add mock data to FixtureBuilder. +pub fn swap_items(vec: &mut BoundedVec, from_index: u64, to_index: u64) { + let tmp = vec.storage[from_index]; + vec.storage[from_index] = vec.storage[to_index]; + vec.storage[to_index] = tmp; +} 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 01af1206fecc..5a9c351fc9b0 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,3 @@ -use dep::std::cmp::Eq; use crate::utils::field::field_from_bytes; // Trait: is_empty diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/transaction.nr b/noir-projects/noir-protocol-circuits/crates/types/src/transaction/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/transaction.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/transaction/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index ba638d16e2d2..179d1f893f3a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -1,14 +1,20 @@ mod assert_sorted_array; mod assert_sorted_transformed_value_array; +mod assert_split_sorted_transformed_value_arrays; mod sort_by_counters; mod sort_get_order_hints; +mod sort_get_sorted_hints; mod sort_get_sorted_tuple; +mod sort_get_split_order_hints; // Re-exports. use assert_sorted_array::assert_sorted_array; +use assert_split_sorted_transformed_value_arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc}; use assert_sorted_transformed_value_array::assert_sorted_transformed_value_array; use sort_by_counters::{sort_by_counters_asc, sort_by_counters_desc}; -use sort_get_order_hints::{OrderHint, sort_get_order_hints_asc}; +use sort_get_order_hints::{OrderHint, sort_get_order_hints_asc, sort_get_order_hints_desc}; +use sort_get_sorted_hints::sort_get_sorted_hints; +use sort_get_split_order_hints::{sort_get_split_order_hints_asc, sort_get_split_order_hints_desc, SplitOrderHints}; use crate::traits::{Empty, is_empty}; use crate::abis::side_effect::{Positioned, Ordered}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr index 1de3ea15a0a2..c07e2d54c43a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_sorted_transformed_value_array.nr @@ -1,7 +1,8 @@ use crate::{abis::side_effect::Ordered, traits::{Empty, is_empty}, utils::arrays::sort_get_order_hints::OrderHint}; // original_array must be valid, i.e. validate_array(original_array) == true -pub fn assert_sorted_transformed_value_array( +// transformed_value_array must be verified against original_array before calling this function. +pub fn assert_sorted_transformed_value_array( original_array: [T; N], transformed_value_array: [S; N], sorted_transformed_value_array: [S; N], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr new file mode 100644 index 000000000000..e977ad2fc03d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/assert_split_sorted_transformed_value_arrays.nr @@ -0,0 +1,543 @@ +use crate::{ + abis::side_effect::Ordered, traits::{Empty, is_empty}, + utils::arrays::{array_length, sort_get_split_order_hints::SplitOrderHints, validate_array} +}; + +// original_array must be valid, i.e. validate_array(original_array) == true +// transformed_value_array must be verified against original_array before calling this function. +fn assert_split_sorted_transformed_value_arrays( + original_array: [T; N], + transformed_value_array: [S; N], + split_counter: u32, + sorted_transformed_value_array_lt: [S; N], // Values whose counters are less than the split counter. + sorted_transformed_value_array_gte: [S; N], // Values whose counters are greater than or equal to the split counter. + sorted_counters_lt: [u32; N], // Counters of the values in sorted_transformed_value_array_lt. + sorted_counters_gte: [u32; N], // Counters of the values in sorted_transformed_value_array_gte. + index_hints: [u32; N], // The index of the item in the correspinding sorted_transformed_value_array_(lt/gte) for each item in the original_array. + ascending: bool // Whether the items in sorted_transformed_value_array_(lt/gte) is in ascending order. +) where T: Ordered + Empty + Eq, S: Empty + Eq { + // Can use array_length instead of validate_array for the original_array because it's taken from the previous kernel and guaranteed to be valid. + let total_num = array_length(original_array); + + let mut num_lt = 0; + let mut num_gte = 0; + let mut should_check = true; + for i in 0..N { + should_check &= i != total_num; + if should_check { + let original = original_array[i]; + let value = transformed_value_array[i]; + let sorted_index = index_hints[i]; + let is_lt = (original.counter() < split_counter) | (original.counter() == 0); // If counter is 0, the value should always be in the lt(non-revertible) set. Currently this only applies to the first nullifier. + let mut sorted_array = sorted_transformed_value_array_gte; + let mut sorted_counters = sorted_counters_gte; + let mut num = num_gte; + if is_lt { + sorted_array = sorted_transformed_value_array_lt; + sorted_counters = sorted_counters_lt; + num = num_lt; + }; + assert_eq(value, sorted_array[sorted_index], "mismatch sorted values"); + assert_eq(original.counter(), sorted_counters[sorted_index], "mismatch counters"); + if num != 0 { + let is_incrementing = sorted_counters[num] > sorted_counters[num - 1]; + assert(ascending == is_incrementing, "value array must be sorted by counter"); + assert(sorted_counters[num] != sorted_counters[num - 1], "counters must not be the same"); + } + if is_lt { + num_lt += 1; + } else { + num_gte += 1; + } + } + } + + let num_non_empty_values_lt = validate_array(sorted_transformed_value_array_lt); + assert_eq(num_non_empty_values_lt, num_lt, "mismatch number of values lt"); + + let num_non_empty_values_gte = validate_array(sorted_transformed_value_array_gte); + assert_eq(num_non_empty_values_gte, num_gte, "mismatch number of values gte"); +} + +pub fn assert_split_sorted_transformed_value_arrays_asc( + original_array: [T; N], + transformed_value_array: [S; N], + split_counter: u32, + sorted_transformed_value_array_lt: [S; N], + sorted_transformed_value_array_gte: [S; N], + hints: SplitOrderHints +) where T: Ordered + Empty + Eq, S: Empty + Eq { + assert_split_sorted_transformed_value_arrays( + original_array, + transformed_value_array, + split_counter, + sorted_transformed_value_array_lt, + sorted_transformed_value_array_gte, + hints.sorted_counters_lt, + hints.sorted_counters_gte, + hints.sorted_indexes, + true + ); +} + +pub fn assert_split_sorted_transformed_value_arrays_desc( + original_array: [T; N], + transformed_value_array: [S; N], + split_counter: u32, + sorted_transformed_value_array_lt: [S; N], + sorted_transformed_value_array_gte: [S; N], + hints: SplitOrderHints +) where T: Ordered + Empty + Eq, S: Empty + Eq { + assert_split_sorted_transformed_value_arrays( + original_array, + transformed_value_array, + split_counter, + sorted_transformed_value_array_lt, + sorted_transformed_value_array_gte, + hints.sorted_counters_lt, + hints.sorted_counters_gte, + hints.sorted_indexes, + false + ); +} + +mod tests { + use crate::{ + abis::side_effect::Ordered, traits::Empty, + utils::arrays::{ + assert_split_sorted_transformed_value_arrays::{assert_split_sorted_transformed_value_arrays_asc, assert_split_sorted_transformed_value_arrays_desc}, + sort_get_split_order_hints::SplitOrderHints + } + }; + + struct TestItem { + name: Field, + price: Field, + tax: Field, + counter: u32, + } + + impl Ordered for TestItem { + fn counter(self) -> u32 { + self.counter + } + } + + impl Empty for TestItem { + fn empty() -> Self { + TestItem { name: 0, price: 0, tax: 0, counter: 0 } + } + } + + impl Eq for TestItem { + fn eq(self, other: Self) -> bool { + (self.name == other.name) & (self.price == other.price) & (self.tax == other.tax) & (self.counter == other.counter) + } + } + + struct TestValue { + name: Field, + total: Field, + } + + impl Empty for TestValue { + fn empty() -> Self { + TestValue { name: 0, total: 0 } + } + } + + impl Eq for TestValue { + fn eq(self, other: Self) -> bool { + (self.name == other.name) & (self.total == other.total) + } + } + + fn transform_value(item: TestItem) -> TestValue { + TestValue { name: item.name, total: item.price + item.tax } + } + + global original_array = [ + TestItem { name: 0, price: 1, tax: 0, counter: 33 }, + TestItem { name: 1, price: 10, tax: 6, counter: 44 }, + TestItem { name: 2, price: 20, tax: 7, counter: 11 }, + TestItem { name: 3, price: 30, tax: 8, counter: 0 }, + TestItem { name: 4, price: 40, tax: 9, counter: 22 }, + TestItem::empty(), + TestItem::empty(), + TestItem::empty() + ]; + + struct TestDataBuilder { + original_array: [T; N], + transformed_value_array: [S; N], + sorted_transformed_value_array_lt: [S; N], + sorted_transformed_value_array_gte: [S; N], + split_counter: u32, + hints: SplitOrderHints, + ascending: bool, + } + + impl TestDataBuilder { + pub fn empty() -> Self { + TestDataBuilder { + original_array: [TestItem::empty(); 8], + transformed_value_array: [TestValue::empty(); 8], + sorted_transformed_value_array_lt: [TestValue::empty(); 8], + sorted_transformed_value_array_gte: [TestValue::empty(); 8], + split_counter: 0, + hints: SplitOrderHints::empty(), + ascending: false + } + } + + pub fn new() -> Self { + let transformed_value_array = original_array.map(|item: TestItem| transform_value(item)); + + let split_counter = 15; + let sorted_transformed_value_array_lt = [ + TestValue { name: 3, total: 38 }, + TestValue { name: 2, total: 27 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + let sorted_transformed_value_array_gte = [ + TestValue { name: 4, total: 49 }, + TestValue { name: 0, total: 1 }, + TestValue { name: 1, total: 16 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + let hints = SplitOrderHints { + sorted_counters_lt: [0, 11, 0, 0, 0, 0, 0, 0], + sorted_counters_gte: [22, 33, 44, 0, 0, 0, 0, 0], + sorted_indexes: [1, 2, 1, 0, 0, 0, 0, 0] + }; + + TestDataBuilder { + original_array, + transformed_value_array, + sorted_transformed_value_array_lt, + sorted_transformed_value_array_gte, + split_counter, + hints, + ascending: true + } + } + + pub fn new_desc() -> Self { + let transformed_value_array = original_array.map(|item: TestItem| transform_value(item)); + + let split_counter = 15; + let sorted_transformed_value_array_lt = [ + TestValue { name: 2, total: 27 }, + TestValue { name: 3, total: 38 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + let sorted_transformed_value_array_gte = [ + TestValue { name: 1, total: 16 }, + TestValue { name: 0, total: 1 }, + TestValue { name: 4, total: 49 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + let hints = SplitOrderHints { + sorted_counters_lt: [11, 0, 0, 0, 0, 0, 0, 0], + sorted_counters_gte: [44, 33, 22, 0, 0, 0, 0, 0], + sorted_indexes: [1, 0, 0, 1, 2, 0, 0, 0] + }; + + TestDataBuilder { + original_array, + transformed_value_array, + sorted_transformed_value_array_lt, + sorted_transformed_value_array_gte, + split_counter, + hints, + ascending: false + } + } + + pub fn with_zero_split_counter(&mut self) -> Self { + self.split_counter = 0; + + if self.ascending { + self.sorted_transformed_value_array_gte = [ + TestValue { name: 2, total: 27 }, + TestValue { name: 4, total: 49 }, + TestValue { name: 0, total: 1 }, + TestValue { name: 1, total: 16 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + self.hints = SplitOrderHints { + sorted_counters_lt: [0; 8], + sorted_counters_gte: [11, 22, 33, 44, 0, 0, 0, 0], + sorted_indexes: [2, 3, 0, 0, 1, 0, 0, 0] + }; + } else { + self.sorted_transformed_value_array_gte = [ + TestValue { name: 1, total: 16 }, + TestValue { name: 0, total: 1 }, + TestValue { name: 4, total: 49 }, + TestValue { name: 2, total: 27 }, + TestValue::empty(), + TestValue::empty(), + TestValue::empty(), + TestValue::empty() + ]; + self.hints = SplitOrderHints { + sorted_counters_lt: [0; 8], + sorted_counters_gte: [44, 33, 22, 11, 0, 0, 0, 0], + sorted_indexes: [1, 0, 3, 0, 2, 0, 0, 0], + }; + } + + self.sorted_transformed_value_array_lt = [TestValue::empty(); 8]; + // The item with 0 counter should always be in the _lt array. + self.sorted_transformed_value_array_lt[0] = TestValue { name: 3, total: 38 }; + + *self + } + + pub fn update_sorted_index(&mut self, counter: u32, new_index: u32) { + let mut original_index = original_array.len(); + for i in 0..original_array.len() { + if (original_index == original_array.len()) & (original_array[i].counter == counter) { + original_index = i; + } + } + self.hints.sorted_indexes[original_index] = new_index; + } + + pub fn execute(self) { + if self.ascending { + assert_split_sorted_transformed_value_arrays_asc( + self.original_array, + self.transformed_value_array, + self.split_counter, + self.sorted_transformed_value_array_lt, + self.sorted_transformed_value_array_gte, + self.hints + ); + } else { + assert_split_sorted_transformed_value_arrays_desc( + self.original_array, + self.transformed_value_array, + self.split_counter, + self.sorted_transformed_value_array_lt, + self.sorted_transformed_value_array_gte, + self.hints + ); + } + } + } + + /** + * asc + */ + + #[test] + fn assert_split_sorted_transformed_value_array_asc_non_zero_split_counter_succeeds() { + let builder = TestDataBuilder::new(); + builder.execute(); + } + + #[test] + fn assert_split_sorted_transformed_value_array_asc_zero_split_counter_succeeds() { + let builder = TestDataBuilder::new().with_zero_split_counter(); + builder.execute(); + } + + #[test] + fn assert_split_sorted_transformed_value_array_asc_empty_succeeds() { + let builder = TestDataBuilder::empty(); + builder.execute(); + } + + /** + * desc + */ + + #[test] + fn assert_split_sorted_transformed_value_array_desc_non_zero_split_counter_succeeds() { + let builder = TestDataBuilder::new_desc(); + builder.execute(); + } + + #[test] + fn assert_split_sorted_transformed_value_array_desc_zero_split_counter_succeeds() { + let builder = TestDataBuilder::new_desc().with_zero_split_counter(); + builder.execute(); + } + + /** + * Failed cases. + */ + + #[test(should_fail_with="mismatch sorted values")] + fn assert_split_sorted_transformed_value_array_asc_lt_wrong_sorted_value_fails() { + let mut builder = TestDataBuilder::new(); + + builder.sorted_transformed_value_array_lt[0].total += 1; + + builder.execute(); + } + + #[test(should_fail_with="mismatch sorted values")] + fn assert_split_sorted_transformed_value_array_asc_gte_wrong_sorted_value_fails() { + let mut builder = TestDataBuilder::new(); + + // Swap two values in the sorted array. + let tmp = builder.sorted_transformed_value_array_gte[0]; + builder.sorted_transformed_value_array_gte[0] = builder.sorted_transformed_value_array_gte[1]; + builder.sorted_transformed_value_array_gte[1] = tmp; + + builder.execute(); + } + + #[test(should_fail_with="value array must be sorted by counter")] + fn assert_split_sorted_transformed_value_array_asc_gte_wrong_sorted_order_fails() { + let mut builder = TestDataBuilder::new(); + + // Swap two values in the sorted array, also update their hints. + let tmp = builder.sorted_transformed_value_array_gte[0]; + builder.sorted_transformed_value_array_gte[0] = builder.sorted_transformed_value_array_gte[1]; + builder.sorted_transformed_value_array_gte[1] = tmp; + builder.hints.sorted_counters_gte[0] = 33; + builder.hints.sorted_counters_gte[1] = 22; + builder.update_sorted_index(33, 0); // Item of counter 33 is now at index 0 of the sorted array. + builder.update_sorted_index(22, 1); // Item of counter 22 is now at index 1 of the sorted array. + + builder.execute(); + } + + #[test(should_fail_with="mismatch counters")] + fn assert_split_sorted_transformed_value_array_asc_gte_wrong_counter_fails() { + let mut builder = TestDataBuilder::new(); + + // Swap two values in the sorted array, but keep their counters in the correct order. + let tmp = builder.sorted_transformed_value_array_gte[0]; + builder.sorted_transformed_value_array_gte[0] = builder.sorted_transformed_value_array_gte[1]; + builder.sorted_transformed_value_array_gte[1] = tmp; + builder.update_sorted_index(33, 0); // Item of counter 33 is now at index 0 of the sorted array. + builder.update_sorted_index(22, 1); // Item of counter 22 is now at index 1 of the sorted array. + + builder.execute(); + } + + #[test(should_fail_with="mismatch sorted values")] + fn assert_split_sorted_transformed_value_array_asc_misplace_lt_to_gte_fails() { + let mut builder = TestDataBuilder::new(); + + // Move the item with counter 44 from _gte to _lt. + builder.sorted_transformed_value_array_lt[2] = builder.sorted_transformed_value_array_gte[2]; + builder.hints.sorted_counters_lt[2] = 44; + builder.sorted_transformed_value_array_gte[2] = TestValue::empty(); + builder.hints.sorted_counters_lt[2] = 0; + builder.update_sorted_index(44, 2); // Item of counter 44 is now at index 2 of the sorted array. + + builder.execute(); + } + + #[test(should_fail_with="mismatch number of values lt")] + fn assert_split_sorted_transformed_value_array_asc_duplicate_lt_to_gte_fails() { + let mut builder = TestDataBuilder::new(); + + // Copy the item with counter 44 to _lt. + builder.sorted_transformed_value_array_lt[2] = builder.sorted_transformed_value_array_gte[2]; + builder.hints.sorted_counters_lt[2] = 44; + + builder.execute(); + } + + #[test(should_fail_with="mismatch number of values gte")] + fn assert_split_sorted_transformed_value_array_asc_gte_duplicate_items_fails() { + let mut builder = TestDataBuilder::new(); + + // Duplicate the item with counter 44. + builder.sorted_transformed_value_array_gte[3] = builder.sorted_transformed_value_array_gte[2]; + builder.hints.sorted_counters_gte[3] = 44; + + builder.execute(); + } + + #[test(should_fail_with="value array must be sorted by counter")] + fn assert_split_sorted_transformed_value_array_asc_multiple_zero_counter_items_fails() { + let mut builder = TestDataBuilder::new(); + + // Change the counter of the item from 11 to 0. + builder.original_array[2].counter = 0; + builder.hints.sorted_counters_lt[1] = 0; + + builder.execute(); + } + + #[test(should_fail_with="counters must not be the same")] + fn assert_split_sorted_transformed_value_array_desc_multiple_zero_counter_items_fails() { + let mut builder = TestDataBuilder::new_desc(); + + // Change the counter of the item from 11 to 0. + builder.original_array[2].counter = 0; + builder.hints.sorted_counters_lt[0] = 0; + + builder.execute(); + } + + #[test(should_fail_with="value array must be sorted by counter")] + fn assert_split_sorted_transformed_value_array_asc_lt_empty_item_at_index_0_fails() { + let mut builder = TestDataBuilder::new(); + + // Move the item at index i to index i + 1. + let num_items = 2; + for i in 0..num_items { + let from_index = num_items - 1 - i; + let to_index = num_items - i; + builder.sorted_transformed_value_array_lt[to_index] = builder.sorted_transformed_value_array_lt[from_index]; + let counter = builder.hints.sorted_counters_lt[from_index]; + builder.hints.sorted_counters_lt[to_index] = counter; + builder.update_sorted_index(counter, to_index); + } + // Empty the values at index 0. + builder.sorted_transformed_value_array_lt[0] = TestValue::empty(); + builder.hints.sorted_counters_lt[0] = 0; + + builder.execute(); + } + + #[test(should_fail_with="invalid array")] + fn assert_split_sorted_transformed_value_array_asc_gte_empty_item_at_index_0_fails() { + let mut builder = TestDataBuilder::new(); + + let num_items = 3; + for i in 0..num_items { + let from_index = num_items - 1 - i; + let to_index = num_items - i; + builder.sorted_transformed_value_array_gte[to_index] = builder.sorted_transformed_value_array_gte[from_index]; + let counter = builder.hints.sorted_counters_gte[from_index]; + builder.hints.sorted_counters_gte[to_index] = counter; + builder.update_sorted_index(counter, to_index); + } + // Empty the values at index 0. + builder.sorted_transformed_value_array_gte[0] = TestValue::empty(); + builder.hints.sorted_counters_gte[0] = 0; + + builder.execute(); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counters.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counters.nr index ecb342862b75..9c83a138f264 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counters.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_by_counters.nr @@ -8,14 +8,14 @@ pub fn order_by_counters_empty_padded_desc(a: T, b: T) -> bool where T: Order is_empty(b) | (!is_empty(a) & !is_empty(b) & a.counter() > b.counter()) } -pub fn sort_by_counters(array: [T; N], ordering: fn(T, T) -> bool) -> [T; N] { +fn sort_by(array: [T; N], ordering: fn(T, T) -> bool) -> [T; N] { array.sort_via(|a, b| ordering(a, b)) } pub fn sort_by_counters_asc(array: [T; N]) -> [T; N] where T: Ordered + Eq + Empty { - sort_by_counters(array, order_by_counters_empty_padded_asc) + sort_by(array, order_by_counters_empty_padded_asc) } pub fn sort_by_counters_desc(array: [T; N]) -> [T; N] where T: Ordered + Eq + Empty { - sort_by_counters(array, order_by_counters_empty_padded_desc) + sort_by(array, order_by_counters_empty_padded_desc) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_order_hints.nr index c8901d6722c5..5163b3bc7f78 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_order_hints.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_order_hints.nr @@ -8,7 +8,7 @@ use crate::{ struct OrderHint { counter: u32, - sorted_index: u64, + sorted_index: u32, } impl OrderHint { @@ -23,7 +23,7 @@ impl Eq for OrderHint { } } -fn sort_get_order_hints( +pub fn sort_get_order_hints( array: [T; N], ordering: fn(T, T) -> bool ) -> [OrderHint; N] where T: Ordered + Eq + Empty { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_hints.nr new file mode 100644 index 000000000000..6fdde87227a1 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_hints.nr @@ -0,0 +1,62 @@ +use crate::{ + traits::{Empty, is_empty}, + utils::arrays::{sort_get_sorted_tuple::{sort_get_sorted_tuple, SortedTuple}} +}; + +struct SortedResult { + sorted_array: [T; N], + sorted_index_hints: [u32; N], +} + +pub fn sort_get_sorted_hints( + values: [T; N], + ordering: fn(T, T) -> bool +) -> SortedResult where T: Eq + Empty { + let sorted = sort_get_sorted_tuple( + values, + |a: T, b: T| is_empty(b) | (!is_empty(a) & !is_empty(b) & ordering(a, b)) + ); + + let sorted_array = sorted.map(|t: SortedTuple| t.elem); + let mut sorted_index_hints = [0; N]; + for i in 0..N { + if !is_empty(sorted[i].elem) { + let original_index = sorted[i].original_index; + sorted_index_hints[original_index] = i; + } + } + + SortedResult { sorted_array, sorted_index_hints } +} + +#[test] +fn sort_get_sorted_hints_asc_non_padded() { + let values = [40, 60, 20, 50]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); + assert_eq(res.sorted_array, [20, 40, 50, 60]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2]); +} + +#[test] +fn sort_get_sorted_hints_desc_non_padded() { + let values = [40, 20, 60, 50]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); + assert_eq(res.sorted_array, [60, 50, 40, 20]); + assert_eq(res.sorted_index_hints, [2, 3, 0, 1]); +} + +#[test] +fn sort_get_sorted_hints_asc_padded() { + let values = [40, 60, 20, 50, 0, 0]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| a.lt(b)); + assert_eq(res.sorted_array, [20, 40, 50, 60, 0, 0]); + assert_eq(res.sorted_index_hints, [1, 3, 0, 2, 0, 0]); +} + +#[test] +fn sort_get_sorted_hints_desc_padded() { + let values = [40, 20, 60, 50, 0, 0]; + let res = sort_get_sorted_hints(values, |a: Field, b: Field| b.lt(a)); + assert_eq(res.sorted_array, [60, 50, 40, 20, 0, 0]); + assert_eq(res.sorted_index_hints, [2, 3, 0, 1, 0, 0]); +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_tuple.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_tuple.nr index 4c2395332a8a..848933a97637 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_tuple.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_sorted_tuple.nr @@ -3,7 +3,7 @@ struct SortedTuple { original_index: u64, } -pub fn sort_get_sorted_tuple(array: [T; N], ordering: fn(T, T) -> bool) -> [SortedTuple; N] { +pub fn sort_get_sorted_tuple(array: [T; N], ordering: fn[Env](T, T) -> bool) -> [SortedTuple; N] { let mut tuples = [SortedTuple { elem: array[0], original_index: 0 }; N]; for i in 0..N { tuples[i] = SortedTuple { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_split_order_hints.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_split_order_hints.nr new file mode 100644 index 000000000000..448e649d4012 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays/sort_get_split_order_hints.nr @@ -0,0 +1,279 @@ +use crate::{ + abis::side_effect::Ordered, traits::{Empty, is_empty}, + utils::arrays::{ + sort_by_counters::{order_by_counters_empty_padded_asc, order_by_counters_empty_padded_desc}, + sort_get_sorted_tuple::sort_get_sorted_tuple +} +}; + +struct SplitOrderHints { + sorted_counters_lt: [u32; N], + sorted_counters_gte: [u32; N], + sorted_indexes: [u32; N], +} + +impl SplitOrderHints { + pub fn empty() -> SplitOrderHints { + SplitOrderHints { sorted_counters_lt: [0; N], sorted_counters_gte: [0; N], sorted_indexes: [0; N] } + } +} + +impl Eq for SplitOrderHints { + fn eq(self, other: Self) -> bool { + (self.sorted_counters_lt == other.sorted_counters_lt) + & (self.sorted_counters_gte == other.sorted_counters_gte) + & (self.sorted_indexes == other.sorted_indexes) + } +} + +fn sort_get_split_order_hints( + array: [T; N], + split_counter: u32, + ascending: bool +) -> SplitOrderHints where T: Ordered + Eq + Empty { + let ordering = if ascending { + order_by_counters_empty_padded_asc + } else { + order_by_counters_empty_padded_desc + }; + let sorted_tuples = sort_get_sorted_tuple(array, ordering); + + let mut sorted_counters_lt = [0; N]; + let mut sorted_counters_gte = [0; N]; + let mut sorted_indexes = [0; N]; + let mut num_lt = 0; + let mut num_gte = 0; + let mut found_split = false; + for i in 0..N { + let elem = sorted_tuples[i].elem; + if !is_empty(elem) { + let is_gte = (elem.counter() >= split_counter) & (elem.counter() != 0); + found_split |= ascending == is_gte; + let mut index_offet = 0; + if found_split != ascending { + sorted_counters_lt[num_lt] = elem.counter(); + num_lt += 1; + index_offet = num_gte; + } else { + sorted_counters_gte[num_gte] = elem.counter(); + num_gte += 1; + index_offet = num_lt; + } + let original_index = sorted_tuples[i].original_index; + sorted_indexes[original_index] = if !found_split { i } else { i - index_offet }; + } + } + + SplitOrderHints { sorted_counters_lt, sorted_counters_gte, sorted_indexes } +} + +pub fn sort_get_split_order_hints_asc( + array: [T; N], + split_counter: u32 +) -> SplitOrderHints where T: Ordered + Eq + Empty { + sort_get_split_order_hints(array, split_counter, true) +} + +pub fn sort_get_split_order_hints_desc( + array: [T; N], + split_counter: u32 +) -> SplitOrderHints where T: Ordered + Eq + Empty { + sort_get_split_order_hints(array, split_counter, false) +} + +mod tests { + use crate::{ + abis::side_effect::Ordered, traits::Empty, + utils::arrays::sort_get_split_order_hints::{sort_get_split_order_hints_asc, sort_get_split_order_hints_desc, SplitOrderHints} + }; + + struct TestItem { + value: Field, + counter: u32, + } + + impl Ordered for TestItem { + fn counter(self) -> u32 { + self.counter + } + } + + impl Eq for TestItem { + fn eq(self, other: Self) -> bool { + (self.value == other.value) & (self.counter == other.counter) + } + } + + impl Empty for TestItem { + fn empty() -> Self { + TestItem { value: 0, counter: 0 } + } + } + + global full_array = [ + TestItem { value: 100, counter: 11 }, + TestItem { value: 200, counter: 17 }, + TestItem { value: 300, counter: 7 }, + TestItem { value: 400, counter: 5 }, + TestItem { value: 500, counter: 13 } + ]; + + global padded_array = [ + TestItem { value: 100, counter: 11 }, + TestItem { value: 200, counter: 17 }, + TestItem { value: 300, counter: 7 }, + TestItem { value: 400, counter: 5 }, + TestItem { value: 500, counter: 13 }, + TestItem::empty(), + TestItem::empty() + ]; + + // asc + + #[test] + fn sort_get_split_order_hints_asc_zero_split_counter_full() { + let split_counter = 0; + let hints = sort_get_split_order_hints_asc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [0, 0, 0, 0, 0], + sorted_counters_gte: [5, 7, 11, 13, 17], + sorted_indexes: [2, 4, 1, 0, 3] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_asc_non_zero_split_counter_full() { + let split_counter = 9; + let hints = sort_get_split_order_hints_asc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [5, 7, 0, 0, 0], + sorted_counters_gte: [11, 13, 17, 0, 0], + sorted_indexes: [0, 2, 1, 0, 1] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_asc_non_zero_split_counter_equal_full() { + let split_counter = 11; // Equal one of the item's counter. + let hints = sort_get_split_order_hints_asc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [5, 7, 0, 0, 0], + sorted_counters_gte: [11, 13, 17, 0, 0], + sorted_indexes: [0, 2, 1, 0, 1] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_asc_zero_split_counter_padded_empty() { + let split_counter = 0; + let hints = sort_get_split_order_hints_asc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [0, 0, 0, 0, 0, 0, 0], + sorted_counters_gte: [5, 7, 11, 13, 17, 0, 0], + sorted_indexes: [2, 4, 1, 0, 3, 0, 0] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_asc_non_zero_split_counter_padded_empty() { + let split_counter = 9; + let hints = sort_get_split_order_hints_asc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [5, 7, 0, 0, 0, 0, 0], + sorted_counters_gte: [11, 13, 17, 0, 0, 0, 0], + sorted_indexes: [0, 2, 1, 0, 1, 0, 0] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_asc_non_zero_split_counter_equal_padded_empty() { + let split_counter = 11; + let hints = sort_get_split_order_hints_asc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [5, 7, 0, 0, 0, 0, 0], + sorted_counters_gte: [11, 13, 17, 0, 0, 0, 0], + sorted_indexes: [0, 2, 1, 0, 1, 0, 0] + }; + assert_eq(hints, expected_hints); + } + + // desc + + #[test] + fn sort_get_split_order_hints_desc_zero_split_counter_empty() { + let split_counter = 0; + let hints = sort_get_split_order_hints_desc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [0, 0, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 7, 5], + sorted_indexes: [2, 0, 3, 4, 1] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_desc_non_zero_split_counter_empty() { + let split_counter = 9; + let hints = sort_get_split_order_hints_desc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [7, 5, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 0, 0], + sorted_indexes: [2, 0, 0, 1, 1] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_desc_non_zero_split_counter_equal_empty() { + let split_counter = 11; + let hints = sort_get_split_order_hints_desc(full_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [7, 5, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 0, 0], + sorted_indexes: [2, 0, 0, 1, 1] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_desc_zero_split_counter_padded_empty() { + let split_counter = 0; + let hints = sort_get_split_order_hints_desc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [0, 0, 0, 0, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 7, 5, 0, 0], + sorted_indexes: [2, 0, 3, 4, 1, 0, 0] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_desc_non_zero_split_counter_padded_empty() { + let split_counter = 9; + let hints = sort_get_split_order_hints_desc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [7, 5, 0, 0, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 0, 0, 0, 0], + sorted_indexes: [2, 0, 0, 1, 1, 0, 0] + }; + assert_eq(hints, expected_hints); + } + + #[test] + fn sort_get_split_order_hints_desc_non_zero_split_counter_equal_padded_empty() { + let split_counter = 11; + let hints = sort_get_split_order_hints_desc(padded_array, split_counter); + let expected_hints = SplitOrderHints { + sorted_counters_lt: [7, 5, 0, 0, 0, 0, 0], + sorted_counters_gte: [17, 13, 11, 0, 0, 0, 0], + sorted_indexes: [2, 0, 0, 1, 1, 0, 0] + }; + assert_eq(hints, expected_hints); + } +} + diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/types/src/utils.nr rename to noir-projects/noir-protocol-circuits/crates/types/src/utils/mod.nr diff --git a/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh new file mode 100755 index 000000000000..4a92d76b8eb4 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/scripts/flamegraph.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +set -eu + +EXAMPLE_CMD="$0 private_kernel_init" + +# First arg is the circuit name. +if [[ $# -eq 0 || ($1 == -* && $1 != "-h") ]]; then + echo "Please specify the name of the circuit." + echo "e.g.: $EXAMPLE_CMD" + exit 1 +fi + +CIRCUIT_NAME=$1 +SERVE=false +PORT=5000 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + echo "Generates a flamegraph for the specified protocol circuit." + echo "" + echo "Usage:" + echo " $0 " + echo "" + echo " e.g.: $EXAMPLE_CMD" + echo "" + echo "Arguments:" + echo " -s Serve the file over http" + echo " -p Specify custom port. Default: ${PORT}" + echo "" + exit 0 + ;; + -s|--serve) + SERVE=true + shift + ;; + -p|--port) + if [[ $# -lt 2 || $2 == -* ]]; then + echo "Please specify a port number." + echo "e.g.: $EXAMPLE_CMD -s -p 8080" + exit 1 + fi + PORT=$2 + shift 2 + ;; + *) + shift + ;; + esac +done + +# Get the directory of the script. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Check if the artifact exists. +ARTIFACT="$SCRIPT_DIR/../target/$CIRCUIT_NAME.json" +if [[ ! -f $ARTIFACT ]]; then + echo "Cannot find artifact: ${ARTIFACT}" + exit 1 +fi + +# Build profier if it's not available. +PROFILER="$SCRIPT_DIR/../../../noir/noir-repo/target/debug/noir-profiler" +if [ ! -f $PROFILER ]; then + echo "Profiler not found, building profiler" + cd "$SCRIPT_DIR/../../../noir/noir-repo/tooling/profiler" + cargo build + cd "$SCRIPT_DIR" +fi + +# We create dest directory and use it as an output for the generated main.svg file. +DEST="$SCRIPT_DIR/../dest" +mkdir -p $DEST + +# At last, generate the flamegraph. +$PROFILER gates-flamegraph --artifact-path "${ARTIFACT}" --backend-path "$SCRIPT_DIR/../../../barretenberg/cpp/build/bin/bb" --output "$DEST" + +# Serve the file over http if -s is set. +if $SERVE; then + echo "Serving flamegraph at http://0.0.0.0:${PORT}/main.svg" + python3 -m http.server --directory "$SCRIPT_DIR/../dest" $PORT +fi \ No newline at end of file diff --git a/noir/bb-version b/noir/bb-version index 72a8a6313bb9..8298bb08b2d5 100644 --- a/noir/bb-version +++ b/noir/bb-version @@ -1 +1 @@ -0.41.0 +0.43.0 diff --git a/noir/noir-repo/.release-please-manifest.json b/noir/noir-repo/.release-please-manifest.json index 83338327d88d..a30d3e16ba74 100644 --- a/noir/noir-repo/.release-please-manifest.json +++ b/noir/noir-repo/.release-please-manifest.json @@ -1,4 +1,4 @@ { - ".": "0.30.0", - "acvm-repo": "0.46.0" + ".": "0.31.0", + "acvm-repo": "0.47.0" } diff --git a/noir/noir-repo/CHANGELOG.md b/noir/noir-repo/CHANGELOG.md index db4ec8f4567a..30678c05fb19 100644 --- a/noir/noir-repo/CHANGELOG.md +++ b/noir/noir-repo/CHANGELOG.md @@ -1,5 +1,97 @@ # Changelog +## [0.31.0](https://github.com/noir-lang/noir/compare/v0.30.0...v0.31.0) (2024-06-17) + + +### ⚠ BREAKING CHANGES + +* remove `dep::` prefix ([#4946](https://github.com/noir-lang/noir/issues/4946)) +* remove `distinct` keyword ([#5219](https://github.com/noir-lang/noir/issues/5219)) +* remove `param_witnesses` and `return_witnesses` from ABI ([#5154](https://github.com/noir-lang/noir/issues/5154)) +* add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) +* restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) +* separate proving from `noir_js` ([#5072](https://github.com/noir-lang/noir/issues/5072)) +* switch `bb` over to read ACIR from nargo artifacts (https://github.com/AztecProtocol/aztec-packages/pull/6283) +* specify databus arrays for BB (https://github.com/AztecProtocol/aztec-packages/pull/6239) +* **stdlib:** eddsa function using turbofish ([#5050](https://github.com/noir-lang/noir/issues/5050)) + +### Features + +* `pxe.addNullifiedNote(...)` (https://github.com/AztecProtocol/aztec-packages/pull/6948) ([7de19f5](https://github.com/noir-lang/noir/commit/7de19f5856591203271836f07154abae13f5102b)) +* Activate return_data in ACIR opcodes ([#5080](https://github.com/noir-lang/noir/issues/5080)) ([c9fda3c](https://github.com/noir-lang/noir/commit/c9fda3c7fd4575bfe7d457e8d4230e071f0129a0)) +* Add `as_witness` builtin function in order to constrain a witness to be equal to a variable ([#4641](https://github.com/noir-lang/noir/issues/4641)) ([faf5bd8](https://github.com/noir-lang/noir/commit/faf5bd8ed80fb89b4bb6a2536b9bfa9649579da7)) +* Add `set` and `set_unchecked` methods to `Vec` and `BoundedVec` ([#5241](https://github.com/noir-lang/noir/issues/5241)) ([1849389](https://github.com/noir-lang/noir/commit/1849389362e22e8236177f84b735dadf840cd637)) +* Add BoundedVec::map ([#5250](https://github.com/noir-lang/noir/issues/5250)) ([da1549c](https://github.com/noir-lang/noir/commit/da1549cfb296261b273a3a64908382e7b71512ad)) +* Add intrinsic to get if running inside an unconstrained context ([#5098](https://github.com/noir-lang/noir/issues/5098)) ([281ebf2](https://github.com/noir-lang/noir/commit/281ebf26e4cd16daf361938de505697f8d5fbd5e)) +* Add native rust implementation of schnorr signature verification ([#5053](https://github.com/noir-lang/noir/issues/5053)) ([fab1c35](https://github.com/noir-lang/noir/commit/fab1c3567d731ea7902635a7a020a8d14f94fd27)) +* Add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) ([14adafc](https://github.com/noir-lang/noir/commit/14adafc965fa9c833e096ec037e086aae67703ad)) +* Consider block parameters in variable liveness ([#5097](https://github.com/noir-lang/noir/issues/5097)) ([e4eb5f5](https://github.com/noir-lang/noir/commit/e4eb5f539f377fd3c2e1a874707ffce62a5bc10a)) +* **experimental:** Implement macro calls & splicing into `Expr` values ([#5203](https://github.com/noir-lang/noir/issues/5203)) ([d9b4712](https://github.com/noir-lang/noir/commit/d9b4712bf1a62548dd7ed17b181882ae537d70dd)) +* Implement println in the comptime interpreter ([#5197](https://github.com/noir-lang/noir/issues/5197)) ([7f08343](https://github.com/noir-lang/noir/commit/7f08343dfcafddfcec1b238746a69273ae4f4e2b)) +* Implement turbofish operator ([#3542](https://github.com/noir-lang/noir/issues/3542)) ([226724e](https://github.com/noir-lang/noir/commit/226724e3b54c2e0d9ba005661c76b40a87d9295a)) +* Make ACVM generic across fields ([#5114](https://github.com/noir-lang/noir/issues/5114)) ([70f374c](https://github.com/noir-lang/noir/commit/70f374c06642962d8f2b95b80f8c938fcf7761d7)) +* Move abi demonomorphizer to noir_codegen and use noir_codegen in protocol types (https://github.com/AztecProtocol/aztec-packages/pull/6302) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Move to_radix to a blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6294) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* **nargo:** Hidden option to show contract artifact paths written by `nargo compile` (https://github.com/AztecProtocol/aztec-packages/pull/6131) ([ff67e14](https://github.com/noir-lang/noir/commit/ff67e145d086bf6fdf58fb5e57927033e52e03d3)) +* Place return value witnesses directly after function arguments ([#5142](https://github.com/noir-lang/noir/issues/5142)) ([1252b5f](https://github.com/noir-lang/noir/commit/1252b5fcc7ed56bb55e95745b83be6e556805397)) +* Private Kernel Recursion (https://github.com/AztecProtocol/aztec-packages/pull/6278) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Proper padding in ts AES and constrained AES in body and header computations (https://github.com/AztecProtocol/aztec-packages/pull/6269) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Remove `dep::` prefix ([#4946](https://github.com/noir-lang/noir/issues/4946)) ([d6d0ae2](https://github.com/noir-lang/noir/commit/d6d0ae26d2fef083dc240539b834d934c84b0326)) +* Remove conditional compilation of `bn254_blackbox_solver` ([#5058](https://github.com/noir-lang/noir/issues/5058)) ([9420d7c](https://github.com/noir-lang/noir/commit/9420d7c2ba6bbbf5ecb9a066837c505310955b6c)) +* Remove external blackbox solver from acir simulator (https://github.com/AztecProtocol/aztec-packages/pull/6586) ([a40a9a5](https://github.com/noir-lang/noir/commit/a40a9a55571deed386688fb84260bdf2794d4d38)) +* Replace stdlib poseidon implementation with optimized version ([#5122](https://github.com/noir-lang/noir/issues/5122)) ([11e98f3](https://github.com/noir-lang/noir/commit/11e98f348d1d43a9b28d83ec3308027b7afc0da6)) +* Restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) ([bdb2bc6](https://github.com/noir-lang/noir/commit/bdb2bc608ea8fd52d46545a38b68dd2558b28110)) +* Separate proving from `noir_js` ([#5072](https://github.com/noir-lang/noir/issues/5072)) ([c93c738](https://github.com/noir-lang/noir/commit/c93c7380c705fcec5c77bfc436c2f5ea085edd77)) +* Separate runtimes of SSA functions before inlining ([#5121](https://github.com/noir-lang/noir/issues/5121)) ([69eca9b](https://github.com/noir-lang/noir/commit/69eca9b8671fa54192bef814dd584fdb5387a5f7)) +* Specify databus arrays for BB (https://github.com/AztecProtocol/aztec-packages/pull/6239) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Standardize pedersen functions to return `EmbeddedCurvePoint` ([#5190](https://github.com/noir-lang/noir/issues/5190)) ([3b85b36](https://github.com/noir-lang/noir/commit/3b85b3637f81f3894a7faa07fd299f9d64747214)) +* **stdlib:** Eddsa function using turbofish ([#5050](https://github.com/noir-lang/noir/issues/5050)) ([7936262](https://github.com/noir-lang/noir/commit/79362629ed8cf42b6601e9a551ed8f9fe03e0112)) +* Support casting in globals ([#5164](https://github.com/noir-lang/noir/issues/5164)) ([6d3e732](https://github.com/noir-lang/noir/commit/6d3e732e06033b53506656acdd3d7759bd27f106)) +* Switch `bb` over to read ACIR from nargo artifacts (https://github.com/AztecProtocol/aztec-packages/pull/6283) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6280) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6332) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6573) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6986) ([7de19f5](https://github.com/noir-lang/noir/commit/7de19f5856591203271836f07154abae13f5102b)) +* ToRadix BB + avm transpiler support (https://github.com/AztecProtocol/aztec-packages/pull/6330) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) + + +### Bug Fixes + +* Add support for nested arrays returned by oracles ([#5132](https://github.com/noir-lang/noir/issues/5132)) ([f846879](https://github.com/noir-lang/noir/commit/f846879dd038328bd0a1d39a72b448ef52a1002b)) +* Apply self type from generic trait constraint before instantiating identifiers ([#5087](https://github.com/noir-lang/noir/issues/5087)) ([2b4755c](https://github.com/noir-lang/noir/commit/2b4755c2b57460d5eb839ee835f8c9acd5773a7c)) +* Auto dereference trait methods in the elaborator ([#5124](https://github.com/noir-lang/noir/issues/5124)) ([56c1a85](https://github.com/noir-lang/noir/commit/56c1a85056ed338644595f1aa58cc94563786b9e)) +* Check for public args in aztec functions (https://github.com/AztecProtocol/aztec-packages/pull/6355) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Disable `if` optimization ([#5240](https://github.com/noir-lang/noir/issues/5240)) ([a2816db](https://github.com/noir-lang/noir/commit/a2816dbf7f9d31967fc95205a43fdfdf181029b0)) +* **elaborator:** Fix duplicate methods error ([#5225](https://github.com/noir-lang/noir/issues/5225)) ([87a1d8e](https://github.com/noir-lang/noir/commit/87a1d8ebaadb5f0f1ed637b96816f971f946af87)) +* **elaborator:** Fix regression introduced by lazy-global changes ([#5223](https://github.com/noir-lang/noir/issues/5223)) ([fde432a](https://github.com/noir-lang/noir/commit/fde432aacc436b6c57f0d937d7c86836bac0b465)) +* **elaborator:** Invert unconstrained check ([#5176](https://github.com/noir-lang/noir/issues/5176)) ([967c0fa](https://github.com/noir-lang/noir/commit/967c0fa76da9384afe918a8b23eef60f12f29292)) +* **elaborator:** Lazily elaborate globals ([#5191](https://github.com/noir-lang/noir/issues/5191)) ([9c99a97](https://github.com/noir-lang/noir/commit/9c99a97ca8f42bee23cf97ebd724fdc51e647c60)) +* Error for allocate instructions in acir-gen ([#5200](https://github.com/noir-lang/noir/issues/5200)) ([58c7532](https://github.com/noir-lang/noir/commit/58c7532da8dd86ee02b20d7e7809f5437f667845)) +* **experimental elaborator:** Avoid calling `add_generics` twice on trait methods ([#5108](https://github.com/noir-lang/noir/issues/5108)) ([7d8c0a3](https://github.com/noir-lang/noir/commit/7d8c0a3a1ae143b574b2fa62cae7c0a493005c70)) +* **experimental elaborator:** Clear generics after elaborating type aliases ([#5136](https://github.com/noir-lang/noir/issues/5136)) ([b0a7d0b](https://github.com/noir-lang/noir/commit/b0a7d0b12328d3ed9faed87b78792b77786018e0)) +* **experimental elaborator:** Fix `impl Trait` when `--use-elaborator` is selected ([#5138](https://github.com/noir-lang/noir/issues/5138)) ([7ea5962](https://github.com/noir-lang/noir/commit/7ea5962e77b7183374a4e14da3a237ccd63f00a0)) +* **experimental elaborator:** Fix definition kind of globals and tuple patterns with `--use-elaborator` flag ([#5139](https://github.com/noir-lang/noir/issues/5139)) ([a140dec](https://github.com/noir-lang/noir/commit/a140dec4580459c5856d44337de3ea08aa7fb44a)) +* **experimental elaborator:** Fix duplicate `resolve_type` on self type and don't leak a trait impl's generics ([#5102](https://github.com/noir-lang/noir/issues/5102)) ([db561e2](https://github.com/noir-lang/noir/commit/db561e229cfcb35f23205cbb7e41fcf5ece68ee5)) +* **experimental elaborator:** Fix frontend tests when `--use-elaborator` flag is specified ([#5145](https://github.com/noir-lang/noir/issues/5145)) ([d6122eb](https://github.com/noir-lang/noir/commit/d6122eb9e88aa2b1bb6c990e452fa9678ae49704)) +* **experimental elaborator:** Fix global values used in the elaborator ([#5135](https://github.com/noir-lang/noir/issues/5135)) ([e73cdbb](https://github.com/noir-lang/noir/commit/e73cdbb93b0714331fef754f862d89c08c28a9e5)) +* **experimental elaborator:** Fix globals which use function calls ([#5172](https://github.com/noir-lang/noir/issues/5172)) ([ab0b1a8](https://github.com/noir-lang/noir/commit/ab0b1a85cc91f8ed748ee393ece54f5c3b43d7ef)) +* **experimental elaborator:** Fix panic in the elaborator ([#5082](https://github.com/noir-lang/noir/issues/5082)) ([ffcb410](https://github.com/noir-lang/noir/commit/ffcb410978a362c73783fbfe5bbdc9691499609e)) +* **experimental elaborator:** Only call `add_generics` once ([#5091](https://github.com/noir-lang/noir/issues/5091)) ([f5d2946](https://github.com/noir-lang/noir/commit/f5d294645e82fc85d8dc28ee2a846ba11af85ce5)) +* Fix panic in `get_global_let_statement` ([#5177](https://github.com/noir-lang/noir/issues/5177)) ([b769b01](https://github.com/noir-lang/noir/commit/b769b01fd06a6a2c66c72f9aa4e1d346b0fca123)) +* **frontend:** Call trait method with mut self from generic definition ([#5041](https://github.com/noir-lang/noir/issues/5041)) ([89846cf](https://github.com/noir-lang/noir/commit/89846cfbc4961c5258d91b5973f027be80885a20)) +* **frontend:** Correctly monomorphize turbofish functions ([#5049](https://github.com/noir-lang/noir/issues/5049)) ([fd772e7](https://github.com/noir-lang/noir/commit/fd772e7a764004373f5a41a54eb6847f4decda77)) +* **frontend:** Resolve object types from method calls a single time ([#5131](https://github.com/noir-lang/noir/issues/5131)) ([3afe023](https://github.com/noir-lang/noir/commit/3afe023543e301aafaf2b79f0ccd6d7936dd53a9)) +* Temporarily revert to_radix blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6304) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Use plain integer addresses for opcodes in DAP disassembly view ([#4941](https://github.com/noir-lang/noir/issues/4941)) ([d43ba1b](https://github.com/noir-lang/noir/commit/d43ba1bddbf6ebd56a7bee0e1db38d155fec95d5)) +* Use predicate for curve operations ([#5076](https://github.com/noir-lang/noir/issues/5076)) ([145b909](https://github.com/noir-lang/noir/commit/145b90945486907cb6db75d3f3f93a58d19b2a32)) +* Wrapping in signed division ([#5134](https://github.com/noir-lang/noir/issues/5134)) ([29baeb4](https://github.com/noir-lang/noir/commit/29baeb41e15918935c437e0a2759c6b936f125a4)) + + +### Miscellaneous Chores + +* Remove `distinct` keyword ([#5219](https://github.com/noir-lang/noir/issues/5219)) ([1d62c59](https://github.com/noir-lang/noir/commit/1d62c59a8f02f7d277c5bf9ed637348a3b2f399c)) +* Remove `param_witnesses` and `return_witnesses` from ABI ([#5154](https://github.com/noir-lang/noir/issues/5154)) ([21562ae](https://github.com/noir-lang/noir/commit/21562aeea162d246573967115e7c519715f6d3d8)) + ## [0.30.0](https://github.com/noir-lang/noir/compare/v0.29.0...v0.30.0) (2024-05-20) diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 50b65919f1e9..589c3d179d8f 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -4,7 +4,7 @@ version = 3 [[package]] name = "acir" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir_field", "base64 0.21.2", @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "acir_field" -version = "0.46.0" +version = "0.47.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -40,7 +40,7 @@ dependencies = [ [[package]] name = "acvm" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -55,7 +55,7 @@ dependencies = [ [[package]] name = "acvm_blackbox_solver" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "blake2", @@ -93,7 +93,7 @@ dependencies = [ [[package]] name = "acvm_js" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acvm", "bn254_blackbox_solver", @@ -443,7 +443,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "aztec_macros" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "convert_case 0.6.0", @@ -571,7 +571,7 @@ dependencies = [ [[package]] name = "bn254_blackbox_solver" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -589,7 +589,7 @@ dependencies = [ [[package]] name = "brillig" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir_field", "serde", @@ -597,7 +597,7 @@ dependencies = [ [[package]] name = "brillig_vm" -version = "0.46.0" +version = "0.47.0" dependencies = [ "acir", "acvm_blackbox_solver", @@ -1537,12 +1537,11 @@ dependencies = [ [[package]] name = "fm" -version = "0.30.0" +version = "0.31.0" dependencies = [ "codespan-reporting", "iter-extended", "serde", - "tempfile", ] [[package]] @@ -2103,7 +2102,7 @@ dependencies = [ [[package]] name = "iter-extended" -version = "0.30.0" +version = "0.31.0" [[package]] name = "itertools" @@ -2498,10 +2497,9 @@ dependencies = [ [[package]] name = "nargo" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", - "codespan-reporting", "fm", "iter-extended", "jsonrpc", @@ -2524,7 +2522,7 @@ dependencies = [ [[package]] name = "nargo_cli" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "assert_cmd", @@ -2546,8 +2544,10 @@ dependencies = [ "nargo_fmt", "nargo_toml", "noir_debugger", + "noir_fuzzer", "noir_lsp", "noirc_abi", + "noirc_artifacts", "noirc_driver", "noirc_errors", "noirc_frontend", @@ -2557,6 +2557,7 @@ dependencies = [ "pprof 0.13.0", "predicates 2.1.5", "prettytable-rs", + "proptest", "rayon", "serde", "serde_json", @@ -2576,7 +2577,7 @@ dependencies = [ [[package]] name = "nargo_fmt" -version = "0.30.0" +version = "0.31.0" dependencies = [ "bytecount", "noirc_frontend", @@ -2588,7 +2589,7 @@ dependencies = [ [[package]] name = "nargo_toml" -version = "0.30.0" +version = "0.31.0" dependencies = [ "dirs", "fm", @@ -2667,7 +2668,7 @@ dependencies = [ [[package]] name = "noir_debugger" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "assert_cmd", @@ -2677,6 +2678,7 @@ dependencies = [ "easy-repl", "fm", "nargo", + "noirc_artifacts", "noirc_driver", "noirc_errors", "noirc_frontend", @@ -2688,6 +2690,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "noir_fuzzer" +version = "0.31.0" +dependencies = [ + "acvm", + "nargo", + "noirc_abi", + "noirc_artifacts", + "proptest", + "rand 0.8.5", +] + [[package]] name = "noir_grumpkin" version = "0.1.0" @@ -2702,7 +2716,7 @@ dependencies = [ [[package]] name = "noir_lsp" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "async-lsp", @@ -2713,6 +2727,7 @@ dependencies = [ "nargo", "nargo_fmt", "nargo_toml", + "noirc_artifacts", "noirc_driver", "noirc_errors", "noirc_frontend", @@ -2728,18 +2743,17 @@ dependencies = [ [[package]] name = "noir_profiler" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acir", "clap", - "codespan-reporting", "color-eyre", "const_format", "fm", "im", "inferno", - "nargo", "noirc_abi", + "noirc_artifacts", "noirc_driver", "noirc_errors", "serde", @@ -2751,7 +2765,7 @@ dependencies = [ [[package]] name = "noir_wasm" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "build-data", @@ -2761,6 +2775,7 @@ dependencies = [ "gloo-utils", "js-sys", "nargo", + "noirc_artifacts", "noirc_driver", "noirc_errors", "noirc_evaluator", @@ -2774,14 +2789,15 @@ dependencies = [ [[package]] name = "noirc_abi" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "iter-extended", - "noirc_frontend", "noirc_printable_type", "num-bigint", "num-traits", + "proptest", + "proptest-derive", "serde", "serde_json", "strum", @@ -2792,7 +2808,7 @@ dependencies = [ [[package]] name = "noirc_abi_wasm" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "build-data", @@ -2809,11 +2825,26 @@ dependencies = [ [[package]] name = "noirc_arena" -version = "0.30.0" +version = "0.31.0" + +[[package]] +name = "noirc_artifacts" +version = "0.31.0" +dependencies = [ + "acvm", + "codespan-reporting", + "fm", + "noirc_abi", + "noirc_driver", + "noirc_errors", + "noirc_printable_type", + "serde", + "tempfile", +] [[package]] name = "noirc_driver" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "aztec_macros", @@ -2833,7 +2864,7 @@ dependencies = [ [[package]] name = "noirc_errors" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "base64 0.21.2", @@ -2851,9 +2882,10 @@ dependencies = [ [[package]] name = "noirc_evaluator" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", + "bn254_blackbox_solver", "chrono", "fxhash", "im", @@ -2868,7 +2900,7 @@ dependencies = [ [[package]] name = "noirc_frontend" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "base64 0.21.2", @@ -2893,14 +2925,13 @@ dependencies = [ "smol_str", "strum", "strum_macros", - "tempfile", "thiserror", "tracing", ] [[package]] name = "noirc_printable_type" -version = "0.30.0" +version = "0.31.0" dependencies = [ "acvm", "iter-extended", @@ -3381,9 +3412,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", @@ -3393,12 +3424,23 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", ] +[[package]] +name = "proptest-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -3630,12 +3672,6 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - [[package]] name = "regex-syntax" version = "0.8.2" diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index be4cd81ab585..8cd5defa1211 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -15,10 +15,12 @@ members = [ # Crates related to tooling built on top of the Noir compiler "tooling/lsp", "tooling/debugger", + "tooling/fuzzer", "tooling/nargo", "tooling/nargo_fmt", "tooling/nargo_cli", "tooling/nargo_toml", + "tooling/noirc_artifacts", "tooling/noirc_abi", "tooling/noirc_abi_wasm", "tooling/acvm_cli", @@ -40,7 +42,7 @@ resolver = "2" [workspace.package] # x-release-please-start-version -version = "0.30.0" +version = "0.31.0" # x-release-please-end authors = ["The Noir Team "] edition = "2021" @@ -51,13 +53,13 @@ repository = "https://github.com/noir-lang/noir/" [workspace.dependencies] # ACVM workspace dependencies -acir_field = { version = "0.46.0", path = "acvm-repo/acir_field", default-features = false } -acir = { version = "0.46.0", path = "acvm-repo/acir", default-features = false } -acvm = { version = "0.46.0", path = "acvm-repo/acvm" } -brillig = { version = "0.46.0", path = "acvm-repo/brillig", default-features = false } -brillig_vm = { version = "0.46.0", path = "acvm-repo/brillig_vm", default-features = false } -acvm_blackbox_solver = { version = "0.46.0", path = "acvm-repo/blackbox_solver", default-features = false } -bn254_blackbox_solver = { version = "0.46.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } +acir_field = { version = "0.47.0", path = "acvm-repo/acir_field", default-features = false } +acir = { version = "0.47.0", path = "acvm-repo/acir", default-features = false } +acvm = { version = "0.47.0", path = "acvm-repo/acvm" } +brillig = { version = "0.47.0", path = "acvm-repo/brillig", default-features = false } +brillig_vm = { version = "0.47.0", path = "acvm-repo/brillig_vm", default-features = false } +acvm_blackbox_solver = { version = "0.47.0", path = "acvm-repo/blackbox_solver", default-features = false } +bn254_blackbox_solver = { version = "0.47.0", path = "acvm-repo/bn254_blackbox_solver", default-features = false } # Noir compiler workspace dependencies fm = { path = "compiler/fm" } @@ -69,12 +71,14 @@ noirc_frontend = { path = "compiler/noirc_frontend" } noirc_printable_type = { path = "compiler/noirc_printable_type" } # Noir tooling workspace dependencies +noir_fuzzer = { path = "tooling/fuzzer" } nargo = { path = "tooling/nargo" } nargo_fmt = { path = "tooling/nargo_fmt" } nargo_toml = { path = "tooling/nargo_toml" } noir_lsp = { path = "tooling/lsp" } noir_debugger = { path = "tooling/debugger" } noirc_abi = { path = "tooling/noirc_abi" } +noirc_artifacts = { path = "tooling/noirc_artifacts" } bb_abstraction_leaks = { path = "tooling/bb_abstraction_leaks" } acvm_cli = { path = "tooling/acvm_cli" } @@ -143,6 +147,8 @@ flate2 = "1.0.24" color-eyre = "0.6.2" rand = "0.8.5" proptest = "1.2.0" +proptest-derive = "0.4.0" + im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" tracing-web = "0.1.3" diff --git a/noir/noir-repo/acvm-repo/CHANGELOG.md b/noir/noir-repo/acvm-repo/CHANGELOG.md index c9bb0d610eb3..4db36aadec91 100644 --- a/noir/noir-repo/acvm-repo/CHANGELOG.md +++ b/noir/noir-repo/acvm-repo/CHANGELOG.md @@ -5,6 +5,154 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.47.0](https://github.com/noir-lang/noir/compare/v0.46.0...v0.47.0) (2024-06-17) + + +### ⚠ BREAKING CHANGES + +* add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) +* restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) +* switch `bb` over to read ACIR from nargo artifacts (https://github.com/AztecProtocol/aztec-packages/pull/6283) +* specify databus arrays for BB (https://github.com/AztecProtocol/aztec-packages/pull/6239) +* remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) +* contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) +* change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) +* trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) +* remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) +* storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) +* contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) +* automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) +* move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) +* note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) +* rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) +* init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) + +### Features + +* `multi_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6097) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* `variable_base_scalar_mul` blackbox func (https://github.com/AztecProtocol/aztec-packages/pull/6039) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Acir call opcode (https://github.com/AztecProtocol/aztec-packages/pull/4773) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **acir_gen:** Brillig stdlib ([#4848](https://github.com/noir-lang/noir/issues/4848)) ([0c8175c](https://github.com/noir-lang/noir/commit/0c8175cb539efd9427c73ae5af0d48abe688ebab)) +* **acir_gen:** Fold attribute at compile-time and initial non inlined ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5341) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* **acir:** Add predicate to call opcode (https://github.com/AztecProtocol/aztec-packages/pull/5616) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **acir:** BrilligCall opcode (https://github.com/AztecProtocol/aztec-packages/pull/5709) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* **acir:** Program and witness stack structure (https://github.com/AztecProtocol/aztec-packages/pull/5149) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Activate return_data in ACIR opcodes ([#5080](https://github.com/noir-lang/noir/issues/5080)) ([c9fda3c](https://github.com/noir-lang/noir/commit/c9fda3c7fd4575bfe7d457e8d4230e071f0129a0)) +* **acvm_js:** Execute program ([#4694](https://github.com/noir-lang/noir/issues/4694)) ([386f6d0](https://github.com/noir-lang/noir/commit/386f6d0a5822912db878285cb001032a7c0ff622)) +* **acvm:** Execute multiple circuits (https://github.com/AztecProtocol/aztec-packages/pull/5380) ([a0f7474](https://github.com/noir-lang/noir/commit/a0f7474ae6bd74132efdb945d2eb2383f3913cce)) +* Add bit size to const opcode (https://github.com/AztecProtocol/aztec-packages/pull/4385) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add CMOV instruction to brillig and brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5308) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* Add expression width into acir (https://github.com/AztecProtocol/aztec-packages/pull/4014) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Add instrumentation for tracking variables in debugging ([#4122](https://github.com/noir-lang/noir/issues/4122)) ([c58d691](https://github.com/noir-lang/noir/commit/c58d69141b54a918cd1675400c00bfd48720f896)) +* Add native rust implementation of schnorr signature verification ([#5053](https://github.com/noir-lang/noir/issues/5053)) ([fab1c35](https://github.com/noir-lang/noir/commit/fab1c3567d731ea7902635a7a020a8d14f94fd27)) +* Add native rust implementations of pedersen functions ([#4871](https://github.com/noir-lang/noir/issues/4871)) ([fb039f7](https://github.com/noir-lang/noir/commit/fb039f74df23aea39bc0593a5d538d82b4efadf0)) +* Add poseidon2 opcode implementation for acvm/brillig, and Noir ([#4398](https://github.com/noir-lang/noir/issues/4398)) ([10e8292](https://github.com/noir-lang/noir/commit/10e82920798380f50046e52db4a20ca205191ab7)) +* Add return values to aztec fns (https://github.com/AztecProtocol/aztec-packages/pull/5389) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Add session id to foreign call RPC requests ([#5205](https://github.com/noir-lang/noir/issues/5205)) ([14adafc](https://github.com/noir-lang/noir/commit/14adafc965fa9c833e096ec037e086aae67703ad)) +* Added cast opcode and cast calldata (https://github.com/AztecProtocol/aztec-packages/pull/4423) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* AES blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6016) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Allow brillig to read arrays directly from memory (https://github.com/AztecProtocol/aztec-packages/pull/4460) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow nested arrays and vectors in Brillig foreign calls (https://github.com/AztecProtocol/aztec-packages/pull/4478) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Allow variables and stack trace inspection in the debugger ([#4184](https://github.com/noir-lang/noir/issues/4184)) ([bf263fc](https://github.com/noir-lang/noir/commit/bf263fc8d843940f328a90f6366edd2671fb2682)) +* Automatic NoteInterface and NoteGetterOptions auto select (https://github.com/AztecProtocol/aztec-packages/pull/4508) ([13eb71b](https://github.com/noir-lang/noir/commit/13eb71b8de44eb6aad9c37943ad06fc73db589f5)) +* **avm:** Back in avm context with macro - refactor context (https://github.com/AztecProtocol/aztec-packages/pull/4438) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* **avm:** Brillig CONST of size > u128 (https://github.com/AztecProtocol/aztec-packages/pull/5217) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **avm:** Integrate AVM with initializers (https://github.com/AztecProtocol/aztec-packages/pull/5469) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* **aztec-nr:** Initial work for aztec public vm macro (https://github.com/AztecProtocol/aztec-packages/pull/4400) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Backpropagate constants in ACIR during optimization ([#3926](https://github.com/noir-lang/noir/issues/3926)) ([aad0da0](https://github.com/noir-lang/noir/commit/aad0da024c69663f42e6913e674682d5864b26ae)) +* Bit shift is restricted to u8 right operand ([#4907](https://github.com/noir-lang/noir/issues/4907)) ([c4b0369](https://github.com/noir-lang/noir/commit/c4b03691feca17ef268acab523292f3051f672ea)) +* Brillig heterogeneous memory cells (https://github.com/AztecProtocol/aztec-packages/pull/5608) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Brillig IR refactor (https://github.com/AztecProtocol/aztec-packages/pull/5233) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Brillig pointer codegen and execution (https://github.com/AztecProtocol/aztec-packages/pull/5737) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Brillig typed memory (https://github.com/AztecProtocol/aztec-packages/pull/5395) ([0bc18c4](https://github.com/noir-lang/noir/commit/0bc18c4f78171590dd58bded959f68f53a44cc8c)) +* Change backend width to 4 (https://github.com/AztecProtocol/aztec-packages/pull/5374) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Check initializer msg.sender matches deployer from address preimage (https://github.com/AztecProtocol/aztec-packages/pull/5222) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Contract interfaces and better function calls (https://github.com/AztecProtocol/aztec-packages/pull/5687) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Contract_abi-exports (https://github.com/AztecProtocol/aztec-packages/pull/5386) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Dynamic assertion payloads v2 (https://github.com/AztecProtocol/aztec-packages/pull/5949) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Evaluation of dynamic assert messages ([#4101](https://github.com/noir-lang/noir/issues/4101)) ([c284e01](https://github.com/noir-lang/noir/commit/c284e01bfe20ceae4414dc123624b5cbb8b66d09)) +* Handle `BrilligCall` opcodes in the debugger ([#4897](https://github.com/noir-lang/noir/issues/4897)) ([b380dc4](https://github.com/noir-lang/noir/commit/b380dc44de5c9f8de278ece3d531ebbc2c9238ba)) +* Impl of missing functionality in new key store (https://github.com/AztecProtocol/aztec-packages/pull/5750) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Increase default expression width to 4 ([#4995](https://github.com/noir-lang/noir/issues/4995)) ([f01d309](https://github.com/noir-lang/noir/commit/f01d3090759a5ff0f1f83c5616d22890c6bd76be)) +* Init storage macro (https://github.com/AztecProtocol/aztec-packages/pull/4200) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Initial Earthly CI (https://github.com/AztecProtocol/aztec-packages/pull/5069) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Internal as a macro (https://github.com/AztecProtocol/aztec-packages/pull/4898) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Make ACVM generic across fields ([#5114](https://github.com/noir-lang/noir/issues/5114)) ([70f374c](https://github.com/noir-lang/noir/commit/70f374c06642962d8f2b95b80f8c938fcf7761d7)) +* Move abi demonomorphizer to noir_codegen and use noir_codegen in protocol types (https://github.com/AztecProtocol/aztec-packages/pull/6302) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Move to_radix to a blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6294) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* **nargo:** Handle call stacks for multiple Acir calls ([#4711](https://github.com/noir-lang/noir/issues/4711)) ([5b23171](https://github.com/noir-lang/noir/commit/5b231714740447d82cde7cdbe65d4a8b46a31df4)) +* **nargo:** Hidden option to show contract artifact paths written by `nargo compile` (https://github.com/AztecProtocol/aztec-packages/pull/6131) ([ff67e14](https://github.com/noir-lang/noir/commit/ff67e145d086bf6fdf58fb5e57927033e52e03d3)) +* New brillig field operations and refactor of binary operations (https://github.com/AztecProtocol/aztec-packages/pull/5208) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Note type ids (https://github.com/AztecProtocol/aztec-packages/pull/4500) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Parsing non-string assertion payloads in noir js (https://github.com/AztecProtocol/aztec-packages/pull/6079) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Private Kernel Recursion (https://github.com/AztecProtocol/aztec-packages/pull/6278) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Proper padding in ts AES and constrained AES in body and header computations (https://github.com/AztecProtocol/aztec-packages/pull/6269) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Remove conditional compilation of `bn254_blackbox_solver` ([#5058](https://github.com/noir-lang/noir/issues/5058)) ([9420d7c](https://github.com/noir-lang/noir/commit/9420d7c2ba6bbbf5ecb9a066837c505310955b6c)) +* Remove external blackbox solver from acir simulator (https://github.com/AztecProtocol/aztec-packages/pull/6586) ([a40a9a5](https://github.com/noir-lang/noir/commit/a40a9a55571deed386688fb84260bdf2794d4d38)) +* Restore hashing args via slice for performance (https://github.com/AztecProtocol/aztec-packages/pull/5539) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Restrict noir word size to u32 ([#5180](https://github.com/noir-lang/noir/issues/5180)) ([bdb2bc6](https://github.com/noir-lang/noir/commit/bdb2bc608ea8fd52d46545a38b68dd2558b28110)) +* Separate runtimes of SSA functions before inlining ([#5121](https://github.com/noir-lang/noir/issues/5121)) ([69eca9b](https://github.com/noir-lang/noir/commit/69eca9b8671fa54192bef814dd584fdb5387a5f7)) +* Set aztec private functions to be recursive (https://github.com/AztecProtocol/aztec-packages/pull/6192) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Signed integer division and modulus in brillig gen (https://github.com/AztecProtocol/aztec-packages/pull/5279) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* **simulator:** Fetch return values at circuit execution (https://github.com/AztecProtocol/aztec-packages/pull/5642) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Specify databus arrays for BB (https://github.com/AztecProtocol/aztec-packages/pull/6239) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Storage_layout and `#[aztec(storage)]` (https://github.com/AztecProtocol/aztec-packages/pull/5387) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Support contracts with no constructor (https://github.com/AztecProtocol/aztec-packages/pull/5175) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Switch `bb` over to read ACIR from nargo artifacts (https://github.com/AztecProtocol/aztec-packages/pull/6283) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from aztec-packages ([#4483](https://github.com/noir-lang/noir/issues/4483)) ([fe8f277](https://github.com/noir-lang/noir/commit/fe8f2776ccfde29209a2c3fc162311c99e4f59be)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5234) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5286) ([c3c9e19](https://github.com/noir-lang/noir/commit/c3c9e19a20d61272a04b95fd6c7d34cc4cb96e45)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5572) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5619) ([2bd006a](https://github.com/noir-lang/noir/commit/2bd006ae07499e8702b0fa9565855f0a5ef1a589)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5697) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5794) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5814) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5935) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5955) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/5999) ([1b867b1](https://github.com/noir-lang/noir/commit/1b867b121fba5db3087ca845b4934e6732b23fd1)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6280) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6332) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Sync from noir (https://github.com/AztecProtocol/aztec-packages/pull/6573) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* ToRadix BB + avm transpiler support (https://github.com/AztecProtocol/aztec-packages/pull/6330) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Trap with revert data (https://github.com/AztecProtocol/aztec-packages/pull/5732) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Use fixed size arrays in black box functions where sizes are known (https://github.com/AztecProtocol/aztec-packages/pull/5620) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Variable length returns (https://github.com/AztecProtocol/aztec-packages/pull/5633) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) + + +### Bug Fixes + +* **acvm:** Mark outputs of Opcode::Call solvable ([#4708](https://github.com/noir-lang/noir/issues/4708)) ([8fea405](https://github.com/noir-lang/noir/commit/8fea40576f262bd5bb588923c0660d8967404e56)) +* Add support for nested arrays returned by oracles ([#5132](https://github.com/noir-lang/noir/issues/5132)) ([f846879](https://github.com/noir-lang/noir/commit/f846879dd038328bd0a1d39a72b448ef52a1002b)) +* Avoid huge unrolling in hash_args (https://github.com/AztecProtocol/aztec-packages/pull/5703) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Catch panics from EC point creation (e.g. the point is at infinity) ([#4790](https://github.com/noir-lang/noir/issues/4790)) ([645dba1](https://github.com/noir-lang/noir/commit/645dba192f16ef34018828186ffb297422a8dc73)) +* Check for public args in aztec functions (https://github.com/AztecProtocol/aztec-packages/pull/6355) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) +* Don't reuse brillig with slice arguments (https://github.com/AztecProtocol/aztec-packages/pull/5800) ([0f9ae0a](https://github.com/noir-lang/noir/commit/0f9ae0ac1d68714b56ba4524aedcc67212494f1b)) +* Issue 4682 and add solver for unconstrained bigintegers ([#4729](https://github.com/noir-lang/noir/issues/4729)) ([e4d33c1](https://github.com/noir-lang/noir/commit/e4d33c126a2795d9aaa6048d4e91b64cb4bbe4f2)) +* Noir test incorrect reporting (https://github.com/AztecProtocol/aztec-packages/pull/4925) ([5f57ebb](https://github.com/noir-lang/noir/commit/5f57ebb7ff4b810802f90699a10f4325ef904f2e)) +* Proper field inversion for bigints ([#4802](https://github.com/noir-lang/noir/issues/4802)) ([b46d0e3](https://github.com/noir-lang/noir/commit/b46d0e39f4252f8bbaa987f88d112e4c233b3d61)) +* Temporarily revert to_radix blackbox (https://github.com/AztecProtocol/aztec-packages/pull/6304) ([436bbda](https://github.com/noir-lang/noir/commit/436bbdaadb2a294b94f93e53d7d3cad3859c7e46)) + + +### Miscellaneous Chores + +* **acir:** Move `is_recursive` flag to be part of the circuit definition (https://github.com/AztecProtocol/aztec-packages/pull/4221) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) +* Move noir out of yarn-project (https://github.com/AztecProtocol/aztec-packages/pull/4479) ([78ef013](https://github.com/noir-lang/noir/commit/78ef0134b82e76a73dadb6c7975def22290e3a1a)) +* Remove `Opcode::Brillig` from ACIR (https://github.com/AztecProtocol/aztec-packages/pull/5995) ([73a635e](https://github.com/noir-lang/noir/commit/73a635e5086cf3407f9846ce39807cd15b4e485a)) +* Remove fixed-length keccak256 (https://github.com/AztecProtocol/aztec-packages/pull/5617) ([305bcdc](https://github.com/noir-lang/noir/commit/305bcdcbd01cb84dbaac900f14cb6cf867f83bda)) +* Rename bigint_neg into bigint_sub (https://github.com/AztecProtocol/aztec-packages/pull/4420) ([158c8ce](https://github.com/noir-lang/noir/commit/158c8cec7f0dc698042e9512001dd2c9d6b40bcc)) + ## [0.46.0](https://github.com/noir-lang/noir/compare/v0.45.0...v0.46.0) (2024-05-20) diff --git a/noir/noir-repo/acvm-repo/acir/Cargo.toml b/noir/noir-repo/acvm-repo/acir/Cargo.toml index 101ce7a0f39e..7a8f10c98ef8 100644 --- a/noir/noir-repo/acvm-repo/acir/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir/Cargo.toml @@ -2,7 +2,7 @@ name = "acir" description = "ACIR is the IR that the VM processes, it is analogous to LLVM IR" # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs index 419c0266b69f..fb7d9eb584ca 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/black_box_functions.rs @@ -82,43 +82,10 @@ pub enum BlackBoxFunc { /// /// [grumpkin]: https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations SchnorrVerify, - - /// Calculates a Pedersen commitment to the inputs. - /// - /// Computes a Pedersen commitment of the inputs using generators of the - /// embedded curve - /// - input: vector of (witness, 254) - /// - output: 2 witnesses representing the x,y coordinates of the resulting - /// Grumpkin point - /// - domain separator: a constant public value (a field element) that you - /// can use so that the commitment also depends on the domain separator. - /// Noir uses 0 as domain separator. - /// - /// The backend should handle proper conversion between the inputs being ACIR - /// field elements and the scalar field of the embedded curve. In the case of - /// Aztec's Barretenberg, the latter is bigger than the ACIR field so it is - /// straightforward. The Pedersen generators are managed by the proving - /// system. - /// - /// The commitment is expected to be additively homomorphic + /// Will be deprecated PedersenCommitment, - - /// Calculates a Pedersen hash to the inputs. - /// - /// Computes a Pedersen hash of the inputs and their number, using - /// generators of the embedded curve - /// - input: vector of (witness, 254) - /// - output: the x-coordinate of the pedersen commitment of the - /// 'prepended input' (see below) - /// - domain separator: a constant public value (a field element) that you - /// can use so that the hash also depends on the domain separator. Noir - /// uses 0 as domain separator. - /// - /// In Barretenberg, PedersenHash is doing the same as PedersenCommitment, - /// except that it prepends the inputs with their length. This is expected - /// to not be additively homomorphic. + /// Will be deprecated PedersenHash, - /// Verifies a ECDSA signature over the secp256k1 curve. /// - inputs: /// - x coordinate of public key as 32 bytes @@ -242,8 +209,6 @@ impl BlackBoxFunc { BlackBoxFunc::SchnorrVerify => "schnorr_verify", BlackBoxFunc::Blake2s => "blake2s", BlackBoxFunc::Blake3 => "blake3", - BlackBoxFunc::PedersenCommitment => "pedersen_commitment", - BlackBoxFunc::PedersenHash => "pedersen_hash", BlackBoxFunc::EcdsaSecp256k1 => "ecdsa_secp256k1", BlackBoxFunc::MultiScalarMul => "multi_scalar_mul", BlackBoxFunc::EmbeddedCurveAdd => "embedded_curve_add", @@ -262,6 +227,8 @@ impl BlackBoxFunc { BlackBoxFunc::BigIntToLeBytes => "bigint_to_le_bytes", BlackBoxFunc::Poseidon2Permutation => "poseidon2_permutation", BlackBoxFunc::Sha256Compression => "sha256_compression", + BlackBoxFunc::PedersenCommitment => "pedersen_commitment", + BlackBoxFunc::PedersenHash => "pedersen_hash", } } @@ -272,8 +239,6 @@ impl BlackBoxFunc { "schnorr_verify" => Some(BlackBoxFunc::SchnorrVerify), "blake2s" => Some(BlackBoxFunc::Blake2s), "blake3" => Some(BlackBoxFunc::Blake3), - "pedersen_commitment" => Some(BlackBoxFunc::PedersenCommitment), - "pedersen_hash" => Some(BlackBoxFunc::PedersenHash), "ecdsa_secp256k1" => Some(BlackBoxFunc::EcdsaSecp256k1), "ecdsa_secp256r1" => Some(BlackBoxFunc::EcdsaSecp256r1), "multi_scalar_mul" => Some(BlackBoxFunc::MultiScalarMul), @@ -292,6 +257,8 @@ impl BlackBoxFunc { "bigint_to_le_bytes" => Some(BlackBoxFunc::BigIntToLeBytes), "poseidon2_permutation" => Some(BlackBoxFunc::Poseidon2Permutation), "sha256_compression" => Some(BlackBoxFunc::Sha256Compression), + "pedersen_commitment" => Some(BlackBoxFunc::PedersenCommitment), + "pedersen_hash" => Some(BlackBoxFunc::PedersenHash), _ => None, } } diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 362e9ba59362..b8be81fcdef1 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -54,11 +54,13 @@ pub enum BlackBoxFuncCall { message: Vec, output: Witness, }, + /// Will be deprecated PedersenCommitment { inputs: Vec, domain_separator: u32, outputs: (Witness, Witness), }, + /// Will be deprecated PedersenHash { inputs: Vec, domain_separator: u32, @@ -189,8 +191,6 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::Blake2s { .. } => BlackBoxFunc::Blake2s, BlackBoxFuncCall::Blake3 { .. } => BlackBoxFunc::Blake3, BlackBoxFuncCall::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, - BlackBoxFuncCall::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, - BlackBoxFuncCall::PedersenHash { .. } => BlackBoxFunc::PedersenHash, BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxFuncCall::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, BlackBoxFuncCall::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, @@ -206,6 +206,8 @@ impl BlackBoxFuncCall { BlackBoxFuncCall::BigIntToLeBytes { .. } => BlackBoxFunc::BigIntToLeBytes, BlackBoxFuncCall::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxFuncCall::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, + BlackBoxFuncCall::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, + BlackBoxFuncCall::PedersenHash { .. } => BlackBoxFunc::PedersenHash, } } @@ -219,9 +221,9 @@ impl BlackBoxFuncCall { | BlackBoxFuncCall::SHA256 { inputs, .. } | BlackBoxFuncCall::Blake2s { inputs, .. } | BlackBoxFuncCall::Blake3 { inputs, .. } + | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } | BlackBoxFuncCall::PedersenCommitment { inputs, .. } | BlackBoxFuncCall::PedersenHash { inputs, .. } - | BlackBoxFuncCall::BigIntFromLeBytes { inputs, .. } | BlackBoxFuncCall::Poseidon2Permutation { inputs, .. } => inputs.to_vec(), BlackBoxFuncCall::Keccakf1600 { inputs, .. } => inputs.to_vec(), @@ -421,6 +423,14 @@ fn get_outputs_string(outputs: &[Witness]) -> String { impl std::fmt::Display for BlackBoxFuncCall { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BlackBoxFuncCall::PedersenCommitment { .. } => { + return write!(f, "BLACKBOX::Deprecated") + } + BlackBoxFuncCall::PedersenHash { .. } => return write!(f, "BLACKBOX::Deprecated"), + _ => (), + } + let uppercase_name = self.name().to_uppercase(); write!(f, "BLACKBOX::{uppercase_name} ")?; // INPUTS @@ -440,13 +450,7 @@ impl std::fmt::Display for BlackBoxFuncCall { write!(f, "]")?; - // SPECIFIC PARAMETERS - match self { - BlackBoxFuncCall::PedersenCommitment { domain_separator, .. } => { - write!(f, " domain_separator: {domain_separator}") - } - _ => write!(f, ""), - } + write!(f, "") } } diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index dfcb1a8bb863..84a9aa719f2d 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -100,33 +100,6 @@ fn multi_scalar_mul_circuit() { assert_eq!(bytes, expected_serialization) } -#[test] -fn pedersen_circuit() { - let pedersen = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::PedersenCommitment { - inputs: vec![FunctionInput { witness: Witness(1), num_bits: FieldElement::max_num_bits() }], - outputs: (Witness(2), Witness(3)), - domain_separator: 0, - }); - - let circuit: Circuit = Circuit { - current_witness_index: 4, - opcodes: vec![pedersen], - private_parameters: BTreeSet::from([Witness(1)]), - return_values: PublicInputs(BTreeSet::from_iter(vec![Witness(2), Witness(3)])), - ..Circuit::default() - }; - let program = Program { functions: vec![circuit], unconstrained_functions: vec![] }; - - let bytes = Program::serialize_program(&program); - - let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 73, 10, 0, 0, 4, 180, 29, 252, 255, 193, 66, 40, - 76, 77, 179, 34, 20, 36, 136, 237, 83, 245, 101, 107, 79, 65, 94, 253, 214, 217, 255, 239, - 192, 1, 43, 124, 181, 238, 113, 0, 0, 0, - ]; - assert_eq!(bytes, expected_serialization) -} - #[test] fn schnorr_verify_circuit() { let public_key_x = diff --git a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml index 801935c90f95..303d7b6471f3 100644 --- a/noir/noir-repo/acvm-repo/acir_field/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acir_field/Cargo.toml @@ -2,7 +2,7 @@ name = "acir_field" description = "The field implementation being used by ACIR." # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm/Cargo.toml b/noir/noir-repo/acvm-repo/acvm/Cargo.toml index 59305ec49f04..892575902a46 100644 --- a/noir/noir-repo/acvm-repo/acvm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm" description = "The virtual machine that processes ACIR given a backend/proof system." # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/csat.rs b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/csat.rs index f2a3cc2c84ec..19cc18ca7f38 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/csat.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/compiler/transformers/csat.rs @@ -432,7 +432,7 @@ fn fits_in_one_identity(expr: &Expression, width: usize) -> boo return true; } - // We now know that we have a single mul term. We also know that the mul term must match up with two other terms + // We now know that we have a single mul term. We also know that the mul term must match up with at least one of the other terms // A polynomial whose mul terms are non zero which do not match up with two terms in the fan-in cannot fit into one opcode // An example of this is: Axy + Bx + Cy + ... // Notice how the bivariate monomial xy has two univariate monomials with their respective coefficients @@ -461,7 +461,25 @@ fn fits_in_one_identity(expr: &Expression, width: usize) -> boo } } - found_x & found_y + // If the multiplication is a squaring then we must assign the two witnesses to separate wires and so we + // can never get a zero contribution to the width. + let multiplication_is_squaring = mul_term.1 == mul_term.2; + + let mul_term_width_contribution = if !multiplication_is_squaring && (found_x & found_y) { + // Both witnesses involved in the multiplication exist elsewhere in the expression. + // They both do not contribute to the width of the expression as this would be double-counting + // due to their appearance in the linear terms. + 0 + } else if found_x || found_y { + // One of the witnesses involved in the multiplication exists elsewhere in the expression. + // The multiplication then only contributes 1 new witness to the width. + 1 + } else { + // Worst case scenario, the multiplication is using completely unique witnesses so has a contribution of 2. + 2 + }; + + mul_term_width_contribution + expr.linear_combinations.len() <= width } #[cfg(test)] @@ -573,4 +591,20 @@ mod tests { let contains_b = got_optimized_opcode_a.linear_combinations.iter().any(|(_, w)| *w == b); assert!(contains_b); } + + #[test] + fn recognize_expr_with_single_shared_witness_which_fits_in_single_identity() { + // Regression test for an expression which Zac found which should have been preserved but + // was being split into two expressions. + let expr = Expression { + mul_terms: vec![(-FieldElement::from(555u128), Witness(8), Witness(10))], + linear_combinations: vec![ + (FieldElement::one(), Witness(10)), + (FieldElement::one(), Witness(11)), + (-FieldElement::one(), Witness(13)), + ], + q_c: FieldElement::zero(), + }; + assert!(fits_in_one_identity(&expr, 4)); + } } 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 8bda9221d8a9..0c65759ebcd3 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 @@ -7,7 +7,7 @@ use acvm_blackbox_solver::{blake2s, blake3, keccak256, keccakf1600, sha256}; use self::{ aes128::solve_aes128_encryption_opcode, bigint::AcvmBigIntSolver, - hash::solve_poseidon2_permutation_opcode, pedersen::pedersen_hash, + hash::solve_poseidon2_permutation_opcode, }; use super::{insert_value, OpcodeNotSolvable, OpcodeResolutionError}; @@ -27,7 +27,7 @@ use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; // Hash functions should eventually be exposed for external consumers. use hash::{solve_generic_256_hash_opcode, solve_sha_256_permutation_opcode}; use logic::{and, xor}; -use pedersen::pedersen; +use pedersen::{pedersen, pedersen_hash}; pub(crate) use range::solve_range_opcode; use signature::{ ecdsa::{secp256k1_prehashed, secp256r1_prehashed}, diff --git a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml index 63f64e97729f..e457b6391ab3 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml +++ b/noir/noir-repo/acvm-repo/acvm_js/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_js" description = "Typescript wrapper around the ACVM allowing execution of ACIR code" # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/acvm_js/package.json b/noir/noir-repo/acvm-repo/acvm_js/package.json index 48c5b2a8644e..6085bc0563ee 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/package.json +++ b/noir/noir-repo/acvm-repo/acvm_js/package.json @@ -1,6 +1,6 @@ { "name": "@noir-lang/acvm_js", - "version": "0.46.0", + "version": "0.47.0", "publishConfig": { "access": "public" }, diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts b/noir/noir-repo/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts index cfd5523b79f6..aaa82f8f1e52 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/browser/execute_circuit.test.ts @@ -75,16 +75,6 @@ it('successfully processes complex brillig foreign call opcodes', async () => { expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a Pedersen opcode', async function () { - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); -}); - it('successfully executes a MultiScalarMul opcode', async () => { const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/multi_scalar_mul'); diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/node/execute_circuit.test.ts b/noir/noir-repo/acvm-repo/acvm_js/test/node/execute_circuit.test.ts index 1e3517e8814d..120ad0fa7384 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/node/execute_circuit.test.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/node/execute_circuit.test.ts @@ -76,17 +76,6 @@ it('successfully processes complex brillig foreign call opcodes', async () => { expect(solved_witness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes a Pedersen opcode', async function () { - this.timeout(10000); - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - const solvedWitness: WitnessMap = await executeCircuit(bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); -}); - it('successfully executes a MultiScalarMul opcode', async () => { const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/multi_scalar_mul'); @@ -117,25 +106,6 @@ it('successfully executes a MemoryOp opcode', async () => { expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); }); -it('successfully executes 500 pedersen circuits', async function () { - this.timeout(100000); - - // Pedersen opcodes used to have a large upfront cost due to generator calculation - // so we'd need to pass around the blackbox solver in JS to avoid redoing this work. - // - // This test now shows that we don't need to do this anymore without a performance regression. - - const { bytecode, initialWitnessMap, expectedWitnessMap } = await import('../shared/pedersen'); - - for (let i = 0; i < 500; i++) { - const solvedWitness = await executeCircuit(bytecode, initialWitnessMap, () => { - throw Error('unexpected oracle'); - }); - - expect(solvedWitness).to.be.deep.eq(expectedWitnessMap); - } -}); - /** * Below are all the same tests as above but using `executeProgram` * TODO: also add a couple tests for executing multiple circuits diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts deleted file mode 100644 index 6e3ec403d650..000000000000 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/pedersen.ts +++ /dev/null @@ -1,13 +0,0 @@ -// See `pedersen_circuit` integration test in `acir/tests/test_program_serialization.rs`. -export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 93, 74, 73, 10, 0, 0, 4, 180, 29, 252, 255, 193, 66, 40, 76, 77, 179, 34, 20, 36, - 136, 237, 83, 245, 101, 107, 79, 65, 94, 253, 214, 217, 255, 239, 192, 1, 43, 124, 181, 238, 113, 0, 0, 0, -]); - -export const initialWitnessMap = new Map([[1, '0x0000000000000000000000000000000000000000000000000000000000000001']]); - -export const expectedWitnessMap = new Map([ - [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], - [2, '0x083e7911d835097629f0067531fc15cafd79a89beecb39903f69572c636f4a5a'], - [3, '0x1a7f5efaad7f315c25a918f30cc8d7333fccab7ad7c90f14de81bcc528f9935d'], -]); diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml index dd7f84e63e46..06bd3ceabefe 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "acvm_blackbox_solver" description = "A solver for the blackbox functions found in ACIR and Brillig" # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/curve_specific_solver.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/curve_specific_solver.rs index 0ee3a2528409..f729a5033fb6 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/src/curve_specific_solver.rs +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/curve_specific_solver.rs @@ -81,6 +81,7 @@ impl BlackBoxFunctionSolver for StubbedBlackBoxSolver { ) -> Result { Err(Self::fail(BlackBoxFunc::PedersenHash)) } + fn multi_scalar_mul( &self, _points: &[F], 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 37d40de71a9e..cc2d15aaa86e 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -2,7 +2,7 @@ name = "bn254_blackbox_solver" description = "Solvers for black box functions which are specific for the bn254 curve" # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true 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 index cbcb75a32911..e7917fa1adcf 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/benches/criterion.rs +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/benches/criterion.rs @@ -13,22 +13,6 @@ fn bench_poseidon2(c: &mut Criterion) { c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs), 4))); } -fn bench_pedersen_commitment(c: &mut Criterion) { - let inputs = [FieldElement::one(); 2]; - - c.bench_function("pedersen_commitment", |b| { - b.iter(|| Bn254BlackBoxSolver.pedersen_commitment(black_box(&inputs), 0)) - }); -} - -fn bench_pedersen_hash(c: &mut Criterion) { - let inputs = [FieldElement::one(); 2]; - - c.bench_function("pedersen_hash", |b| { - b.iter(|| Bn254BlackBoxSolver.pedersen_hash(black_box(&inputs), 0)) - }); -} - fn bench_schnorr_verify(c: &mut Criterion) { let pub_key_x = FieldElement::from_hex( "0x04b260954662e97f00cab9adb773a259097f7a274b83b113532bce27fa3fb96a", @@ -62,7 +46,7 @@ fn bench_schnorr_verify(c: &mut Criterion) { 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, bench_pedersen_commitment, bench_pedersen_hash, bench_schnorr_verify + targets = bench_poseidon2, bench_schnorr_verify ); criterion_main!(benches); diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs index f89d582d1673..bb51426b33b5 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/generator/generators.rs @@ -38,7 +38,7 @@ fn default_generators() -> &'static [Affine; NUM_DEFAULT_GEN /// index-addressable generators. /// /// [hash_to_curve]: super::hash_to_curve::hash_to_curve -pub(crate) fn derive_generators( +pub fn derive_generators( domain_separator_bytes: &[u8], num_generators: u32, starting_index: u32, 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 08e0fb66a6d2..6897116e90ec 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 @@ -12,6 +12,7 @@ mod schnorr; use ark_ec::AffineRepr; pub use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul}; +pub use generator::generators::derive_generators; pub use poseidon2::poseidon2_permutation; // Temporary hack, this ensure that we always use a bn254 field here @@ -47,11 +48,13 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { let inputs: Vec = inputs.iter().map(|input| input.into_repr()).collect(); let result = pedersen::commitment::commit_native_with_index(&inputs, domain_separator); - let res_x = - FieldElement::from_repr(*result.x().expect("should not commit to point at infinity")); - let res_y = - FieldElement::from_repr(*result.y().expect("should not commit to point at infinity")); - Ok((res_x, res_y)) + let result = if let Some((x, y)) = result.xy() { + (FieldElement::from_repr(*x), FieldElement::from_repr(*y)) + } else { + (FieldElement::from(0_u128), FieldElement::from(0_u128)) + }; + + Ok(result) } fn pedersen_hash( diff --git a/noir/noir-repo/acvm-repo/brillig/Cargo.toml b/noir/noir-repo/acvm-repo/brillig/Cargo.toml index 245767dcecd9..7c1965c8f3e4 100644 --- a/noir/noir-repo/acvm-repo/brillig/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig" description = "Brillig is the bytecode ACIR uses for non-determinism." # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true diff --git a/noir/noir-repo/acvm-repo/brillig/src/black_box.rs b/noir/noir-repo/acvm-repo/brillig/src/black_box.rs index 3887092a8c27..60e4af11ea21 100644 --- a/noir/noir-repo/acvm-repo/brillig/src/black_box.rs +++ b/noir/noir-repo/acvm-repo/brillig/src/black_box.rs @@ -61,13 +61,13 @@ pub enum BlackBoxOp { signature: HeapVector, result: MemoryAddress, }, - /// Calculates a Pedersen commitment to the inputs. + /// Will be deprecated PedersenCommitment { inputs: HeapVector, domain_separator: MemoryAddress, output: HeapArray, }, - /// Calculates a Pedersen hash to the inputs. + /// Will be deprecated PedersenHash { inputs: HeapVector, domain_separator: MemoryAddress, diff --git a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml index 4735514c9a76..d048d625083f 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml +++ b/noir/noir-repo/acvm-repo/brillig_vm/Cargo.toml @@ -2,7 +2,7 @@ name = "brillig_vm" description = "The virtual machine that processes Brillig bytecode, used to introduce non-determinism to the ACVM" # x-release-please-start-version -version = "0.46.0" +version = "0.47.0" # x-release-please-end authors.workspace = true edition.workspace = true 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 2053f4e7c860..53599f79bc72 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 @@ -42,7 +42,7 @@ pub(crate) fn evaluate_black_box op: &BlackBoxOp, solver: &Solver, memory: &mut Memory, - bigint_solver: &mut BigIntSolver, + bigint_solver: &mut BrilligBigintSolver, ) -> Result<(), BlackBoxResolutionError> { match op { BlackBoxOp::AES128Encrypt { inputs, iv, key, outputs } => { @@ -241,7 +241,7 @@ pub(crate) fn evaluate_black_box memory.read(*domain_separator).try_into().map_err(|_| { BlackBoxResolutionError::Failed( BlackBoxFunc::PedersenCommitment, - "Invalid signature length".to_string(), + "Invalid separator length".to_string(), ) })?; let (x, y) = solver.pedersen_commitment(&inputs, domain_separator)?; @@ -260,7 +260,7 @@ pub(crate) fn evaluate_black_box memory.read(*domain_separator).try_into().map_err(|_| { BlackBoxResolutionError::Failed( BlackBoxFunc::PedersenCommitment, - "Invalid signature length".to_string(), + "Invalid separator length".to_string(), ) })?; let hash = solver.pedersen_hash(&inputs, domain_separator)?; @@ -270,29 +270,33 @@ pub(crate) fn evaluate_black_box 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)?; + + let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntAdd)?; + memory.write(*output, new_id.into()); 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)?; + + let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntSub)?; + memory.write(*output, new_id.into()); 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)?; + + let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntMul)?; + memory.write(*output, new_id.into()); 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)?; + + let new_id = bigint_solver.bigint_op(lhs, rhs, BlackBoxFunc::BigIntDiv)?; + memory.write(*output, new_id.into()); Ok(()) } BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { @@ -300,8 +304,10 @@ pub(crate) fn evaluate_black_box 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)?; + + let new_id = bigint_solver.bigint_from_bytes(&input, &modulus)?; + memory.write(*output, new_id.into()); + Ok(()) } BlackBoxOp::BigIntToLeBytes { input, output } => { @@ -381,6 +387,46 @@ pub(crate) fn evaluate_black_box } } +/// Wrapper over the generic bigint solver to automatically assign bigint ids in brillig +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub(crate) struct BrilligBigintSolver { + bigint_solver: BigIntSolver, + last_id: u32, +} + +impl BrilligBigintSolver { + pub(crate) fn create_bigint_id(&mut self) -> u32 { + let output = self.last_id; + self.last_id += 1; + output + } + + pub(crate) fn bigint_from_bytes( + &mut self, + inputs: &[u8], + modulus: &[u8], + ) -> Result { + let id = self.create_bigint_id(); + self.bigint_solver.bigint_from_bytes(inputs, modulus, id)?; + Ok(id) + } + + pub(crate) fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { + self.bigint_solver.bigint_to_bytes(input) + } + + pub(crate) fn bigint_op( + &mut self, + lhs: u32, + rhs: u32, + func: BlackBoxFunc, + ) -> Result { + let id = self.create_bigint_id(); + self.bigint_solver.bigint_op(lhs, rhs, id, func)?; + Ok(id) + } +} + fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { match op { BlackBoxOp::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt, @@ -392,8 +438,6 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1, BlackBoxOp::EcdsaSecp256r1 { .. } => BlackBoxFunc::EcdsaSecp256r1, BlackBoxOp::SchnorrVerify { .. } => BlackBoxFunc::SchnorrVerify, - BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, - BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, BlackBoxOp::MultiScalarMul { .. } => BlackBoxFunc::MultiScalarMul, BlackBoxOp::EmbeddedCurveAdd { .. } => BlackBoxFunc::EmbeddedCurveAdd, BlackBoxOp::BigIntAdd { .. } => BlackBoxFunc::BigIntAdd, @@ -405,6 +449,8 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { BlackBoxOp::Poseidon2Permutation { .. } => BlackBoxFunc::Poseidon2Permutation, BlackBoxOp::Sha256Compression { .. } => BlackBoxFunc::Sha256Compression, BlackBoxOp::ToRadix { .. } => unreachable!("ToRadix is not an ACIR BlackBoxFunc"), + BlackBoxOp::PedersenCommitment { .. } => BlackBoxFunc::PedersenCommitment, + BlackBoxOp::PedersenHash { .. } => BlackBoxFunc::PedersenHash, } } @@ -414,10 +460,10 @@ mod test { brillig::{BlackBoxOp, MemoryAddress}, FieldElement, }; - use acvm_blackbox_solver::{BigIntSolver, StubbedBlackBoxSolver}; + use acvm_blackbox_solver::StubbedBlackBoxSolver; use crate::{ - black_box::{evaluate_black_box, to_u8_vec, to_value_vec}, + black_box::{evaluate_black_box, to_u8_vec, to_value_vec, BrilligBigintSolver}, HeapArray, HeapVector, Memory, }; @@ -439,8 +485,13 @@ mod test { output: HeapArray { pointer: 2.into(), size: 32 }, }; - evaluate_black_box(&op, &StubbedBlackBoxSolver, &mut memory, &mut BigIntSolver::default()) - .unwrap(); + evaluate_black_box( + &op, + &StubbedBlackBoxSolver, + &mut memory, + &mut BrilligBigintSolver::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 da9a34f1044e..4d2dd2b83339 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -16,9 +16,9 @@ use acir::brillig::{ HeapVector, MemoryAddress, Opcode, ValueOrArray, }; use acir::AcirField; -use acvm_blackbox_solver::{BigIntSolver, BlackBoxFunctionSolver}; +use acvm_blackbox_solver::BlackBoxFunctionSolver; use arithmetic::{evaluate_binary_field_op, evaluate_binary_int_op, BrilligArithmeticError}; -use black_box::evaluate_black_box; +use black_box::{evaluate_black_box, BrilligBigintSolver}; use num_bigint::BigUint; // Re-export `brillig`. @@ -88,7 +88,7 @@ pub struct VM<'a, F, B: BlackBoxFunctionSolver> { /// The solver for blackbox functions black_box_solver: &'a B, // The solver for big integers - bigint_solver: BigIntSolver, + bigint_solver: BrilligBigintSolver, } impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { @@ -482,60 +482,69 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { destinations.iter().zip(destination_value_types).zip(&values) { match (destination, value_type) { - (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(bit_size)) => { - match output { - ForeignCallParam::Single(value) => { - self.write_value_to_memory(*value_index, value, *bit_size)?; - } - _ => return Err(format!( - "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}") - ), + (ValueOrArray::MemoryAddress(value_index), HeapValueType::Simple(bit_size)) => { + match output { + ForeignCallParam::Single(value) => { + self.write_value_to_memory(*value_index, value, *bit_size)?; } + _ => return Err(format!( + "Function result size does not match brillig bytecode. Expected 1 result but got {output:?}") + ), } - ( - ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), - HeapValueType::Array { value_types, size: type_size }, - ) if size == type_size => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - if values.len() != *size { - return Err("Foreign call result array doesn't match expected size".to_string()); - } + } + ( + ValueOrArray::HeapArray(HeapArray { pointer: pointer_index, size }), + HeapValueType::Array { value_types, size: type_size }, + ) if size == type_size => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + if values.len() != *size { + // foreign call returning flattened values into a nested type, so the sizes do not match + let destination = self.memory.read_ref(*pointer_index); + let return_type = value_type; + let mut flatten_values_idx = 0; //index of values read from flatten_values + self.write_slice_of_values_to_memory(destination, &output.fields(), &mut flatten_values_idx, return_type)?; + } else { self.write_values_to_memory_slice(*pointer_index, values, value_types)?; } - _ => { - return Err("Function result size does not match brillig bytecode size".to_string()); - } } - } else { - unimplemented!("deflattening heap arrays from foreign calls"); + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); + } } - } - ( - ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), - HeapValueType::Vector { value_types }, - ) => { - if HeapValueType::all_simple(value_types) { - match output { - ForeignCallParam::Array(values) => { - // Set our size in the size address - self.memory.write(*size_index, values.len().into()); + } else { + // foreign call returning flattened values into a nested type, so the sizes do not match + let destination = self.memory.read_ref(*pointer_index); + let return_type = value_type; + let mut flatten_values_idx = 0; //index of values read from flatten_values + self.write_slice_of_values_to_memory(destination, &output.fields(), &mut flatten_values_idx, return_type)?; + } + } + ( + ValueOrArray::HeapVector(HeapVector {pointer: pointer_index, size: size_index }), + HeapValueType::Vector { value_types }, + ) => { + if HeapValueType::all_simple(value_types) { + match output { + ForeignCallParam::Array(values) => { + // Set our size in the size address + self.memory.write(*size_index, values.len().into()); + self.write_values_to_memory_slice(*pointer_index, values, value_types)?; - self.write_values_to_memory_slice(*pointer_index, values, value_types)?; - } - _ => { - return Err("Function result size does not match brillig bytecode size".to_string()); - } } - } else { - unimplemented!("deflattening heap vectors from foreign calls"); + _ => { + return Err("Function result size does not match brillig bytecode size".to_string()); + } } - } - _ => { - return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); + } else { + unimplemented!("deflattening heap vectors from foreign calls"); } } + _ => { + return Err(format!("Unexpected value type {value_type:?} for destination {destination:?}")); + } + } } let _ = @@ -596,6 +605,66 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { Ok(()) } + /// Writes flattened values to memory, using the provided type + /// Function calls itself recursively in order to work with recursive types (nested arrays) + /// values_idx is the current index in the values vector and is incremented every time + /// a value is written to memory + /// The function returns the address of the next value to be written + fn write_slice_of_values_to_memory( + &mut self, + destination: MemoryAddress, + values: &Vec, + values_idx: &mut usize, + value_type: &HeapValueType, + ) -> Result { + let mut current_pointer = destination; + match value_type { + HeapValueType::Simple(bit_size) => { + self.write_value_to_memory(destination, &values[*values_idx], *bit_size)?; + *values_idx += 1; + Ok(MemoryAddress(destination.to_usize() + 1)) + } + HeapValueType::Array { value_types, size } => { + for _ in 0..*size { + for typ in value_types { + match typ { + HeapValueType::Simple(len) => { + self.write_value_to_memory( + current_pointer, + &values[*values_idx], + *len, + )?; + *values_idx += 1; + current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + } + HeapValueType::Array { .. } => { + let destination = self.memory.read_ref(current_pointer); + let destination = self.memory.read_ref(destination); + self.write_slice_of_values_to_memory( + destination, + values, + values_idx, + typ, + )?; + current_pointer = MemoryAddress(current_pointer.to_usize() + 1); + } + HeapValueType::Vector { .. } => { + return Err(format!( + "Unsupported returned type in foreign calls {:?}", + typ + )); + } + } + } + } + Ok(current_pointer) + } + HeapValueType::Vector { .. } => { + Err(format!("Unsupported returned type in foreign calls {:?}", value_type)) + } + } + } + /// Process a binary operation. /// This method will not modify the program counter. fn process_binary_field_op( diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs index 30c0f63a2d45..40fde39a06f9 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_optionally_a_nullifier.rs @@ -176,7 +176,7 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( format!( " unconstrained fn compute_note_hash_and_optionally_a_nullifier( - contract_address: dep::aztec::protocol_types::address::AztecAddress, + contract_address: aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, @@ -194,7 +194,7 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( let if_statements: Vec = note_types.iter().map(|note_type| format!( "if (note_type_id == {0}::get_note_type_id()) {{ - dep::aztec::note::utils::compute_note_hash_and_optionally_a_nullifier({0}::deserialize_content, note_header, compute_nullifier, serialized_note) + aztec::note::utils::compute_note_hash_and_optionally_a_nullifier({0}::deserialize_content, note_header, compute_nullifier, serialized_note) }}" , note_type)).collect(); @@ -208,14 +208,14 @@ fn generate_compute_note_hash_and_optionally_a_nullifier_source( format!( " unconstrained fn compute_note_hash_and_optionally_a_nullifier( - contract_address: dep::aztec::protocol_types::address::AztecAddress, + contract_address: aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, compute_nullifier: bool, serialized_note: [Field; {}], ) -> pub [Field; 4] {{ - let note_header = dep::aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); + let note_header = aztec::prelude::NoteHeader::new(contract_address, nonce, storage_slot); {} }}", diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs index 8b763dfcc574..b9323644379b 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -30,8 +30,8 @@ use crate::utils::{ // 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)); +// let args_hash = aztec::hash::hash_args(args_acc); +// assert(args_hash == aztec::oracle::arguments::pack_arguments(args_acc)); // PublicCallInterface { // target_contract: self.target_contract, // selector: FunctionSelector::from_signature("SELECTOR_PLACEHOLDER"), @@ -56,7 +56,10 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call .join(", "); let fn_return_type: noirc_frontend::ast::UnresolvedType = func.return_type(); - let fn_selector = format!("dep::aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature(\"{}\")", SELECTOR_PLACEHOLDER); + 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 { "" }; @@ -134,8 +137,8 @@ pub fn stub_function(aztec_visibility: &str, func: &NoirFunction, is_static_call 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));", + let args_hash = aztec::hash::hash_args(args_acc); + assert(args_hash == aztec::oracle::arguments::pack_arguments(args_acc));", call_args ) } else { @@ -231,14 +234,14 @@ pub fn generate_contract_interface( let contract_interface = format!( " struct {0} {{ - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress }} impl {0} {{ {1} pub fn at( - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress ) -> Self {{ Self {{ target_contract }} }} @@ -252,7 +255,7 @@ pub fn generate_contract_interface( #[contract_library_method] pub fn at( - target_contract: dep::aztec::protocol_types::address::AztecAddress + target_contract: aztec::protocol_types::address::AztecAddress ) -> {0} {{ {0} {{ target_contract }} }} 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 3ace22a89c30..49525fc2ae12 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -72,6 +72,7 @@ pub fn generate_note_interface_impl(module: &mut SortedModule) -> Result<(), Azt type_span: note_struct.name.span(), generics: vec![], methods: vec![], + where_clause: vec![], }; module.impls.push(default_impl.clone()); module.impls.last_mut().unwrap() @@ -271,7 +272,7 @@ fn generate_note_get_header( ) -> Result { let function_source = format!( " - fn get_header(note: {}) -> dep::aztec::note::note_header::NoteHeader {{ + fn get_header(note: {}) -> aztec::note::note_header::NoteHeader {{ note.{} }} ", @@ -302,7 +303,7 @@ fn generate_note_set_header( ) -> Result { let function_source = format!( " - fn set_header(self: &mut {}, header: dep::aztec::note::note_header::NoteHeader) {{ + fn set_header(self: &mut {}, header: aztec::note::note_header::NoteHeader) {{ self.{} = header; }} ", @@ -492,7 +493,7 @@ fn generate_note_properties_fn( // Automatically generate the method to compute the note's content hash as: // fn compute_note_content_hash(self: NoteType) -> Field { -// dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) +// aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) // } // fn generate_compute_note_content_hash( @@ -502,7 +503,7 @@ fn generate_compute_note_content_hash( let function_source = format!( " fn compute_note_content_hash(self: {}) -> Field {{ - dep::aztec::hash::pedersen_hash(self.serialize_content(), dep::aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) + aztec::hash::pedersen_hash(self.serialize_content(), aztec::protocol_types::constants::GENERATOR_INDEX__NOTE_CONTENT_HASH) }} ", note_type @@ -562,8 +563,7 @@ fn generate_note_properties_struct_source( .filter_map(|(field_name, _)| { if field_name != note_header_field_name { Some(format!( - "{}: dep::aztec::note::note_getter_options::PropertySelector", - field_name + "{field_name}: dep::aztec::note::note_getter_options::PropertySelector" )) } else { None @@ -592,7 +592,7 @@ fn generate_note_properties_fn_source( .filter_map(|(index, (field_name, _))| { if field_name != note_header_field_name { Some(format!( - "{}: dep::aztec::note::note_getter_options::PropertySelector {{ index: {}, offset: 0, length: 32 }}", + "{}: aztec::note::note_getter_options::PropertySelector {{ index: {}, offset: 0, length: 32 }}", field_name, index )) @@ -670,8 +670,7 @@ fn generate_note_deserialize_content_source( } } else { format!( - "{}: dep::aztec::note::note_header::NoteHeader::empty()", - note_header_field_name + "{note_header_field_name}: dep::aztec::note::note_header::NoteHeader::empty()" ) } }) diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs index bac87502c7d1..c302dd87aa5e 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/storage.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -91,7 +91,7 @@ pub fn inject_context_in_storage(module: &mut SortedModule) -> Result<(), AztecM r#struct.attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) }) .unwrap(); - storage_struct.generics.push(ident("Context")); + storage_struct.generics.push(ident("Context").into()); storage_struct .fields .iter_mut() @@ -243,9 +243,11 @@ pub fn generate_storage_implementation( span: Some(Span::default()), }, type_span: Span::default(), - generics: vec![generic_context_ident], + generics: vec![generic_context_ident.into()], methods: vec![(init, Span::default())], + + where_clause: vec![], }; module.impls.push(storage_impl); diff --git a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs index 4706be2df25b..4467c4bca4b5 100644 --- a/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/ast_utils.rs @@ -47,12 +47,17 @@ pub fn method_call( object, method_name: ident(method_name), arguments, + is_macro_call: false, generics: None, }))) } pub fn call(func: Expression, arguments: Vec) -> Expression { - expression(ExpressionKind::Call(Box::new(CallExpression { func: Box::new(func), arguments }))) + expression(ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(func), + is_macro_call: false, + arguments, + }))) } pub fn pattern(name: &str) -> Pattern { @@ -156,7 +161,7 @@ macro_rules! chained_dep { ( $base:expr $(, $tail:expr)* ) => { { let mut base_path = ident_path($base); - base_path.kind = PathKind::Dep; + base_path.kind = PathKind::Plain; $( base_path.segments.push(ident($tail)); )* diff --git a/noir/noir-repo/compiler/fm/Cargo.toml b/noir/noir-repo/compiler/fm/Cargo.toml index f556f305c784..1a356d93d896 100644 --- a/noir/noir-repo/compiler/fm/Cargo.toml +++ b/noir/noir-repo/compiler/fm/Cargo.toml @@ -13,5 +13,4 @@ codespan-reporting.workspace = true serde.workspace = true [dev-dependencies] -tempfile.workspace = true iter-extended.workspace = true diff --git a/noir/noir-repo/compiler/fm/src/lib.rs b/noir/noir-repo/compiler/fm/src/lib.rs index bb080c62c0ea..2e52d802479b 100644 --- a/noir/noir-repo/compiler/fm/src/lib.rs +++ b/noir/noir-repo/compiler/fm/src/lib.rs @@ -185,24 +185,17 @@ mod path_normalization { #[cfg(test)] mod tests { use super::*; - use tempfile::{tempdir, TempDir}; - // Returns the absolute path to the file - fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { - let file_path = dir.path().join(file_name); - let _file = std::fs::File::create(&file_path).unwrap(); - file_path + fn add_file(fm: &mut FileManager, file_name: &Path) -> FileId { + fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap() } #[test] fn path_resolve_file_module_other_ext() { - let dir = tempdir().unwrap(); - let file_name = Path::new("foo.nr"); - create_dummy_file(&dir, file_name); + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); - let mut fm = FileManager::new(dir.path()); - - let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); + let file_id = add_file(&mut fm, &dir.join("foo.nr")); assert!(fm.path(file_id).unwrap().ends_with("foo.nr")); } @@ -213,23 +206,19 @@ mod tests { /// they should both resolve to ../foo.nr #[test] fn path_resolve_modules_with_different_paths_as_same_file() { - let dir = tempdir().unwrap(); - let sub_dir = TempDir::new_in(&dir).unwrap(); - let sub_sub_dir = TempDir::new_in(&sub_dir).unwrap(); - - let mut fm = FileManager::new(dir.path()); - - // Create a lib.nr file at the root. - let file_name = Path::new("lib.nr"); - create_dummy_file(&dir, file_name); - - // Create another path with `./` and `../` inside it - let second_file_name = PathBuf::from(sub_sub_dir.path()).join("./../../lib.nr"); - - // Add both files to the file manager - let file_id = fm.add_file_with_source(file_name, "fn foo() {}".to_string()).unwrap(); - let second_file_id = - fm.add_file_with_source(&second_file_name, "fn foo() {}".to_string()).unwrap(); + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + // Create a lib.nr file at the root and add it to the file manager. + let file_id = add_file(&mut fm, &dir.join("lib.nr")); + + // Create another path with `./` and `../` inside it, and add it to the file manager + let sub_dir = dir.join("sub_dir"); + let sub_sub_dir = sub_dir.join("sub_sub_dir"); + let second_file_id = add_file( + &mut fm, + PathBuf::from(sub_sub_dir.as_path()).join("./../../lib.nr").as_path(), + ); assert_eq!(file_id, second_file_id); } diff --git a/noir/noir-repo/compiler/integration-tests/circuits/assert_lt/src/main.nr b/noir/noir-repo/compiler/integration-tests/circuits/assert_lt/src/main.nr index b8e255ca492c..47e229d6c8bb 100644 --- a/noir/noir-repo/compiler/integration-tests/circuits/assert_lt/src/main.nr +++ b/noir/noir-repo/compiler/integration-tests/circuits/assert_lt/src/main.nr @@ -1,10 +1,7 @@ -use dep::std; - fn main(x: u64, y: pub u64) -> pub u64 { // We include a println statement to show that noirJS will ignore this and continue execution std::println("foo"); - assert(x < y); x + y } diff --git a/noir/noir-repo/compiler/integration-tests/circuits/recursion/src/main.nr b/noir/noir-repo/compiler/integration-tests/circuits/recursion/src/main.nr index 173207766fb9..94cae14daa72 100644 --- a/noir/noir-repo/compiler/integration-tests/circuits/recursion/src/main.nr +++ b/noir/noir-repo/compiler/integration-tests/circuits/recursion/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main( verification_key: [Field; 114], proof: [Field; 93], diff --git a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs index e959c61732a2..d0b33945f40e 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/abi_gen.rs @@ -3,14 +3,17 @@ use std::collections::BTreeMap; use acvm::acir::circuit::ErrorSelector; use acvm::AcirField; use iter_extended::vecmap; -use noirc_abi::{Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue}; -use noirc_frontend::ast::Visibility; +use noirc_abi::{ + Abi, AbiErrorType, AbiParameter, AbiReturnType, AbiType, AbiValue, AbiVisibility, Sign, +}; +use noirc_frontend::ast::{Signedness, Visibility}; use noirc_frontend::{ hir::Context, hir_def::{expr::HirArrayLiteral, function::Param, stmt::HirPattern, types::Type}, macros_api::{HirExpression, HirLiteral}, node_interner::{FuncId, NodeInterner}, }; +use noirc_frontend::{TypeBinding, TypeVariableKind}; /// Arranges a function signature and a generated circuit's return witnesses into a /// `noirc_abi::Abi`. @@ -21,15 +24,102 @@ pub(super) fn gen_abi( error_types: BTreeMap, ) -> Abi { let (parameters, return_type) = compute_function_abi(context, func_id); - let return_type = return_type - .map(|typ| AbiReturnType { abi_type: typ, visibility: return_visibility.into() }); + let return_type = return_type.map(|typ| AbiReturnType { + abi_type: typ, + visibility: to_abi_visibility(return_visibility), + }); let error_types = error_types .into_iter() - .map(|(selector, typ)| (selector, AbiErrorType::from_type(context, &typ))) + .map(|(selector, typ)| (selector, build_abi_error_type(context, &typ))) .collect(); Abi { parameters, return_type, error_types } } +fn build_abi_error_type(context: &Context, typ: &Type) -> AbiErrorType { + match typ { + Type::FmtString(len, item_types) => { + let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); + let Type::Tuple(item_types) = item_types.as_ref() else { + unreachable!("FmtString items must be a tuple") + }; + let item_types = + item_types.iter().map(|typ| abi_type_from_hir_type(context, typ)).collect(); + AbiErrorType::FmtString { length, item_types } + } + _ => AbiErrorType::Custom(abi_type_from_hir_type(context, typ)), + } +} + +pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType { + match typ { + Type::FieldElement => AbiType::Field, + Type::Array(size, typ) => { + let length = size + .evaluate_to_u32() + .expect("Cannot have variable sized arrays as a parameter to main"); + let typ = typ.as_ref(); + AbiType::Array { length, typ: Box::new(abi_type_from_hir_type(context, typ)) } + } + Type::Integer(sign, bit_width) => { + let sign = match sign { + Signedness::Unsigned => Sign::Unsigned, + Signedness::Signed => Sign::Signed, + }; + + AbiType::Integer { sign, width: (*bit_width).into() } + } + Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) + | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { + TypeBinding::Bound(typ) => abi_type_from_hir_type(context, typ), + TypeBinding::Unbound(_) => { + abi_type_from_hir_type(context, &Type::default_int_or_field_type()) + } + }, + Type::Bool => AbiType::Boolean, + Type::String(size) => { + let size = size + .evaluate_to_u32() + .expect("Cannot have variable sized strings as a parameter to main"); + AbiType::String { length: size } + } + + Type::Struct(def, args) => { + let struct_type = def.borrow(); + let fields = struct_type.get_fields(args); + let fields = + vecmap(fields, |(name, typ)| (name, abi_type_from_hir_type(context, &typ))); + // For the ABI, we always want to resolve the struct paths from the root crate + let path = context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id); + AbiType::Struct { fields, path } + } + Type::Alias(def, args) => abi_type_from_hir_type(context, &def.borrow().get_type(args)), + Type::Tuple(fields) => { + let fields = vecmap(fields, |typ| abi_type_from_hir_type(context, typ)); + AbiType::Tuple { fields } + } + Type::Error + | Type::Unit + | Type::Constant(_) + | Type::TraitAsType(..) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(..) + | Type::Forall(..) + | Type::Quoted(_) + | Type::Slice(_) + | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), + Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), + Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), + } +} + +fn to_abi_visibility(value: Visibility) -> AbiVisibility { + match value { + Visibility::Public => AbiVisibility::Public, + Visibility::Private => AbiVisibility::Private, + Visibility::DataBus => AbiVisibility::DataBus, + } +} + pub(super) fn compute_function_abi( context: &Context, func_id: &FuncId, @@ -38,7 +128,7 @@ pub(super) fn compute_function_abi( let (parameters, return_type) = func_meta.function_signature(); let parameters = into_abi_params(context, parameters); - let return_type = return_type.map(|typ| AbiType::from_type(context, &typ)); + let return_type = return_type.map(|typ| abi_type_from_hir_type(context, &typ)); (parameters, return_type) } @@ -58,8 +148,8 @@ fn into_abi_params(context: &Context, params: Vec) -> Vec { let param_name = get_param_name(&pattern, &context.def_interner) .expect("Abi for tuple and struct parameters is unimplemented") .to_owned(); - let as_abi = AbiType::from_type(context, &typ); - AbiParameter { name: param_name, typ: as_abi, visibility: vis.into() } + let as_abi = abi_type_from_hir_type(context, &typ); + AbiParameter { name: param_name, typ: as_abi, visibility: to_abi_visibility(vis) } }) } diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index f8043a60f8cf..4ba9b85f967b 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -3,7 +3,7 @@ #![warn(unreachable_pub)] #![warn(clippy::semicolon_if_nothing_returned)] -use abi_gen::value_from_hir_expression; +use abi_gen::{abi_type_from_hir_type, value_from_hir_expression}; use acvm::acir::circuit::ExpressionWidth; use clap::Args; use fm::{FileId, FileManager}; @@ -99,9 +99,9 @@ pub struct CompileOptions { #[arg(long, hide = true)] pub force_brillig: bool, - /// Enable the experimental elaborator pass + /// Use the deprecated name resolution & type checking passes instead of the elaborator #[arg(long, hide = true)] - pub use_elaborator: bool, + pub use_legacy: bool, /// Outputs the paths to any modified artifacts #[arg(long, hide = true)] @@ -257,13 +257,13 @@ pub fn check_crate( crate_id: CrateId, deny_warnings: bool, disable_macros: bool, - use_elaborator: bool, + use_legacy: bool, ) -> CompilationResult<()> { let macros: &[&dyn MacroProcessor] = if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; let mut errors = vec![]; - let diagnostics = CrateDefMap::collect_defs(crate_id, context, use_elaborator, macros); + let diagnostics = CrateDefMap::collect_defs(crate_id, context, use_legacy, macros); errors.extend(diagnostics.into_iter().map(|(error, file_id)| { let diagnostic = CustomDiagnostic::from(&error); diagnostic.in_file(file_id) @@ -300,7 +300,7 @@ pub fn compile_main( crate_id, options.deny_warnings, options.disable_macros, - options.use_elaborator, + options.use_legacy, )?; let main = context.get_main_function(&crate_id).ok_or_else(|| { @@ -341,7 +341,7 @@ pub fn compile_contract( crate_id, options.deny_warnings, options.disable_macros, - options.use_elaborator, + options.use_legacy, )?; // TODO: We probably want to error if contracts is empty @@ -468,7 +468,7 @@ fn compile_contract_inner( let typ = context.def_interner.get_struct(struct_id); let typ = typ.borrow(); let fields = vecmap(typ.get_fields(&[]), |(name, typ)| { - (name, AbiType::from_type(context, &typ)) + (name, abi_type_from_hir_type(context, &typ)) }); let path = context.fully_qualified_struct_path(context.root_crate_id(), typ.id); @@ -544,14 +544,15 @@ pub fn compile_no_check( return Ok(cached_program.expect("cache must exist for hashes to match")); } let return_visibility = program.return_visibility; + let ssa_evaluator_options = noirc_evaluator::ssa::SsaEvaluatorOptions { + enable_ssa_logging: options.show_ssa, + enable_brillig_logging: options.show_brillig, + force_brillig_output: options.force_brillig, + print_codegen_timings: options.benchmark_codegen, + }; - let SsaProgramArtifact { program, debug, warnings, names, error_types, .. } = create_program( - program, - options.show_ssa, - options.show_brillig, - options.force_brillig, - options.benchmark_codegen, - )?; + let SsaProgramArtifact { program, debug, warnings, names, error_types, .. } = + create_program(program, &ssa_evaluator_options)?; let abi = abi_gen::gen_abi(context, &main_function, return_visibility, error_types); let file_map = filter_relevant_files(&debug, &context.file_manager); diff --git a/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs b/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs index 327c8daad065..47ce893d2025 100644 --- a/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs +++ b/noir/noir-repo/compiler/noirc_driver/tests/stdlib_warnings.rs @@ -27,7 +27,7 @@ fn stdlib_does_not_produce_constant_warnings() -> Result<(), ErrorsAndWarnings> let ((), warnings) = noirc_driver::check_crate(&mut context, root_crate_id, false, false, false)?; - assert_eq!(warnings, Vec::new(), "stdlib is producing warnings"); + assert_eq!(warnings, Vec::new(), "stdlib is producing {} warnings", warnings.len()); Ok(()) } diff --git a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs index 42cab72345d6..d817b48691f8 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs @@ -1,3 +1,5 @@ +use std::io::IsTerminal; + use crate::{FileDiagnostic, Location, Span}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::files::Files; @@ -148,7 +150,9 @@ pub fn report<'files>( call_stack: &[Location], deny_warnings: bool, ) -> bool { - let writer = StandardStream::stderr(ColorChoice::Always); + let color_choice = + if std::io::stderr().is_terminal() { ColorChoice::Auto } else { ColorChoice::Never }; + let writer = StandardStream::stderr(color_choice); let config = codespan_reporting::term::Config::default(); let stack_trace = stack_trace(files, call_stack); diff --git a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml index aa30eef9156b..72a52b43741e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_evaluator/Cargo.toml @@ -12,6 +12,7 @@ license.workspace = true noirc_frontend.workspace = true noirc_errors.workspace = true acvm.workspace = true +bn254_blackbox_solver.workspace = true fxhash.workspace = true iter-extended.workspace = true thiserror.workspace = true diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs index 5576d673f1de..ee61a9d13d3c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen.rs @@ -6,12 +6,17 @@ pub(crate) mod brillig_fn; pub(crate) mod brillig_slice_ops; mod variable_liveness; +use acvm::FieldElement; + use self::{brillig_block::BrilligBlock, brillig_fn::FunctionContext}; use super::brillig_ir::{artifact::BrilligArtifact, BrilligContext}; use crate::ssa::ir::function::Function; /// Converting an SSA function into Brillig bytecode. -pub(crate) fn convert_ssa_function(func: &Function, enable_debug_trace: bool) -> BrilligArtifact { +pub(crate) fn convert_ssa_function( + func: &Function, + enable_debug_trace: bool, +) -> BrilligArtifact { let mut brillig_context = BrilligContext::new(enable_debug_trace); let mut function_context = FunctionContext::new(func); 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 f56c5daf315b..aa9cb8cd7a33 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,18 +1,19 @@ use acvm::{ acir::{brillig::BlackBoxOp, BlackBoxFunc}, - FieldElement, + AcirField, }; use crate::brillig::brillig_ir::{ brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligBinaryOp, BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions /// Extracting arguments and results from the SSA function call /// And making any necessary type conversions to adapt noir's blackbox calls to brillig's -pub(crate) fn convert_black_box_call( - brillig_context: &mut BrilligContext, +pub(crate) fn convert_black_box_call( + brillig_context: &mut BrilligContext, bb_func: &BlackBoxFunc, function_arguments: &[BrilligVariable], function_results: &[BrilligVariable], @@ -242,13 +243,7 @@ pub(crate) fn convert_black_box_call( [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { - prepare_bigint_output( - brillig_context, - lhs_modulus, - rhs_modulus, - output, - modulus_id, - ); + prepare_bigint_output(brillig_context, lhs_modulus, rhs_modulus, modulus_id); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntAdd { lhs: lhs.address, rhs: rhs.address, @@ -266,13 +261,7 @@ pub(crate) fn convert_black_box_call( [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { - prepare_bigint_output( - brillig_context, - lhs_modulus, - rhs_modulus, - output, - modulus_id, - ); + prepare_bigint_output(brillig_context, lhs_modulus, rhs_modulus, modulus_id); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntSub { lhs: lhs.address, rhs: rhs.address, @@ -290,13 +279,7 @@ pub(crate) fn convert_black_box_call( [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { - prepare_bigint_output( - brillig_context, - lhs_modulus, - rhs_modulus, - output, - modulus_id, - ); + prepare_bigint_output(brillig_context, lhs_modulus, rhs_modulus, modulus_id); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntMul { lhs: lhs.address, rhs: rhs.address, @@ -314,13 +297,7 @@ pub(crate) fn convert_black_box_call( [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { - prepare_bigint_output( - brillig_context, - lhs_modulus, - rhs_modulus, - output, - modulus_id, - ); + prepare_bigint_output(brillig_context, lhs_modulus, rhs_modulus, modulus_id); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntDiv { lhs: lhs.address, rhs: rhs.address, @@ -340,8 +317,6 @@ pub(crate) fn convert_black_box_call( { 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(), @@ -426,8 +401,8 @@ pub(crate) fn convert_black_box_call( } } -fn convert_array_or_vector( - brillig_context: &mut BrilligContext, +fn convert_array_or_vector( + brillig_context: &mut BrilligContext, array_or_vector: &BrilligVariable, bb_func: &BlackBoxFunc, ) -> BrilligVector { @@ -442,11 +417,10 @@ fn convert_array_or_vector( } } -fn prepare_bigint_output( - brillig_context: &mut BrilligContext, +fn prepare_bigint_output( + brillig_context: &mut BrilligContext, lhs_modulus: &SingleAddrVariable, rhs_modulus: &SingleAddrVariable, - output: &SingleAddrVariable, modulus_id: &SingleAddrVariable, ) { // Check moduli @@ -463,8 +437,6 @@ fn prepare_bigint_output( 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 1fa4f41b29cf..c2bc1e32cd69 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 @@ -22,6 +22,7 @@ use acvm::{acir::AcirField, FieldElement}; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use iter_extended::vecmap; use num_bigint::BigUint; +use std::rc::Rc; use super::brillig_black_box::convert_black_box_call; use super::brillig_block_variables::BlockVariables; @@ -33,7 +34,7 @@ pub(crate) struct BrilligBlock<'block> { /// The basic block that is being converted pub(crate) block_id: BasicBlockId, /// Context for creating brillig opcodes - pub(crate) brillig_context: &'block mut BrilligContext, + pub(crate) brillig_context: &'block mut BrilligContext, /// Tracks the available variable during the codegen of the block pub(crate) variables: BlockVariables, /// For each instruction, the set of values that are not used anymore after it. @@ -44,7 +45,7 @@ impl<'block> BrilligBlock<'block> { /// Converts an SSA Basic block into a sequence of Brillig opcodes pub(crate) fn compile( function_context: &'block mut FunctionContext, - brillig_context: &'block mut BrilligContext, + brillig_context: &'block mut BrilligContext, block_id: BasicBlockId, dfg: &DataFlowGraph, ) { @@ -582,6 +583,11 @@ impl<'block> BrilligBlock<'block> { 1, ); } + + // `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting. + // It is then useless in the brillig runtime and so we can ignore it + Value::Intrinsic(Intrinsic::AsWitness) => (), + _ => { unreachable!("unsupported function call type {:?}", dfg[*func]) } @@ -944,7 +950,7 @@ impl<'block> BrilligBlock<'block> { } pub(crate) fn store_variable_in_array_with_ctx( - ctx: &mut BrilligContext, + ctx: &mut BrilligContext, destination_pointer: MemoryAddress, index_register: SingleAddrVariable, value_variable: BrilligVariable, @@ -1629,7 +1635,7 @@ impl<'block> BrilligBlock<'block> { new_variable } } - Value::Array { array, .. } => { + Value::Array { array, typ } => { if let Some(variable) = self.variables.get_constant(value_id, dfg) { variable } else { @@ -1664,23 +1670,7 @@ impl<'block> BrilligBlock<'block> { // Write the items - // Allocate a register for the iterator - let iterator_register = - self.brillig_context.make_usize_constant_instruction(0_usize.into()); - - for element_id in array.iter() { - let element_variable = self.convert_ssa_value(*element_id, dfg); - // Store the item in memory - self.store_variable_in_array(pointer, iterator_register, element_variable); - // Increment the iterator - self.brillig_context.codegen_usize_op_in_place( - iterator_register.address, - BrilligBinaryOp::Add, - 1, - ); - } - - self.brillig_context.deallocate_single_addr(iterator_register); + self.initialize_constant_array(array, typ, dfg, pointer); new_variable } @@ -1705,6 +1695,125 @@ impl<'block> BrilligBlock<'block> { } } + fn initialize_constant_array( + &mut self, + data: &im::Vector, + typ: &Type, + dfg: &DataFlowGraph, + pointer: MemoryAddress, + ) { + if data.is_empty() { + return; + } + let item_types = typ.clone().element_types(); + + // Find out if we are repeating the same item over and over + let first_item = data.iter().take(item_types.len()).copied().collect(); + let mut is_repeating = true; + + for item_index in (item_types.len()..data.len()).step_by(item_types.len()) { + let item: Vec<_> = (0..item_types.len()).map(|i| data[item_index + i]).collect(); + if first_item != item { + is_repeating = false; + break; + } + } + + // If all the items are single address, and all have the same initial value, we can initialize the array in a runtime loop. + // Since the cost in instructions for a runtime loop is in the order of magnitude of 10, we only do this if the item_count is bigger than that. + let item_count = data.len() / item_types.len(); + + if item_count > 10 + && is_repeating + && item_types.iter().all(|typ| matches!(typ, Type::Numeric(_))) + { + self.initialize_constant_array_runtime( + item_types, first_item, item_count, pointer, dfg, + ); + } else { + self.initialize_constant_array_comptime(data, dfg, pointer); + } + } + + fn initialize_constant_array_runtime( + &mut self, + item_types: Rc>, + item_to_repeat: Vec, + item_count: usize, + pointer: MemoryAddress, + dfg: &DataFlowGraph, + ) { + let mut subitem_to_repeat_variables = Vec::with_capacity(item_types.len()); + for subitem_id in item_to_repeat.into_iter() { + subitem_to_repeat_variables.push(self.convert_ssa_value(subitem_id, dfg)); + } + + let data_length_variable = self + .brillig_context + .make_usize_constant_instruction((item_count * item_types.len()).into()); + + // If this is an array with complex subitems, we need a custom step in the loop to write all the subitems while iterating. + if item_types.len() > 1 { + let step_variable = + self.brillig_context.make_usize_constant_instruction(item_types.len().into()); + + let subitem_pointer = + SingleAddrVariable::new_usize(self.brillig_context.allocate_register()); + + let initializer_fn = |ctx: &mut BrilligContext<_>, iterator: SingleAddrVariable| { + ctx.mov_instruction(subitem_pointer.address, iterator.address); + for subitem in subitem_to_repeat_variables.into_iter() { + Self::store_variable_in_array_with_ctx(ctx, pointer, subitem_pointer, subitem); + ctx.codegen_usize_op_in_place(subitem_pointer.address, BrilligBinaryOp::Add, 1); + } + }; + + self.brillig_context.codegen_loop_with_bound_and_step( + data_length_variable.address, + step_variable.address, + initializer_fn, + ); + + self.brillig_context.deallocate_single_addr(step_variable); + self.brillig_context.deallocate_single_addr(subitem_pointer); + } else { + let subitem = subitem_to_repeat_variables.into_iter().next().unwrap(); + + let initializer_fn = |ctx: &mut _, iterator_register| { + Self::store_variable_in_array_with_ctx(ctx, pointer, iterator_register, subitem); + }; + + self.brillig_context.codegen_loop(data_length_variable.address, initializer_fn); + } + + self.brillig_context.deallocate_single_addr(data_length_variable); + } + + fn initialize_constant_array_comptime( + &mut self, + data: &im::Vector>, + dfg: &DataFlowGraph, + pointer: MemoryAddress, + ) { + // Allocate a register for the iterator + let iterator_register = + self.brillig_context.make_usize_constant_instruction(0_usize.into()); + + for element_id in data.iter() { + let element_variable = self.convert_ssa_value(*element_id, dfg); + // Store the item in memory + self.store_variable_in_array(pointer, iterator_register, element_variable); + // Increment the iterator + self.brillig_context.codegen_usize_op_in_place( + iterator_register.address, + BrilligBinaryOp::Add, + 1, + ); + } + + self.brillig_context.deallocate_single_addr(iterator_register); + } + /// Converts an SSA `ValueId` into a `MemoryAddress`. Initializes if necessary. fn convert_ssa_single_addr_value( &mut self, @@ -1737,8 +1846,7 @@ impl<'block> BrilligBlock<'block> { dfg, ); let array = variable.extract_array(); - self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); - self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); + self.allocate_nested_array(typ, Some(array)); variable } @@ -1765,6 +1873,43 @@ impl<'block> BrilligBlock<'block> { } } + fn allocate_nested_array( + &mut self, + typ: &Type, + array: Option, + ) -> BrilligVariable { + match typ { + Type::Array(types, size) => { + let array = array.unwrap_or(BrilligArray { + pointer: self.brillig_context.allocate_register(), + size: *size, + rc: self.brillig_context.allocate_register(), + }); + self.brillig_context.codegen_allocate_fixed_length_array(array.pointer, array.size); + self.brillig_context.usize_const_instruction(array.rc, 1_usize.into()); + + let mut index = 0_usize; + for _ in 0..*size { + for element_type in types.iter() { + match element_type { + Type::Array(_, _) => { + let inner_array = self.allocate_nested_array(element_type, None); + let idx = + self.brillig_context.make_usize_constant_instruction(index.into()); + self.store_variable_in_array(array.pointer, idx, inner_array); + } + Type::Slice(_) => unreachable!("ICE: unsupported slice type in allocate_nested_array(), expects an array or a numeric type"), + _ => (), + } + index += 1; + } + } + BrilligVariable::BrilligArray(array) + } + _ => unreachable!("ICE: allocate_nested_array() expects an array, got {typ:?}"), + } + } + /// Gets the "user-facing" length of an array. /// An array of structs with two fields would be stored as an 2 * array.len() array/vector. /// So we divide the length by the number of subitems in an item to get the user-facing length. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs index fb9a8577d945..ffbca256d285 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block_variables.rs @@ -1,3 +1,4 @@ +use acvm::FieldElement; use fxhash::{FxHashMap as HashMap, FxHashSet as HashSet}; use crate::{ @@ -50,7 +51,7 @@ impl BlockVariables { pub(crate) fn define_variable( &mut self, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, ) -> BrilligVariable { @@ -70,7 +71,7 @@ impl BlockVariables { pub(crate) fn define_single_addr_variable( &mut self, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value: ValueId, dfg: &DataFlowGraph, ) -> SingleAddrVariable { @@ -83,7 +84,7 @@ impl BlockVariables { &mut self, value_id: &ValueId, function_context: &mut FunctionContext, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, ) { assert!(self.available_variables.remove(value_id), "ICE: Variable is not available"); let variable = function_context @@ -122,7 +123,7 @@ impl BlockVariables { /// We keep constants block-local. pub(crate) fn allocate_constant( &mut self, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, value_id: ValueId, dfg: &DataFlowGraph, ) -> BrilligVariable { @@ -154,9 +155,9 @@ pub(crate) fn compute_array_length(item_typ: &CompositeType, elem_count: usize) } /// For a given value_id, allocates the necessary registers to hold it. -pub(crate) fn allocate_value( +pub(crate) fn allocate_value( value_id: ValueId, - brillig_context: &mut BrilligContext, + brillig_context: &mut BrilligContext, dfg: &DataFlowGraph, ) -> BrilligVariable { let typ = dfg.type_of_value(value_id); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index 743195957957..ae159f2c45c2 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,13 +1,12 @@ use acvm::{ acir::brillig::{BinaryFieldOp, BinaryIntOp, MemoryAddress, Opcode as BrilligOpcode}, acir::AcirField, - FieldElement, }; use crate::brillig::brillig_ir::artifact::GeneratedBrillig; /// Generates brillig bytecode which computes the inverse of its input if not null, and zero else. -pub(crate) fn directive_invert() -> GeneratedBrillig { +pub(crate) fn directive_invert() -> GeneratedBrillig { // We generate the following code: // fn invert(x : Field) -> Field { // 1/ x @@ -28,8 +27,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value zero in register (2) BrilligOpcode::Const { destination: zero_const, - value: FieldElement::from(0_usize), - bit_size: FieldElement::max_num_bits(), + value: F::from(0_usize), + bit_size: F::max_num_bits(), }, BrilligOpcode::BinaryFieldOp { op: BinaryFieldOp::Equals, @@ -42,8 +41,8 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { // Put value one in register (1) BrilligOpcode::Const { destination: one_const, - value: FieldElement::from(1_usize), - bit_size: FieldElement::max_num_bits(), + value: F::one(), + bit_size: F::max_num_bits(), }, // Divide 1 by the input, and set the result of the division into register (0) BrilligOpcode::BinaryFieldOp { @@ -68,13 +67,13 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { /// (a/b, a-a/b*b) /// } /// ``` -pub(crate) fn directive_quotient(bit_size: u32) -> GeneratedBrillig { +pub(crate) fn directive_quotient(bit_size: u32) -> GeneratedBrillig { // `a` is (0) (i.e register index 0) // `b` is (1) // TODO: The only difference between these implementations is the integer version will truncate the input to the `bit_size` via cast. // Once we deduplicate brillig functions then we can modify this so that fields and integers share the same quotient function. - if bit_size >= FieldElement::max_num_bits() { + if bit_size >= F::max_num_bits() { // Field version GeneratedBrillig { byte_code: vec![ diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs index 000d1230ece7..f0752c80c465 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_fn.rs @@ -28,7 +28,7 @@ pub(crate) struct FunctionContext { } impl FunctionContext { - /// Creates a new function context. It will compute the liveness of every variable. + /// Creates a new function context. It will allocate parameters for all blocks and compute the liveness of every variable. pub(crate) fn new(function: &Function) -> Self { let id = function.id(); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs index 491086e8c0f8..d17b15a13b55 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_slice_ops.rs @@ -372,7 +372,7 @@ mod tests { use crate::ssa::ir::map::Id; use crate::ssa::ssa_gen::Ssa; - fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { + fn create_test_environment() -> (Ssa, FunctionContext, BrilligContext) { let mut builder = FunctionBuilder::new("main".to_string(), Id::test_new(0)); builder.set_runtime(RuntimeType::Brillig); @@ -385,7 +385,7 @@ mod tests { fn create_brillig_block<'a>( function_context: &'a mut FunctionContext, - brillig_context: &'a mut BrilligContext, + brillig_context: &'a mut BrilligContext, ) -> BrilligBlock<'a> { let variables = BlockVariables::default(); BrilligBlock { 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 ebccf7a0bf19..80367d07635f 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 @@ -25,11 +25,13 @@ mod instructions; pub(crate) use instructions::BrilligBinaryOp; -use self::{artifact::BrilligArtifact, registers::BrilligRegistersContext}; +use self::{ + artifact::BrilligArtifact, debug_show::DebugToString, registers::BrilligRegistersContext, +}; use crate::ssa::ir::dfg::CallStack; use acvm::{ acir::brillig::{MemoryAddress, Opcode as BrilligOpcode}, - FieldElement, + AcirField, }; use debug_show::DebugShow; @@ -76,8 +78,8 @@ impl ReservedRegisters { /// Brillig context object that is used while constructing the /// Brillig bytecode. -pub(crate) struct BrilligContext { - obj: BrilligArtifact, +pub(crate) struct BrilligContext { + obj: BrilligArtifact, /// Tracks register allocations registers: BrilligRegistersContext, /// Context label, must be unique with respect to the function @@ -89,13 +91,11 @@ 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 { +impl BrilligContext { /// Initial context state - pub(crate) fn new(enable_debug_trace: bool) -> BrilligContext { + pub(crate) fn new(enable_debug_trace: bool) -> BrilligContext { BrilligContext { obj: BrilligArtifact::default(), registers: BrilligRegistersContext::new(), @@ -103,22 +103,16 @@ 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) { + fn push_opcode(&mut self, opcode: BrilligOpcode) { self.obj.push_opcode(opcode); } /// Returns the artifact - pub(crate) fn artifact(self) -> BrilligArtifact { + pub(crate) fn artifact(self) -> BrilligArtifact { self.obj } @@ -200,17 +194,17 @@ pub(crate) mod tests { } } - pub(crate) fn create_context() -> BrilligContext { + pub(crate) fn create_context() -> BrilligContext { let mut context = BrilligContext::new(true); context.enter_context("test"); context } pub(crate) fn create_entry_point_bytecode( - context: BrilligContext, + context: BrilligContext, arguments: Vec, returns: Vec, - ) -> GeneratedBrillig { + ) -> GeneratedBrillig { let artifact = context.artifact(); let mut entry_point_artifact = BrilligContext::new_entry_point_artifact(arguments, returns, "test".to_string()); 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 99e922c1580b..2d0bdb5955c0 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 @@ -1,4 +1,4 @@ -use acvm::{acir::brillig::Opcode as BrilligOpcode, FieldElement}; +use acvm::acir::brillig::Opcode as BrilligOpcode; use std::collections::{BTreeMap, HashMap}; use crate::ssa::ir::dfg::CallStack; @@ -18,8 +18,8 @@ pub(crate) enum BrilligParameter { /// The result of compiling and linking brillig artifacts. /// This is ready to run bytecode with attached metadata. #[derive(Debug, Default)] -pub(crate) struct GeneratedBrillig { - pub(crate) byte_code: Vec>, +pub(crate) struct GeneratedBrillig { + pub(crate) byte_code: Vec>, pub(crate) locations: BTreeMap, pub(crate) assert_messages: BTreeMap, } @@ -27,8 +27,8 @@ pub(crate) struct GeneratedBrillig { #[derive(Default, Debug, Clone)] /// Artifacts resulting from the compilation of a function into brillig byte code. /// It includes the bytecode of the function and all the metadata that allows linking with other functions. -pub(crate) struct BrilligArtifact { - pub(crate) byte_code: Vec>, +pub(crate) struct BrilligArtifact { + pub(crate) byte_code: Vec>, /// A map of bytecode positions to assertion messages. /// Some error messages (compiler intrinsics) are not emitted via revert data, /// instead, they are handled externally so they don't add size to user programs. @@ -73,9 +73,9 @@ pub(crate) type JumpInstructionPosition = OpcodeLocation; /// to their position in the bytecode. pub(crate) type UnresolvedJumpLocation = Label; -impl BrilligArtifact { +impl BrilligArtifact { /// Resolves all jumps and generates the final bytecode - pub(crate) fn finish(mut self) -> GeneratedBrillig { + pub(crate) fn finish(mut self) -> GeneratedBrillig { self.resolve_jumps(); GeneratedBrillig { byte_code: self.byte_code, @@ -94,7 +94,7 @@ impl BrilligArtifact { /// This method will offset the positions in the Brillig artifact to /// account for the fact that it is being appended to the end of this /// Brillig artifact (self). - pub(crate) fn link_with(&mut self, obj: &BrilligArtifact) { + pub(crate) fn link_with(&mut self, obj: &BrilligArtifact) { // Add the unresolved jumps of the linked function to this artifact. self.add_unresolved_jumps_and_calls(obj); @@ -128,7 +128,7 @@ impl BrilligArtifact { } /// Adds unresolved jumps & function calls from another artifact offset by the current opcode count in the artifact. - fn add_unresolved_jumps_and_calls(&mut self, obj: &BrilligArtifact) { + fn add_unresolved_jumps_and_calls(&mut self, obj: &BrilligArtifact) { let offset = self.index_of_next_opcode(); for (jump_label, jump_location) in &obj.unresolved_jumps { self.unresolved_jumps.push((jump_label + offset, jump_location.clone())); @@ -154,7 +154,7 @@ impl BrilligArtifact { } /// Adds a brillig instruction to the brillig byte code - pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: BrilligOpcode) { if !self.call_stack.is_empty() { self.locations.insert(self.index_of_next_opcode(), self.call_stack.clone()); } @@ -164,7 +164,7 @@ impl BrilligArtifact { /// Adds a unresolved jump to be fixed at the end of bytecode processing. pub(crate) fn add_unresolved_jump( &mut self, - jmp_instruction: BrilligOpcode, + jmp_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { assert!( @@ -178,7 +178,7 @@ impl BrilligArtifact { /// Adds a unresolved external call that will be fixed once linking has been done. pub(crate) fn add_unresolved_external_call( &mut self, - call_instruction: BrilligOpcode, + call_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { // TODO: Add a check to ensure that the opcode is a call instruction @@ -188,7 +188,7 @@ impl BrilligArtifact { } /// Returns true if the opcode is a jump instruction - fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { + fn is_jmp_instruction(instruction: &BrilligOpcode) -> bool { matches!( instruction, BrilligOpcode::JumpIfNot { .. } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs index 4ef279bd532c..a9c4f238491d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_binary.rs @@ -1,8 +1,8 @@ -use acvm::{acir::brillig::MemoryAddress, FieldElement}; +use acvm::{acir::brillig::MemoryAddress, AcirField}; -use super::{instructions::BrilligBinaryOp, BrilligContext}; +use super::{debug_show::DebugToString, instructions::BrilligBinaryOp, BrilligContext}; -impl BrilligContext { +impl BrilligContext { /// Utility method to perform a binary instruction with a constant value in place pub(crate) fn codegen_usize_op_in_place( &mut self, @@ -21,7 +21,7 @@ impl BrilligContext { op: BrilligBinaryOp, constant: usize, ) { - let const_register = self.make_usize_constant_instruction(FieldElement::from(constant)); + let const_register = self.make_usize_constant_instruction(F::from(constant)); self.memory_op_instruction(operand, const_register.address, destination, op); // Mark as no longer used for this purpose, frees for reuse self.deallocate_single_addr(const_register); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs index db65849a6b86..2d93cf70181f 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -1,10 +1,11 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; use super::{ - brillig_variable::BrilligVariable, BrilligBinaryOp, BrilligContext, ReservedRegisters, + brillig_variable::BrilligVariable, debug_show::DebugToString, BrilligBinaryOp, BrilligContext, + ReservedRegisters, }; -impl BrilligContext { +impl BrilligContext { /// Saves all of the registers that have been used up until this point. fn codegen_save_registers_of_vars(&mut self, vars: &[BrilligVariable]) -> Vec { // Save all of the used registers at this point in memory diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs index fee3a4501193..5741089a497c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_control_flow.rs @@ -1,12 +1,16 @@ -use acvm::acir::brillig::{HeapArray, MemoryAddress}; +use acvm::{ + acir::brillig::{HeapArray, MemoryAddress}, + AcirField, +}; use super::{ artifact::BrilligParameter, brillig_variable::{BrilligVariable, SingleAddrVariable}, + debug_show::DebugToString, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -impl BrilligContext { +impl BrilligContext { /// Codegens a return from the current function. /// /// For Brillig, the return is implicit, since there is no explicit return instruction. @@ -34,12 +38,14 @@ impl BrilligContext { self.stop_instruction(); } - /// This codegen will issue a loop that will iterate iteration_count times + /// This codegen will issue a loop do for (let iterator_register = 0; i < loop_bound; i += step) /// The body of the loop should be issued by the caller in the on_iteration closure. - pub(crate) fn codegen_loop(&mut self, iteration_count: MemoryAddress, on_iteration: F) - where - F: FnOnce(&mut BrilligContext, SingleAddrVariable), - { + pub(crate) fn codegen_loop_with_bound_and_step( + &mut self, + loop_bound: MemoryAddress, + step: MemoryAddress, + on_iteration: impl FnOnce(&mut BrilligContext, SingleAddrVariable), + ) { let iterator_register = self.make_usize_constant_instruction(0_u128.into()); let (loop_section, loop_label) = self.reserve_next_section_label(); @@ -47,13 +53,13 @@ impl BrilligContext { // Loop body - // Check if iterator < iteration_count + // Check if iterator < loop_bound let iterator_less_than_iterations = SingleAddrVariable { address: self.allocate_register(), bit_size: 1 }; self.memory_op_instruction( iterator_register.address, - iteration_count, + loop_bound, iterator_less_than_iterations.address, BrilligBinaryOp::LessThan, ); @@ -67,8 +73,13 @@ impl BrilligContext { // Call the on iteration function on_iteration(self, iterator_register); - // Increment the iterator register - self.codegen_usize_op_in_place(iterator_register.address, BrilligBinaryOp::Add, 1); + // Add step to the iterator register + self.memory_op_instruction( + iterator_register.address, + step, + iterator_register.address, + BrilligBinaryOp::Add, + ); self.jump_instruction(loop_label); @@ -80,6 +91,18 @@ impl BrilligContext { self.deallocate_single_addr(iterator_register); } + /// This codegen will issue a loop that will iterate iteration_count times + /// The body of the loop should be issued by the caller in the on_iteration closure. + pub(crate) fn codegen_loop( + &mut self, + iteration_count: MemoryAddress, + on_iteration: impl FnOnce(&mut BrilligContext, SingleAddrVariable), + ) { + let step = self.make_usize_constant_instruction(1_u128.into()); + self.codegen_loop_with_bound_and_step(iteration_count, step.address, on_iteration); + self.deallocate_single_addr(step); + } + /// This codegen will issue an if-then branch that will check if the condition is true /// and if so, perform the instructions given in `f(self, true)` and otherwise perform the /// instructions given in `f(self, false)`. A boolean is passed instead of two separate @@ -87,7 +110,7 @@ impl BrilligContext { pub(crate) fn codegen_branch( &mut self, condition: MemoryAddress, - mut f: impl FnMut(&mut BrilligContext, bool), + mut f: impl FnMut(&mut BrilligContext, bool), ) { // Reserve 3 sections let (then_section, then_label) = self.reserve_next_section_label(); @@ -112,7 +135,7 @@ impl BrilligContext { pub(crate) fn codegen_if( &mut self, condition: MemoryAddress, - f: impl FnOnce(&mut BrilligContext), + f: impl FnOnce(&mut BrilligContext), ) { let (end_section, end_label) = self.reserve_next_section_label(); let (then_section, then_label) = self.reserve_next_section_label(); @@ -130,7 +153,7 @@ impl BrilligContext { pub(crate) fn codegen_if_not( &mut self, condition: MemoryAddress, - f: impl FnOnce(&mut BrilligContext), + f: impl FnOnce(&mut BrilligContext), ) { let (end_section, end_label) = self.reserve_next_section_label(); @@ -156,7 +179,7 @@ impl BrilligContext { let revert_data = HeapArray { pointer: ctx.allocate_register(), // + 1 due to the revert data id being the first item returned - size: BrilligContext::flattened_tuple_size(&revert_data_types) + 1, + size: Self::flattened_tuple_size(&revert_data_types) + 1, }; ctx.codegen_allocate_fixed_length_array(revert_data.pointer, revert_data.size); @@ -169,7 +192,7 @@ impl BrilligContext { for (revert_variable, revert_param) in revert_data_items.into_iter().zip(revert_data_types.into_iter()) { - let flattened_size = BrilligContext::flattened_size(&revert_param); + let flattened_size = Self::flattened_size(&revert_param); match revert_param { BrilligParameter::SingleAddr(_) => { ctx.store_instruction( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs index 42f3b34aea0c..b1cb2b197648 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_intrinsic.rs @@ -1,15 +1,15 @@ use acvm::{ acir::brillig::{BlackBoxOp, HeapArray}, acir::AcirField, - FieldElement, }; use super::{ brillig_variable::{BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, }; -impl BrilligContext { +impl BrilligContext { /// Codegens a truncation of a value to the given bit size pub(crate) fn codegen_truncate( &mut self, @@ -43,7 +43,7 @@ impl BrilligContext { big_endian: bool, limb_bit_size: u32, ) { - assert!(source_field.bit_size == FieldElement::max_num_bits()); + assert!(source_field.bit_size == F::max_num_bits()); self.usize_const_instruction(target_vector.size, limb_count.into()); self.usize_const_instruction(target_vector.rc, 1_usize.into()); @@ -55,12 +55,10 @@ impl BrilligContext { output: HeapArray { pointer: target_vector.pointer, size: limb_count }, }); - let limb_field = - SingleAddrVariable::new(self.allocate_register(), FieldElement::max_num_bits()); - + let limb_field = SingleAddrVariable::new(self.allocate_register(), F::max_num_bits()); let limb_casted = SingleAddrVariable::new(self.allocate_register(), limb_bit_size); - if limb_bit_size != FieldElement::max_num_bits() { + if limb_bit_size != F::max_num_bits() { self.codegen_loop(target_vector.size, |ctx, iterator_register| { // Read the limb ctx.codegen_array_get(target_vector.pointer, iterator_register, limb_field.address); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs index 15761113f517..81c1c3847b14 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_memory.rs @@ -1,13 +1,14 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; use crate::brillig::brillig_ir::BrilligBinaryOp; use super::{ brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; -impl BrilligContext { +impl BrilligContext { /// Allocates an array of size `size` and stores the pointer to the array /// in `pointer_register` pub(crate) fn codegen_allocate_fixed_length_array( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs index 1c30f0f848fd..943b0b9d7a35 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_stack.rs @@ -1,8 +1,8 @@ -use acvm::acir::brillig::MemoryAddress; +use acvm::{acir::brillig::MemoryAddress, AcirField}; -use super::BrilligContext; +use super::{debug_show::DebugToString, BrilligContext}; -impl BrilligContext { +impl BrilligContext { /// This function moves values from a set of registers to another set of registers. /// It first moves all sources to new allocated registers to avoid overwriting. pub(crate) fn codegen_mov_registers_to_registers( diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index def91f82bfd7..b258905d657e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -8,7 +8,7 @@ use acvm::{ }; /// Trait for converting values into debug-friendly strings. -trait DebugToString { +pub(crate) trait DebugToString { fn debug_to_string(&self) -> String; } @@ -59,8 +59,8 @@ impl DebugToString for BrilligBinaryOp { BrilligBinaryOp::UnsignedDiv => "/".into(), BrilligBinaryOp::LessThan => "<".into(), BrilligBinaryOp::LessThanEquals => "<=".into(), - BrilligBinaryOp::And => "&&".into(), - BrilligBinaryOp::Or => "||".into(), + BrilligBinaryOp::And => "&".into(), + BrilligBinaryOp::Or => "|".into(), BrilligBinaryOp::Xor => "^".into(), BrilligBinaryOp::Shl => "<<".into(), BrilligBinaryOp::Shr => ">>".into(), @@ -169,7 +169,7 @@ impl DebugShow { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: FieldElement) { + pub(crate) fn const_instruction(&self, result: MemoryAddress, constant: F) { debug_println!(self.enable_debug_trace, " CONST {} = {}", result, constant); } 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 9023183eb365..d10e31533dcf 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 @@ -1,21 +1,21 @@ use super::{ artifact::{BrilligArtifact, BrilligParameter}, brillig_variable::{BrilligArray, BrilligVariable, BrilligVector, SingleAddrVariable}, - debug_show::DebugShow, + debug_show::{DebugShow, DebugToString}, registers::BrilligRegistersContext, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -use acvm::{acir::brillig::MemoryAddress, acir::AcirField, FieldElement}; +use acvm::{acir::brillig::MemoryAddress, acir::AcirField}; pub(crate) const MAX_STACK_SIZE: usize = 2048; -impl BrilligContext { +impl BrilligContext { /// Creates an entry point artifact that will jump to the function label provided. pub(crate) fn new_entry_point_artifact( arguments: Vec, return_parameters: Vec, target_function: T, - ) -> BrilligArtifact { + ) -> BrilligArtifact { let mut context = BrilligContext { obj: BrilligArtifact::default(), registers: BrilligRegistersContext::new(), @@ -23,7 +23,6 @@ impl BrilligContext { section_label: 0, next_section: 1, debug_show: DebugShow::new(false), - bigint_new_id: 0, }; context.codegen_entry_point(&arguments, &return_parameters); @@ -42,8 +41,8 @@ impl BrilligContext { arguments: &[BrilligParameter], return_parameters: &[BrilligParameter], ) { - let calldata_size = BrilligContext::flattened_tuple_size(arguments); - let return_data_size = BrilligContext::flattened_tuple_size(return_parameters); + let calldata_size = Self::flattened_tuple_size(arguments); + let return_data_size = Self::flattened_tuple_size(return_parameters); // Set initial value of stack pointer: MAX_STACK_SIZE + calldata_size + return_data_size self.const_instruction( @@ -74,7 +73,7 @@ impl BrilligContext { let pointer_to_the_array_in_calldata = self.make_usize_constant_instruction(current_calldata_pointer.into()); let rc_register = self.make_usize_constant_instruction(1_usize.into()); - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let var = BrilligVariable::BrilligArray(BrilligArray { pointer: pointer_to_the_array_in_calldata.address, size: flattened_size, @@ -88,7 +87,7 @@ impl BrilligContext { let pointer_to_the_array_in_calldata = self.make_usize_constant_instruction(current_calldata_pointer.into()); - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let size_register = self.make_usize_constant_instruction(flattened_size.into()); let rc_register = self.make_usize_constant_instruction(1_usize.into()); @@ -121,7 +120,7 @@ impl BrilligContext { BrilligVariable::BrilligVector(vector), BrilligParameter::Slice(item_type, item_count), ) => { - let flattened_size = BrilligContext::flattened_size(argument); + let flattened_size = Self::flattened_size(argument); let deflattened_address = self.deflatten_array(item_type, flattened_size, vector.pointer); @@ -139,7 +138,7 @@ impl BrilligContext { } fn copy_and_cast_calldata(&mut self, arguments: &[BrilligParameter]) { - let calldata_size = BrilligContext::flattened_tuple_size(arguments); + let calldata_size = Self::flattened_tuple_size(arguments); self.calldata_copy_instruction(MemoryAddress(MAX_STACK_SIZE), calldata_size, 0); fn flat_bit_sizes(param: &BrilligParameter) -> Box + '_> { @@ -154,7 +153,7 @@ impl BrilligContext { for (i, bit_size) in arguments.iter().flat_map(flat_bit_sizes).enumerate() { // Calldatacopy tags everything with field type, so when downcast when necessary - if bit_size < FieldElement::max_num_bits() { + if bit_size < F::max_num_bits() { self.cast_instruction( SingleAddrVariable::new(MemoryAddress(MAX_STACK_SIZE + i), bit_size), SingleAddrVariable::new_field(MemoryAddress(MAX_STACK_SIZE + i)), @@ -169,7 +168,7 @@ impl BrilligContext { BrilligParameter::SingleAddr(_) => 1, BrilligParameter::Array(item_types, item_count) | BrilligParameter::Slice(item_types, item_count) => { - let item_size: usize = item_types.iter().map(BrilligContext::flattened_size).sum(); + let item_size: usize = item_types.iter().map(Self::flattened_size).sum(); item_count * item_size } } @@ -177,7 +176,7 @@ impl BrilligContext { /// Computes the size of a parameter if it was flattened pub(super) fn flattened_tuple_size(tuple: &[BrilligParameter]) -> usize { - tuple.iter().map(BrilligContext::flattened_size).sum() + tuple.iter().map(Self::flattened_size).sum() } /// Computes the size of a parameter if it was flattened @@ -193,12 +192,12 @@ impl BrilligContext { item_count: usize, flattened_array_pointer: MemoryAddress, ) -> MemoryAddress { - if BrilligContext::has_nested_arrays(item_type) { + if Self::has_nested_arrays(item_type) { let movement_register = self.allocate_register(); let deflattened_array_pointer = self.allocate_register(); let target_item_size = item_type.len(); - let source_item_size = BrilligContext::flattened_tuple_size(item_type); + let source_item_size = Self::flattened_tuple_size(item_type); self.codegen_allocate_fixed_length_array( deflattened_array_pointer, @@ -276,7 +275,7 @@ impl BrilligContext { .into_iter() .for_each(|register| self.deallocate_register(register)); - source_offset += BrilligContext::flattened_size(subitem); + source_offset += Self::flattened_size(subitem); } BrilligParameter::Slice(..) => unreachable!("ICE: Cannot deflatten slices"), } @@ -328,8 +327,8 @@ impl BrilligContext { .collect(); // Now, we deflatten the return data - let calldata_size = BrilligContext::flattened_tuple_size(arguments); - let return_data_size = BrilligContext::flattened_tuple_size(return_parameters); + let calldata_size = Self::flattened_tuple_size(arguments); + let return_data_size = Self::flattened_tuple_size(return_parameters); // Return data has a reserved space after calldata let return_data_offset = MAX_STACK_SIZE + calldata_size; @@ -357,7 +356,7 @@ impl BrilligContext { ); self.deallocate_single_addr(pointer_to_return_data); - return_data_index += BrilligContext::flattened_size(return_param); + return_data_index += Self::flattened_size(return_param); } BrilligParameter::Slice(..) => { unreachable!("ICE: Cannot return slices from brillig entrypoints") @@ -376,12 +375,11 @@ impl BrilligContext { flattened_array_pointer: MemoryAddress, deflattened_array_pointer: MemoryAddress, ) { - if BrilligContext::has_nested_arrays(item_type) { + if Self::has_nested_arrays(item_type) { let movement_register = self.allocate_register(); let source_item_size = item_type.len(); - let target_item_size: usize = - item_type.iter().map(BrilligContext::flattened_size).sum(); + let target_item_size: usize = item_type.iter().map(Self::flattened_size).sum(); for item_index in 0..item_count { let source_item_base_index = item_index * source_item_size; @@ -462,7 +460,7 @@ impl BrilligContext { .into_iter() .for_each(|register| self.deallocate_register(register)); - target_offset += BrilligContext::flattened_size(subitem); + target_offset += Self::flattened_size(subitem); } BrilligParameter::Slice(..) => unreachable!("ICE: Cannot flatten slices"), } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index 03a9216b73aa..a614f93fa30d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -10,12 +10,13 @@ use acvm::{ use super::{ artifact::UnresolvedJumpLocation, brillig_variable::{BrilligArray, BrilligVector, SingleAddrVariable}, + debug_show::DebugToString, BrilligContext, ReservedRegisters, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE, }; /// Low level instructions of the brillig IR, used by the brillig ir codegens and brillig_gen /// Printed using debug_slow -impl BrilligContext { +impl BrilligContext { /// Processes a binary instruction according `operation`. /// /// This method will compute lhs rhs @@ -42,8 +43,7 @@ impl BrilligContext { ) { self.debug_show.not_instruction(input.address, input.bit_size, result.address); // Compile !x as ((-1) - x) - let u_max = FieldElement::from(2_i128).pow(&FieldElement::from(input.bit_size as i128)) - - FieldElement::one(); + let u_max = F::from(2_u128).pow(&F::from(input.bit_size as u128)) - F::one(); let max = self.make_constant(u_max, input.bit_size); self.binary(max, input, result, BrilligBinaryOp::Sub); @@ -63,7 +63,7 @@ impl BrilligContext { SingleAddrVariable::new_usize(rhs), SingleAddrVariable::new( destination, - BrilligContext::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), + Self::binary_result_bit_size(op, BRILLIG_MEMORY_ADDRESSING_BIT_SIZE), ), op, ); @@ -77,8 +77,7 @@ impl BrilligContext { operation: BrilligBinaryOp, ) { let is_field_op = lhs.bit_size == FieldElement::max_num_bits(); - let expected_result_bit_size = - BrilligContext::binary_result_bit_size(operation, lhs.bit_size); + let expected_result_bit_size = Self::binary_result_bit_size(operation, lhs.bit_size); assert!( result.bit_size == expected_result_bit_size, "Expected result bit size to be {}, got {} for operation {:?}", @@ -213,7 +212,7 @@ impl BrilligContext { /// Adds a unresolved `Jump` to the bytecode. fn add_unresolved_jump( &mut self, - jmp_instruction: BrilligOpcode, + jmp_instruction: BrilligOpcode, destination: UnresolvedJumpLocation, ) { self.obj.add_unresolved_jump(jmp_instruction, destination); @@ -369,12 +368,12 @@ impl BrilligContext { } /// Stores the value of `constant` in the `result` register - pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: FieldElement) { + pub(crate) fn const_instruction(&mut self, result: SingleAddrVariable, constant: F) { self.debug_show.const_instruction(result.address, constant); self.constant(result, constant); } - fn constant(&mut self, result: SingleAddrVariable, constant: FieldElement) { + fn constant(&mut self, result: SingleAddrVariable, constant: F) { assert!( result.bit_size >= constant.num_bits(), "Constant {} does not fit in bit size {}", @@ -382,10 +381,10 @@ impl BrilligContext { result.bit_size ); if result.bit_size > 128 && constant.num_bits() > 128 { - let high = FieldElement::from_be_bytes_reduce( + let high = F::from_be_bytes_reduce( constant.to_be_bytes().get(0..16).expect("FieldElement::to_be_bytes() too short!"), ); - let low = FieldElement::from(constant.to_u128()); + let low = F::from(constant.to_u128()); let high_register = SingleAddrVariable::new(self.allocate_register(), 254); let low_register = SingleAddrVariable::new(self.allocate_register(), 254); let intermediate_register = SingleAddrVariable::new(self.allocate_register(), 254); @@ -393,7 +392,7 @@ impl BrilligContext { self.constant(low_register, low); // I want to multiply high by 2^128, but I can't get that big constant in. // So I'll multiply by 2^64 twice. - self.constant(intermediate_register, FieldElement::from(1_u128 << 64)); + self.constant(intermediate_register, F::from(1_u128 << 64)); self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); self.binary(high_register, intermediate_register, high_register, BrilligBinaryOp::Mul); // Now we can add. @@ -411,18 +410,14 @@ impl BrilligContext { } } - pub(crate) fn usize_const_instruction( - &mut self, - result: MemoryAddress, - constant: FieldElement, - ) { + pub(crate) fn usize_const_instruction(&mut self, result: MemoryAddress, constant: F) { self.const_instruction(SingleAddrVariable::new_usize(result), constant); } /// Returns a register which holds the value of a constant pub(crate) fn make_constant_instruction( &mut self, - constant: FieldElement, + constant: F, bit_size: u32, ) -> SingleAddrVariable { let var = SingleAddrVariable::new(self.allocate_register(), bit_size); @@ -430,17 +425,14 @@ impl BrilligContext { var } - fn make_constant(&mut self, constant: FieldElement, bit_size: u32) -> SingleAddrVariable { + fn make_constant(&mut self, constant: F, bit_size: u32) -> SingleAddrVariable { let var = SingleAddrVariable::new(self.allocate_register(), bit_size); self.constant(var, constant); var } /// Returns a register which holds the value of an usize constant - pub(crate) fn make_usize_constant_instruction( - &mut self, - constant: FieldElement, - ) -> SingleAddrVariable { + pub(crate) fn make_usize_constant_instruction(&mut self, constant: F) -> SingleAddrVariable { let register = self.allocate_register(); self.usize_const_instruction(register, constant); SingleAddrVariable::new_usize(register) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs index f756f06aa691..ae506462b257 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/registers.rs @@ -82,7 +82,7 @@ impl BrilligRegistersContext { } } -impl BrilligContext { +impl BrilligContext { /// Returns the i'th register after the reserved ones pub(crate) fn register(&self, i: usize) -> MemoryAddress { MemoryAddress::from(ReservedRegisters::NUM_RESERVED_REGISTERS + i) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs index eda1ac97c1e8..70c0959517bd 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/mod.rs @@ -1,6 +1,8 @@ pub(crate) mod brillig_gen; pub(crate) mod brillig_ir; +use acvm::FieldElement; + use self::{ brillig_gen::{brillig_fn::FunctionContext, convert_ssa_function}, brillig_ir::artifact::{BrilligArtifact, Label}, @@ -16,7 +18,7 @@ use std::collections::{BTreeSet, HashMap}; #[derive(Default)] pub struct Brillig { /// Maps SSA function labels to their brillig artifact - ssa_function_to_brillig: HashMap, + ssa_function_to_brillig: HashMap>, } impl Brillig { @@ -27,7 +29,10 @@ impl Brillig { } /// Finds a brillig function artifact by its function label - pub(crate) fn find_by_function_label(&self, function_label: Label) -> Option<&BrilligArtifact> { + pub(crate) fn find_by_function_label( + &self, + function_label: Label, + ) -> Option<&BrilligArtifact> { self.ssa_function_to_brillig.iter().find_map(|(function_id, obj)| { if FunctionContext::function_id_to_function_label(*function_id) == function_label { Some(obj) @@ -39,7 +44,7 @@ impl Brillig { } impl std::ops::Index for Brillig { - type Output = BrilligArtifact; + type Output = BrilligArtifact; fn index(&self, id: FunctionId) -> &Self::Output { &self.ssa_function_to_brillig[&id] } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs index dd63a254a18b..0879056ad36e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs @@ -35,6 +35,12 @@ pub enum RuntimeError { UnknownLoopBound { call_stack: CallStack }, #[error("Argument is not constant")] AssertConstantFailed { call_stack: CallStack }, + #[error("The static_assert message is not constant")] + StaticAssertDynamicMessage { call_stack: CallStack }, + #[error("Argument is dynamic")] + StaticAssertDynamicPredicate { call_stack: CallStack }, + #[error("Argument is false")] + StaticAssertFailed { call_stack: CallStack }, #[error("Nested slices are not supported")] NestedSlice { call_stack: CallStack }, #[error("Big Integer modulus do no match")] @@ -120,6 +126,9 @@ impl RuntimeError { | RuntimeError::UnInitialized { call_stack, .. } | RuntimeError::UnknownLoopBound { call_stack } | RuntimeError::AssertConstantFailed { call_stack } + | RuntimeError::StaticAssertDynamicMessage { call_stack } + | RuntimeError::StaticAssertDynamicPredicate { call_stack } + | RuntimeError::StaticAssertFailed { call_stack } | RuntimeError::IntegerOutOfBounds { call_stack, .. } | RuntimeError::UnsupportedIntegerSize { call_stack, .. } | RuntimeError::NestedSlice { call_stack, .. } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 80a63f223e73..0e0c3f1e6310 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -48,47 +48,54 @@ pub mod ssa_gen; /// 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, + options: &SsaEvaluatorOptions, ) -> Result { let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); let ssa_gen_span_guard = ssa_gen_span.enter(); - let ssa = SsaBuilder::new(program, print_passes, force_brillig_output, print_timings)? - .run_pass(Ssa::defunctionalize, "After Defunctionalization:") - .run_pass(Ssa::remove_paired_rc, "After Removing Paired rc_inc & rc_decs:") - .run_pass(Ssa::separate_runtime, "After Runtime Separation:") - .run_pass(Ssa::resolve_is_unconstrained, "After Resolving IsUnconstrained:") - .run_pass(Ssa::inline_functions, "After Inlining:") - // Run mem2reg with the CFG separated into blocks - .run_pass(Ssa::mem2reg, "After Mem2Reg:") - .run_pass(Ssa::as_slice_optimization, "After `as_slice` optimization") - .try_run_pass(Ssa::evaluate_assert_constant, "After Assert Constant:")? - .try_run_pass(Ssa::unroll_loops_iteratively, "After Unrolling:")? - .run_pass(Ssa::simplify_cfg, "After Simplifying:") - .run_pass(Ssa::flatten_cfg, "After Flattening:") - .run_pass(Ssa::remove_bit_shifts, "After Removing Bit Shifts:") - // Run mem2reg once more with the flattened CFG to catch any remaining loads/stores - .run_pass(Ssa::mem2reg, "After Mem2Reg:") - // Run the inlining pass again to handle functions with `InlineType::NoPredicates`. - // Before flattening is run, we treat functions marked with the `InlineType::NoPredicates` as an entry point. - // This pass must come immediately following `mem2reg` as the succeeding passes - // may create an SSA which inlining fails to handle. - .run_pass(Ssa::inline_functions_with_no_predicates, "After Inlining:") - .run_pass(Ssa::remove_if_else, "After Remove IfElse:") - .run_pass(Ssa::fold_constants, "After Constant Folding:") - .run_pass(Ssa::remove_enable_side_effects, "After EnableSideEffects removal:") - .run_pass(Ssa::fold_constants_using_constraints, "After Constraint Folding:") - .run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:") - .run_pass(Ssa::array_set_optimization, "After Array Set Optimizations:") - .finish(); - - let brillig = time("SSA to Brillig", print_timings, || ssa.to_brillig(print_brillig_trace)); + let ssa = SsaBuilder::new( + program, + options.enable_ssa_logging, + options.force_brillig_output, + options.print_codegen_timings, + )? + .run_pass(Ssa::defunctionalize, "After Defunctionalization:") + .run_pass(Ssa::remove_paired_rc, "After Removing Paired rc_inc & rc_decs:") + .run_pass(Ssa::separate_runtime, "After Runtime Separation:") + .run_pass(Ssa::resolve_is_unconstrained, "After Resolving IsUnconstrained:") + .run_pass(Ssa::inline_functions, "After Inlining:") + // Run mem2reg with the CFG separated into blocks + .run_pass(Ssa::mem2reg, "After Mem2Reg:") + .run_pass(Ssa::as_slice_optimization, "After `as_slice` optimization") + .try_run_pass( + Ssa::evaluate_static_assert_and_assert_constant, + "After `static_assert` and `assert_constant`:", + )? + .try_run_pass(Ssa::unroll_loops_iteratively, "After Unrolling:")? + .run_pass(Ssa::simplify_cfg, "After Simplifying:") + .run_pass(Ssa::flatten_cfg, "After Flattening:") + .run_pass(Ssa::remove_bit_shifts, "After Removing Bit Shifts:") + // Run mem2reg once more with the flattened CFG to catch any remaining loads/stores + .run_pass(Ssa::mem2reg, "After Mem2Reg:") + // Run the inlining pass again to handle functions with `InlineType::NoPredicates`. + // Before flattening is run, we treat functions marked with the `InlineType::NoPredicates` as an entry point. + // This pass must come immediately following `mem2reg` as the succeeding passes + // may create an SSA which inlining fails to handle. + .run_pass(Ssa::inline_functions_with_no_predicates, "After Inlining:") + .run_pass(Ssa::remove_if_else, "After Remove IfElse:") + .run_pass(Ssa::fold_constants, "After Constant Folding:") + .run_pass(Ssa::remove_enable_side_effects, "After EnableSideEffects removal:") + .run_pass(Ssa::fold_constants_using_constraints, "After Constraint Folding:") + .run_pass(Ssa::dead_instruction_elimination, "After Dead Instruction Elimination:") + .run_pass(Ssa::array_set_optimization, "After Array Set Optimizations:") + .finish(); + + let brillig = time("SSA to Brillig", options.print_codegen_timings, || { + ssa.to_brillig(options.enable_brillig_logging) + }); drop(ssa_gen_span_guard); - time("SSA to ACIR", print_timings, || ssa.into_acir(&brillig)) + time("SSA to ACIR", options.print_codegen_timings, || ssa.into_acir(&brillig)) } // Helper to time SSA passes @@ -144,17 +151,26 @@ impl SsaProgramArtifact { } } +pub struct SsaEvaluatorOptions { + /// Emit debug information for the intermediate SSA IR + pub enable_ssa_logging: bool, + + pub enable_brillig_logging: bool, + + /// Force Brillig output (for step debugging) + pub force_brillig_output: bool, + + /// Pretty print benchmark times of each code generation pass + pub print_codegen_timings: bool, +} + /// Compiles the [`Program`] into [`ACIR``][acvm::acir::circuit::Program]. /// -/// The output ACIR is is backend-agnostic and so must go through a transformation pass before usage in proof generation. -#[allow(clippy::type_complexity)] +/// The output ACIR is backend-agnostic and so must go through a transformation pass before usage in proof generation. #[tracing::instrument(level = "trace", skip_all)] pub fn create_program( program: Program, - enable_ssa_logging: bool, - enable_brillig_logging: bool, - force_brillig_output: bool, - print_codegen_timings: bool, + options: &SsaEvaluatorOptions, ) -> Result { let debug_variables = program.debug_variables.clone(); let debug_types = program.debug_types.clone(); @@ -163,13 +179,7 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let (generated_acirs, generated_brillig, error_types) = optimize_into_acir( - program, - enable_ssa_logging, - enable_brillig_logging, - force_brillig_output, - print_codegen_timings, - )?; + let (generated_acirs, generated_brillig, error_types) = optimize_into_acir(program, options)?; assert_eq!( generated_acirs.len(), func_sigs.len(), @@ -206,7 +216,7 @@ pub struct SsaCircuitArtifact { } fn convert_generated_acir_into_circuit( - mut generated_acir: GeneratedAcir, + mut generated_acir: GeneratedAcir, func_sig: FunctionSignature, recursive: bool, debug_variables: DebugVariables, 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 ac7f2c096877..928a7b105eae 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 @@ -20,7 +20,6 @@ use acvm::{ native_types::{Expression, Witness}, BlackBoxFunc, }, - FieldElement, }; use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; @@ -48,12 +47,12 @@ impl AcirType { } /// Returns the bit size of the underlying type - pub(crate) fn bit_size(&self) -> u32 { + pub(crate) fn bit_size(&self) -> u32 { match self { AcirType::NumericType(numeric_type) => match numeric_type { NumericType::Signed { bit_size } => *bit_size, NumericType::Unsigned { bit_size } => *bit_size, - NumericType::NativeField => FieldElement::max_num_bits(), + NumericType::NativeField => F::max_num_bits(), }, AcirType::Array(_, _) => unreachable!("cannot fetch bit size of array type"), } @@ -106,13 +105,13 @@ impl From for AcirType { /// Context object which holds the relationship between /// `Variables`(AcirVar) and types such as `Expression` and `Witness` /// which are placed into ACIR. -pub(crate) struct AcirContext { +pub(crate) struct AcirContext { /// Two-way map that links `AcirVar` to `AcirVarData`. /// /// The vars object is an instance of the `TwoWayMap`, which provides a bidirectional mapping between `AcirVar` and `AcirVarData`. - vars: HashMap, + vars: HashMap>, - constant_witnesses: HashMap, + constant_witnesses: HashMap, /// An in-memory representation of ACIR. /// @@ -121,13 +120,13 @@ pub(crate) struct AcirContext { /// For example, If one was to add two Variables together, /// then the `acir_ir` will be populated to assert this /// addition. - acir_ir: GeneratedAcir, + acir_ir: GeneratedAcir, /// The BigIntContext, used to generate identifiers for BigIntegers big_int_ctx: BigIntContext, } -impl AcirContext { +impl AcirContext { pub(crate) fn current_witness_index(&self) -> Witness { self.acir_ir.current_witness_index() } @@ -148,7 +147,7 @@ impl AcirContext { } /// Adds a constant to the context and assigns a Variable to represent it - pub(crate) fn add_constant(&mut self, constant: impl Into) -> AcirVar { + pub(crate) fn add_constant(&mut self, constant: impl Into) -> AcirVar { let constant_data = AcirVarData::Const(constant.into()); self.add_data(constant_data) } @@ -156,7 +155,7 @@ impl AcirContext { /// Returns the constant represented by the given variable. /// /// Panics: if the variable does not represent a constant. - pub(crate) fn constant(&self, var: AcirVar) -> FieldElement { + pub(crate) fn constant(&self, var: AcirVar) -> &F { self.vars[&var].as_constant().expect("ICE - expected the variable to be a constant value") } @@ -270,10 +269,7 @@ impl AcirContext { } /// Converts an [`AcirVar`] to an [`Expression`] - pub(crate) fn var_to_expression( - &self, - var: AcirVar, - ) -> Result, InternalError> { + pub(crate) fn var_to_expression(&self, var: AcirVar) -> Result, InternalError> { let var_data = match self.vars.get(&var) { Some(var_data) => var_data, None => { @@ -408,7 +404,7 @@ impl AcirContext { if lhs_expr == rhs_expr { // x ^ x == 0 - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); return Ok(zero); } else if lhs_expr.is_zero() { // 0 ^ x == x @@ -418,14 +414,14 @@ impl AcirContext { return Ok(lhs); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans. // // a ^ b == a + b - 2*a*b let prod = self.mul_var(lhs, rhs)?; let sum = self.add_var(lhs, rhs)?; - self.add_mul_var(sum, -FieldElement::from(2_i128), prod) + self.add_mul_var(sum, -F::from(2_u128), prod) } else { let inputs = vec![AcirValue::Var(lhs, typ.clone()), AcirValue::Var(rhs, typ)]; let outputs = self.black_box_function(BlackBoxFunc::XOR, inputs, 1)?; @@ -448,11 +444,11 @@ impl AcirContext { return Ok(lhs); } else if lhs_expr.is_zero() || rhs_expr.is_zero() { // x & 0 == 0 and 0 & x == 0 - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); return Ok(zero); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans. self.mul_var(lhs, rhs) @@ -480,7 +476,7 @@ impl AcirContext { return Ok(lhs); } - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); if bit_size == 1 { // Operands are booleans // a + b - ab @@ -502,7 +498,7 @@ impl AcirContext { &mut self, lhs: AcirVar, rhs: AcirVar, - assert_message: Option>, + assert_message: Option>, ) -> Result<(), RuntimeError> { let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -531,7 +527,7 @@ impl AcirContext { pub(crate) fn vars_to_expressions_or_memory( &self, values: &[AcirValue], - ) -> Result>, RuntimeError> { + ) -> Result>, RuntimeError> { let mut result = Vec::with_capacity(values.len()); for value in values { match value { @@ -597,7 +593,7 @@ impl AcirContext { (AcirVarData::Const(constant), _) | (_, AcirVarData::Const(constant)) if constant.is_zero() => { - self.add_constant(FieldElement::zero()) + self.add_constant(F::zero()) } (AcirVarData::Const(lhs_constant), AcirVarData::Const(rhs_constant)) => { @@ -615,7 +611,7 @@ impl AcirContext { } (AcirVarData::Witness(lhs_witness), AcirVarData::Witness(rhs_witness)) => { let mut expr = Expression::default(); - expr.push_multiplication_term(FieldElement::one(), lhs_witness, rhs_witness); + expr.push_multiplication_term(F::one(), lhs_witness, rhs_witness); self.add_data(AcirVarData::Expr(expr)) } (AcirVarData::Expr(expression), AcirVarData::Witness(witness)) @@ -681,12 +677,7 @@ impl AcirContext { /// Adds a new Variable to context whose value will /// be constrained to be the expression `lhs + k * rhs` - fn add_mul_var( - &mut self, - lhs: AcirVar, - k: FieldElement, - rhs: AcirVar, - ) -> Result { + fn add_mul_var(&mut self, lhs: AcirVar, k: F, rhs: AcirVar) -> Result { let k_var = self.add_constant(k); let intermediate = self.mul_var(k_var, rhs)?; @@ -695,7 +686,7 @@ impl AcirContext { /// Adds a new variable that is constrained to be the logical NOT of `x`. pub(crate) fn not_var(&mut self, x: AcirVar, typ: AcirType) -> Result { - let bit_size = typ.bit_size(); + let bit_size = typ.bit_size::(); // Subtracting from max flips the bits let max = self.add_constant((1_u128 << bit_size) - 1); self.sub_var(max, x) @@ -709,8 +700,8 @@ impl AcirContext { bit_size: u32, predicate: AcirVar, ) -> Result<(AcirVar, AcirVar), RuntimeError> { - let zero = self.add_constant(FieldElement::zero()); - let one = self.add_constant(FieldElement::one()); + let zero = self.add_constant(F::zero()); + let one = self.add_constant(F::one()); let lhs_expr = self.var_to_expression(lhs)?; let rhs_expr = self.var_to_expression(rhs)?; @@ -829,7 +820,7 @@ impl AcirContext { // Avoids overflow: 'q*b+r < 2^max_q_bits*2^max_rhs_bits' let mut avoid_overflow = false; - if max_q_bits + max_rhs_bits >= FieldElement::max_num_bits() - 1 { + if max_q_bits + max_rhs_bits >= F::max_num_bits() - 1 { // q*b+r can overflow; we avoid this when b is constant if rhs_expr.is_const() { avoid_overflow = true; @@ -843,16 +834,16 @@ impl AcirContext { if avoid_overflow { // we compute q0 = p/rhs let rhs_big = BigUint::from_bytes_be(&rhs_const.to_be_bytes()); - let q0_big = FieldElement::modulus() / &rhs_big; - let q0 = FieldElement::from_be_bytes_reduce(&q0_big.to_bytes_be()); + let q0_big = F::modulus() / &rhs_big; + let q0 = F::from_be_bytes_reduce(&q0_big.to_bytes_be()); let q0_var = self.add_constant(q0); // when q == q0, b*q+r can overflow so we need to bound r to avoid the overflow. let size_predicate = self.eq_var(q0_var, quotient_var)?; let predicate = self.mul_var(size_predicate, predicate)?; // Ensure that there is no overflow, under q == q0 predicate - let max_r_big = FieldElement::modulus() - q0_big * rhs_big; - let max_r = FieldElement::from_be_bytes_reduce(&max_r_big.to_bytes_be()); + let max_r_big = F::modulus() - q0_big * rhs_big; + let max_r = F::from_be_bytes_reduce(&max_r_big.to_bytes_be()); let max_r_var = self.add_constant(max_r); let max_r_predicate = self.mul_var(predicate, max_r_var)?; @@ -897,7 +888,7 @@ impl AcirContext { } assert!( - bits < FieldElement::max_num_bits(), + bits < F::max_num_bits(), "range check with bit size of the prime field is not implemented yet" ); @@ -921,7 +912,7 @@ impl AcirContext { // however, since it is a constant, we can compute it's actual bit size let r_bit_size = bit_size_u128(r); // witness = lhs_offset + r - assert!(bits + r_bit_size < FieldElement::max_num_bits()); //we need to ensure lhs_offset + r does not overflow + assert!(bits + r_bit_size < F::max_num_bits()); //we need to ensure lhs_offset + r does not overflow let r_var = self.add_constant(r); let aor = self.add_var(lhs_offset, r_var)?; @@ -945,14 +936,13 @@ impl AcirContext { leading: AcirVar, max_bit_size: u32, ) -> Result { - let max_power_of_two = self.add_constant( - FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)), - ); + let max_power_of_two = + self.add_constant(F::from(2_u128).pow(&F::from(max_bit_size as u128 - 1))); let intermediate = self.sub_var(max_power_of_two, lhs)?; let intermediate = self.mul_var(intermediate, leading)?; - self.add_mul_var(lhs, FieldElement::from(2_i128), intermediate) + self.add_mul_var(lhs, F::from(2_u128), intermediate) } /// Returns the quotient and remainder such that lhs = rhs * quotient + remainder @@ -976,11 +966,10 @@ impl AcirContext { assert_ne!(bit_size, 0, "signed integer should have at least one bit"); // 2^{max_bit size-1} - let max_power_of_two = self.add_constant( - FieldElement::from(2_i128).pow(&FieldElement::from(bit_size as i128 - 1)), - ); - let zero = self.add_constant(FieldElement::zero()); - let one = self.add_constant(FieldElement::one()); + let max_power_of_two = + self.add_constant(F::from(2_u128).pow(&F::from(bit_size as u128 - 1))); + let zero = self.add_constant(F::zero()); + let one = self.add_constant(F::one()); // Get the sign bit of rhs by computing rhs / max_power_of_two let (rhs_leading, _) = self.euclidean_division_var(rhs, max_power_of_two, bit_size, one)?; @@ -1071,9 +1060,8 @@ impl AcirContext { max_bit_size: u32, ) -> Result { // 2^{rhs} - let divisor = - self.add_constant(FieldElement::from(2_u128).pow(&FieldElement::from(rhs as u128))); - let one = self.add_constant(FieldElement::one()); + let divisor = self.add_constant(F::from(2_u128).pow(&F::from(rhs as u128))); + let one = self.add_constant(F::one()); // Computes lhs = 2^{rhs} * q + r let (_, remainder) = self.euclidean_division_var(lhs, divisor, max_bit_size, one)?; @@ -1093,8 +1081,8 @@ impl AcirContext { rhs: AcirVar, bit_count: u32, ) -> Result { - let pow_last = self.add_constant(FieldElement::from(1_u128 << (bit_count - 1))); - let pow = self.add_constant(FieldElement::from(1_u128 << (bit_count))); + let pow_last = self.add_constant(F::from(1_u128 << (bit_count - 1))); + let pow = self.add_constant(F::from(1_u128 << (bit_count))); // We check whether the inputs have same sign or not by computing the XOR of their bit sign @@ -1163,10 +1151,9 @@ impl AcirContext { // Ensure that 2^{max_bits + 1} is less than the field size // // TODO: perhaps this should be a user error, instead of an assert - assert!(max_bits + 1 < FieldElement::max_num_bits()); + assert!(max_bits + 1 < F::max_num_bits()); - let two_max_bits = self - .add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(max_bits as i128))); + let two_max_bits = self.add_constant(F::from(2_u128).pow(&F::from(max_bits as u128))); let diff = self.sub_var(lhs, rhs)?; let comparison_evaluation = self.add_var(diff, two_max_bits)?; @@ -1214,7 +1201,7 @@ impl AcirContext { // compute less than. let comparison = self.more_than_eq_var(lhs, rhs, bit_size)?; - let one = self.add_constant(FieldElement::one()); + let one = self.add_constant(F::one()); self.sub_var(one, comparison) // comparison_negated } @@ -1251,7 +1238,7 @@ impl AcirContext { } }; - (vec![domain_constant], Vec::new()) + (vec![*domain_constant], Vec::new()) } BlackBoxFunc::Poseidon2Permutation => { // The last argument is the state length, which must be a constant @@ -1276,7 +1263,7 @@ impl AcirContext { } }; - (vec![state_len], Vec::new()) + (vec![*state_len], Vec::new()) } BlackBoxFunc::BigIntAdd | BlackBoxFunc::BigIntSub @@ -1297,7 +1284,7 @@ impl AcirContext { output_count = 0; let mut field_inputs = Vec::new(); for i in const_inputs { - field_inputs.push(i?); + field_inputs.push(*i?); } if field_inputs[1] != field_inputs[3] { return Err(RuntimeError::BigIntModulus { call_stack: self.get_call_stack() }); @@ -1306,7 +1293,7 @@ impl AcirContext { let result_id = self.big_int_ctx.new_big_int(field_inputs[1]); ( vec![field_inputs[0], field_inputs[2]], - vec![result_id.bigint_id(), result_id.modulus_id()], + vec![result_id.bigint_id::(), result_id.modulus_id::()], ) } BlackBoxFunc::BigIntToLeBytes => { @@ -1323,10 +1310,10 @@ impl AcirContext { inputs = Vec::new(); let mut field_inputs = Vec::new(); for i in const_inputs { - field_inputs.push(i?); + field_inputs.push(*i?); } let bigint = self.big_int_ctx.get(field_inputs[0]); - let modulus = self.big_int_ctx.modulus(bigint.modulus_id()); + 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; assert!(bytes_len == 32); @@ -1339,7 +1326,7 @@ impl AcirContext { match inputs.pop().expect(invalid_input) { AcirValue::Array(values) => { for value in values { - modulus.push(self.vars[&value.into_var()?].as_constant().ok_or( + modulus.push(*self.vars[&value.into_var()?].as_constant().ok_or( RuntimeError::InternalError(InternalError::NotAConstant { name: "big integer".to_string(), call_stack: self.get_call_stack(), @@ -1359,9 +1346,8 @@ impl AcirContext { output_count = 0; let modulus_id = self.big_int_ctx.get_or_insert_modulus(big_modulus); - let result_id = - self.big_int_ctx.new_big_int(FieldElement::from(modulus_id as u128)); - (modulus, vec![result_id.bigint_id(), result_id.modulus_id()]) + let result_id = self.big_int_ctx.new_big_int(F::from(modulus_id as u128)); + (modulus, vec![result_id.bigint_id::(), result_id.modulus_id::()]) } BlackBoxFunc::AES128Encrypt => { let invalid_input = "aes128_encrypt - operation requires a plaintext to encrypt"; @@ -1376,7 +1362,7 @@ impl AcirContext { } }?; output_count = input_size + (16 - input_size % 16); - (vec![], vec![FieldElement::from(output_count as u128)]) + (vec![], vec![F::from(output_count as u128)]) } _ => (vec![], vec![]), }; @@ -1420,7 +1406,7 @@ impl AcirContext { // constants too. let witness_var = self.get_or_create_witness_var(input)?; let witness = self.var_to_witness(witness_var)?; - let num_bits = typ.bit_size(); + let num_bits = typ.bit_size::(); single_val_witnesses.push(FunctionInput { witness, num_bits }); } witnesses.push(single_val_witnesses); @@ -1531,7 +1517,7 @@ impl AcirContext { inputs: Vec, return_values: Vec, warnings: Vec, - ) -> GeneratedAcir { + ) -> GeneratedAcir { self.acir_ir.input_witnesses = inputs; self.acir_ir.return_witnesses = return_values; self.acir_ir.warnings = warnings; @@ -1543,7 +1529,7 @@ impl AcirContext { /// Variable can be seen as an index into the context. /// We use a two-way map so that it is efficient to lookup /// either the key or the value. - fn add_data(&mut self, data: AcirVarData) -> AcirVar { + fn add_data(&mut self, data: AcirVarData) -> AcirVar { let id = AcirVar(self.vars.len()); self.vars.insert(id, data); id @@ -1553,7 +1539,7 @@ impl AcirContext { pub(crate) fn brillig_call( &mut self, predicate: AcirVar, - generated_brillig: &GeneratedBrillig, + generated_brillig: &GeneratedBrillig, inputs: Vec, outputs: Vec, attempt_execution: bool, @@ -1561,14 +1547,34 @@ impl AcirContext { brillig_function_index: u32, brillig_stdlib_func: Option, ) -> Result, RuntimeError> { - let brillig_inputs: Vec> = + let predicate = self.var_to_expression(predicate)?; + if predicate.is_zero() { + // If the predicate has a constant value of zero, the brillig call will never be executed. + // We can then immediately zero out all of its outputs as this is the value which would be written + // if we waited until runtime to resolve this call. + let outputs_var = vecmap(outputs, |output| match output { + AcirType::NumericType(_) => { + let var = self.add_constant(F::zero()); + AcirValue::Var(var, output.clone()) + } + AcirType::Array(element_types, size) => { + self.zeroed_array_output(&element_types, size) + } + }); + + return Ok(outputs_var); + } + // Remove "always true" predicates. + let predicate = if predicate == Expression::one() { None } else { Some(predicate) }; + + let brillig_inputs: Vec> = 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(); + let mut var_expressions: Vec> = Vec::new(); for var in vars { self.brillig_array_input(&mut var_expressions, var)?; } @@ -1608,10 +1614,9 @@ impl AcirContext { acir_value } }); - let predicate = self.var_to_expression(predicate)?; self.acir_ir.brillig_call( - Some(predicate), + predicate, generated_brillig, brillig_inputs, brillig_outputs, @@ -1619,8 +1624,8 @@ impl AcirContext { brillig_stdlib_func, ); - fn range_constraint_value( - context: &mut AcirContext, + fn range_constraint_value( + context: &mut AcirContext, value: &AcirValue, ) -> Result<(), RuntimeError> { match value { @@ -1655,7 +1660,7 @@ impl AcirContext { fn brillig_array_input( &mut self, - var_expressions: &mut Vec>, + var_expressions: &mut Vec>, input: AcirValue, ) -> Result<(), InternalError> { match input { @@ -1682,6 +1687,27 @@ impl AcirContext { Ok(()) } + /// Recursively create zeroed-out acir values for returned arrays. This is necessary because a brillig returned array can have nested arrays as elements. + fn zeroed_array_output(&mut self, element_types: &[AcirType], size: usize) -> AcirValue { + let mut array_values = im::Vector::new(); + for _ in 0..size { + for element_type in element_types { + match element_type { + AcirType::Array(nested_element_types, nested_size) => { + let nested_acir_value = + self.zeroed_array_output(nested_element_types, *nested_size); + array_values.push_back(nested_acir_value); + } + AcirType::NumericType(_) => { + let var = self.add_constant(F::zero()); + array_values.push_back(AcirValue::Var(var, element_type.clone())); + } + } + } + } + AcirValue::Array(array_values) + } + /// Recursively create acir values for returned arrays. This is necessary because a brillig returned array can have nested arrays as elements. /// A singular array of witnesses is collected for a top level array, by deflattening the assigned witnesses at each level. fn brillig_array_output( @@ -1714,8 +1740,8 @@ impl AcirContext { fn execute_brillig( &mut self, - code: &[BrilligOpcode], - inputs: &[BrilligInputs], + code: &[BrilligOpcode], + inputs: &[BrilligInputs], outputs_types: &[AcirType], ) -> Option> { let mut memory = (execute_brillig(code, inputs)?).into_iter(); @@ -1740,7 +1766,7 @@ impl AcirContext { &mut self, element_types: &[AcirType], size: usize, - memory_iter: &mut impl Iterator>, + memory_iter: &mut impl Iterator>, ) -> AcirValue { let mut array_values = im::Vector::new(); for _ in 0..size { @@ -1821,7 +1847,7 @@ impl AcirContext { ) -> Result<(), InternalError> { let initialized_values = match optional_value { None => { - let zero = self.add_constant(FieldElement::zero()); + let zero = self.add_constant(F::zero()); let zero_witness = self.var_to_witness(zero)?; vec![zero_witness; len] } @@ -1893,13 +1919,13 @@ impl AcirContext { /// Enum representing the possible values that a /// Variable can be given. #[derive(Debug, Eq, Clone)] -enum AcirVarData { +enum AcirVarData { Witness(Witness), - Expr(Expression), - Const(FieldElement), + Expr(Expression), + Const(F), } -impl PartialEq for AcirVarData { +impl PartialEq for AcirVarData { fn eq(&self, other: &Self) -> bool { match (self, other) { (Self::Witness(l0), Self::Witness(r0)) => l0 == r0, @@ -1911,23 +1937,26 @@ impl PartialEq for AcirVarData { } // TODO: check/test this hash impl -impl std::hash::Hash for AcirVarData { +impl std::hash::Hash for AcirVarData { fn hash(&self, state: &mut H) { core::mem::discriminant(self).hash(state); } } -impl AcirVarData { +impl AcirVarData { /// Returns a FieldElement, if the underlying `AcirVarData` /// represents a constant. - pub(crate) fn as_constant(&self) -> Option { + pub(crate) fn as_constant(&self) -> Option<&F> { if let AcirVarData::Const(field) = self { - return Some(*field); + return Some(field); } None } +} + +impl AcirVarData { /// Converts all enum variants to an Expression. - pub(crate) fn to_expression(&self) -> Cow> { + pub(crate) fn to_expression(&self) -> Cow> { match self { AcirVarData::Witness(witness) => Cow::Owned(Expression::from(*witness)), AcirVarData::Expr(expr) => Cow::Borrowed(expr), @@ -1936,23 +1965,17 @@ impl AcirVarData { } } -impl From for AcirVarData { - fn from(constant: FieldElement) -> Self { - AcirVarData::Const(constant) - } -} - -impl From for AcirVarData { +impl From for AcirVarData { fn from(witness: Witness) -> Self { AcirVarData::Witness(witness) } } -impl From> for AcirVarData { - fn from(expr: Expression) -> Self { +impl From> for AcirVarData { + fn from(expr: Expression) -> Self { // Prefer simpler variants if possible. if let Some(constant) = expr.to_const() { - AcirVarData::from(*constant) + AcirVarData::Const(*constant) } else if let Some(witness) = expr.to_witness() { AcirVarData::from(witness) } else { @@ -1970,12 +1993,12 @@ pub(crate) struct AcirVar(usize); /// Returns the finished state of the Brillig VM if execution can complete. /// /// Returns `None` if complete execution of the Brillig bytecode is not possible. -fn execute_brillig( - code: &[BrilligOpcode], - inputs: &[BrilligInputs], -) -> Option>> { +fn execute_brillig( + code: &[BrilligOpcode], + inputs: &[BrilligInputs], +) -> Option>> { // Set input values - let mut calldata: Vec = Vec::new(); + let mut calldata: Vec = Vec::new(); // Each input represents a constant or array of constants. // Iterate over each input and push it into registers and/or memory. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs index b9c596d80c7b..30297b42ecf8 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/big_int.rs @@ -1,4 +1,4 @@ -use acvm::{acir::AcirField, FieldElement}; +use acvm::acir::AcirField; use num_bigint::BigUint; /// Represents a bigint value in the form (id, modulus) where @@ -11,12 +11,12 @@ pub(crate) struct BigIntId { } impl BigIntId { - pub(crate) fn bigint_id(&self) -> FieldElement { - FieldElement::from(self.bigint_id as u128) + pub(crate) fn bigint_id>(&self) -> F { + F::from(self.bigint_id as u128) } - pub(crate) fn modulus_id(&self) -> FieldElement { - FieldElement::from(self.modulus_id as u128) + pub(crate) fn modulus_id>(&self) -> F { + F::from(self.modulus_id as u128) } } @@ -29,7 +29,7 @@ pub(crate) struct BigIntContext { impl BigIntContext { /// Creates a new BigIntId for the given modulus identifier and returns it. - pub(crate) fn new_big_int(&mut self, modulus_id: FieldElement) -> BigIntId { + pub(crate) fn new_big_int(&mut self, modulus_id: F) -> BigIntId { let id = self.big_integers.len() as u32; let result = BigIntId { bigint_id: id, modulus_id: modulus_id.to_u128() as u32 }; self.big_integers.push(result); @@ -37,12 +37,12 @@ impl BigIntContext { } /// Returns the modulus corresponding to the given modulus index - pub(crate) fn modulus(&self, idx: FieldElement) -> BigUint { + pub(crate) fn modulus(&self, idx: F) -> BigUint { self.modulus[idx.to_u128() as usize].clone() } /// Returns the BigIntId corresponding to the given identifier - pub(crate) fn get(&self, id: FieldElement) -> BigIntId { + pub(crate) fn get(&self, id: F) -> BigIntId { self.big_integers[id.to_u128() as usize] } 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 9a09e7c06ee2..bcccfac89505 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 @@ -19,7 +19,6 @@ use acvm::acir::{ use acvm::{ acir::AcirField, acir::{circuit::directives::Directive, native_types::Expression}, - FieldElement, }; use iter_extended::vecmap; use num_bigint::BigUint; @@ -32,7 +31,7 @@ pub(crate) const PLACEHOLDER_BRILLIG_INDEX: u32 = 0; #[derive(Debug, Default)] /// The output of the Acir-gen pass, which should only be produced for entry point Acir functions -pub(crate) struct GeneratedAcir { +pub(crate) struct GeneratedAcir { /// The next witness index that may be declared. /// If witness index is `None` then we have not yet created a witness /// and thus next witness index that be declared is zero. @@ -42,7 +41,7 @@ pub(crate) struct GeneratedAcir { current_witness_index: Option, /// The opcodes of which the compiled ACIR will comprise. - opcodes: Vec>, + opcodes: Vec>, /// All witness indices that comprise the final return value of the program pub(crate) return_witnesses: Vec, @@ -58,7 +57,7 @@ pub(crate) struct GeneratedAcir { pub(crate) call_stack: CallStack, /// Correspondence between an opcode index and the error message associated with it. - pub(crate) assertion_payloads: BTreeMap>, + pub(crate) assertion_payloads: BTreeMap>, pub(crate) warnings: Vec, @@ -80,7 +79,7 @@ pub(crate) enum BrilligStdlibFunc { } impl BrilligStdlibFunc { - pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { + pub(crate) fn get_generated_brillig(&self) -> GeneratedBrillig { match self { BrilligStdlibFunc::Inverse => brillig_directive::directive_invert(), BrilligStdlibFunc::Quotient(bit_size) => { @@ -90,25 +89,25 @@ impl BrilligStdlibFunc { } } -impl GeneratedAcir { +impl GeneratedAcir { /// Returns the current witness index. pub(crate) fn current_witness_index(&self) -> Witness { Witness(self.current_witness_index.unwrap_or(0)) } /// Adds a new opcode into ACIR. - pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { + pub(crate) fn push_opcode(&mut self, opcode: AcirOpcode) { self.opcodes.push(opcode); if !self.call_stack.is_empty() { self.locations.insert(self.last_acir_opcode_location(), self.call_stack.clone()); } } - pub(crate) fn opcodes(&self) -> &[AcirOpcode] { + pub(crate) fn opcodes(&self) -> &[AcirOpcode] { &self.opcodes } - pub(crate) fn take_opcodes(&mut self) -> Vec> { + pub(crate) fn take_opcodes(&mut self) -> Vec> { std::mem::take(&mut self.opcodes) } @@ -127,7 +126,7 @@ impl GeneratedAcir { /// /// If `expr` can be represented as a `Witness` then this function will return it, /// else a new opcode will be added to create a `Witness` that is equal to `expr`. - pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { + pub(crate) fn get_or_create_witness(&mut self, expr: &Expression) -> Witness { match expr.to_witness() { Some(witness) => witness, None => self.create_witness_for_expression(expr), @@ -140,10 +139,7 @@ impl GeneratedAcir { /// This means you cannot multiply an infinite amount of `Expression`s together. /// Once the `Expression` goes over degree-2, then it needs to be reduced to a `Witness` /// which has degree-1 in order to be able to continue the multiplication chain. - pub(crate) fn create_witness_for_expression( - &mut self, - expression: &Expression, - ) -> Witness { + pub(crate) fn create_witness_for_expression(&mut self, expression: &Expression) -> Witness { let fresh_witness = self.next_witness_index(); // Create a constraint that sets them to be equal to each other @@ -163,15 +159,15 @@ impl GeneratedAcir { } } -impl GeneratedAcir { +impl GeneratedAcir { /// Calls a black box function and returns the output /// of said blackbox function. pub(crate) fn call_black_box( &mut self, func_name: BlackBoxFunc, inputs: &[Vec], - constant_inputs: Vec, - constant_outputs: Vec, + constant_inputs: Vec, + constant_outputs: Vec, output_count: usize, ) -> Result, InternalError> { let input_count = inputs.iter().fold(0usize, |sum, val| sum + val.len()); @@ -388,7 +384,7 @@ impl GeneratedAcir { /// Only radix that are a power of two are supported pub(crate) fn radix_le_decompose( &mut self, - input_expr: &Expression, + input_expr: &Expression, radix: u32, limb_count: u32, bit_size: u32, @@ -414,7 +410,7 @@ impl GeneratedAcir { self.range_constraint(*limb_witness, bit_size)?; composed_limbs = composed_limbs.add_mul( - FieldElement::from_be_bytes_reduce(&radix_pow.to_bytes_be()), + F::from_be_bytes_reduce(&radix_pow.to_bytes_be()), &Expression::from(*limb_witness), ); @@ -434,7 +430,7 @@ impl GeneratedAcir { /// /// Safety: It is the callers responsibility to ensure that the /// resulting `Witness` is constrained to be the inverse. - pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { + pub(crate) fn brillig_inverse(&mut self, expr: Expression) -> Witness { // Create the witness for the result let inverted_witness = self.next_witness_index(); @@ -443,7 +439,7 @@ impl GeneratedAcir { let inputs = vec![BrilligInputs::Single(expr)]; let outputs = vec![BrilligOutputs::Simple(inverted_witness)]; self.brillig_call( - Some(Expression::one()), + None, &inverse_code, inputs, outputs, @@ -458,18 +454,14 @@ impl GeneratedAcir { /// /// If `expr` is not zero, then the constraint system will /// fail upon verification. - pub(crate) fn assert_is_zero(&mut self, expr: Expression) { + pub(crate) fn assert_is_zero(&mut self, expr: Expression) { self.push_opcode(AcirOpcode::AssertZero(expr)); } /// Returns a `Witness` that is constrained to be: /// - `1` if `lhs == rhs` /// - `0` otherwise - pub(crate) fn is_equal( - &mut self, - lhs: &Expression, - rhs: &Expression, - ) -> Witness { + pub(crate) fn is_equal(&mut self, lhs: &Expression, rhs: &Expression) -> Witness { let t = lhs - rhs; self.is_zero(&t) @@ -527,13 +519,13 @@ impl GeneratedAcir { /// By setting `z` to be `0`, we can make `y` equal to `1`. /// This is easily observed: `y = 1 - t * 0` /// Now since `y` is one, this means that `t` needs to be zero, or else `y * t == 0` will fail. - fn is_zero(&mut self, t_expr: &Expression) -> Witness { + fn is_zero(&mut self, t_expr: &Expression) -> Witness { // We're checking for equality with zero so we can negate the expression without changing the result. // This is useful as it will sometimes allow us to simplify an expression down to a witness. let t_witness = if let Some(witness) = t_expr.to_witness() { witness } else { - let negated_expr = t_expr * -FieldElement::one(); + let negated_expr = t_expr * -F::one(); self.get_or_create_witness(&negated_expr) }; @@ -545,17 +537,17 @@ impl GeneratedAcir { // Add constraint y == 1 - tz => y + tz - 1 == 0 let y_is_boolean_constraint = Expression { - mul_terms: vec![(FieldElement::one(), t_witness, z)], - linear_combinations: vec![(FieldElement::one(), y)], - q_c: -FieldElement::one(), + mul_terms: vec![(F::one(), t_witness, z)], + linear_combinations: vec![(F::one(), y)], + q_c: -F::one(), }; self.assert_is_zero(y_is_boolean_constraint); // Add constraint that y * t == 0; let ty_zero_constraint = Expression { - mul_terms: vec![(FieldElement::one(), t_witness, y)], + mul_terms: vec![(F::one(), t_witness, y)], linear_combinations: vec![], - q_c: FieldElement::zero(), + q_c: F::zero(), }; self.assert_is_zero(ty_zero_constraint); @@ -571,9 +563,9 @@ impl GeneratedAcir { ) -> Result<(), RuntimeError> { // We class this as an error because users should instead // do `as Field`. - if num_bits >= FieldElement::max_num_bits() { + if num_bits >= F::max_num_bits() { return Err(RuntimeError::InvalidRangeConstraint { - num_bits: FieldElement::max_num_bits(), + num_bits: F::max_num_bits(), call_stack: self.call_stack.clone(), }); }; @@ -588,9 +580,9 @@ impl GeneratedAcir { pub(crate) fn brillig_call( &mut self, - predicate: Option>, - generated_brillig: &GeneratedBrillig, - inputs: Vec>, + predicate: Option>, + generated_brillig: &GeneratedBrillig, + inputs: Vec>, outputs: Vec, brillig_function_index: u32, stdlib_func: Option, @@ -717,6 +709,7 @@ fn black_box_expected_output_size(name: BlackBoxFunc) -> Option { BlackBoxFunc::Poseidon2Permutation => None, BlackBoxFunc::Sha256Compression => Some(8), + // Pedersen commitment returns a point BlackBoxFunc::PedersenCommitment => Some(2), 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 40170e58a306..aaa483b91c9d 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 @@ -42,11 +42,11 @@ use im::Vector; use iter_extended::{try_vecmap, vecmap}; #[derive(Default)] -struct SharedContext { +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, + 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 @@ -65,7 +65,7 @@ struct SharedContext { brillig_stdlib_calls_to_resolve: HashMap>, } -impl SharedContext { +impl SharedContext { fn generated_brillig_pointer( &self, func_id: FunctionId, @@ -74,7 +74,7 @@ impl SharedContext { self.brillig_generated_func_pointers.get(&(func_id, arguments)) } - fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { + fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { &self.generated_brillig[func_pointer] } @@ -83,7 +83,7 @@ impl SharedContext { func_id: FunctionId, arguments: Vec, generated_pointer: u32, - code: GeneratedBrillig, + code: GeneratedBrillig, ) { self.brillig_generated_func_pointers.insert((func_id, arguments), generated_pointer); self.generated_brillig.push(code); @@ -123,7 +123,7 @@ impl SharedContext { generated_pointer: u32, func_id: FunctionId, opcode_location: OpcodeLocation, - code: GeneratedBrillig, + code: GeneratedBrillig, ) { self.brillig_stdlib_func_pointer.insert(brillig_stdlib_func, generated_pointer); self.add_call_to_resolve(func_id, (opcode_location, generated_pointer)); @@ -151,7 +151,7 @@ struct Context<'a> { current_side_effects_enabled_var: AcirVar, /// Manages and builds the `AcirVar`s to which the converted SSA values refer. - acir_context: AcirContext, + acir_context: AcirContext, /// Track initialized acir dynamic arrays /// @@ -189,7 +189,7 @@ struct Context<'a> { data_bus: DataBus, /// Contains state that is generated and also used across ACIR functions - shared_context: &'a mut SharedContext, + shared_context: &'a mut SharedContext, } #[derive(Clone)] @@ -274,8 +274,11 @@ impl AcirValue { } } -pub(crate) type Artifacts = - (Vec, Vec>, BTreeMap); +pub(crate) type Artifacts = ( + Vec>, + Vec>, + BTreeMap, +); impl Ssa { #[tracing::instrument(level = "trace", skip_all)] @@ -331,7 +334,7 @@ impl Ssa { } impl<'a> Context<'a> { - fn new(shared_context: &'a mut SharedContext) -> 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()); @@ -354,7 +357,7 @@ impl<'a> Context<'a> { ssa: &Ssa, function: &Function, brillig: &Brillig, - ) -> Result, RuntimeError> { + ) -> Result>, RuntimeError> { match function.runtime() { RuntimeType::Acir(inline_type) => { match inline_type { @@ -386,7 +389,7 @@ impl<'a> Context<'a> { main_func: &Function, ssa: &Ssa, brillig: &Brillig, - ) -> Result { + ) -> Result, RuntimeError> { let dfg = &main_func.dfg; let entry_block = &dfg[main_func.entry_block()]; let input_witness = self.convert_ssa_block_params(entry_block.parameters(), dfg)?; @@ -435,7 +438,7 @@ impl<'a> Context<'a> { mut self, main_func: &Function, brillig: &Brillig, - ) -> Result { + ) -> Result, RuntimeError> { let dfg = &main_func.dfg; let inputs = try_vecmap(dfg[main_func.entry_block()].parameters(), |param_id| { @@ -919,7 +922,7 @@ impl<'a> Context<'a> { func: &Function, arguments: Vec, brillig: &Brillig, - ) -> Result { + ) -> Result, InternalError> { // Create the entry point artifact let mut entry_point = BrilligContext::new_entry_point_artifact( arguments, @@ -1897,7 +1900,7 @@ impl<'a> Context<'a> { } let binary_type = AcirType::from(binary_type); - let bit_count = binary_type.bit_size(); + let bit_count = binary_type.bit_size::(); let num_type = binary_type.to_numeric_type(); let result = match binary.operator { BinaryOp::Add => self.acir_context.add_var(lhs, rhs), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index f763ae52d50d..994386f8197d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -497,9 +497,22 @@ impl DataFlowGraph { } } - /// True if the given ValueId refers to a constant value + /// True if the given ValueId refers to a (recursively) constant value pub(crate) fn is_constant(&self, argument: ValueId) -> bool { - !matches!(&self[self.resolve(argument)], Value::Instruction { .. } | Value::Param { .. }) + match &self[self.resolve(argument)] { + Value::Instruction { .. } | Value::Param { .. } => false, + Value::Array { array, .. } => array.iter().all(|element| self.is_constant(*element)), + _ => true, + } + } + + /// True that the input is a non-zero `Value::NumericConstant` + pub(crate) fn is_constant_true(&self, argument: ValueId) -> bool { + if let Some(constant) = self.get_numeric_constant(argument) { + !constant.is_zero() + } else { + false + } } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs index 68ece87c7c7e..a063a7ff2685 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/function_inserter.rs @@ -16,11 +16,12 @@ pub(crate) struct FunctionInserter<'f> { pub(crate) function: &'f mut Function, values: HashMap, + const_arrays: HashMap, ValueId>, } impl<'f> FunctionInserter<'f> { pub(crate) fn new(function: &'f mut Function) -> FunctionInserter<'f> { - Self { function, values: HashMap::default() } + Self { function, values: HashMap::default(), const_arrays: HashMap::default() } } /// Resolves a ValueId to its new, updated value. @@ -34,10 +35,17 @@ impl<'f> FunctionInserter<'f> { super::value::Value::Array { array, typ } => { let array = array.clone(); let typ = typ.clone(); - let new_array = array.iter().map(|id| self.resolve(*id)).collect(); - let new_id = self.function.dfg.make_array(new_array, typ); - self.values.insert(value, new_id); - new_id + let new_array: im::Vector = + array.iter().map(|id| self.resolve(*id)).collect(); + if self.const_arrays.get(&new_array) == Some(&value) { + value + } else { + let new_array_clone = new_array.clone(); + let new_id = self.function.dfg.make_array(new_array, typ); + self.values.insert(value, new_id); + self.const_arrays.insert(new_array_clone, new_id); + new_id + } } _ => value, }, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index e21deb9ef790..f854e8e06931 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -52,6 +52,7 @@ pub(crate) enum Intrinsic { ArrayLen, AsSlice, AssertConstant, + StaticAssert, SlicePushBack, SlicePushFront, SlicePopBack, @@ -67,6 +68,7 @@ pub(crate) enum Intrinsic { AsField, AsWitness, IsUnconstrained, + DerivePedersenGenerators, } impl std::fmt::Display for Intrinsic { @@ -75,6 +77,7 @@ impl std::fmt::Display for Intrinsic { Intrinsic::ArrayLen => write!(f, "array_len"), Intrinsic::AsSlice => write!(f, "as_slice"), Intrinsic::AssertConstant => write!(f, "assert_constant"), + Intrinsic::StaticAssert => write!(f, "static_assert"), Intrinsic::SlicePushBack => write!(f, "slice_push_back"), Intrinsic::SlicePushFront => write!(f, "slice_push_front"), Intrinsic::SlicePopBack => write!(f, "slice_pop_back"), @@ -92,6 +95,7 @@ impl std::fmt::Display for Intrinsic { Intrinsic::AsField => write!(f, "as_field"), Intrinsic::AsWitness => write!(f, "as_witness"), Intrinsic::IsUnconstrained => write!(f, "is_unconstrained"), + Intrinsic::DerivePedersenGenerators => write!(f, "derive_pedersen_generators"), } } } @@ -102,9 +106,10 @@ impl Intrinsic { /// If there are no side effects then the `Intrinsic` can be removed if the result is unused. pub(crate) fn has_side_effects(&self) -> bool { match self { - Intrinsic::AssertConstant | Intrinsic::ApplyRangeConstraint | Intrinsic::AsWitness => { - true - } + Intrinsic::AssertConstant + | Intrinsic::StaticAssert + | Intrinsic::ApplyRangeConstraint + | Intrinsic::AsWitness => true, // These apply a constraint that the input must fit into a specified number of limbs. Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => true, @@ -120,7 +125,8 @@ impl Intrinsic { | Intrinsic::StrAsBytes | Intrinsic::FromField | Intrinsic::AsField - | Intrinsic::IsUnconstrained => false, + | Intrinsic::IsUnconstrained + | Intrinsic::DerivePedersenGenerators => false, // Some black box functions have side-effects Intrinsic::BlackBox(func) => matches!( @@ -139,6 +145,7 @@ impl Intrinsic { "array_len" => Some(Intrinsic::ArrayLen), "as_slice" => Some(Intrinsic::AsSlice), "assert_constant" => Some(Intrinsic::AssertConstant), + "static_assert" => Some(Intrinsic::StaticAssert), "apply_range_constraint" => Some(Intrinsic::ApplyRangeConstraint), "slice_push_back" => Some(Intrinsic::SlicePushBack), "slice_push_front" => Some(Intrinsic::SlicePushFront), @@ -155,6 +162,7 @@ impl Intrinsic { "as_field" => Some(Intrinsic::AsField), "as_witness" => Some(Intrinsic::AsWitness), "is_unconstrained" => Some(Intrinsic::IsUnconstrained), + "derive_pedersen_generators" => Some(Intrinsic::DerivePedersenGenerators), other => BlackBoxFunc::lookup(other).map(Intrinsic::BlackBox), } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index 74e5653c7bab..281ab7c3057a 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -2,6 +2,7 @@ use fxhash::FxHashMap as HashMap; use std::{collections::VecDeque, rc::Rc}; use acvm::{acir::AcirField, acir::BlackBoxFunc, BlackBoxResolutionError, FieldElement}; +use bn254_blackbox_solver::derive_generators; use iter_extended::vecmap; use num_bigint::BigUint; @@ -245,6 +246,21 @@ pub(super) fn simplify_call( SimplifyResult::None } } + Intrinsic::StaticAssert => { + if arguments.len() != 2 { + panic!("ICE: static_assert called with wrong number of arguments") + } + + if !dfg.is_constant(arguments[1]) { + return SimplifyResult::None; + } + + if dfg.is_constant_true(arguments[0]) { + SimplifyResult::Remove + } else { + SimplifyResult::None + } + } Intrinsic::ApplyRangeConstraint => { let value = arguments[0]; let max_bit_size = dfg.get_numeric_constant(arguments[1]); @@ -295,6 +311,13 @@ pub(super) fn simplify_call( } Intrinsic::AsWitness => SimplifyResult::None, Intrinsic::IsUnconstrained => SimplifyResult::None, + Intrinsic::DerivePedersenGenerators => { + if let Some(Type::Array(_, len)) = ctrl_typevars.unwrap().first() { + simplify_derive_generators(dfg, arguments, *len as u32) + } else { + unreachable!("Derive Pedersen Generators must return an array"); + } + } } } @@ -438,7 +461,9 @@ fn simplify_black_box_func( BlackBoxFunc::SHA256 => simplify_hash(dfg, arguments, acvm::blackbox_solver::sha256), BlackBoxFunc::Blake2s => simplify_hash(dfg, arguments, acvm::blackbox_solver::blake2s), BlackBoxFunc::Blake3 => simplify_hash(dfg, arguments, acvm::blackbox_solver::blake3), - BlackBoxFunc::Keccakf1600 => SimplifyResult::None, //TODO(Guillaume) + BlackBoxFunc::PedersenCommitment + | BlackBoxFunc::PedersenHash + | BlackBoxFunc::Keccakf1600 => SimplifyResult::None, //TODO(Guillaume) BlackBoxFunc::Keccak256 => { match (dfg.get_array_constant(arguments[0]), dfg.get_numeric_constant(arguments[1])) { (Some((input, _)), Some(num_bytes)) if array_is_constant(dfg, &input) => { @@ -468,8 +493,6 @@ fn simplify_black_box_func( BlackBoxFunc::MultiScalarMul | BlackBoxFunc::SchnorrVerify - | BlackBoxFunc::PedersenCommitment - | BlackBoxFunc::PedersenHash | BlackBoxFunc::EmbeddedCurveAdd => { // Currently unsolvable here as we rely on an implementation in the backend. SimplifyResult::None @@ -626,3 +649,47 @@ fn simplify_signature( _ => SimplifyResult::None, } } + +fn simplify_derive_generators( + dfg: &mut DataFlowGraph, + arguments: &[ValueId], + num_generators: u32, +) -> SimplifyResult { + if arguments.len() == 2 { + let domain_separator_string = dfg.get_array_constant(arguments[0]); + let starting_index = dfg.get_numeric_constant(arguments[1]); + if let (Some(domain_separator_string), Some(starting_index)) = + (domain_separator_string, starting_index) + { + let domain_separator_bytes = domain_separator_string + .0 + .iter() + .map(|&x| dfg.get_numeric_constant(x).unwrap().to_u128() as u8) + .collect::>(); + let generators = derive_generators( + &domain_separator_bytes, + num_generators, + starting_index.try_to_u32().expect("argument is declared as u32"), + ); + let is_infinite = dfg.make_constant(FieldElement::zero(), Type::bool()); + let mut results = Vec::new(); + for gen in generators { + let x_big: BigUint = gen.x.into(); + let x = FieldElement::from_be_bytes_reduce(&x_big.to_bytes_be()); + let y_big: BigUint = gen.y.into(); + let y = FieldElement::from_be_bytes_reduce(&y_big.to_bytes_be()); + results.push(dfg.make_constant(x, Type::field())); + results.push(dfg.make_constant(y, Type::field())); + results.push(is_infinite); + } + let len = results.len(); + let result = + dfg.make_array(results.into(), Type::Array(vec![Type::field()].into(), len)); + SimplifyResult::SimplifiedTo(result) + } else { + SimplifyResult::None + } + } else { + unreachable!("Unexpected number of arguments to derive_generators"); + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs index a3608f89612e..ae0681a55ff7 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs @@ -22,7 +22,9 @@ impl Ssa { /// since we must go through every instruction to find all references to `assert_constant` /// while loop unrolling only touches blocks with loops in them. #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn evaluate_assert_constant(mut self) -> Result { + pub(crate) fn evaluate_static_assert_and_assert_constant( + mut self, + ) -> Result { for function in self.functions.values_mut() { for block in function.reachable_blocks() { // Unfortunately we can't just use instructions.retain(...) here since @@ -54,10 +56,13 @@ fn check_instruction( instruction: InstructionId, ) -> Result { let assert_constant_id = function.dfg.import_intrinsic(Intrinsic::AssertConstant); + let static_assert_id = function.dfg.import_intrinsic(Intrinsic::StaticAssert); match &function.dfg[instruction] { Instruction::Call { func, arguments } => { if *func == assert_constant_id { evaluate_assert_constant(function, instruction, arguments) + } else if *func == static_assert_id { + evaluate_static_assert(function, instruction, arguments) } else { Ok(true) } @@ -82,3 +87,35 @@ fn evaluate_assert_constant( Err(RuntimeError::AssertConstantFailed { call_stack }) } } + +/// Evaluate a call to `static_assert`, returning an error if the value is false +/// or not constant (see assert_constant). +/// +/// When it passes, Ok(false) is returned. This signifies a +/// success but also that the instruction need not be reinserted into the block being unrolled +/// since it has already been evaluated. +fn evaluate_static_assert( + function: &Function, + instruction: InstructionId, + arguments: &[ValueId], +) -> Result { + if arguments.len() != 2 { + panic!("ICE: static_assert called with wrong number of arguments") + } + + if !function.dfg.is_constant(arguments[1]) { + let call_stack = function.dfg.get_call_stack(instruction); + return Err(RuntimeError::StaticAssertDynamicMessage { call_stack }); + } + + if function.dfg.is_constant_true(arguments[0]) { + Ok(false) + } else { + let call_stack = function.dfg.get_call_stack(instruction); + if function.dfg.is_constant(arguments[0]) { + Err(RuntimeError::StaticAssertFailed { call_stack }) + } else { + Err(RuntimeError::StaticAssertDynamicPredicate { call_stack }) + } + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index e07f947db8d9..c7ce3aaa1556 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -375,7 +375,6 @@ impl<'f> Context<'f> { let old_condition = *condition; let then_condition = self.inserter.resolve(old_condition); - let one = FieldElement::one(); let old_stores = std::mem::take(&mut self.store_values); let old_allocations = std::mem::take(&mut self.local_allocations); let branch = ConditionalBranch { @@ -393,15 +392,6 @@ impl<'f> Context<'f> { }; self.condition_stack.push(cond_context); self.insert_current_side_effects_enabled(); - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = self.inserter.function.dfg.make_constant(one, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } vec![self.branch_ends[if_entry], *else_destination, *then_destination] } @@ -414,7 +404,6 @@ impl<'f> Context<'f> { self.insert_instruction(Instruction::Not(cond_context.condition), CallStack::new()); let else_condition = self.link_condition(else_condition); - let zero = FieldElement::zero(); // Make sure the else branch sees the previous values of each store // rather than any values created in the 'then' branch. let old_stores = std::mem::take(&mut cond_context.then_branch.store_values); @@ -429,21 +418,12 @@ impl<'f> Context<'f> { local_allocations: old_allocations, last_block: *block, }; - let old_condition = else_branch.old_condition; cond_context.then_branch.local_allocations.clear(); cond_context.else_branch = Some(else_branch); self.condition_stack.push(cond_context); self.insert_current_side_effects_enabled(); - // Optimization: within the then branch we know the condition to be true, so replace - // any references of it within this branch with true. Likewise, do the same with false - // with the else branch. We must be careful not to replace the condition if it is a - // known constant, otherwise we can end up setting 1 = 0 or vice-versa. - if self.inserter.function.dfg.get_numeric_constant(old_condition).is_none() { - let known_value = self.inserter.function.dfg.make_constant(zero, Type::bool()); - - self.inserter.map_value(old_condition, known_value); - } + assert_eq!(self.cfg.successors(*block).len(), 1); vec![self.cfg.successors(*block).next().unwrap()] } @@ -471,11 +451,6 @@ impl<'f> Context<'f> { // known to be true/false within the then/else branch respectively. self.insert_current_side_effects_enabled(); - // We must map back to `then_condition` here. Mapping `old_condition` to itself would - // lose any previous mappings. - self.inserter - .map_value(cond_context.then_branch.old_condition, cond_context.then_branch.condition); - // While there is a condition on the stack we don't compile outside the condition // until it is popped. This ensures we inline the full then and else branches // before continuing from the end of the conditional here where they can be merged properly. @@ -1404,28 +1379,28 @@ mod test { fn should_not_merge_incorrectly_to_false() { // Regression test for #1792 // Tests that it does not simplify a true constraint an always-false constraint - // fn main f1 { - // b0(): - // v4 = call pedersen([Field 0], u32 0) - // v5 = array_get v4, index Field 0 - // v6 = cast v5 as u32 - // v8 = mod v6, u32 2 - // v9 = cast v8 as u1 - // v10 = allocate - // store Field 0 at v10 - // jmpif v9 then: b1, else: b2 - // b1(): - // v14 = add v5, Field 1 - // store v14 at v10 - // jmp b3() - // b3(): - // v12 = eq v9, u1 1 - // constrain v12 - // return - // b2(): - // store Field 0 at v10 - // jmp b3() - // } + // acir(inline) fn main f1 { + // b0(v0: [u8; 2]): + // v4 = call keccak256(v0, u8 2) + // v5 = array_get v4, index u8 0 + // v6 = cast v5 as u32 + // v8 = truncate v6 to 1 bits, max_bit_size: 32 + // v9 = cast v8 as u1 + // v10 = allocate + // store u8 0 at v10 + // jmpif v9 then: b2, else: b3 + // b2(): + // v12 = cast v5 as Field + // v13 = add v12, Field 1 + // store v13 at v10 + // jmp b4() + // b4(): + // constrain v9 == u1 1 + // return + // b3(): + // store u8 0 at v10 + // jmp b4() + // } let main_id = Id::test_new(1); let mut builder = FunctionBuilder::new("main".into(), main_id); @@ -1434,20 +1409,18 @@ mod test { let b2 = builder.insert_block(); let b3 = builder.insert_block(); - let element_type = Rc::new(vec![Type::field()]); - let array_type = Type::Array(element_type.clone(), 1); - - let zero = builder.field_constant(0_u128); - let zero_array = builder.array_constant(im::Vector::unit(zero), array_type); - let i_zero = builder.numeric_constant(0_u128, Type::unsigned(32)); - let pedersen = builder - .import_intrinsic_id(Intrinsic::BlackBox(acvm::acir::BlackBoxFunc::PedersenCommitment)); - let v4 = builder.insert_call( - pedersen, - vec![zero_array, i_zero], - vec![Type::Array(element_type, 2)], - )[0]; - let v5 = builder.insert_array_get(v4, zero, Type::field()); + let element_type = Rc::new(vec![Type::unsigned(8)]); + let array_type = Type::Array(element_type.clone(), 2); + let array = builder.add_parameter(array_type); + + let zero = builder.numeric_constant(0_u128, Type::unsigned(8)); + let two = builder.numeric_constant(2_u128, Type::unsigned(8)); + + let keccak = + builder.import_intrinsic_id(Intrinsic::BlackBox(acvm::acir::BlackBoxFunc::Keccak256)); + let v4 = + builder.insert_call(keccak, vec![array, two], vec![Type::Array(element_type, 32)])[0]; + let v5 = builder.insert_array_get(v4, zero, Type::unsigned(8)); let v6 = builder.insert_cast(v5, Type::unsigned(32)); let i_two = builder.numeric_constant(2_u128, Type::unsigned(32)); let v8 = builder.insert_binary(v6, BinaryOp::Mod, i_two); @@ -1460,7 +1433,9 @@ mod test { builder.switch_to_block(b1); let one = builder.field_constant(1_u128); - let v14 = builder.insert_binary(v5, BinaryOp::Add, one); + let v5b = builder.insert_cast(v5, Type::field()); + let v13: Id = builder.insert_binary(v5b, BinaryOp::Add, one); + let v14 = builder.insert_cast(v13, Type::unsigned(8)); builder.insert_store(v10, v14); builder.terminate_with_jmp(b3, vec![]); @@ -1474,8 +1449,9 @@ mod test { builder.insert_constrain(v12, v_true, None); builder.terminate_with_return(vec![]); - let ssa = builder.finish().flatten_cfg(); - let main = ssa.main(); + let ssa = builder.finish(); + let flattened_ssa = ssa.flatten_cfg(); + let main = flattened_ssa.main(); // Now assert that there is not an always-false constraint after flattening: let mut constrain_count = 0; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs index c59134e4ecc4..de75d34565e9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg/value_merger.rs @@ -304,7 +304,7 @@ impl<'a> ValueMerger<'a> { let mut current_then = then_value; let mut current_else = else_value; - // Arbitrarily limit this to looking at at most 10 past ArraySet operations. + // Arbitrarily limit this to looking at most 10 past ArraySet operations. // If there are more than that, we assume 2 completely separate arrays are being merged. let max_iters = 2; let mut seen_then = Vec::with_capacity(max_iters); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs index 6db769967474..f9a3c9a55eba 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs @@ -150,6 +150,7 @@ impl Context { Intrinsic::ArrayLen | Intrinsic::AssertConstant + | Intrinsic::StaticAssert | Intrinsic::ApplyRangeConstraint | Intrinsic::StrAsBytes | Intrinsic::ToBits(_) @@ -159,7 +160,8 @@ impl Context { | Intrinsic::AsField | Intrinsic::AsSlice | Intrinsic::AsWitness - | Intrinsic::IsUnconstrained => false, + | Intrinsic::IsUnconstrained + | Intrinsic::DerivePedersenGenerators => false, }, // We must assume that functions contain a side effect as we cannot inspect more deeply. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs index 6ca7eb74e9d7..242eea7d6f4c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs @@ -226,6 +226,7 @@ fn slice_capacity_change( // These cases don't affect slice capacities Intrinsic::AssertConstant + | Intrinsic::StaticAssert | Intrinsic::ApplyRangeConstraint | Intrinsic::ArrayLen | Intrinsic::StrAsBytes @@ -233,6 +234,7 @@ fn slice_capacity_change( | Intrinsic::FromField | Intrinsic::AsField | Intrinsic::AsWitness - | Intrinsic::IsUnconstrained => SizeChange::None, + | Intrinsic::IsUnconstrained + | Intrinsic::DerivePedersenGenerators => SizeChange::None, } } diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index 381eb4a9bb99..cc5a9b1e652a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -36,7 +36,6 @@ lalrpop-util = { version = "0.20.2", features = ["lexer"] } base64.workspace = true strum = "0.24" strum_macros = "0.24" -tempfile.workspace = true [build-dependencies] lalrpop = "0.20.2" diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index 50836add8de4..87cc79907533 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -5,9 +5,11 @@ use crate::ast::{ Ident, ItemVisibility, Path, Pattern, Recoverable, Statement, StatementKind, UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, Visibility, }; +use crate::hir::def_collector::errors::DefCollectorErrorKind; use crate::macros_api::StructId; use crate::node_interner::ExprId; -use crate::token::{Attributes, Token}; +use crate::token::{Attributes, Token, Tokens}; +use crate::{Kind, Type}; use acvm::{acir::AcirField, FieldElement}; use iter_extended::vecmap; use noirc_errors::{Span, Spanned}; @@ -33,7 +35,8 @@ pub enum ExpressionKind { Tuple(Vec), Lambda(Box), Parenthesized(Box), - Quote(BlockExpression), + Quote(Tokens), + Unquote(Box), Comptime(BlockExpression, Span), // This variant is only emitted when inlining the result of comptime @@ -45,7 +48,72 @@ pub enum ExpressionKind { /// A Vec of unresolved names for type variables. /// For `fn foo(...)` this corresponds to vec!["A", "B"]. -pub type UnresolvedGenerics = Vec; +pub type UnresolvedGenerics = Vec; + +#[derive(Debug, PartialEq, Eq, Clone, Hash)] +pub enum UnresolvedGeneric { + Variable(Ident), + Numeric { ident: Ident, typ: UnresolvedType }, +} + +impl UnresolvedGeneric { + pub fn span(&self) -> Span { + match self { + UnresolvedGeneric::Variable(ident) => ident.0.span(), + UnresolvedGeneric::Numeric { ident, typ } => { + ident.0.span().merge(typ.span.unwrap_or_default()) + } + } + } + + pub fn kind(&self) -> Result { + match self { + UnresolvedGeneric::Variable(_) => Ok(Kind::Normal), + UnresolvedGeneric::Numeric { typ, .. } => { + let typ = self.resolve_numeric_kind_type(typ)?; + Ok(Kind::Numeric(Box::new(typ))) + } + } + } + + fn resolve_numeric_kind_type( + &self, + typ: &UnresolvedType, + ) -> Result { + use crate::ast::UnresolvedTypeData::{FieldElement, Integer}; + + match typ.typ { + FieldElement => Ok(Type::FieldElement), + Integer(sign, bits) => Ok(Type::Integer(sign, bits)), + // Only fields and integers are supported for numeric kinds + _ => Err(DefCollectorErrorKind::UnsupportedNumericGenericType { + ident: self.ident().clone(), + typ: typ.typ.clone(), + }), + } + } + + pub(crate) fn ident(&self) -> &Ident { + match self { + UnresolvedGeneric::Variable(ident) | UnresolvedGeneric::Numeric { ident, .. } => ident, + } + } +} + +impl Display for UnresolvedGeneric { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + UnresolvedGeneric::Variable(ident) => write!(f, "{ident}"), + UnresolvedGeneric::Numeric { ident, typ } => write!(f, "let {ident}: {typ}"), + } + } +} + +impl From for UnresolvedGeneric { + fn from(value: Ident) -> Self { + UnresolvedGeneric::Variable(value) + } +} impl ExpressionKind { pub fn into_path(self) -> Option { @@ -121,23 +189,6 @@ impl ExpressionKind { struct_type: None, })) } - - /// Returns true if the expression is a literal integer - pub fn is_integer(&self) -> bool { - self.as_integer().is_some() - } - - fn as_integer(&self) -> Option { - let literal = match self { - ExpressionKind::Literal(literal) => literal, - _ => return None, - }; - - match literal { - Literal::Integer(integer, _) => Some(*integer), - _ => None, - } - } } impl Recoverable for ExpressionKind { @@ -179,19 +230,21 @@ impl Expression { pub fn member_access_or_method_call( lhs: Expression, - (rhs, args): UnaryRhsMemberAccess, + rhs: UnaryRhsMemberAccess, span: Span, ) -> Expression { - let kind = match args { - None => ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })), - Some((generics, arguments)) => { - ExpressionKind::MethodCall(Box::new(MethodCallExpression { - object: lhs, - method_name: rhs, - generics, - arguments, - })) + let kind = match rhs.method_call { + None => { + let rhs = rhs.method_or_field; + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { lhs, rhs })) } + Some(method_call) => ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: lhs, + method_name: rhs.method_or_field, + generics: method_call.turbofish, + arguments: method_call.args, + is_macro_call: method_call.macro_call, + })), }; Expression::new(kind, span) } @@ -206,7 +259,12 @@ impl Expression { Expression::new(kind, span) } - pub fn call(lhs: Expression, arguments: Vec, span: Span) -> Expression { + pub fn call( + lhs: Expression, + is_macro_call: bool, + arguments: Vec, + span: Span, + ) -> Expression { // Need to check if lhs is an if expression since users can sequence if expressions // with tuples without calling them. E.g. `if c { t } else { e }(a, b)` is interpreted // as a sequence of { if, tuple } rather than a function call. This behavior matches rust. @@ -224,7 +282,11 @@ impl Expression { ], }) } else { - ExpressionKind::Call(Box::new(CallExpression { func: Box::new(lhs), arguments })) + ExpressionKind::Call(Box::new(CallExpression { + func: Box::new(lhs), + is_macro_call, + arguments, + })) }; Expression::new(kind, span) } @@ -447,6 +509,7 @@ pub enum ArrayLiteral { pub struct CallExpression { pub func: Box, pub arguments: Vec, + pub is_macro_call: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -456,6 +519,7 @@ pub struct MethodCallExpression { /// Method calls have an optional list of generics if the turbofish operator was used pub generics: Option>, pub arguments: Vec, + pub is_macro_call: bool, } #[derive(Debug, PartialEq, Eq, Clone)] @@ -535,10 +599,14 @@ impl Display for ExpressionKind { } Lambda(lambda) => lambda.fmt(f), Parenthesized(sub_expr) => write!(f, "({sub_expr})"), - Quote(block) => write!(f, "quote {block}"), Comptime(block, _) => write!(f, "comptime {block}"), Error => write!(f, "Error"), Resolved(_) => write!(f, "?Resolved"), + Unquote(expr) => write!(f, "$({expr})"), + Quote(tokens) => { + let tokens = vecmap(&tokens.0, ToString::to_string); + write!(f, "quote {{ {} }}", tokens.join(" ")) + } } } } @@ -739,22 +807,32 @@ impl Display for FunctionDefinition { writeln!(f, "{:?}", self.attributes)?; let parameters = vecmap(&self.parameters, |Param { visibility, pattern, typ, span: _ }| { - format!("{pattern}: {visibility} {typ}") + if *visibility == Visibility::Public { + format!("{pattern}: {visibility} {typ}") + } else { + format!("{pattern}: {typ}") + } }); let where_clause = vecmap(&self.where_clause, ToString::to_string); let where_clause_str = if !where_clause.is_empty() { - format!("where {}", where_clause.join(", ")) + format!(" where {}", where_clause.join(", ")) } else { "".to_string() }; + let return_type = if matches!(&self.return_type, FunctionReturnType::Default(_)) { + String::new() + } else { + format!(" -> {}", self.return_type) + }; + write!( f, - "fn {}({}) -> {} {} {}", + "fn {}({}){}{} {}", self.name, parameters.join(", "), - self.return_type, + return_type, where_clause_str, self.body ) 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 bd2b45d9c487..dfe4258744a8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -22,6 +22,7 @@ pub use traits::*; pub use type_alias::*; use crate::{ + node_interner::QuotedTypeId, parser::{ParserError, ParserErrorReason}, token::IntType, BinaryTypeOperator, @@ -117,7 +118,11 @@ pub enum UnresolvedTypeData { ), // The type of quoted code for metaprogramming - Code, + Quoted(crate::QuotedType), + + /// An already resolved type. These can only be parsed if they were present in the token stream + /// as a result of being spliced into a macro's token stream input. + Resolved(QuotedTypeId), Unspecified, // This is for when the user declares a variable without specifying it's type Error, @@ -134,11 +139,19 @@ pub struct UnresolvedType { } /// Type wrapper for a member access -pub(crate) type UnaryRhsMemberAccess = - (Ident, Option<(Option>, Vec)>); +pub struct UnaryRhsMemberAccess { + pub method_or_field: Ident, + pub method_call: Option, +} + +pub struct UnaryRhsMethodCall { + pub turbofish: Option>, + pub macro_call: bool, + pub args: Vec, +} /// The precursor to TypeExpression, this is the type that the parser allows -/// to be used in the length position of an array type. Only constants, variables, +/// to be used in the length position of an array type. Only constant integers, variables, /// and numeric binary operators are allowed here. #[derive(Debug, PartialEq, Eq, Clone, Hash)] pub enum UnresolvedTypeExpression { @@ -208,11 +221,12 @@ impl std::fmt::Display for UnresolvedTypeData { } } MutableReference(element) => write!(f, "&mut {element}"), - Code => write!(f, "Code"), + Quoted(quoted) => write!(f, "{}", quoted), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), Parenthesized(typ) => write!(f, "({typ})"), + Resolved(_) => write!(f, "(resolved type)"), } } } @@ -251,6 +265,10 @@ impl UnresolvedType { pub fn unspecified() -> UnresolvedType { UnresolvedType { typ: UnresolvedTypeData::Unspecified, span: None } } + + pub(crate) fn is_type_expression(&self) -> bool { + matches!(&self.typ, UnresolvedTypeData::Expression(_)) + } } impl UnresolvedTypeData { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs index 9b2c0fbfee82..48e34ad7fc9b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/statement.rs @@ -608,6 +608,7 @@ impl ForRange { object: Expression::new(array_ident.clone(), array_span), method_name: Ident::new("len".to_string(), array_span), generics: None, + is_macro_call: false, arguments: vec![], })); let end_range = Expression::new(end_range, array_span); @@ -727,7 +728,11 @@ impl Display for LValue { impl Display for Path { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let segments = vecmap(&self.segments, ToString::to_string); - write!(f, "{}::{}", self.kind, segments.join("::")) + if self.kind == PathKind::Plain { + write!(f, "{}", segments.join("::")) + } else { + write!(f, "{}::{}", self.kind, segments.join("::")) + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs index bda6b8c0b114..bb2d89841b96 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/structure.rs @@ -20,7 +20,7 @@ impl NoirStruct { pub fn new( name: Ident, attributes: Vec, - generics: Vec, + generics: UnresolvedGenerics, fields: Vec<(Ident, UnresolvedType)>, span: Span, ) -> NoirStruct { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs index 772675723b53..b1b14e3f6570 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/traits.rs @@ -14,7 +14,7 @@ use crate::node_interner::TraitId; #[derive(Clone, Debug)] pub struct NoirTrait { pub name: Ident, - pub generics: Vec, + pub generics: UnresolvedGenerics, pub where_clause: Vec, pub span: Span, pub items: Vec, @@ -26,7 +26,7 @@ pub struct NoirTrait { pub enum TraitItem { Function { name: Ident, - generics: Vec, + generics: UnresolvedGenerics, parameters: Vec<(Ident, UnresolvedType)>, return_type: FunctionReturnType, where_clause: Vec, @@ -49,6 +49,7 @@ pub struct TypeImpl { pub object_type: UnresolvedType, pub type_span: Span, pub generics: UnresolvedGenerics, + pub where_clause: Vec, pub methods: Vec<(NoirFunction, Span)>, } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs index c222e08e77a5..443267380b54 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/debug/mod.rs @@ -470,7 +470,7 @@ impl DebugInstrumenter { .join(",\n"); let (program, errors) = parse_program(&format!( r#" - use dep::__debug::{{ + use __debug::{{ __debug_var_assign, __debug_var_drop, __debug_fn_enter, @@ -581,6 +581,7 @@ fn build_assign_var_stmt(var_id: SourceVarId, expr: ast::Expression) -> ast::Sta ), span, }), + is_macro_call: false, arguments: vec![uint_expr(var_id.0 as u128, span), expr], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } @@ -599,6 +600,7 @@ fn build_drop_var_stmt(var_id: SourceVarId, span: Span) -> ast::Statement { ), span, }), + is_macro_call: false, arguments: vec![uint_expr(var_id.0 as u128, span)], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } @@ -626,6 +628,7 @@ fn build_assign_member_stmt( ), span, }), + is_macro_call: false, arguments: [ vec![uint_expr(var_id.0 as u128, span)], vec![expr.clone()], @@ -649,6 +652,7 @@ fn build_debug_call_stmt(fname: &str, fn_id: DebugFnId, span: Span) -> ast::Stat ), span, }), + is_macro_call: false, arguments: vec![uint_expr(fn_id.0 as u128, span)], })); ast::Statement { kind: ast::StatementKind::Semi(ast::Expression { kind, span }), span } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index a922f552c4b1..7d304990dd81 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -28,7 +28,8 @@ use crate::{ MethodCallExpression, PrefixExpression, }, node_interner::{DefinitionKind, ExprId, FuncId}, - Shared, StructType, Type, + token::Tokens, + Kind, QuotedType, Shared, StructType, Type, }; use super::Elaborator; @@ -51,7 +52,20 @@ impl<'context> Elaborator<'context> { ExpressionKind::If(if_) => self.elaborate_if(*if_), ExpressionKind::Variable(variable, generics) => { let generics = generics.map(|option_inner| { - option_inner.into_iter().map(|generic| self.resolve_type(generic)).collect() + option_inner + .into_iter() + .map(|generic| { + // All type expressions should resolve to a `Type::Constant` + if generic.is_type_expression() { + self.resolve_type_inner( + generic, + &Kind::Numeric(Box::new(Type::default_int_type())), + ) + } else { + self.resolve_type(generic) + } + }) + .collect() }); return self.elaborate_variable(variable, generics); } @@ -64,6 +78,10 @@ impl<'context> Elaborator<'context> { } ExpressionKind::Resolved(id) => return (id, self.interner.id_type(id)), ExpressionKind::Error => (HirExpression::Error, Type::Error), + ExpressionKind::Unquote(_) => { + self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span }); + (HirExpression::Error, Type::Error) + } }; let id = self.interner.push_expr(hir_expr); self.interner.push_expr_location(id, expr.span, self.file); @@ -280,10 +298,22 @@ impl<'context> Elaborator<'context> { (typ, arg, span) }); + // Avoid cloning arguments unless this is a macro call + let mut comptime_args = Vec::new(); + if call.is_macro_call { + comptime_args = arguments.clone(); + } + let location = Location::new(span, self.file); - let call = HirCallExpression { func, arguments, location }; - let typ = self.type_check_call(&call, func_type, args, span); - (HirExpression::Call(call), typ) + let hir_call = HirCallExpression { func, arguments, location }; + let typ = self.type_check_call(&hir_call, func_type, args, span); + + if call.is_macro_call { + self.call_macro(func, comptime_args, location, typ) + .unwrap_or_else(|| (HirExpression::Error, Type::Error)) + } else { + (HirExpression::Call(hir_call), typ) + } } fn elaborate_method_call( @@ -627,13 +657,15 @@ impl<'context> Elaborator<'context> { (expr, Type::Function(arg_types, Box::new(body_type), Box::new(env_type))) } - fn elaborate_quote(&mut self, block: BlockExpression) -> (HirExpression, Type) { - (HirExpression::Quote(block), Type::Code) + fn elaborate_quote(&mut self, mut tokens: Tokens) -> (HirExpression, Type) { + tokens = self.find_unquoted_exprs_tokens(tokens); + (HirExpression::Quote(tokens), Type::Quoted(QuotedType::Quoted)) } fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { let (block, _typ) = self.elaborate_block_expression(block); - let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + let mut interpreter = + Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_block(block); self.inline_comptime_value(value, span) } @@ -661,4 +693,75 @@ impl<'context> Elaborator<'context> { Err(error) => make_error(self, error), } } + + fn try_get_comptime_function( + &mut self, + func: ExprId, + location: Location, + ) -> Result { + match self.interner.expression(&func) { + HirExpression::Ident(ident, _generics) => { + let definition = self.interner.definition(ident.id); + if let DefinitionKind::Function(function) = definition.kind { + let meta = self.interner.function_modifiers(&function); + if meta.is_comptime { + Ok(function) + } else { + Err(ResolverError::MacroIsNotComptime { span: location.span }) + } + } else { + Err(ResolverError::InvalidSyntaxInMacroCall { span: location.span }) + } + } + _ => Err(ResolverError::InvalidSyntaxInMacroCall { span: location.span }), + } + } + + /// Call a macro function and inlines its code at the call site. + /// This will also perform a type check to ensure that the return type is an `Expr` value. + fn call_macro( + &mut self, + func: ExprId, + arguments: Vec, + location: Location, + return_type: Type, + ) -> Option<(HirExpression, Type)> { + self.unify(&return_type, &Type::Quoted(QuotedType::Quoted), || { + TypeCheckError::MacroReturningNonExpr { typ: return_type.clone(), span: location.span } + }); + + let function = match self.try_get_comptime_function(func, location) { + Ok(function) => function, + Err(error) => { + self.push_err(error); + return None; + } + }; + + let mut interpreter = + Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + + let mut comptime_args = Vec::new(); + let mut errors = Vec::new(); + + for argument in arguments { + match interpreter.evaluate(argument) { + Ok(arg) => { + let location = interpreter.interner.expr_location(&argument); + comptime_args.push((arg, location)); + } + Err(error) => errors.push((error.into(), self.file)), + } + } + + if !errors.is_empty() { + self.errors.append(&mut errors); + return None; + } + + let bindings = interpreter.interner.get_instantiation_bindings(func).clone(); + let result = interpreter.call_function(function, comptime_args, bindings, location); + let (expr_id, typ) = self.inline_comptime_value(result, location.span); + Some((self.interner.expression(&expr_id), typ)) + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs index 4859ac5f97ca..af6f4cdb42f3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/lints.rs @@ -130,15 +130,6 @@ pub(super) fn recursive_non_entrypoint_function( } } -/// Test functions cannot have arguments in order to be executable. -pub(super) fn test_function_with_args(func: &NoirFunction) -> Option { - if func.attributes().is_test_function() && !func.parameters().is_empty() { - Some(ResolverError::TestFunctionHasParameters { span: func.name_ident().span() }) - } else { - None - } -} - /// Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime. pub(super) fn unconstrained_function_args( function_args: &[(Type, ExprId, Span)], @@ -146,7 +137,7 @@ pub(super) fn unconstrained_function_args( function_args .iter() .filter_map(|(typ, _, span)| { - if type_contains_mutable_reference(typ) { + if !typ.is_valid_for_unconstrained_boundary() { Some(TypeCheckError::ConstrainedReferenceToUnconstrained { span: *span }) } else { None @@ -162,17 +153,13 @@ pub(super) fn unconstrained_function_return( ) -> Option { if return_type.contains_slice() { Some(TypeCheckError::UnconstrainedSliceReturnToConstrained { span }) - } else if type_contains_mutable_reference(return_type) { + } else if !return_type.is_valid_for_unconstrained_boundary() { Some(TypeCheckError::UnconstrainedReferenceToConstrained { span }) } else { None } } -fn type_contains_mutable_reference(typ: &Type) -> bool { - matches!(&typ.follow_bindings(), Type::MutableReference(_)) -} - /// Only entrypoint functions require a `pub` visibility modifier applied to their return types. /// /// Application of `pub` to other functions is not meaningful and is a mistake. diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index 37ad74b78b0a..e0671d6f7ffa 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -6,12 +6,13 @@ use std::{ use crate::{ ast::{FunctionKind, UnresolvedTraitConstraint}, hir::{ - comptime::{self, Interpreter}, + comptime::{self, Interpreter, InterpreterError, Value}, def_collector::{ dc_crate::{ filter_literal_globals, CompilationError, ImplMap, UnresolvedGlobal, UnresolvedStruct, UnresolvedTypeAlias, }, + dc_mod, errors::DuplicateType, }, resolution::{errors::ResolverError, path_resolver::PathResolver, resolver::LambdaContext}, @@ -22,6 +23,7 @@ use crate::{ expr::HirIdent, function::{FunctionBody, Parameters}, traits::TraitConstraint, + types::{Generics, Kind, ResolvedGeneric}, }, macros_api::{ BlockExpression, Ident, NodeInterner, NoirFunction, NoirStruct, Pattern, @@ -30,10 +32,11 @@ use crate::{ node_interner::{ DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, TraitId, TypeAliasId, }, - Shared, Type, TypeVariable, + parser::TopLevelStatement, + Shared, Type, TypeBindings, TypeVariable, }; use crate::{ - ast::{TraitBound, UnresolvedGenerics}, + ast::{TraitBound, UnresolvedGeneric, UnresolvedGenerics}, graph::CrateId, hir::{ def_collector::{dc_crate::CollectedItems, errors::DefCollectorErrorKind}, @@ -44,7 +47,6 @@ use crate::{ hir_def::function::{FuncMeta, HirFunction}, macros_api::{Param, Path, UnresolvedType, UnresolvedTypeData}, node_interner::TraitImplId, - Generics, }; use crate::{ hir::{ @@ -62,6 +64,7 @@ mod scope; mod statements; mod traits; mod types; +mod unquote; use fm::FileId; use iter_extended::vecmap; @@ -89,22 +92,13 @@ pub struct Elaborator<'context> { file: FileId, - in_unconstrained_fn: bool, nested_loops: usize, - /// True if the current module is a contract. - /// This is usually determined by self.path_resolver.module_id(), but it can - /// be overridden for impls. Impls are an odd case since the methods within resolve - /// as if they're in the parent module, but should be placed in a child module. - /// Since they should be within a child module, in_contract is manually set to false - /// for these so we can still resolve them in the parent module without them being in a contract. - in_contract: bool, - /// Contains a mapping of the current struct or functions's generics to /// unique type variables if we're resolving a struct. Empty otherwise. /// This is a Vec rather than a map to preserve the order a functions generics /// were declared in. - generics: Vec<(Rc, TypeVariable, Span)>, + generics: Vec, /// When resolving lambda expressions, we need to keep track of the variables /// that are captured. We do this in order to create the hidden environment @@ -180,9 +174,7 @@ impl<'context> Elaborator<'context> { interner: &mut context.def_interner, def_maps: &mut context.def_maps, file: FileId::dummy(), - in_unconstrained_fn: false, nested_loops: 0, - in_contract: false, generics: Vec::new(), lambda_stack: Vec::new(), self_type: None, @@ -204,10 +196,22 @@ impl<'context> Elaborator<'context> { pub fn elaborate( context: &'context mut Context, crate_id: CrateId, - mut items: CollectedItems, + items: CollectedItems, ) -> Vec<(CompilationError, FileId)> { let mut this = Self::new(context, crate_id); + // Filter out comptime items to execute their functions first if needed. + // This step is why comptime items can only refer to other comptime items + // in the same crate, but can refer to any item in dependencies. Trying to + // run these at the same time as other items would lead to them seeing empty + // function bodies from functions that have yet to be elaborated. + let (comptime_items, runtime_items) = Self::filter_comptime_items(items); + this.elaborate_items(comptime_items); + this.elaborate_items(runtime_items); + this.errors + } + + fn elaborate_items(&mut self, mut items: CollectedItems) { // We must first resolve and intern the globals before we can resolve any stmts inside each function. // Each function uses its own resolver with a newly created ScopeForest, and must be resolved again to be within a function's scope // @@ -215,61 +219,67 @@ impl<'context> Elaborator<'context> { // the values of integer globals as numeric generics. let (literal_globals, non_literal_globals) = filter_literal_globals(items.globals); for global in non_literal_globals { - this.unresolved_globals.insert(global.global_id, global); + self.unresolved_globals.insert(global.global_id, global); } for global in literal_globals { - this.elaborate_global(global); + self.elaborate_global(global); } for (alias_id, alias) in items.type_aliases { - this.define_type_alias(alias_id, alias); + self.define_type_alias(alias_id, alias); } - this.define_function_metas(&mut items.functions, &mut items.impls, &mut items.trait_impls); - this.collect_traits(items.traits); - // Must resolve structs before we resolve globals. - this.collect_struct_definitions(items.types); + let generated_items = self.collect_struct_definitions(items.types); - // Bind trait impls to their trait. Collect trait functions, that have a - // default implementation, which hasn't been overridden. - for trait_impl in &mut items.trait_impls { - this.collect_trait_impl(trait_impl); - } + self.define_function_metas(&mut items.functions, &mut items.impls, &mut items.trait_impls); + + self.collect_traits(items.traits); // Before we resolve any function symbols we must go through our impls and // re-collect the methods within into their proper module. This cannot be // done during def collection since we need to be able to resolve the type of // the impl since that determines the module we should collect into. - // - // These are resolved after trait impls so that struct methods are chosen - // over trait methods if there are name conflicts. for ((_self_type, module), impls) in &mut items.impls { - this.collect_impls(*module, impls); + self.collect_impls(*module, impls); + } + + // Bind trait impls to their trait. Collect trait functions, that have a + // default implementation, which hasn't been overridden. + for trait_impl in &mut items.trait_impls { + self.collect_trait_impl(trait_impl); } // We must wait to resolve non-literal globals until after we resolve structs since struct - // globals will need to reference the struct type they're initialized to to ensure they are valid. - while let Some((_, global)) = this.unresolved_globals.pop_first() { - this.elaborate_global(global); + // globals will need to reference the struct type they're initialized to ensure they are valid. + while let Some((_, global)) = self.unresolved_globals.pop_first() { + self.elaborate_global(global); + } + + // After everything is collected, we can elaborate our generated items. + // It may be better to inline these within `items` entirely since elaborating them + // all here means any globals will not see these. Inlining them completely within `items` + // means we must be more careful about missing any additional items that need to be already + // elaborated. E.g. if a new struct is created, we've already passed the code path to + // elaborate them. + if !generated_items.is_empty() { + self.elaborate_items(generated_items); } for functions in items.functions { - this.elaborate_functions(functions); + self.elaborate_functions(functions); } for impls in items.impls.into_values() { - this.elaborate_impls(impls); + self.elaborate_impls(impls); } for trait_impl in items.trait_impls { - this.elaborate_trait_impl(trait_impl); + self.elaborate_trait_impl(trait_impl); } - let cycle_errors = this.interner.check_for_dependency_cycles(); - this.errors.extend(cycle_errors); - this.errors + self.errors.extend(self.interner.check_for_dependency_cycles()); } /// Runs `f` and if it modifies `self.generics`, `self.generics` is truncated @@ -310,11 +320,6 @@ impl<'context> Elaborator<'context> { let old_function = std::mem::replace(&mut self.current_function, Some(id)); - // Without this, impl methods can accidentally be placed in contracts. See #3254 - if self.self_type.is_some() { - self.in_contract = false; - } - self.scopes.start_function(); let old_item = std::mem::replace(&mut self.current_item, Some(DependencyId::Function(id))); @@ -322,18 +327,26 @@ impl<'context> Elaborator<'context> { self.trait_bounds = func_meta.trait_constraints.clone(); - if self.interner.function_modifiers(&id).is_unconstrained { - self.in_unconstrained_fn = true; + // Introduce all numeric generics into scope + for generic in &func_meta.all_generics { + if let Kind::Numeric(typ) = &generic.kind { + let definition = DefinitionKind::GenericType(generic.type_var.clone()); + let ident = Ident::new(generic.name.to_string(), generic.span); + let hir_ident = + self.add_variable_decl_inner(ident, false, false, false, definition); + self.interner.push_definition_type(hir_ident.id, *typ.clone()); + } } // The DefinitionIds for each parameter were already created in define_function_meta // so we need to reintroduce the same IDs into scope here. for parameter in &func_meta.parameter_idents { let name = self.interner.definition_name(parameter.id).to_owned(); - self.add_existing_variable_to_scope(name, parameter.clone()); + self.add_existing_variable_to_scope(name, parameter.clone(), true); } self.generics = func_meta.all_generics.clone(); + self.declare_numeric_generics(&func_meta.parameters, func_meta.return_type()); self.add_trait_constraints_to_scope(&func_meta); @@ -404,7 +417,7 @@ impl<'context> Elaborator<'context> { meta.function_body = FunctionBody::Resolved; self.trait_bounds.clear(); - self.in_unconstrained_fn = false; + self.type_variables.clear(); self.interner.update_fn(id, hir_func); self.current_function = old_function; self.current_item = old_item; @@ -428,7 +441,7 @@ impl<'context> Elaborator<'context> { generics.push(new_generic.clone()); let name = format!("impl {trait_path}"); - let generic_type = Type::NamedGeneric(new_generic, Rc::new(name)); + let generic_type = Type::NamedGeneric(new_generic, Rc::new(name), Kind::Normal); let trait_bound = TraitBound { trait_path, trait_id: None, trait_generics }; if let Some(new_constraint) = self.resolve_trait_bound(&trait_bound, generic_type.clone()) { @@ -445,25 +458,56 @@ impl<'context> Elaborator<'context> { // Map the generic to a fresh type variable let id = self.interner.next_type_variable_id(); let typevar = TypeVariable::unbound(id); - let span = generic.0.span(); + let ident = generic.ident(); + let span = ident.0.span(); + + // Resolve the generic's kind + let kind = self.resolve_generic_kind(generic); // Check for name collisions of this generic - let name = Rc::new(generic.0.contents.clone()); + let name = Rc::new(ident.0.contents.clone()); + + let resolved_generic = + ResolvedGeneric { name: name.clone(), type_var: typevar.clone(), kind, span }; - if let Some((_, _, first_span)) = self.find_generic(&name) { + if let Some(generic) = self.find_generic(&name) { self.push_err(ResolverError::DuplicateDefinition { - name: generic.0.contents.clone(), - first_span: *first_span, + name: ident.0.contents.clone(), + first_span: generic.span, second_span: span, }); } else { - self.generics.push((name, typevar.clone(), span)); + self.generics.push(resolved_generic.clone()); } - typevar + resolved_generic }) } + /// Return the kind of an unresolved generic. + /// If a numeric generic has been specified, resolve the annotated type to make + /// sure only primitive numeric types are being used. + pub(super) fn resolve_generic_kind(&mut self, generic: &UnresolvedGeneric) -> Kind { + if let UnresolvedGeneric::Numeric { ident, typ } = generic { + let typ = typ.clone(); + let typ = if typ.is_type_expression() { + self.resolve_type_inner(typ, &Kind::Numeric(Box::new(Type::default_int_type()))) + } else { + self.resolve_type(typ.clone()) + }; + if !matches!(typ, Type::FieldElement | Type::Integer(_, _)) { + let unsupported_typ_err = ResolverError::UnsupportedNumericGenericType { + ident: ident.clone(), + typ: typ.clone(), + }; + self.push_err(unsupported_typ_err); + } + Kind::Numeric(Box::new(typ)) + } else { + Kind::Normal + } + } + fn push_err(&mut self, error: impl Into) { self.errors.push((error.into(), self.file)); } @@ -512,12 +556,20 @@ impl<'context> Elaborator<'context> { } fn resolve_trait_bound(&mut self, bound: &TraitBound, typ: Type) -> Option { - let trait_generics = vecmap(&bound.trait_generics, |typ| self.resolve_type(typ.clone())); + let the_trait = self.lookup_trait_or_error(bound.trait_path.clone())?; + + let resolved_generics = &the_trait.generics.clone(); + assert_eq!(resolved_generics.len(), bound.trait_generics.len()); + let generics_with_types = resolved_generics.iter().zip(&bound.trait_generics); + let trait_generics = vecmap(generics_with_types, |(generic, typ)| { + self.resolve_type_inner(typ.clone(), &generic.kind) + }); - let span = bound.trait_path.span(); let the_trait = self.lookup_trait_or_error(bound.trait_path.clone())?; let trait_id = the_trait.id; + let span = bound.trait_path.span(); + let expected_generics = the_trait.generics.len(); let actual_generics = trait_generics.len(); @@ -546,10 +598,13 @@ impl<'context> Elaborator<'context> { ) { self.current_function = Some(func_id); - // Without this, impl methods can accidentally be placed in contracts. See #3254 - if self.self_type.is_some() { - self.in_contract = false; - } + let in_contract = if self.self_type.is_some() { + // Without this, impl methods can accidentally be placed in contracts. + // See: https://github.com/noir-lang/noir/issues/3254 + false + } else { + self.in_contract() + }; self.scopes.start_function(); self.current_item = Some(DependencyId::Function(func_id)); @@ -558,18 +613,18 @@ impl<'context> Elaborator<'context> { let id = self.interner.function_definition_id(func_id); let name_ident = HirIdent::non_trait_method(id, location); - let is_entry_point = self.is_entry_point_function(func); + let is_entry_point = self.is_entry_point_function(func, in_contract); self.run_lint(|_| lints::inlining_attributes(func).map(Into::into)); self.run_lint(|_| lints::missing_pub(func, is_entry_point).map(Into::into)); self.run_lint(|elaborator| { - lints::unnecessary_pub_return(func, elaborator.pub_allowed(func)).map(Into::into) + lints::unnecessary_pub_return(func, elaborator.pub_allowed(func, in_contract)) + .map(Into::into) }); self.run_lint(|_| lints::oracle_not_marked_unconstrained(func).map(Into::into)); self.run_lint(|elaborator| { lints::low_level_function_outside_stdlib(func, elaborator.crate_id).map(Into::into) }); - self.run_lint(|_| lints::test_function_with_args(func).map(Into::into)); self.run_lint(|_| { lints::recursive_non_entrypoint_function(func, is_entry_point).map(Into::into) }); @@ -580,12 +635,12 @@ impl<'context> Elaborator<'context> { let has_no_predicates_attribute = func.attributes().is_no_predicates(); let should_fold = func.attributes().is_foldable(); let has_inline_attribute = has_no_predicates_attribute || should_fold; - let is_pub_allowed = self.pub_allowed(func); + let is_pub_allowed = self.pub_allowed(func, in_contract); self.add_generics(&func.def.generics); let mut trait_constraints = self.resolve_trait_constraints(&func.def.where_clause); - let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); + let mut generics = vecmap(&self.generics, |generic| generic.type_var.clone()); let mut parameters = Vec::new(); let mut parameter_types = Vec::new(); let mut parameter_idents = Vec::new(); @@ -601,7 +656,7 @@ impl<'context> Elaborator<'context> { UnresolvedTypeData::TraitAsType(path, args) => { self.desugar_impl_trait_arg(path, args, &mut generics, &mut trait_constraints) } - _ => self.resolve_type_inner(typ), + _ => self.resolve_type_inner(typ, &Kind::Normal), }; self.check_if_type_is_valid_for_program_input( @@ -610,6 +665,7 @@ impl<'context> Elaborator<'context> { has_inline_attribute, type_span, ); + let pattern = self.elaborate_pattern_and_store_ids( pattern, typ.clone(), @@ -634,8 +690,8 @@ impl<'context> Elaborator<'context> { let direct_generics = func.def.generics.iter(); let direct_generics = direct_generics - .filter_map(|generic| self.find_generic(&generic.0.contents)) - .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) + .filter_map(|generic| self.find_generic(&generic.ident().0.contents)) + .map(|ResolvedGeneric { name, type_var, .. }| (name.clone(), type_var.clone())) .collect(); let statements = std::mem::take(&mut func.def.body.statements); @@ -658,6 +714,7 @@ impl<'context> Elaborator<'context> { is_entry_point, is_trait_function, has_inline_attribute, + source_crate: self.crate_id, function_body: FunctionBody::Unresolved(func.kind, body, func.def.span), }; @@ -686,18 +743,30 @@ impl<'context> Elaborator<'context> { /// True if the `pub` keyword is allowed on parameters in this function /// `pub` on function parameters is only allowed for entry point functions - fn pub_allowed(&self, func: &NoirFunction) -> bool { - self.is_entry_point_function(func) || func.attributes().is_foldable() + fn pub_allowed(&self, func: &NoirFunction, in_contract: bool) -> bool { + self.is_entry_point_function(func, in_contract) || func.attributes().is_foldable() } - fn is_entry_point_function(&self, func: &NoirFunction) -> bool { - if self.in_contract { + /// Returns `true` if the current module is a contract. + /// + /// This is usually determined by `self.module_id()`, but it can + /// be overridden for impls. Impls are an odd case since the methods within resolve + /// as if they're in the parent module, but should be placed in a child module. + /// Since they should be within a child module, they should be elaborated as if + /// `in_contract` is `false` so we can still resolve them in the parent module without them being in a contract. + fn in_contract(&self) -> bool { + self.module_id().module(self.def_maps).is_contract + } + + fn is_entry_point_function(&self, func: &NoirFunction, in_contract: bool) -> bool { + if in_contract { func.attributes().is_contract_entry_point() } else { func.name() == MAIN_FUNCTION } } + // TODO(https://github.com/noir-lang/noir/issues/5156): Remove implicit numeric generics fn declare_numeric_generics(&mut self, params: &Parameters, return_type: &Type) { if self.generics.is_empty() { return; @@ -710,12 +779,27 @@ impl<'context> Elaborator<'context> { // We can fail to find the generic in self.generics if it is an implicit one created // by the compiler. This can happen when, e.g. eliding array lengths using the slice // syntax [T]. - if let Some((name, _, span)) = - self.generics.iter().find(|(name, _, _)| name.as_ref() == &name_to_find) + if let Some(ResolvedGeneric { name, span, kind, .. }) = + self.generics.iter_mut().find(|generic| generic.name.as_ref() == &name_to_find) { + let scope = self.scopes.get_mut_scope(); + let value = scope.find(&name_to_find); + if value.is_some() { + // With the addition of explicit numeric generics we do not want to introduce numeric generics in this manner + // However, this is going to be a big breaking change so for now we simply issue a warning while users have time + // to transition to the new syntax + // e.g. this code would break with a duplicate definition error: + // ``` + // fn foo(arr: [Field; N]) { } + // ``` + continue; + } + *kind = Kind::Numeric(Box::new(Type::default_int_type())); let ident = Ident::new(name.to_string(), *span); let definition = DefinitionKind::GenericType(type_variable); - self.add_variable_decl_inner(ident, false, false, false, definition); + self.add_variable_decl_inner(ident.clone(), false, false, false, definition); + + self.push_err(ResolverError::UseExplicitNumericGeneric { ident }); } } } @@ -741,7 +825,7 @@ impl<'context> Elaborator<'context> { } } - fn elaborate_impls(&mut self, impls: Vec<(Vec, Span, UnresolvedFunctions)>) { + fn elaborate_impls(&mut self, impls: Vec<(UnresolvedGenerics, Span, UnresolvedFunctions)>) { for (_, _, functions) in impls { self.file = functions.file_id; self.recover_generics(|this| this.elaborate_functions(functions)); @@ -771,7 +855,7 @@ impl<'context> Elaborator<'context> { fn collect_impls( &mut self, module: LocalModuleId, - impls: &mut [(Vec, Span, UnresolvedFunctions)], + impls: &mut [(UnresolvedGenerics, Span, UnresolvedFunctions)], ) { self.local_module = module; @@ -788,7 +872,6 @@ impl<'context> Elaborator<'context> { self.local_module = trait_impl.module_id; self.file = trait_impl.file_id; self.current_trait_impl = trait_impl.impl_id; - trait_impl.trait_id = self.resolve_trait_by_path(trait_impl.trait_path.clone()); let self_type = trait_impl.methods.self_type.clone(); let self_type = @@ -832,7 +915,7 @@ impl<'context> Elaborator<'context> { methods, }); - let generics = vecmap(&self.generics, |(_, type_variable, _)| type_variable.clone()); + let generics = vecmap(&self.generics, |generic| generic.type_var.clone()); if let Err((prev_span, prev_file)) = self.interner.add_trait_implementation( self_type.clone(), @@ -856,13 +939,17 @@ impl<'context> Elaborator<'context> { } self.generics.clear(); + self.current_trait_impl = None; self.self_type = None; } - fn get_module_mut(&mut self, module: ModuleId) -> &mut ModuleData { + fn get_module_mut( + def_maps: &mut BTreeMap, + module: ModuleId, + ) -> &mut ModuleData { let message = "A crate should always be present for a given crate id"; - &mut self.def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] + &mut def_maps.get_mut(&module.krate).expect(message).modules[module.local_id.0] } fn declare_methods_on_struct( @@ -890,7 +977,7 @@ impl<'context> Elaborator<'context> { // Grab the module defined by the struct type. Note that impls are a case // where the module the methods are added to is not the same as the module // they are resolved in. - let module = self.get_module_mut(struct_ref.id.module_id()); + let module = Self::get_module_mut(self.def_maps, struct_ref.id.module_id()); for (_, method_id, method) in &functions.functions { // If this method was already declared, remove it from the module so it cannot @@ -899,22 +986,37 @@ impl<'context> Elaborator<'context> { // If not, that is specialization which is allowed. let name = method.name_ident().clone(); if module.declare_function(name, ItemVisibility::Public, *method_id).is_err() { - module.remove_function(method.name_ident()); + let existing = module.find_func_with_name(method.name_ident()).expect( + "declare_function should only error if there is an existing function", + ); + + // Only remove the existing function from scope if it is from a trait impl as + // well. If it is from a non-trait impl that should override trait impl methods + // anyway so that Foo::bar always resolves to the non-trait impl version. + if self.interner.function_meta(&existing).trait_impl.is_some() { + module.remove_function(method.name_ident()); + } } } - self.declare_struct_methods(self_type, &function_ids); + // Trait impl methods are already declared in NodeInterner::add_trait_implementation + if !is_trait_impl { + self.declare_methods(self_type, &function_ids); + } // We can define methods on primitive types only if we're in the stdlib } else if !is_trait_impl && *self_type != Type::Error { if self.crate_id.is_stdlib() { - self.declare_struct_methods(self_type, &function_ids); + // Trait impl methods are already declared in NodeInterner::add_trait_implementation + if !is_trait_impl { + self.declare_methods(self_type, &function_ids); + } } else { self.push_err(DefCollectorErrorKind::NonStructTypeInImpl { span }); } } } - fn declare_struct_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { + fn declare_methods(&mut self, self_type: &Type, function_ids: &[FuncId]) { for method_id in function_ids { let method_name = self.interner.function_name(method_id).to_owned(); @@ -1057,22 +1159,55 @@ impl<'context> Elaborator<'context> { self.generics.clear(); } - fn collect_struct_definitions(&mut self, structs: BTreeMap) { + fn collect_struct_definitions( + &mut self, + structs: BTreeMap, + ) -> CollectedItems { // This is necessary to avoid cloning the entire struct map // when adding checks after each struct field is resolved. let struct_ids = structs.keys().copied().collect::>(); + // This will contain any additional top-level items that are generated at compile-time + // via macros. This often includes derived trait impls. + let mut generated_items = CollectedItems::default(); + // Resolve each field in each struct. // Each struct should already be present in the NodeInterner after def collection. - for (type_id, typ) in structs { + for (type_id, mut typ) in structs { self.file = typ.file_id; self.local_module = typ.module_id; - let (generics, fields) = self.resolve_struct_fields(typ.struct_def, type_id); + let attributes = std::mem::take(&mut typ.struct_def.attributes); + let span = typ.struct_def.span; + + let fields = self.resolve_struct_fields(typ.struct_def, type_id); self.interner.update_struct(type_id, |struct_def| { struct_def.set_fields(fields); - struct_def.generics = generics; + + // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this with implicit numeric generics + // This is only necessary for resolving named types when implicit numeric generics are used. + let mut found_names = Vec::new(); + struct_def.find_numeric_generics_in_fields(&mut found_names); + for generic in struct_def.generics.iter_mut() { + for found_generic in found_names.iter() { + if found_generic == generic.name.as_str() { + if matches!(generic.kind, Kind::Normal) { + let ident = Ident::new(generic.name.to_string(), generic.span); + self.errors.push(( + CompilationError::ResolverError( + ResolverError::UseExplicitNumericGeneric { ident }, + ), + self.file, + )); + generic.kind = Kind::Numeric(Box::new(Type::default_int_type())); + } + break; + } + } + } }); + + self.run_comptime_attributes_on_struct(attributes, type_id, span, &mut generated_items); } // Check whether the struct fields have nested slices @@ -1080,6 +1215,7 @@ impl<'context> Elaborator<'context> { // make sure every struct's fields is accurately set. for id in struct_ids { let struct_type = self.interner.get_struct(id); + // Only handle structs without generics as any generics args will be checked // after monomorphization when performing SSA codegen if struct_type.borrow().generics.is_empty() { @@ -1093,35 +1229,95 @@ impl<'context> Elaborator<'context> { } } } + + generated_items + } + + fn run_comptime_attributes_on_struct( + &mut self, + attributes: Vec, + struct_id: StructId, + span: Span, + generated_items: &mut CollectedItems, + ) { + for attribute in attributes { + if let SecondaryAttribute::Custom(name) = attribute { + if let Err(error) = + self.run_comptime_attribute_on_struct(name, struct_id, span, generated_items) + { + self.errors.push(error); + } + } + } + } + + fn run_comptime_attribute_on_struct( + &mut self, + attribute: String, + struct_id: StructId, + span: Span, + generated_items: &mut CollectedItems, + ) -> Result<(), (CompilationError, FileId)> { + let id = self + .lookup_global(Path::from_single(attribute, span)) + .map_err(|_| (ResolverError::UnknownAnnotation { span }.into(), self.file))?; + + let definition = self.interner.definition(id); + let DefinitionKind::Function(function) = definition.kind else { + return Err((ResolverError::NonFunctionInAnnotation { span }.into(), self.file)); + }; + let mut interpreter = + Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); + + let location = Location::new(span, self.file); + let arguments = vec![(Value::StructDefinition(struct_id), location)]; + + let value = interpreter + .call_function(function, arguments, TypeBindings::new(), location) + .map_err(|error| error.into_compilation_error_pair())?; + + if value != Value::Unit { + let item = value + .into_top_level_item(location) + .map_err(|error| error.into_compilation_error_pair())?; + + self.add_item(item, generated_items, location); + } + + Ok(()) } pub fn resolve_struct_fields( &mut self, unresolved: NoirStruct, struct_id: StructId, - ) -> (Generics, Vec<(Ident, Type)>) { + ) -> Vec<(Ident, Type)> { self.recover_generics(|this| { - let generics = this.add_generics(&unresolved.generics); - this.current_item = Some(DependencyId::Struct(struct_id)); this.resolving_ids.insert(struct_id); + + let struct_def = this.interner.get_struct(struct_id); + this.add_existing_generics(&unresolved.generics, &struct_def.borrow().generics); + let fields = vecmap(unresolved.fields, |(ident, typ)| (ident, this.resolve_type(typ))); + this.resolving_ids.remove(&struct_id); - (generics, fields) + fields }) } fn elaborate_global(&mut self, global: UnresolvedGlobal) { - self.local_module = global.module_id; - self.file = global.file_id; + let old_module = std::mem::replace(&mut self.local_module, global.module_id); + let old_file = std::mem::replace(&mut self.file, global.file_id); + let old_item = self.current_item.take(); let global_id = global.global_id; self.current_item = Some(DependencyId::Global(global_id)); let let_stmt = global.stmt_def; - if !self.in_contract + if !self.in_contract() && let_stmt.attributes.iter().any(|attr| matches!(attr, SecondaryAttribute::Abi(_))) { let span = let_stmt.pattern.span(); @@ -1147,6 +1343,9 @@ impl<'context> Elaborator<'context> { // Otherwise we may prematurely default to a Field inside the next function if this // global was unused there, even if it is consistently used as a u8 everywhere else. self.type_variables.clear(); + self.local_module = old_module; + self.file = old_file; + self.current_item = old_item; } fn elaborate_comptime_global(&mut self, global_id: GlobalId) { @@ -1159,7 +1358,8 @@ impl<'context> Elaborator<'context> { let definition_id = global.definition_id; let location = global.location; - let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + let mut interpreter = + Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); if let Err(error) = interpreter.evaluate_let(let_statement) { self.errors.push(error.into_compilation_error_pair()); @@ -1186,11 +1386,13 @@ impl<'context> Elaborator<'context> { self.local_module = *local_module; for (generics, _, function_set) in function_sets { + self.file = function_set.file_id; self.add_generics(generics); let self_type = self.resolve_type(self_type.clone()); function_set.self_type = Some(self_type.clone()); self.self_type = Some(self_type); self.define_function_metas_for_functions(function_set); + self.self_type = None; self.generics.clear(); } } @@ -1199,16 +1401,33 @@ impl<'context> Elaborator<'context> { self.file = trait_impl.file_id; self.local_module = trait_impl.module_id; + trait_impl.trait_id = self.resolve_trait_by_path(trait_impl.trait_path.clone()); let unresolved_type = &trait_impl.object_type; + self.add_generics(&trait_impl.generics); trait_impl.resolved_generics = self.generics.clone(); - let trait_generics = - vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone())); + // Fetch trait constraints here + let trait_generics = if let Some(trait_id) = trait_impl.trait_id { + let trait_def = self.interner.get_trait(trait_id); + let resolved_generics = trait_def.generics.clone(); + assert_eq!(resolved_generics.len(), trait_impl.trait_generics.len()); + trait_impl + .trait_generics + .iter() + .enumerate() + .map(|(i, generic)| { + self.resolve_type_inner(generic.clone(), &resolved_generics[i].kind) + }) + .collect() + } else { + // We still resolve as to continue type checking + vecmap(&trait_impl.trait_generics, |generic| self.resolve_type(generic.clone())) + }; + trait_impl.resolved_trait_generics = trait_generics; let self_type = self.resolve_type(unresolved_type.clone()); - self.self_type = Some(self_type.clone()); trait_impl.methods.self_type = Some(self_type); @@ -1233,4 +1452,129 @@ impl<'context> Elaborator<'context> { }); } } + + /// Filters out comptime items from non-comptime items. + /// Returns a pair of (comptime items, non-comptime items) + fn filter_comptime_items(mut items: CollectedItems) -> (CollectedItems, CollectedItems) { + let mut function_sets = Vec::with_capacity(items.functions.len()); + let mut comptime_function_sets = Vec::new(); + + for function_set in items.functions { + let mut functions = Vec::with_capacity(function_set.functions.len()); + let mut comptime_functions = Vec::new(); + + for function in function_set.functions { + if function.2.def.is_comptime { + comptime_functions.push(function); + } else { + functions.push(function); + } + } + + let file_id = function_set.file_id; + let self_type = function_set.self_type; + let trait_id = function_set.trait_id; + + if !comptime_functions.is_empty() { + comptime_function_sets.push(UnresolvedFunctions { + functions: comptime_functions, + file_id, + trait_id, + self_type: self_type.clone(), + }); + } + + function_sets.push(UnresolvedFunctions { functions, file_id, trait_id, self_type }); + } + + let comptime = CollectedItems { + functions: comptime_function_sets, + types: BTreeMap::new(), + type_aliases: BTreeMap::new(), + traits: BTreeMap::new(), + trait_impls: Vec::new(), + globals: Vec::new(), + impls: std::collections::HashMap::new(), + }; + + items.functions = function_sets; + (comptime, items) + } + + fn add_item( + &mut self, + item: TopLevelStatement, + generated_items: &mut CollectedItems, + location: Location, + ) { + match item { + TopLevelStatement::Function(function) => { + let id = self.interner.push_empty_fn(); + let module = self.module_id(); + self.interner.push_function(id, &function.def, module, location); + let functions = vec![(self.local_module, id, function)]; + generated_items.functions.push(UnresolvedFunctions { + file_id: self.file, + functions, + trait_id: None, + self_type: None, + }); + } + TopLevelStatement::TraitImpl(mut trait_impl) => { + let methods = dc_mod::collect_trait_impl_functions( + self.interner, + &mut trait_impl, + self.crate_id, + self.file, + self.local_module, + ); + + generated_items.trait_impls.push(UnresolvedTraitImpl { + file_id: self.file, + module_id: self.local_module, + trait_generics: trait_impl.trait_generics, + trait_path: trait_impl.trait_name, + object_type: trait_impl.object_type, + methods, + generics: trait_impl.impl_generics, + where_clause: trait_impl.where_clause, + + // These last fields are filled in later + trait_id: None, + impl_id: None, + resolved_object_type: None, + resolved_generics: Vec::new(), + resolved_trait_generics: Vec::new(), + }); + } + TopLevelStatement::Global(global) => { + let (global, error) = dc_mod::collect_global( + self.interner, + self.def_maps.get_mut(&self.crate_id).unwrap(), + global, + self.file, + self.local_module, + ); + + generated_items.globals.push(global); + if let Some(error) = error { + self.errors.push(error); + } + } + // Assume that an error has already been issued + TopLevelStatement::Error => (), + + TopLevelStatement::Module(_) + | TopLevelStatement::Import(_) + | TopLevelStatement::Struct(_) + | TopLevelStatement::Trait(_) + | TopLevelStatement::Impl(_) + | TopLevelStatement::TypeAlias(_) + | TopLevelStatement::SubModule(_) => { + let item = item.to_string(); + let error = InterpreterError::UnsupportedTopLevelItemUnquote { item, location }; + self.errors.push(error.into_compilation_error_pair()); + } + } + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index e337726b5795..4f04f5c523c2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -11,11 +11,10 @@ use crate::{ }, hir_def::{ expr::{HirIdent, ImplKind}, - function::FunctionBody, stmt::HirPattern, }, macros_api::{HirExpression, Ident, Path, Pattern}, - node_interner::{DefinitionId, DefinitionKind, DependencyId, ExprId, GlobalId, TraitImplKind}, + node_interner::{DefinitionId, DefinitionKind, ExprId, GlobalId, TraitImplKind}, Shared, StructType, Type, TypeBindings, }; @@ -302,9 +301,14 @@ impl<'context> Elaborator<'context> { ident } - pub fn add_existing_variable_to_scope(&mut self, name: String, ident: HirIdent) { + pub fn add_existing_variable_to_scope( + &mut self, + name: String, + ident: HirIdent, + warn_if_unused: bool, + ) { let second_span = ident.location.span; - let resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused: true }; + let resolver_meta = ResolverMeta { num_times_used: 0, ident, warn_if_unused }; let old_value = self.scopes.get_mut_scope().add_key_value(name.clone(), resolver_meta); @@ -390,6 +394,7 @@ impl<'context> Elaborator<'context> { ) -> (ExprId, Type) { let span = variable.span; let expr = self.resolve_variable(variable); + let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone())); self.interner.push_expr_location(id, span, self.file); let typ = self.type_check_variable(expr, id, generics); @@ -415,16 +420,6 @@ impl<'context> Elaborator<'context> { match self.interner.definition(hir_ident.id).kind { DefinitionKind::Function(id) => { if let Some(current_item) = self.current_item { - // Lazily evaluate functions found within globals if necessary. - // Otherwise if we later attempt to evaluate the global it will - // see an empty function body. - if matches!(current_item, DependencyId::Global(_)) { - let meta = self.interner.function_meta(&id); - - if matches!(&meta.function_body, FunctionBody::Unresolved(..)) { - self.elaborate_function(id); - } - } self.interner.add_function_dependency(current_item, id); } } @@ -475,8 +470,8 @@ impl<'context> Elaborator<'context> { for (param, arg) in the_trait.generics.iter().zip(&constraint.trait_generics) { // Avoid binding t = t - if !arg.occurs(param.id()) { - bindings.insert(param.id(), (param.clone(), arg.clone())); + if !arg.occurs(param.type_var.id()) { + bindings.insert(param.type_var.id(), (param.type_var.clone(), arg.clone())); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index dd3e27787261..0d67c9ed3e3d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -206,7 +206,10 @@ impl<'context> Elaborator<'context> { } fn elaborate_jump(&mut self, is_break: bool, span: noirc_errors::Span) -> (HirStatement, Type) { - if !self.in_unconstrained_fn { + let in_constrained_function = self + .current_function + .map_or(true, |func_id| !self.interner.function_modifiers(&func_id).is_unconstrained); + if in_constrained_function { self.push_err(ResolverError::JumpInConstrainedFn { is_break, span }); } if self.nested_loops == 0 { @@ -432,7 +435,8 @@ impl<'context> Elaborator<'context> { fn elaborate_comptime_statement(&mut self, statement: Statement) -> (HirStatement, Type) { let span = statement.span; let (hir_statement, _typ) = self.elaborate_statement(statement); - let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes); + let mut interpreter = + Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_statement(hir_statement); let (expr, typ) = self.inline_comptime_value(value, span); (HirStatement::Expression(expr), typ) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs index 3e04dbc784a6..77ac8e476f81 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/traits.rs @@ -1,10 +1,12 @@ -use std::collections::BTreeMap; +use std::{collections::BTreeMap, rc::Rc}; use iter_extended::vecmap; use noirc_errors::Location; use crate::{ - ast::{FunctionKind, TraitItem, UnresolvedGenerics, UnresolvedTraitConstraint}, + ast::{ + FunctionKind, TraitItem, UnresolvedGeneric, UnresolvedGenerics, UnresolvedTraitConstraint, + }, hir::def_collector::dc_crate::UnresolvedTrait, hir_def::traits::{TraitConstant, TraitFunction, TraitType}, macros_api::{ @@ -13,7 +15,7 @@ use crate::{ }, node_interner::{FuncId, TraitId}, token::Attributes, - Type, TypeVariableKind, + Kind, ResolvedGeneric, Type, TypeVariableKind, }; use super::Elaborator; @@ -22,7 +24,11 @@ impl<'context> Elaborator<'context> { pub fn collect_traits(&mut self, traits: BTreeMap) { for (trait_id, unresolved_trait) in traits { self.recover_generics(|this| { - this.add_generics(&unresolved_trait.trait_def.generics); + let resolved_generics = this.interner.get_trait(trait_id).generics.clone(); + this.add_existing_generics( + &unresolved_trait.trait_def.generics, + &resolved_generics, + ); // Resolve order // 1. Trait Types ( Trait constants can have a trait type, therefore types before constants) @@ -34,7 +40,6 @@ impl<'context> Elaborator<'context> { this.interner.update_trait(trait_id, |trait_def| { trait_def.set_methods(methods); - trait_def.generics = vecmap(&this.generics, |(_, generic, _)| generic.clone()); }); }); @@ -87,10 +92,20 @@ impl<'context> Elaborator<'context> { Type::TypeVariable(self_typevar.clone(), TypeVariableKind::Normal); let name_span = the_trait.name.span(); - this.add_existing_generic("Self", name_span, self_typevar); + this.add_existing_generic( + &UnresolvedGeneric::Variable(Ident::from("Self")), + name_span, + &ResolvedGeneric { + name: Rc::new("Self".to_owned()), + type_var: self_typevar, + span: name_span, + kind: Kind::Normal, + }, + ); this.self_type = Some(self_type.clone()); let func_id = unresolved_trait.method_ids[&name.0.contents]; + this.resolve_trait_function( name, generics, @@ -105,7 +120,7 @@ impl<'context> Elaborator<'context> { let arguments = vecmap(&func_meta.parameters.0, |(_, typ, _)| typ.clone()); let return_type = func_meta.return_type().clone(); - let generics = vecmap(&this.generics, |(_, type_var, _)| type_var.clone()); + let generics = vecmap(&this.generics, |generic| generic.type_var.clone()); let default_impl_list: Vec<_> = unresolved_trait .fns_with_default_impl @@ -147,6 +162,7 @@ impl<'context> Elaborator<'context> { func_id: FuncId, ) { let old_generic_count = self.generics.len(); + self.scopes.start_function(); let kind = FunctionKind::Normal; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 3baa7054fc58..63cab40f9d3b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -5,13 +5,16 @@ use iter_extended::vecmap; use noirc_errors::{Location, Span}; use crate::{ - ast::{BinaryOpKind, IntegerBitSize, UnresolvedGenerics, UnresolvedTypeExpression}, + ast::{ + BinaryOpKind, IntegerBitSize, UnresolvedGeneric, UnresolvedGenerics, + UnresolvedTypeExpression, + }, hir::{ comptime::{Interpreter, Value}, def_map::ModuleDefId, resolution::{ errors::ResolverError, - resolver::{verify_mutable_reference, SELF_TYPE_NAME}, + resolver::{verify_mutable_reference, SELF_TYPE_NAME, WILDCARD_TYPE}, }, type_check::{Source, TypeCheckError}, }, @@ -28,61 +31,90 @@ use crate::{ UnaryOp, UnresolvedType, UnresolvedTypeData, }, node_interner::{DefinitionKind, ExprId, GlobalId, TraitId, TraitImplKind, TraitMethodId}, - Generics, Type, TypeBinding, TypeVariable, TypeVariableKind, + Generics, Kind, ResolvedGeneric, Type, TypeBinding, TypeVariable, TypeVariableKind, }; use super::{lints, Elaborator}; impl<'context> Elaborator<'context> { - /// Translates an UnresolvedType to a Type + /// Translates an UnresolvedType to a Type with a `TypeKind::Normal` pub(super) fn resolve_type(&mut self, typ: UnresolvedType) -> Type { let span = typ.span; - let resolved_type = self.resolve_type_inner(typ); + let resolved_type = self.resolve_type_inner(typ, &Kind::Normal); if resolved_type.is_nested_slice() { - self.push_err(ResolverError::NestedSlices { span: span.unwrap() }); + self.push_err(ResolverError::NestedSlices { + span: span.expect("Type should have span"), + }); } resolved_type } /// Translates an UnresolvedType into a Type and appends any /// freshly created TypeVariables created to new_variables. - pub fn resolve_type_inner(&mut self, typ: UnresolvedType) -> Type { + pub fn resolve_type_inner(&mut self, typ: UnresolvedType, kind: &Kind) -> Type { use crate::ast::UnresolvedTypeData::*; + let span = typ.span; + let resolved_type = match typ.typ { FieldElement => Type::FieldElement, Array(size, elem) => { - let elem = Box::new(self.resolve_type_inner(*elem)); - let size = self.convert_expression_type(size); + let elem = Box::new(self.resolve_type_inner(*elem, kind)); + let mut size = self.convert_expression_type(size); + // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics + if let Type::NamedGeneric(type_var, name, _) = size { + size = Type::NamedGeneric( + type_var, + name, + Kind::Numeric(Box::new(Type::default_int_type())), + ); + } Type::Array(Box::new(size), elem) } Slice(elem) => { - let elem = Box::new(self.resolve_type_inner(*elem)); + let elem = Box::new(self.resolve_type_inner(*elem, kind)); Type::Slice(elem) } Expression(expr) => self.convert_expression_type(expr), Integer(sign, bits) => Type::Integer(sign, bits), Bool => Type::Bool, String(size) => { - let resolved_size = self.convert_expression_type(size); + let mut resolved_size = self.convert_expression_type(size); + // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this once we only have explicit numeric generics + if let Type::NamedGeneric(type_var, name, _) = resolved_size { + resolved_size = Type::NamedGeneric( + type_var, + name, + Kind::Numeric(Box::new(Type::default_int_type())), + ); + } Type::String(Box::new(resolved_size)) } FormatString(size, fields) => { - let resolved_size = self.convert_expression_type(size); - let fields = self.resolve_type_inner(*fields); + let mut resolved_size = self.convert_expression_type(size); + if let Type::NamedGeneric(type_var, name, _) = resolved_size { + resolved_size = Type::NamedGeneric( + type_var, + name, + Kind::Numeric(Box::new(Type::default_int_type())), + ); + } + let fields = self.resolve_type_inner(*fields, kind); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } - Code => Type::Code, + Quoted(quoted) => Type::Quoted(quoted), Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, Named(path, args, _) => self.resolve_named_type(path, args), TraitAsType(path, args) => self.resolve_trait_as_type(path, args), - Tuple(fields) => Type::Tuple(vecmap(fields, |field| self.resolve_type_inner(field))), + Tuple(fields) => { + Type::Tuple(vecmap(fields, |field| self.resolve_type_inner(field, kind))) + } Function(args, ret, env) => { - let args = vecmap(args, |arg| self.resolve_type_inner(arg)); - let ret = Box::new(self.resolve_type_inner(*ret)); + let args = vecmap(args, |arg| self.resolve_type_inner(arg, kind)); + let ret = Box::new(self.resolve_type_inner(*ret, kind)); // expect() here is valid, because the only places we don't have a span are omitted types // e.g. a function without return type implicitly has a spanless UnresolvedType::Unit return type @@ -90,10 +122,10 @@ impl<'context> Elaborator<'context> { let env_span = env.span.expect("Unexpected missing span for closure environment type"); - let env = Box::new(self.resolve_type_inner(*env)); + let env = Box::new(self.resolve_type_inner(*env, kind)); match *env { - Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _) => { + Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _, _) => { Type::Function(args, ret, env) } _ => { @@ -106,9 +138,10 @@ impl<'context> Elaborator<'context> { } } MutableReference(element) => { - Type::MutableReference(Box::new(self.resolve_type_inner(*element))) + Type::MutableReference(Box::new(self.resolve_type_inner(*element, kind))) } - Parenthesized(typ) => self.resolve_type_inner(*typ), + Parenthesized(typ) => self.resolve_type_inner(*typ, kind), + Resolved(id) => self.interner.get_quoted_type(id).clone(), }; if let Type::Struct(_, _) = resolved_type { @@ -120,11 +153,36 @@ impl<'context> Elaborator<'context> { ); } } + + // Check that any types with a type kind match the expected type kind supplied to this function + // TODO(https://github.com/noir-lang/noir/issues/5156): make this named generic check more general with `*resolved_kind != kind` + // as implicit numeric generics still existing makes this check more challenging to enforce + // An example of a more general check that we should switch to: + // if resolved_type.kind() != kind.clone() { + // let expected_typ_err = CompilationError::TypeError(TypeCheckError::TypeKindMismatch { + // expected_kind: kind.to_string(), + // expr_kind: resolved_type.kind().to_string(), + // expr_span: span.expect("Type should have span"), + // }); + // self.errors.push((expected_typ_err, self.file)); + // return Type::Error; + // } + if let Type::NamedGeneric(_, name, resolved_kind) = &resolved_type { + if matches!(resolved_kind, Kind::Numeric { .. }) && matches!(kind, Kind::Normal) { + let expected_typ_err = ResolverError::NumericGenericUsedForType { + name: name.to_string(), + span: span.expect("Type should have span"), + }; + self.push_err(expected_typ_err); + return Type::Error; + } + } + resolved_type } - pub fn find_generic(&self, target_name: &str) -> Option<&(Rc, TypeVariable, Span)> { - self.generics.iter().find(|(name, _, _)| name.as_ref() == target_name) + pub fn find_generic(&self, target_name: &str) -> Option<&ResolvedGeneric> { + self.generics.iter().find(|generic| generic.name.as_ref() == target_name) } fn resolve_named_type(&mut self, path: Path, args: Vec) -> Type { @@ -146,11 +204,12 @@ impl<'context> Elaborator<'context> { } return self_type; } + } else if name == WILDCARD_TYPE { + return self.interner.next_type_variable(); } } let span = path.span(); - let mut args = vecmap(args, |arg| self.resolve_type_inner(arg)); if let Some(type_alias) = self.lookup_type_alias(path.clone()) { let type_alias = type_alias.borrow(); @@ -158,6 +217,10 @@ impl<'context> Elaborator<'context> { let type_alias_string = type_alias.to_string(); let id = type_alias.id; + let mut args = vecmap(type_alias.generics.iter().zip(args), |(generic, arg)| { + self.resolve_type_inner(arg, &generic.kind) + }); + self.verify_generics_count(expected_generic_count, &mut args, span, || { type_alias_string }); @@ -190,7 +253,7 @@ impl<'context> Elaborator<'context> { } let expected_generic_count = struct_type.borrow().generics.len(); - if !self.in_contract + if !self.in_contract() && self .interner .struct_attributes(&struct_type.borrow().id) @@ -201,6 +264,12 @@ impl<'context> Elaborator<'context> { span: struct_type.borrow().name.span(), }); } + + let mut args = + vecmap(struct_type.borrow().generics.iter().zip(args), |(generic, arg)| { + self.resolve_type_inner(arg, &generic.kind) + }); + self.verify_generics_count(expected_generic_count, &mut args, span, || { struct_type.borrow().to_string() }); @@ -217,10 +286,19 @@ impl<'context> Elaborator<'context> { } fn resolve_trait_as_type(&mut self, path: Path, args: Vec) -> Type { - let args = vecmap(args, |arg| self.resolve_type_inner(arg)); - - if let Some(t) = self.lookup_trait_or_error(path) { - Type::TraitAsType(t.id, Rc::new(t.name.to_string()), args) + // Fetch information needed from the trait as the closure for resolving all the `args` + // requires exclusive access to `self` + let trait_as_type_info = self + .lookup_trait_or_error(path) + .map(|t| (t.id, Rc::new(t.name.to_string()), t.generics.clone())); + + if let Some((id, name, resolved_generics)) = trait_as_type_info { + assert_eq!(resolved_generics.len(), args.len()); + let generics_with_types = resolved_generics.iter().zip(args); + let args = vecmap(generics_with_types, |(generic, typ)| { + self.resolve_type_inner(typ, &generic.kind) + }); + Type::TraitAsType(id, Rc::new(name.to_string()), args) } else { Type::Error } @@ -249,8 +327,9 @@ impl<'context> Elaborator<'context> { pub fn lookup_generic_or_global_type(&mut self, path: &Path) -> Option { if path.segments.len() == 1 { let name = &path.last_segment().0.contents; - if let Some((name, var, _)) = self.find_generic(name) { - return Some(Type::NamedGeneric(var.clone(), name.clone())); + if let Some(generic) = self.find_generic(name) { + let generic = generic.clone(); + return Some(Type::NamedGeneric(generic.type_var, generic.name, generic.kind)); } } @@ -316,9 +395,12 @@ impl<'context> Elaborator<'context> { let constraint = TraitConstraint { typ: self.self_type.clone()?, - trait_generics: Type::from_generics(&the_trait.generics), + trait_generics: Type::from_generics(&vecmap(&the_trait.generics, |generic| { + generic.type_var.clone() + })), trait_id, }; + return Some((method, constraint, false)); } } @@ -347,7 +429,9 @@ impl<'context> Elaborator<'context> { the_trait.self_type_typevar.clone(), TypeVariableKind::Normal, ), - trait_generics: Type::from_generics(&the_trait.generics), + trait_generics: Type::from_generics(&vecmap(&the_trait.generics, |generic| { + generic.type_var.clone() + })), trait_id, }; return Some((method, constraint, false)); @@ -369,7 +453,7 @@ impl<'context> Elaborator<'context> { } for constraint in self.trait_bounds.clone() { - if let Type::NamedGeneric(_, name) = &constraint.typ { + if let Type::NamedGeneric(_, name, _) = &constraint.typ { // if `path` is `T::method_name`, we're looking for constraint of the form `T: SomeTrait` if path.segments[0].0.contents != name.as_str() { continue; @@ -1075,7 +1159,7 @@ impl<'context> Elaborator<'context> { }); None } - Type::NamedGeneric(_, _) => { + Type::NamedGeneric(_, _, _) => { let func_meta = self.interner.function_meta( &self.current_function.expect("unexpected method outside a function"), ); @@ -1351,26 +1435,34 @@ impl<'context> Elaborator<'context> { } } - pub fn add_existing_generics(&mut self, names: &UnresolvedGenerics, generics: &Generics) { - assert_eq!(names.len(), generics.len()); + pub fn add_existing_generics( + &mut self, + unresolved_generics: &UnresolvedGenerics, + generics: &Generics, + ) { + assert_eq!(unresolved_generics.len(), generics.len()); - for (name, typevar) in names.iter().zip(generics) { - self.add_existing_generic(&name.0.contents, name.0.span(), typevar.clone()); + for (unresolved_generic, generic) in unresolved_generics.iter().zip(generics) { + self.add_existing_generic(unresolved_generic, unresolved_generic.span(), generic); } } - pub fn add_existing_generic(&mut self, name: &str, span: Span, typevar: TypeVariable) { - // Check for name collisions of this generic - let rc_name = Rc::new(name.to_owned()); + pub fn add_existing_generic( + &mut self, + unresolved_generic: &UnresolvedGeneric, + span: Span, + resolved_generic: &ResolvedGeneric, + ) { + let name = &unresolved_generic.ident().0.contents; - if let Some((_, _, first_span)) = self.find_generic(&rc_name) { + if let Some(generic) = self.find_generic(name) { self.push_err(ResolverError::DuplicateDefinition { - name: name.to_owned(), - first_span: *first_span, + name: name.clone(), + first_span: generic.span, second_span: span, }); } else { - self.generics.push((rc_name, typevar, span)); + self.generics.push(resolved_generic.clone()); } } @@ -1395,8 +1487,8 @@ impl<'context> Elaborator<'context> { | Type::Error | Type::TypeVariable(_, _) | Type::Constant(_) - | Type::NamedGeneric(_, _) - | Type::Code + | Type::NamedGeneric(_, _, _) + | Type::Quoted(_) | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { @@ -1406,7 +1498,7 @@ impl<'context> Elaborator<'context> { } Type::Array(length, element_type) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } Self::find_numeric_generics_in_type(element_type, found); @@ -1431,7 +1523,7 @@ impl<'context> Elaborator<'context> { Type::Struct(struct_type, generics) => { for (i, generic) in generics.iter().enumerate() { - if let Type::NamedGeneric(type_variable, name) = generic { + if let Type::NamedGeneric(type_variable, name, _) = generic { if struct_type.borrow().generic_is_numeric(i) { found.insert(name.to_string(), type_variable.clone()); } @@ -1442,7 +1534,7 @@ impl<'context> Elaborator<'context> { } Type::Alias(alias, generics) => { for (i, generic) in generics.iter().enumerate() { - if let Type::NamedGeneric(type_variable, name) = generic { + if let Type::NamedGeneric(type_variable, name, _) = generic { if alias.borrow().generic_is_numeric(i) { found.insert(name.to_string(), type_variable.clone()); } @@ -1453,12 +1545,12 @@ impl<'context> Elaborator<'context> { } Type::MutableReference(element) => Self::find_numeric_generics_in_type(element, found), Type::String(length) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } } Type::FmtString(length, fields) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } Self::find_numeric_generics_in_type(fields, found); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs new file mode 100644 index 000000000000..ed12ba21398a --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/unquote.rs @@ -0,0 +1,41 @@ +use crate::{ + macros_api::Path, + token::{SpannedToken, Token, Tokens}, +}; + +use super::Elaborator; + +impl<'a> Elaborator<'a> { + /// Go through the given tokens looking for a '$' token followed by a variable to unquote. + /// Each time these two tokens are found, they are replaced by a new UnquoteMarker token + /// containing the ExprId of the resolved variable to unquote. + pub fn find_unquoted_exprs_tokens(&mut self, tokens: Tokens) -> Tokens { + let token_count = tokens.0.len(); + let mut new_tokens = Vec::with_capacity(token_count); + let mut tokens = tokens.0.into_iter(); + + while let Some(token) = tokens.next() { + let is_unquote = matches!(token.token(), Token::DollarSign); + new_tokens.push(token); + + if is_unquote { + if let Some(next) = tokens.next() { + let span = next.to_span(); + + match next.into_token() { + Token::Ident(name) => { + // Don't want the leading `$` anymore + new_tokens.pop(); + let path = Path::from_single(name, span); + let (expr_id, _) = self.elaborate_variable(path, None); + new_tokens.push(SpannedToken::new(Token::UnquoteMarker(expr_id), span)); + } + other_next => new_tokens.push(SpannedToken::new(other_next, span)), + } + } + } + } + + Tokens(new_tokens) + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs index 05962420f8a6..d2c7acee2a33 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -1,5 +1,11 @@ -use crate::{hir::def_collector::dc_crate::CompilationError, Type}; +use std::rc::Rc; + +use crate::{ + hir::def_collector::dc_crate::CompilationError, parser::ParserError, token::Tokens, Type, +}; use acvm::{acir::AcirField, FieldElement}; +use fm::FileId; +use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Location}; use super::value::Value; @@ -35,6 +41,9 @@ pub enum InterpreterError { NonStructInConstructor { typ: Type, location: Location }, CannotInlineMacro { value: Value, location: Location }, UnquoteFoundDuringEvaluation { location: Location }, + FailedToParseMacro { error: ParserError, tokens: Rc, rule: &'static str, file: FileId }, + UnsupportedTopLevelItemUnquote { item: String, location: Location }, + NonComptimeFnCallInSameCrate { function: String, location: Location }, Unimplemented { item: String, location: Location }, @@ -94,9 +103,14 @@ impl InterpreterError { | InterpreterError::NonStructInConstructor { location, .. } | InterpreterError::CannotInlineMacro { location, .. } | InterpreterError::UnquoteFoundDuringEvaluation { location, .. } + | InterpreterError::UnsupportedTopLevelItemUnquote { location, .. } + | InterpreterError::NonComptimeFnCallInSameCrate { location, .. } | InterpreterError::Unimplemented { location, .. } | InterpreterError::BreakNotInLoop { location, .. } | InterpreterError::ContinueNotInLoop { location, .. } => *location, + InterpreterError::FailedToParseMacro { error, file, .. } => { + Location::new(error.span(), *file) + } InterpreterError::Break | InterpreterError::Continue => { panic!("Tried to get the location of Break/Continue error!") } @@ -249,7 +263,8 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { CustomDiagnostic::simple_error(msg, String::new(), location.span) } InterpreterError::CannotInlineMacro { value, location } => { - let msg = "Cannot inline value into runtime code if it contains references".into(); + let typ = value.get_type(); + let msg = format!("Cannot inline values of type `{typ}` into this position"); let secondary = format!("Cannot inline value {value:?}"); CustomDiagnostic::simple_error(msg, secondary, location.span) } @@ -258,6 +273,45 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let secondary = "This is a bug".into(); CustomDiagnostic::simple_error(msg, secondary, location.span) } + InterpreterError::FailedToParseMacro { error, tokens, rule, file: _ } => { + let message = format!("Failed to parse macro's token stream into {rule}"); + let tokens = vecmap(&tokens.0, ToString::to_string).join(" "); + + // 10 is an aribtrary number of tokens here chosen to fit roughly onto one line + let token_stream = if tokens.len() > 10 { + format!("The resulting token stream was: {tokens}") + } else { + format!( + "The resulting token stream was: (stream starts on next line)\n {tokens}" + ) + }; + + let push_the_problem_on_the_library_author = "To avoid this error in the future, try adding input validation to your macro. Erroring out early with an `assert` can be a good way to provide a user-friendly error message".into(); + + let mut diagnostic = CustomDiagnostic::from(error); + // Swap the parser's primary note to become the secondary note so that it is + // more clear this error originates from failing to parse a macro. + let secondary = std::mem::take(&mut diagnostic.message); + diagnostic.add_secondary(secondary, error.span()); + diagnostic.message = message; + diagnostic.add_note(token_stream); + diagnostic.add_note(push_the_problem_on_the_library_author); + diagnostic + } + InterpreterError::UnsupportedTopLevelItemUnquote { item, location } => { + let msg = "Unsupported statement type to unquote".into(); + let secondary = + "Only functions, globals, and trait impls can be unquoted here".into(); + let mut error = CustomDiagnostic::simple_error(msg, secondary, location.span); + error.add_note(format!("Unquoted item was:\n{item}")); + error + } + InterpreterError::NonComptimeFnCallInSameCrate { function, location } => { + let msg = format!("`{function}` cannot be called in a `comptime` context here"); + let secondary = + "This function must be `comptime` or in a separate crate to be called".into(); + CustomDiagnostic::simple_error(msg, secondary, location.span) + } InterpreterError::Unimplemented { item, location } => { let msg = format!("{item} is currently unimplemented"); CustomDiagnostic::simple_error(msg, String::new(), location.span) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 186eaa58c146..d2b98569bbb0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -7,6 +7,9 @@ use noirc_errors::Location; use rustc_hash::FxHashMap as HashMap; use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; +use crate::graph::CrateId; +use crate::monomorphization::{perform_instantiation_bindings, undo_instantiation_bindings}; +use crate::token::Tokens; use crate::{ hir_def::{ expr::{ @@ -26,18 +29,23 @@ use crate::{ }; use super::errors::{IResult, InterpreterError}; -use super::value::Value; +use super::value::{unwrap_rc, Value}; + +mod builtin; +mod unquote; #[allow(unused)] pub struct Interpreter<'interner> { /// To expand macros the Interpreter may mutate hir nodes within the NodeInterner - pub(super) interner: &'interner mut NodeInterner, + pub interner: &'interner mut NodeInterner, /// Each value currently in scope in the interpreter. /// Each element of the Vec represents a scope with every scope together making /// up all currently visible definitions. scopes: &'interner mut Vec>, + crate_id: CrateId, + in_loop: bool, } @@ -46,18 +54,30 @@ impl<'a> Interpreter<'a> { pub(crate) fn new( interner: &'a mut NodeInterner, scopes: &'a mut Vec>, + crate_id: CrateId, ) -> Self { - Self { interner, scopes, in_loop: false } + Self { interner, scopes, crate_id, in_loop: false } } pub(crate) fn call_function( &mut self, function: FuncId, arguments: Vec<(Value, Location)>, + instantiation_bindings: TypeBindings, location: Location, ) -> IResult { - let previous_state = self.enter_function(); + perform_instantiation_bindings(&instantiation_bindings); + let result = self.call_function_inner(function, arguments, location); + undo_instantiation_bindings(instantiation_bindings); + result + } + fn call_function_inner( + &mut self, + function: FuncId, + arguments: Vec<(Value, Location)>, + location: Location, + ) -> IResult { let meta = self.interner.function_meta(&function); if meta.parameters.len() != arguments.len() { return Err(InterpreterError::ArgumentCountMismatch { @@ -67,11 +87,21 @@ impl<'a> Interpreter<'a> { }); } + let is_comptime = self.interner.function_modifiers(&function).is_comptime; + if !is_comptime && meta.source_crate == self.crate_id { + // Calling non-comptime functions from within the current crate is restricted + // as non-comptime items will have not been elaborated yet. + let function = self.interner.function_name(&function).to_owned(); + return Err(InterpreterError::NonComptimeFnCallInSameCrate { function, location }); + } + if meta.kind != FunctionKind::Normal { return self.call_builtin(function, arguments, location); } let parameters = meta.parameters.0.clone(); + let previous_state = self.enter_function(); + for ((parameter, typ, _), (argument, arg_location)) in parameters.iter().zip(arguments) { self.define_pattern(parameter, typ, argument, arg_location)?; } @@ -94,16 +124,16 @@ impl<'a> Interpreter<'a> { .expect("all builtin functions must contain a function attribute which contains the opcode which it links to"); if let Some(builtin) = func_attrs.builtin() { - let item = format!("Evaluation for builtin functions like {builtin}"); - Err(InterpreterError::Unimplemented { item, location }) + let builtin = builtin.clone(); + builtin::call_builtin(self.interner, &builtin, arguments, location) } else if let Some(foreign) = func_attrs.foreign() { - let item = format!("Evaluation for foreign functions like {foreign}"); + let item = format!("Comptime evaluation for foreign functions like {foreign}"); Err(InterpreterError::Unimplemented { item, location }) } else if let Some(oracle) = func_attrs.oracle() { if oracle == "print" { self.print_oracle(arguments) } else { - let item = format!("Evaluation for oracle functions like {oracle}"); + let item = format!("Comptime evaluation for oracle functions like {oracle}"); Err(InterpreterError::Unimplemented { item, location }) } } else { @@ -184,7 +214,8 @@ impl<'a> Interpreter<'a> { ) -> IResult<()> { match pattern { HirPattern::Identifier(identifier) => { - self.define(identifier.id, typ, argument, location) + self.define(identifier.id, argument); + Ok(()) } HirPattern::Mutable(pattern, _) => { self.define_pattern(pattern, typ, argument, location) @@ -206,8 +237,6 @@ impl<'a> Interpreter<'a> { }, HirPattern::Struct(struct_type, pattern_fields, _) => { self.push_scope(); - self.type_check(typ, &argument, location)?; - self.type_check(struct_type, &argument, location)?; let res = match argument { Value::Struct(fields, struct_type) if fields.len() == pattern_fields.len() => { @@ -243,30 +272,8 @@ impl<'a> Interpreter<'a> { } /// Define a new variable in the current scope - fn define( - &mut self, - id: DefinitionId, - typ: &Type, - argument: Value, - location: Location, - ) -> IResult<()> { - // Temporarily disabled since this fails on generic types - // self.type_check(typ, &argument, location)?; + fn define(&mut self, id: DefinitionId, argument: Value) { self.current_scope_mut().insert(id, argument); - Ok(()) - } - - /// Mutate an existing variable, potentially from a prior scope. - /// Also type checks the value being assigned - fn checked_mutate( - &mut self, - id: DefinitionId, - typ: &Type, - argument: Value, - location: Location, - ) -> IResult<()> { - self.type_check(typ, &argument, location)?; - self.mutate(id, argument, location) } /// Mutate an existing variable, potentially from a prior scope @@ -305,24 +312,12 @@ impl<'a> Interpreter<'a> { Err(InterpreterError::NonComptimeVarReferenced { name, location }) } - fn type_check(&self, typ: &Type, value: &Value, location: Location) -> IResult<()> { - let typ = typ.follow_bindings(); - let value_type = value.get_type(); - - typ.try_unify(&value_type, &mut TypeBindings::new()).map_err(|_| { - InterpreterError::TypeMismatch { expected: typ, value: value.clone(), location } - }) - } - /// Evaluate an expression and return the result - pub(super) fn evaluate(&mut self, id: ExprId) -> IResult { + pub fn evaluate(&mut self, id: ExprId) -> IResult { match self.interner.expression(&id) { HirExpression::Ident(ident, _) => self.evaluate_ident(ident, id), HirExpression::Literal(literal) => self.evaluate_literal(literal, id), - HirExpression::Block(block) => { - dbg!("going to evaluate a block"); - self.evaluate_block(block) - } + HirExpression::Block(block) => self.evaluate_block(block), HirExpression::Prefix(prefix) => self.evaluate_prefix(prefix, id), HirExpression::Infix(infix) => self.evaluate_infix(infix, id), HirExpression::Index(index) => self.evaluate_index(index, id), @@ -334,9 +329,9 @@ impl<'a> Interpreter<'a> { HirExpression::If(if_) => self.evaluate_if(if_, id), HirExpression::Tuple(tuple) => self.evaluate_tuple(tuple), HirExpression::Lambda(lambda) => self.evaluate_lambda(lambda, id), - HirExpression::Quote(block) => Ok(Value::Code(Rc::new(block))), + HirExpression::Quote(tokens) => self.evaluate_quote(tokens, id), HirExpression::Comptime(block) => self.evaluate_block(block), - HirExpression::Unquote(block) => { + HirExpression::Unquote(tokens) => { // An Unquote expression being found is indicative of a macro being // expanded within another comptime fn which we don't currently support. let location = self.interner.expr_location(&id); @@ -354,8 +349,9 @@ impl<'a> Interpreter<'a> { match &definition.kind { DefinitionKind::Function(function_id) => { - let typ = self.interner.id_type(id); - Ok(Value::Function(*function_id, typ)) + let typ = self.interner.id_type(id).follow_bindings(); + let bindings = Rc::new(self.interner.get_instantiation_bindings(id).clone()); + Ok(Value::Function(*function_id, typ, bindings)) } DefinitionKind::Local(_) => self.lookup(&ident), DefinitionKind::Global(global_id) => { @@ -526,7 +522,7 @@ impl<'a> Interpreter<'a> { } fn evaluate_array(&mut self, array: HirArrayLiteral, id: ExprId) -> IResult { - let typ = self.interner.id_type(id); + let typ = self.interner.id_type(id).follow_bindings(); match array { HirArrayLiteral::Standard(elements) => { @@ -608,10 +604,13 @@ impl<'a> Interpreter<'a> { let rhs = self.evaluate(infix.rhs)?; // TODO: Need to account for operator overloading - assert!( - self.interner.get_selected_impl_for_expression(id).is_none(), - "Operator overloading is unimplemented in the interpreter" - ); + // See https://github.com/noir-lang/noir/issues/4925 + if self.interner.get_selected_impl_for_expression(id).is_some() { + return Err(InterpreterError::Unimplemented { + item: "Operator overloading in the interpreter".to_string(), + location: infix.operator.location, + }); + } use InterpreterError::InvalidValuesForBinary; match infix.operator.kind { @@ -920,13 +919,25 @@ impl<'a> Interpreter<'a> { }) .collect::>()?; - let typ = self.interner.id_type(id); + let typ = self.interner.id_type(id).follow_bindings(); Ok(Value::Struct(fields, typ)) } fn evaluate_access(&mut self, access: HirMemberAccess, id: ExprId) -> IResult { let (fields, struct_type) = match self.evaluate(access.lhs)? { Value::Struct(fields, typ) => (fields, typ), + Value::Tuple(fields) => { + let (fields, field_types): (HashMap, Value>, Vec) = fields + .into_iter() + .enumerate() + .map(|(i, field)| { + let field_type = field.get_type().into_owned(); + let key_val_pair = (Rc::new(i.to_string()), field); + (key_val_pair, field_type) + }) + .unzip(); + (fields, Type::Tuple(field_types)) + } value => { let location = self.interner.expr_location(&id); return Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }); @@ -949,7 +960,10 @@ impl<'a> Interpreter<'a> { let location = self.interner.expr_location(&id); match function { - Value::Function(function_id, _) => self.call_function(function_id, arguments, location), + Value::Function(function_id, _, bindings) => { + let bindings = unwrap_rc(bindings); + self.call_function(function_id, arguments, bindings, location) + } Value::Closure(closure, env, _) => self.call_closure(closure, env, arguments, location), value => Err(InterpreterError::NonFunctionCalled { value, location }), } @@ -978,7 +992,7 @@ impl<'a> Interpreter<'a> { }; if let Some(method) = method { - self.call_function(method, arguments, location) + self.call_function(method, arguments, TypeBindings::new(), location) } else { Err(InterpreterError::NoMethodFound { name: method_name.clone(), typ, location }) } @@ -1123,10 +1137,16 @@ impl<'a> Interpreter<'a> { let environment = try_vecmap(&lambda.captures, |capture| self.lookup_id(capture.ident.id, location))?; - let typ = self.interner.id_type(id); + let typ = self.interner.id_type(id).follow_bindings(); Ok(Value::Closure(lambda, environment, typ)) } + fn evaluate_quote(&mut self, mut tokens: Tokens, expr_id: ExprId) -> IResult { + let location = self.interner.expr_location(&expr_id); + tokens = self.substitute_unquoted_values_into_tokens(tokens, location)?; + Ok(Value::Code(Rc::new(tokens))) + } + pub fn evaluate_statement(&mut self, statement: StmtId) -> IResult { match self.interner.statement(&statement) { HirStatement::Let(let_) => self.evaluate_let(let_), @@ -1178,9 +1198,7 @@ impl<'a> Interpreter<'a> { fn store_lvalue(&mut self, lvalue: HirLValue, rhs: Value) -> IResult<()> { match lvalue { - HirLValue::Ident(ident, typ) => { - self.checked_mutate(ident.id, &typ, rhs, ident.location) - } + HirLValue::Ident(ident, typ) => self.mutate(ident.id, rhs, ident.location), HirLValue::Dereference { lvalue, element_type: _, location } => { match self.evaluate_lvalue(&lvalue)? { Value::Pointer(value) => { @@ -1199,7 +1217,7 @@ impl<'a> Interpreter<'a> { } Value::Struct(mut fields, typ) => { fields.insert(Rc::new(field_name.0.contents), rhs); - self.store_lvalue(*object, Value::Struct(fields, typ)) + self.store_lvalue(*object, Value::Struct(fields, typ.follow_bindings())) } value => { Err(InterpreterError::NonTupleOrStructInMemberAccess { value, location }) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs new file mode 100644 index 000000000000..8523e13aeea4 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -0,0 +1,158 @@ +use std::rc::Rc; + +use noirc_errors::Location; + +use crate::{ + hir::comptime::{errors::IResult, InterpreterError, Value}, + macros_api::NodeInterner, + token::{SpannedToken, Token, Tokens}, + QuotedType, Type, +}; + +pub(super) fn call_builtin( + interner: &mut NodeInterner, + name: &str, + arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + match name { + "array_len" => array_len(&arguments), + "as_slice" => as_slice(arguments), + "slice_push_back" => slice_push_back(arguments), + "struct_def_as_type" => struct_def_as_type(interner, arguments), + "struct_def_generics" => struct_def_generics(interner, arguments), + "struct_def_fields" => struct_def_fields(interner, arguments), + _ => { + let item = format!("Comptime evaluation for builtin function {name}"); + Err(InterpreterError::Unimplemented { item, location }) + } + } +} + +fn array_len(arguments: &[(Value, Location)]) -> IResult { + assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument"); + match &arguments[0].0 { + Value::Array(values, _) | Value::Slice(values, _) => Ok(Value::U32(values.len() as u32)), + // Type checking should prevent this branch being taken. + _ => unreachable!("ICE: Cannot query length of types other than arrays or slices"), + } +} + +fn as_slice(mut arguments: Vec<(Value, Location)>) -> IResult { + assert_eq!(arguments.len(), 1, "ICE: `as_slice` should only receive a single argument"); + let (array, _) = arguments.pop().unwrap(); + match array { + Value::Array(values, Type::Array(_, typ)) => Ok(Value::Slice(values, Type::Slice(typ))), + // Type checking should prevent this branch being taken. + _ => unreachable!("ICE: Cannot convert types other than arrays into slices"), + } +} + +fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { + assert_eq!(arguments.len(), 2, "ICE: `slice_push_back` should only receive two arguments"); + let (element, _) = arguments.pop().unwrap(); + let (slice, _) = arguments.pop().unwrap(); + match slice { + Value::Slice(mut values, typ) => { + values.push_back(element); + Ok(Value::Slice(values, typ)) + } + // Type checking should prevent this branch being taken. + _ => unreachable!("ICE: `slice_push_back` expects a slice as its first argument"), + } +} + +/// fn as_type(self) -> Quoted +fn struct_def_as_type( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, +) -> IResult { + assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); + let (struct_def, span) = match arguments.pop() { + Some((Value::StructDefinition(id), location)) => (id, location.span), + other => { + unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + } + }; + + let struct_def = interner.get_struct(struct_def); + let struct_def = struct_def.borrow(); + let make_token = |name| SpannedToken::new(Token::Ident(name), span); + + let mut tokens = vec![make_token(struct_def.name.to_string())]; + + for (i, generic) in struct_def.generics.iter().enumerate() { + if i != 0 { + tokens.push(SpannedToken::new(Token::Comma, span)); + } + tokens.push(make_token(generic.type_var.borrow().to_string())); + } + + Ok(Value::Code(Rc::new(Tokens(tokens)))) +} + +/// fn generics(self) -> [Quoted] +fn struct_def_generics( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, +) -> IResult { + assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); + let (struct_def, span) = match arguments.pop() { + Some((Value::StructDefinition(id), location)) => (id, location.span), + other => { + unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + } + }; + + let struct_def = interner.get_struct(struct_def); + + let generics = struct_def + .borrow() + .generics + .iter() + .map(|generic| { + let name = SpannedToken::new(Token::Ident(generic.type_var.borrow().to_string()), span); + Value::Code(Rc::new(Tokens(vec![name]))) + }) + .collect(); + + let typ = Type::Slice(Box::new(Type::Quoted(QuotedType::Quoted))); + Ok(Value::Slice(generics, typ)) +} + +/// fn fields(self) -> [(Quoted, Quoted)] +/// Returns (name, type) pairs of each field of this StructDefinition +fn struct_def_fields( + interner: &mut NodeInterner, + mut arguments: Vec<(Value, Location)>, +) -> IResult { + assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); + let (struct_def, span) = match arguments.pop() { + Some((Value::StructDefinition(id), location)) => (id, location.span), + other => { + unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + } + }; + + let struct_def = interner.get_struct(struct_def); + let struct_def = struct_def.borrow(); + + let make_token = |name| SpannedToken::new(Token::Ident(name), span); + let make_quoted = |tokens| Value::Code(Rc::new(Tokens(tokens))); + + let mut fields = im::Vector::new(); + + for (name, typ) in struct_def.get_fields_as_written() { + let name = make_quoted(vec![make_token(name)]); + let id = interner.push_quoted_type(typ); + let typ = SpannedToken::new(Token::QuotedType(id), span); + let typ = Value::Code(Rc::new(Tokens(vec![typ]))); + fields.push_back(Value::Tuple(vec![name, typ])); + } + + let typ = Type::Slice(Box::new(Type::Tuple(vec![ + Type::Quoted(QuotedType::Quoted), + Type::Quoted(QuotedType::Quoted), + ]))); + Ok(Value::Slice(fields, typ)) +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs new file mode 100644 index 000000000000..a1ceb27afb28 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/unquote.rs @@ -0,0 +1,42 @@ +use noirc_errors::Location; + +use crate::{ + hir::comptime::{errors::IResult, value::unwrap_rc, Value}, + token::{SpannedToken, Token, Tokens}, +}; + +use super::Interpreter; + +impl<'a> Interpreter<'a> { + /// Evaluates any expressions within UnquoteMarkers in the given token list + /// and replaces the expression held by the marker with the evaluated value + /// in expression form. + pub(super) fn substitute_unquoted_values_into_tokens( + &mut self, + tokens: Tokens, + location: Location, + ) -> IResult { + let mut new_tokens = Vec::with_capacity(tokens.0.len()); + + for token in tokens.0 { + let span = token.to_span(); + match token.token() { + Token::UnquoteMarker(id) => { + match self.evaluate(*id)? { + // If the value is already quoted we don't want to change the token stream by + // turning it into a Quoted block (which would add `quote`, `{`, and `}` tokens). + Value::Code(stream) => new_tokens.extend(unwrap_rc(stream).0), + value => { + let new_id = value.into_hir_expression(self.interner, location)?; + let new_token = Token::UnquoteMarker(new_id); + new_tokens.push(SpannedToken::new(new_token, span)); + } + } + } + _ => new_tokens.push(token), + } + } + + Ok(Tokens(new_tokens)) + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs index 9e3b03ef525c..770c523bd7fb 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -53,9 +53,7 @@ impl<'interner> Interpreter<'interner> { /// Otherwise, scan through its expression for any comptime blocks to evaluate. pub fn scan_global(&mut self, global: GlobalId) -> IResult<()> { if let Some(let_) = self.interner.get_global_let_statement(global) { - // dbg!(let_.clone()); if let_.comptime { - dbg!("got here"); self.evaluate_let(let_)?; } else { self.scan_expression(let_.expression)?; @@ -102,7 +100,7 @@ impl<'interner> Interpreter<'interner> { // missed it somehow. In the future we may allow users to manually write unquote // expressions in their code but for now this is unreachable. HirExpression::Unquote(block) => { - unreachable!("Found unquote block while scanning: {block}") + unreachable!("Found unquote block while scanning: {block:?}") } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs index 43f6e21905b5..870f2bc458a8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/tests.rs @@ -7,15 +7,16 @@ use noirc_errors::Location; use super::errors::InterpreterError; use super::interpreter::Interpreter; use super::value::Value; +use crate::graph::CrateId; use crate::hir::type_check::test::type_check_src_code; fn interpret_helper(src: &str, func_namespace: Vec) -> Result { let (mut interner, main_id) = type_check_src_code(src, func_namespace); let mut scopes = vec![HashMap::default()]; - let mut interpreter = Interpreter::new(&mut interner, &mut scopes); + let mut interpreter = Interpreter::new(&mut interner, &mut scopes, CrateId::Root(0)); let no_location = Location::dummy(); - interpreter.call_function(main_id, Vec::new(), no_location) + interpreter.call_function(main_id, Vec::new(), HashMap::new(), no_location) } fn interpret(src: &str, func_namespace: Vec) -> Value { @@ -30,14 +31,14 @@ fn interpret_expect_error(src: &str, func_namespace: Vec) -> Interpreter #[test] fn interpreter_works() { - let program = "fn main() -> pub Field { 3 }"; + let program = "comptime fn main() -> pub Field { 3 }"; let result = interpret(program, vec!["main".into()]); assert_eq!(result, Value::Field(3u128.into())); } #[test] fn mutation_works() { - let program = "fn main() -> pub i8 { + let program = "comptime fn main() -> pub i8 { let mut x = 3; x = 4; x @@ -48,7 +49,7 @@ fn mutation_works() { #[test] fn mutating_references() { - let program = "fn main() -> pub i32 { + let program = "comptime fn main() -> pub i32 { let x = &mut 3; *x = 4; *x @@ -59,7 +60,7 @@ fn mutating_references() { #[test] fn mutating_mutable_references() { - let program = "fn main() -> pub i64 { + let program = "comptime fn main() -> pub i64 { let mut x = &mut 3; *x = 4; *x @@ -70,7 +71,7 @@ fn mutating_mutable_references() { #[test] fn mutating_arrays() { - let program = "fn main() -> pub u8 { + let program = "comptime fn main() -> pub u8 { let mut a1 = [1, 2, 3, 4]; a1[1] = 22; a1[1] @@ -81,7 +82,7 @@ fn mutating_arrays() { #[test] fn mutate_in_new_scope() { - let program = "fn main() -> pub u8 { + let program = "comptime fn main() -> pub u8 { let mut x = 0; x += 1; { @@ -95,7 +96,7 @@ fn mutate_in_new_scope() { #[test] fn for_loop() { - let program = "fn main() -> pub u8 { + let program = "comptime fn main() -> pub u8 { let mut x = 0; for i in 0 .. 6 { x += i; @@ -108,7 +109,7 @@ fn for_loop() { #[test] fn for_loop_u16() { - let program = "fn main() -> pub u16 { + let program = "comptime fn main() -> pub u16 { let mut x = 0; for i in 0 .. 6 { x += i; @@ -121,7 +122,7 @@ fn for_loop_u16() { #[test] fn for_loop_with_break() { - let program = "unconstrained fn main() -> pub u32 { + let program = "unconstrained comptime fn main() -> pub u32 { let mut x = 0; for i in 0 .. 6 { if i == 4 { @@ -137,7 +138,7 @@ fn for_loop_with_break() { #[test] fn for_loop_with_continue() { - let program = "unconstrained fn main() -> pub u64 { + let program = "unconstrained comptime fn main() -> pub u64 { let mut x = 0; for i in 0 .. 6 { if i == 4 { @@ -153,7 +154,7 @@ fn for_loop_with_continue() { #[test] fn assert() { - let program = "fn main() { + let program = "comptime fn main() { assert(1 == 1); }"; let result = interpret(program, vec!["main".into()]); @@ -162,7 +163,7 @@ fn assert() { #[test] fn assert_fail() { - let program = "fn main() { + let program = "comptime fn main() { assert(1 == 2); }"; let result = interpret_expect_error(program, vec!["main".into()]); @@ -171,7 +172,7 @@ fn assert_fail() { #[test] fn lambda() { - let program = "fn main() -> pub u8 { + let program = "comptime fn main() -> pub u8 { let f = |x: u8| x + 1; f(1) }"; @@ -182,11 +183,11 @@ fn lambda() { #[test] fn non_deterministic_recursion() { let program = " - fn main() -> pub u64 { + comptime fn main() -> pub u64 { fib(10) } - fn fib(x: u64) -> u64 { + comptime fn fib(x: u64) -> u64 { if x <= 1 { x } else { @@ -196,3 +197,18 @@ fn non_deterministic_recursion() { let result = interpret(program, vec!["main".into(), "fib".into()]); assert_eq!(result, Value::U64(55)); } + +#[test] +fn generic_functions() { + let program = " + fn main() -> pub u8 { + apply(1, |x| x + 1) + } + + fn apply(x: T, f: fn[Env](T) -> U) -> U { + f(x) + } + "; + let result = interpret(program, vec!["main".into(), "apply".into()]); + assert!(matches!(result, Value::U8(2))); +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs index 11bbbc7484da..adb13c4bfbc7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/value.rs @@ -1,20 +1,22 @@ use std::{borrow::Cow, fmt::Display, rc::Rc}; use acvm::{AcirField, FieldElement}; +use chumsky::Parser; use im::Vector; use iter_extended::{try_vecmap, vecmap}; use noirc_errors::Location; use crate::{ - ast::{ - ArrayLiteral, BlockExpression, ConstructorExpression, Ident, IntegerBitSize, Signedness, - }, + ast::{ArrayLiteral, ConstructorExpression, Ident, IntegerBitSize, Signedness}, hir_def::expr::{HirArrayLiteral, HirConstructorExpression, HirIdent, HirLambda, ImplKind}, macros_api::{ Expression, ExpressionKind, HirExpression, HirLiteral, Literal, NodeInterner, Path, + StructId, }, node_interner::{ExprId, FuncId}, - Shared, Type, + parser::{self, NoirParser, TopLevelStatement}, + token::{SpannedToken, Token, Tokens}, + QuotedType, Shared, Type, TypeBindings, }; use rustc_hash::FxHashMap as HashMap; @@ -34,14 +36,15 @@ pub enum Value { U32(u32), U64(u64), String(Rc), - Function(FuncId, Type), + Function(FuncId, Type, Rc), Closure(HirLambda, Vec, Type), Tuple(Vec), Struct(HashMap, Value>, Type), Pointer(Shared), Array(Vector, Type), Slice(Vector, Type), - Code(Rc), + Code(Rc), + StructDefinition(StructId), } impl Value { @@ -62,7 +65,7 @@ impl Value { let length = Type::Constant(value.len() as u32); Type::String(Box::new(length)) } - Value::Function(_, typ) => return Cow::Borrowed(typ), + Value::Function(_, typ, _) => return Cow::Borrowed(typ), Value::Closure(_, _, typ) => return Cow::Borrowed(typ), Value::Tuple(fields) => { Type::Tuple(vecmap(fields, |field| field.get_type().into_owned())) @@ -70,7 +73,8 @@ impl Value { Value::Struct(_, typ) => return Cow::Borrowed(typ), Value::Array(_, typ) => return Cow::Borrowed(typ), Value::Slice(_, typ) => return Cow::Borrowed(typ), - Value::Code(_) => Type::Code, + Value::Code(_) => Type::Quoted(QuotedType::Quoted), + Value::StructDefinition(_) => Type::Quoted(QuotedType::StructDefinition), Value::Pointer(element) => { let element = element.borrow().get_type().into_owned(); Type::MutableReference(Box::new(element)) @@ -124,13 +128,14 @@ impl Value { ExpressionKind::Literal(Literal::Integer((value as u128).into(), false)) } Value::String(value) => ExpressionKind::Literal(Literal::Str(unwrap_rc(value))), - Value::Function(id, typ) => { + Value::Function(id, typ, bindings) => { let id = interner.function_definition_id(id); let impl_kind = ImplKind::NotATraitMethod; let ident = HirIdent { location, id, impl_kind }; let expr_id = interner.push_expr(HirExpression::Ident(ident, None)); interner.push_expr_location(expr_id, location.span, location.file); interner.push_expr_type(expr_id, typ); + interner.store_instantiation_bindings(expr_id, unwrap_rc(bindings)); ExpressionKind::Resolved(expr_id) } Value::Closure(_lambda, _env, _typ) => { @@ -171,8 +176,23 @@ impl Value { try_vecmap(elements, |element| element.into_expression(interner, location))?; ExpressionKind::Literal(Literal::Slice(ArrayLiteral::Standard(elements))) } - Value::Code(block) => ExpressionKind::Block(unwrap_rc(block)), - Value::Pointer(_) => { + Value::Code(tokens) => { + // Wrap the tokens in '{' and '}' so that we can parse statements as well. + let mut tokens_to_parse = tokens.as_ref().clone(); + tokens_to_parse.0.insert(0, SpannedToken::new(Token::LeftBrace, location.span)); + tokens_to_parse.0.push(SpannedToken::new(Token::RightBrace, location.span)); + + return match parser::expression().parse(tokens_to_parse) { + Ok(expr) => Ok(expr), + Err(mut errors) => { + let error = errors.swap_remove(0); + let file = location.file; + let rule = "an expression"; + Err(InterpreterError::FailedToParseMacro { error, file, tokens, rule }) + } + }; + } + Value::Pointer(_) | Value::StructDefinition(_) => { return Err(InterpreterError::CannotInlineMacro { value: self, location }) } }; @@ -228,10 +248,15 @@ impl Value { HirExpression::Literal(HirLiteral::Integer((value as u128).into(), false)) } Value::String(value) => HirExpression::Literal(HirLiteral::Str(unwrap_rc(value))), - Value::Function(id, _typ) => { + Value::Function(id, typ, bindings) => { let id = interner.function_definition_id(id); let impl_kind = ImplKind::NotATraitMethod; - HirExpression::Ident(HirIdent { location, id, impl_kind }, None) + let ident = HirIdent { location, id, impl_kind }; + let expr_id = interner.push_expr(HirExpression::Ident(ident, None)); + interner.push_expr_location(expr_id, location.span, location.file); + interner.push_expr_type(expr_id, typ); + interner.store_instantiation_bindings(expr_id, unwrap_rc(bindings)); + return Ok(expr_id); } Value::Closure(_lambda, _env, _typ) => { // TODO: How should a closure's environment be inlined? @@ -273,7 +298,7 @@ impl Value { HirExpression::Literal(HirLiteral::Slice(HirArrayLiteral::Standard(elements))) } Value::Code(block) => HirExpression::Unquote(unwrap_rc(block)), - Value::Pointer(_) => { + Value::Pointer(_) | Value::StructDefinition(_) => { return Err(InterpreterError::CannotInlineMacro { value: self, location }) } }; @@ -300,13 +325,31 @@ impl Value { _ => None, } } + + pub(crate) fn into_top_level_item(self, location: Location) -> IResult { + match self { + Value::Code(tokens) => parse_tokens(tokens, parser::top_level_item(), location.file), + value => Err(InterpreterError::CannotInlineMacro { value, location }), + } + } } /// Unwraps an Rc value without cloning the inner value if the reference count is 1. Clones otherwise. -fn unwrap_rc(rc: Rc) -> T { +pub(crate) fn unwrap_rc(rc: Rc) -> T { Rc::try_unwrap(rc).unwrap_or_else(|rc| (*rc).clone()) } +fn parse_tokens(tokens: Rc, parser: impl NoirParser, file: fm::FileId) -> IResult { + match parser.parse(tokens.as_ref().clone()) { + Ok(expr) => Ok(expr), + Err(mut errors) => { + let error = errors.swap_remove(0); + let rule = "an expression"; + Err(InterpreterError::FailedToParseMacro { error, file, tokens, rule }) + } + } +} + impl Display for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -325,7 +368,7 @@ impl Display for Value { Value::U32(value) => write!(f, "{value}"), Value::U64(value) => write!(f, "{value}"), Value::String(value) => write!(f, "{value}"), - Value::Function(_, _) => write!(f, "(function)"), + Value::Function(..) => write!(f, "(function)"), Value::Closure(_, _, _) => write!(f, "(closure)"), Value::Tuple(fields) => { let fields = vecmap(fields, ToString::to_string); @@ -348,7 +391,14 @@ impl Display for Value { let values = vecmap(values, ToString::to_string); write!(f, "&[{}]", values.join(", ")) } - Value::Code(_) => todo!(), + Value::Code(tokens) => { + write!(f, "quote {{")?; + for token in tokens.0.iter() { + write!(f, " {token}")?; + } + write!(f, " }}") + } + Value::StructDefinition(_) => write!(f, "(struct definition)"), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 9b47a104a402..37ece01c8050 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -5,7 +5,7 @@ use crate::graph::CrateId; use crate::hir::comptime::{Interpreter, InterpreterError}; use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleId}; use crate::hir::resolution::errors::ResolverError; -use crate::{Type, TypeVariable}; +use crate::{ResolvedGeneric, Type}; use crate::hir::resolution::import::{resolve_import, ImportDirective, PathResolution}; use crate::hir::resolution::{ @@ -33,7 +33,6 @@ use iter_extended::vecmap; use noirc_errors::{CustomDiagnostic, Span}; use std::collections::{BTreeMap, HashMap}; -use std::rc::Rc; use std::vec; #[derive(Default)] @@ -125,7 +124,7 @@ pub struct UnresolvedTraitImpl { pub trait_id: Option, pub impl_id: Option, pub resolved_object_type: Option, - pub resolved_generics: Vec<(Rc, TypeVariable, Span)>, + pub resolved_generics: Vec, // The resolved generic on the trait itself. E.g. it is the `` in // `impl Foo for Bar { ... }` @@ -154,6 +153,7 @@ pub struct DefCollector { pub(crate) items: CollectedItems, } +#[derive(Default)] pub struct CollectedItems { pub(crate) functions: Vec, pub(crate) types: BTreeMap, @@ -164,6 +164,18 @@ pub struct CollectedItems { pub(crate) trait_impls: Vec, } +impl CollectedItems { + pub fn is_empty(&self) -> bool { + self.functions.is_empty() + && self.types.is_empty() + && self.type_aliases.is_empty() + && self.traits.is_empty() + && self.globals.is_empty() + && self.impls.is_empty() + && self.trait_impls.is_empty() + } +} + /// Maps the type and the module id in which the impl is defined to the functions contained in that /// impl along with the generics declared on the impl itself. This also contains the Span /// of the object_type of the impl, used to issue an error if the object type fails to resolve. @@ -256,7 +268,7 @@ impl DefCollector { context: &mut Context, ast: SortedModule, root_file_id: FileId, - use_elaborator: bool, + use_legacy: bool, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; @@ -273,7 +285,7 @@ impl DefCollector { errors.extend(CrateDefMap::collect_defs( dep.crate_id, context, - use_elaborator, + use_legacy, macro_processors, )); @@ -351,7 +363,7 @@ impl DefCollector { } } - if use_elaborator { + if !use_legacy { let mut more_errors = Elaborator::elaborate(context, crate_id, def_collector.items); errors.append(&mut more_errors); return errors; @@ -379,6 +391,7 @@ impl DefCollector { def_collector.items.traits, crate_id, )); + // Must resolve structs before we resolve globals. resolved_module.errors.extend(resolve_structs( context, @@ -404,7 +417,7 @@ impl DefCollector { resolved_module.errors.extend(collect_impls(context, crate_id, &def_collector.items.impls)); // We must wait to resolve non-integer globals until after we resolve structs since struct - // globals will need to reference the struct type they're initialized to to ensure they are valid. + // globals will need to reference the struct type they're initialized to ensure they are valid. resolved_module.resolve_globals(context, other_globals, crate_id); // Resolve each function in the crate. This is now possible since imports have been resolved @@ -447,7 +460,7 @@ impl DefCollector { resolved_module.type_check(context); if !cycles_present { - resolved_module.evaluate_comptime(&mut context.def_interner); + resolved_module.evaluate_comptime(&mut context.def_interner, crate_id); } resolved_module.errors @@ -468,7 +481,7 @@ fn inject_prelude( let path = Path { segments: segments.clone(), - kind: crate::ast::PathKind::Dep, + kind: crate::ast::PathKind::Plain, span: Span::default(), }; @@ -489,7 +502,7 @@ fn inject_prelude( 0, ImportDirective { module_id: crate_root, - path: Path { segments, kind: PathKind::Dep, span: Span::default() }, + path: Path { segments, kind: PathKind::Plain, span: Span::default() }, alias: None, is_prelude: true, }, @@ -546,10 +559,10 @@ impl ResolvedModule { } /// Evaluate all `comptime` expressions in this module - fn evaluate_comptime(&mut self, interner: &mut NodeInterner) { + fn evaluate_comptime(&mut self, interner: &mut NodeInterner, crate_id: CrateId) { if self.count_errors() == 0 { let mut scopes = vec![HashMap::default()]; - let mut interpreter = Interpreter::new(interner, &mut scopes); + let mut interpreter = Interpreter::new(interner, &mut scopes, crate_id); for (_file, global) in &self.globals { if let Err(error) = interpreter.scan_global(*global) { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 5c196324b7db..c9198a1d04c8 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,4 +1,5 @@ -use std::{collections::HashMap, path::Path, vec}; +use std::path::Path; +use std::{collections::HashMap, vec}; use acvm::{AcirField, FieldElement}; use fm::{FileId, FileManager, FILE_EXTENSION}; @@ -11,6 +12,7 @@ use crate::ast::{ NoirStruct, NoirTrait, NoirTraitImpl, NoirTypeAlias, Pattern, TraitImplItem, TraitItem, TypeImpl, }; +use crate::macros_api::NodeInterner; use crate::{ graph::CrateId, hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait}, @@ -26,7 +28,7 @@ use super::{ }, errors::{DefCollectorErrorKind, DuplicateType}, }; -use crate::hir::def_map::{LocalModuleId, ModuleData, ModuleId}; +use crate::hir::def_map::{CrateDefMap, LocalModuleId, ModuleData, ModuleId}; use crate::hir::resolution::import::ImportDirective; use crate::hir::Context; @@ -105,35 +107,19 @@ impl<'a> ModCollector<'a> { ) -> Vec<(CompilationError, fm::FileId)> { let mut errors = vec![]; for global in globals { - let name = global.pattern.name_ident().clone(); - - let global_id = context.def_interner.push_empty_global( - name.clone(), - self.module_id, + let (global, error) = collect_global( + &mut context.def_interner, + &mut self.def_collector.def_map, + global, self.file_id, - global.attributes.clone(), - matches!(global.pattern, Pattern::Mutable { .. }), + self.module_id, ); - // Add the statement to the scope so its path can be looked up later - let result = self.def_collector.def_map.modules[self.module_id.0] - .declare_global(name, global_id); - - if let Err((first_def, second_def)) = result { - let err = DefCollectorErrorKind::Duplicate { - typ: DuplicateType::Global, - first_def, - second_def, - }; - errors.push((err.into(), self.file_id)); + if let Some(error) = error { + errors.push(error); } - self.def_collector.items.globals.push(UnresolvedGlobal { - file_id: self.file_id, - module_id: self.module_id, - global_id, - stmt_def: global, - }); + self.def_collector.items.globals.push(global); } errors } @@ -149,8 +135,9 @@ impl<'a> ModCollector<'a> { self_type: None, }; - for (method, _) in r#impl.methods { + for (mut method, _) in r#impl.methods { let func_id = context.def_interner.push_empty_fn(); + method.def.where_clause.extend(r#impl.where_clause.clone()); let location = Location::new(method.span(), self.file_id); context.def_interner.push_function(func_id, &method.def, module_id, location); unresolved_functions.push_fn(self.module_id, func_id, method); @@ -168,11 +155,16 @@ impl<'a> ModCollector<'a> { impls: Vec, krate: CrateId, ) { - for trait_impl in impls { + for mut trait_impl in impls { let trait_name = trait_impl.trait_name.clone(); - let mut unresolved_functions = - self.collect_trait_impl_function_overrides(context, &trait_impl, krate); + let mut unresolved_functions = collect_trait_impl_functions( + &mut context.def_interner, + &mut trait_impl, + krate, + self.file_id, + self.module_id, + ); let module = ModuleId { krate, local_id: self.module_id }; @@ -204,33 +196,6 @@ impl<'a> ModCollector<'a> { } } - fn collect_trait_impl_function_overrides( - &mut self, - context: &mut Context, - trait_impl: &NoirTraitImpl, - krate: CrateId, - ) -> UnresolvedFunctions { - let mut unresolved_functions = UnresolvedFunctions { - file_id: self.file_id, - functions: Vec::new(), - trait_id: None, - self_type: None, - }; - - let module = ModuleId { krate, local_id: self.module_id }; - - for item in &trait_impl.items { - if let TraitImplItem::Function(impl_method) = item { - let func_id = context.def_interner.push_empty_fn(); - let location = Location::new(impl_method.span(), self.file_id); - context.def_interner.push_function(func_id, &impl_method.def, module, location); - unresolved_functions.push_fn(self.module_id, func_id, impl_method.clone()); - } - } - - unresolved_functions - } - fn collect_functions( &mut self, context: &mut Context, @@ -308,11 +273,21 @@ impl<'a> ModCollector<'a> { struct_def: struct_definition, }; + let resolved_generics = context.resolve_generics( + &unresolved.struct_def.generics, + &mut definition_errors, + self.file_id, + ); + // Create the corresponding module for the struct namespace let id = match self.push_child_module(&name, self.file_id, false, false) { - Ok(local_id) => { - context.def_interner.new_struct(&unresolved, krate, local_id, self.file_id) - } + Ok(local_id) => context.def_interner.new_struct( + &unresolved, + resolved_generics, + krate, + local_id, + self.file_id, + ), Err(error) => { definition_errors.push((error.into(), self.file_id)); continue; @@ -356,7 +331,14 @@ impl<'a> ModCollector<'a> { type_alias_def: type_alias, }; - let type_alias_id = context.def_interner.push_type_alias(&unresolved); + let resolved_generics = context.resolve_generics( + &unresolved.type_alias_def.generics, + &mut errors, + self.file_id, + ); + + let type_alias_id = + context.def_interner.push_type_alias(&unresolved, resolved_generics); // Add the type alias to scope so its path can be looked up later let result = self.def_collector.def_map.modules[self.module_id.0] @@ -516,6 +498,9 @@ impl<'a> ModCollector<'a> { } } + let resolved_generics = + context.resolve_generics(&trait_definition.generics, &mut errors, self.file_id); + // And store the TraitId -> TraitType mapping somewhere it is reachable let unresolved = UnresolvedTrait { file_id: self.file_id, @@ -525,7 +510,8 @@ impl<'a> ModCollector<'a> { method_ids, fns_with_default_impl: unresolved_functions, }; - context.def_interner.push_empty_trait(trait_id, &unresolved); + context.def_interner.push_empty_trait(trait_id, &unresolved, resolved_generics); + self.def_collector.items.traits.insert(trait_id, unresolved); } errors @@ -572,17 +558,14 @@ impl<'a> ModCollector<'a> { macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; - let child_file_id = - match find_module(&context.file_manager, self.file_id, &mod_decl.ident.0.contents) { - Ok(child_file_id) => child_file_id, - Err(expected_path) => { - let mod_name = mod_decl.ident.clone(); - let err = - DefCollectorErrorKind::UnresolvedModuleDecl { mod_name, expected_path }; - errors.push((err.into(), self.file_id)); - return errors; - } - }; + let child_file_id = match find_module(&context.file_manager, self.file_id, &mod_decl.ident) + { + Ok(child_file_id) => child_file_id, + Err(err) => { + errors.push((err.into(), self.file_id)); + return errors; + } + }; let location = Location { file: self.file_id, span: mod_decl.ident.span() }; @@ -699,26 +682,47 @@ impl<'a> ModCollector<'a> { fn find_module( file_manager: &FileManager, anchor: FileId, - mod_name: &str, -) -> Result { + mod_name: &Ident, +) -> Result { let anchor_path = file_manager .path(anchor) .expect("File must exist in file manager in order for us to be resolving its imports.") .with_extension(""); let anchor_dir = anchor_path.parent().unwrap(); - // if `anchor` is a `main.nr`, `lib.nr`, `mod.nr` or `{mod_name}.nr`, we check siblings of - // the anchor at `base/mod_name.nr`. - let candidate = if should_check_siblings_for_module(&anchor_path, anchor_dir) { - anchor_dir.join(format!("{mod_name}.{FILE_EXTENSION}")) + // Assuming anchor is called "anchor.nr" and we are looking up a module named "mod_name"... + // This is "mod_name" + let mod_name_str = &mod_name.0.contents; + + // If we are in a special name like "main.nr", "lib.nr", "mod.nr" or "{mod_name}.nr", + // the search starts at the same directory, otherwise it starts in a nested directory. + let start_dir = if should_check_siblings_for_module(&anchor_path, anchor_dir) { + anchor_dir } else { - // Otherwise, we check for children of the anchor at `base/anchor/mod_name.nr` - anchor_path.join(format!("{mod_name}.{FILE_EXTENSION}")) + anchor_path.as_path() }; - file_manager - .name_to_id(candidate.clone()) - .ok_or_else(|| candidate.as_os_str().to_string_lossy().to_string()) + // Check "mod_name.nr" + let mod_name_candidate = start_dir.join(format!("{mod_name_str}.{FILE_EXTENSION}")); + let mod_name_result = file_manager.name_to_id(mod_name_candidate.clone()); + + // Check "mod_name/mod.nr" + let mod_nr_candidate = start_dir.join(mod_name_str).join(format!("mod.{FILE_EXTENSION}")); + let mod_nr_result = file_manager.name_to_id(mod_nr_candidate.clone()); + + match (mod_nr_result, mod_name_result) { + (Some(_), Some(_)) => Err(DefCollectorErrorKind::OverlappingModuleDecls { + mod_name: mod_name.clone(), + expected_path: mod_name_candidate.as_os_str().to_string_lossy().to_string(), + alternative_path: mod_nr_candidate.as_os_str().to_string_lossy().to_string(), + }), + (Some(id), None) | (None, Some(id)) => Ok(id), + (None, None) => Err(DefCollectorErrorKind::UnresolvedModuleDecl { + mod_name: mod_name.clone(), + expected_path: mod_name_candidate.as_os_str().to_string_lossy().to_string(), + alternative_path: mod_nr_candidate.as_os_str().to_string_lossy().to_string(), + }), + } } /// Returns true if a module's child modules are expected to be in the same directory. @@ -761,74 +765,241 @@ fn is_native_field(str: &str) -> bool { } } +pub(crate) fn collect_trait_impl_functions( + interner: &mut NodeInterner, + trait_impl: &mut NoirTraitImpl, + krate: CrateId, + file_id: FileId, + local_id: LocalModuleId, +) -> UnresolvedFunctions { + let mut unresolved_functions = + UnresolvedFunctions { file_id, functions: Vec::new(), trait_id: None, self_type: None }; + + let module = ModuleId { krate, local_id }; + + for item in std::mem::take(&mut trait_impl.items) { + if let TraitImplItem::Function(impl_method) = item { + let func_id = interner.push_empty_fn(); + let location = Location::new(impl_method.span(), file_id); + interner.push_function(func_id, &impl_method.def, module, location); + unresolved_functions.push_fn(local_id, func_id, impl_method); + } + } + + unresolved_functions +} + +pub(crate) fn collect_global( + interner: &mut NodeInterner, + def_map: &mut CrateDefMap, + global: LetStatement, + file_id: FileId, + module_id: LocalModuleId, +) -> (UnresolvedGlobal, Option<(CompilationError, FileId)>) { + let name = global.pattern.name_ident().clone(); + + let global_id = interner.push_empty_global( + name.clone(), + module_id, + file_id, + global.attributes.clone(), + matches!(global.pattern, Pattern::Mutable { .. }), + ); + + // Add the statement to the scope so its path can be looked up later + let result = def_map.modules[module_id.0].declare_global(name, global_id); + + let error = result.err().map(|(first_def, second_def)| { + let err = + DefCollectorErrorKind::Duplicate { typ: DuplicateType::Global, first_def, second_def }; + (err.into(), file_id) + }); + + let global = UnresolvedGlobal { file_id, module_id, global_id, stmt_def: global }; + (global, error) +} + #[cfg(test)] -mod tests { +mod find_module_tests { use super::*; - use std::path::PathBuf; - use tempfile::{tempdir, TempDir}; + use noirc_errors::Spanned; + use std::path::{Path, PathBuf}; + + fn add_file(file_manager: &mut FileManager, dir: &Path, file_name: &str) -> FileId { + let mut target_filename = PathBuf::from(&dir); + for path in file_name.split('/') { + target_filename = target_filename.join(path); + } + + file_manager + .add_file_with_source(&target_filename, "fn foo() {}".to_string()) + .expect("could not add file to file manager and obtain a FileId") + } + + fn find_module( + file_manager: &FileManager, + anchor: FileId, + mod_name: &str, + ) -> Result { + let mod_name = Ident(Spanned::from_position(0, 1, mod_name.to_string())); + super::find_module(file_manager, anchor, &mod_name) + } + + #[test] + fn errors_if_cannot_find_file() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&PathBuf::new()); + + let file_id = add_file(&mut fm, &dir, "my_dummy_file.nr"); - // Returns the absolute path to the file - fn create_dummy_file(dir: &TempDir, file_name: &Path) -> PathBuf { - let file_path = dir.path().join(file_name); - let _file = std::fs::File::create(&file_path).unwrap(); - file_path + let result = find_module(&fm, file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); } #[test] - fn path_resolve_file_module() { - let dir = tempdir().unwrap(); + fn errors_because_cannot_find_mod_relative_to_main() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); - let entry_file_name = Path::new("my_dummy_file.nr"); - create_dummy_file(&dir, entry_file_name); + let main_file_id = add_file(&mut fm, &dir, "main.nr"); + add_file(&mut fm, &dir, "main/foo.nr"); - let mut fm = FileManager::new(dir.path()); + let result = find_module(&fm, main_file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); + } + + #[test] + fn errors_because_cannot_find_mod_relative_to_lib() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); - let file_id = fm.add_file_with_source(entry_file_name, "fn foo() {}".to_string()).unwrap(); + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "lib/foo.nr"); - let dep_file_name = Path::new("foo.nr"); - create_dummy_file(&dir, dep_file_name); - find_module(&fm, file_id, "foo").unwrap_err(); + let result = find_module(&fm, lib_file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); } #[test] - fn path_resolve_sub_module() { - let dir = tempdir().unwrap(); - let mut fm = FileManager::new(dir.path()); - - // Create a lib.nr file at the root. - // we now have dir/lib.nr - let lib_nr_path = create_dummy_file(&dir, Path::new("lib.nr")); - let file_id = fm - .add_file_with_source(lib_nr_path.as_path(), "fn foo() {}".to_string()) - .expect("could not add file to file manager and obtain a FileId"); - - // Create a sub directory - // we now have: - // - dir/lib.nr - // - dir/sub_dir - let sub_dir = TempDir::new_in(&dir).unwrap(); - let sub_dir_name = sub_dir.path().file_name().unwrap().to_str().unwrap(); - - // Add foo.nr to the subdirectory - // we no have: - // - dir/lib.nr - // - dir/sub_dir/foo.nr - let foo_nr_path = create_dummy_file(&sub_dir, Path::new("foo.nr")); - fm.add_file_with_source(foo_nr_path.as_path(), "fn foo() {}".to_string()); - - // Add a parent module for the sub_dir - // we no have: - // - dir/lib.nr - // - dir/sub_dir.nr - // - dir/sub_dir/foo.nr - let sub_dir_nr_path = create_dummy_file(&dir, Path::new(&format!("{sub_dir_name}.nr"))); - fm.add_file_with_source(sub_dir_nr_path.as_path(), "fn foo() {}".to_string()); - - // First check for the sub_dir.nr file and add it to the FileManager - let sub_dir_file_id = find_module(&fm, file_id, sub_dir_name).unwrap(); - - // Now check for files in it's subdirectory + fn errors_because_cannot_find_sibling_mod_for_regular_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let foo_file_id = add_file(&mut fm, &dir, "foo.nr"); + add_file(&mut fm, &dir, "bar.nr"); + + let result = find_module(&fm, foo_file_id, "bar"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); + } + + #[test] + fn cannot_find_module_in_the_same_directory_for_regular_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "bar.nr"); + add_file(&mut fm, &dir, "foo.nr"); + + // `mod bar` from `lib.nr` should find `bar.nr` + let bar_file_id = find_module(&fm, lib_file_id, "bar").unwrap(); + + // `mod foo` from `bar.nr` should fail to find `foo.nr` + let result = find_module(&fm, bar_file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); + } + + #[test] + fn finds_module_in_sibling_dir_for_regular_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let sub_dir_file_id = add_file(&mut fm, &dir, "sub_dir.nr"); + add_file(&mut fm, &dir, "sub_dir/foo.nr"); + + // `mod foo` from `sub_dir.nr` should find `sub_dir/foo.nr` find_module(&fm, sub_dir_file_id, "foo").unwrap(); } + + #[test] + fn finds_module_in_sibling_dir_mod_nr_for_regular_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let sub_dir_file_id = add_file(&mut fm, &dir, "sub_dir.nr"); + add_file(&mut fm, &dir, "sub_dir/foo/mod.nr"); + + // `mod foo` from `sub_dir.nr` should find `sub_dir/foo.nr` + find_module(&fm, sub_dir_file_id, "foo").unwrap(); + } + + #[test] + fn finds_module_in_sibling_dir_for_special_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "sub_dir.nr"); + add_file(&mut fm, &dir, "sub_dir/foo.nr"); + + // `mod sub_dir` from `lib.nr` should find `sub_dir.nr` + let sub_dir_file_id = find_module(&fm, lib_file_id, "sub_dir").unwrap(); + + // `mod foo` from `sub_dir.nr` should find `sub_dir/foo.nr` + find_module(&fm, sub_dir_file_id, "foo").unwrap(); + } + + #[test] + fn finds_mod_dot_nr_for_special_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "foo/mod.nr"); + + // Check that searching "foo" finds the mod.nr file + find_module(&fm, lib_file_id, "foo").unwrap(); + } + + #[test] + fn errors_mod_dot_nr_in_same_directory() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "mod.nr"); + + // Check that searching "foo" does not pick up the mod.nr file + let result = find_module(&fm, lib_file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::UnresolvedModuleDecl { .. }))); + } + + #[test] + fn errors_if_file_exists_at_both_potential_module_locations_for_regular_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let foo_file_id = add_file(&mut fm, &dir, "foo.nr"); + add_file(&mut fm, &dir, "foo/bar.nr"); + add_file(&mut fm, &dir, "foo/bar/mod.nr"); + + // Check that `mod bar` from `foo` gives an error + let result = find_module(&fm, foo_file_id, "bar"); + assert!(matches!(result, Err(DefCollectorErrorKind::OverlappingModuleDecls { .. }))); + } + + #[test] + fn errors_if_file_exists_at_both_potential_module_locations_for_special_name() { + let dir = PathBuf::new(); + let mut fm = FileManager::new(&dir); + + let lib_file_id = add_file(&mut fm, &dir, "lib.nr"); + add_file(&mut fm, &dir, "foo.nr"); + add_file(&mut fm, &dir, "foo/mod.nr"); + + // Check that searching "foo" gives an error + let result = find_module(&fm, lib_file_id, "foo"); + assert!(matches!(result, Err(DefCollectorErrorKind::OverlappingModuleDecls { .. }))); + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs index edeb463e10d6..37c5a460667f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/errors.rs @@ -1,4 +1,4 @@ -use crate::ast::{Ident, Path}; +use crate::ast::{Ident, Path, UnresolvedTypeData}; use crate::hir::resolution::import::PathResolutionError; use noirc_errors::CustomDiagnostic as Diagnostic; @@ -27,7 +27,9 @@ pub enum DefCollectorErrorKind { #[error("duplicate {typ} found in namespace")] Duplicate { typ: DuplicateType, first_def: Ident, second_def: Ident }, #[error("unresolved import")] - UnresolvedModuleDecl { mod_name: Ident, expected_path: String }, + UnresolvedModuleDecl { mod_name: Ident, expected_path: String, alternative_path: String }, + #[error("overlapping imports")] + OverlappingModuleDecls { mod_name: Ident, expected_path: String, alternative_path: String }, #[error("path resolution error")] PathResolutionError(PathResolutionError), #[error("Non-struct type used in impl")] @@ -66,6 +68,8 @@ pub enum DefCollectorErrorKind { TraitImplOrphaned { span: Span }, #[error("macro error : {0:?}")] MacroError(MacroError), + #[error("The only supported types of numeric generics are integers, fields, and booleans")] + UnsupportedNumericGenericType { ident: Ident, typ: UnresolvedTypeData }, } /// An error struct that macro processors can return. @@ -119,12 +123,22 @@ impl<'a> From<&'a DefCollectorErrorKind> for Diagnostic { diag } } - DefCollectorErrorKind::UnresolvedModuleDecl { mod_name, expected_path } => { + DefCollectorErrorKind::UnresolvedModuleDecl { mod_name, expected_path, alternative_path } => { let span = mod_name.0.span(); let mod_name = &mod_name.0.contents; Diagnostic::simple_error( - format!("No module `{mod_name}` at path `{expected_path}`"), + format!("No module `{mod_name}` at path `{expected_path}` or `{alternative_path}`"), + String::new(), + span, + ) + } + DefCollectorErrorKind::OverlappingModuleDecls { mod_name, expected_path, alternative_path } => { + let span = mod_name.0.span(); + let mod_name = &mod_name.0.contents; + + Diagnostic::simple_error( + format!("Overlapping modules `{mod_name}` at path `{expected_path}` and `{alternative_path}`"), String::new(), span, ) @@ -228,6 +242,15 @@ impl<'a> From<&'a DefCollectorErrorKind> for Diagnostic { DefCollectorErrorKind::MacroError(macro_error) => { Diagnostic::simple_error(macro_error.primary_message.clone(), macro_error.secondary_message.clone().unwrap_or_default(), macro_error.span.unwrap_or_default()) }, + DefCollectorErrorKind::UnsupportedNumericGenericType { ident, typ } => { + let name = &ident.0.contents; + + Diagnostic::simple_error( + format!("{name} has a type of {typ}. The only supported types of numeric generics are integers and fields"), + "Unsupported numeric generic type".to_string(), + ident.0.span(), + ) + } } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs index 19e06387d431..59205f74d89d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -73,7 +73,7 @@ impl CrateDefMap { pub fn collect_defs( crate_id: CrateId, context: &mut Context, - use_elaborator: bool, + use_legacy: bool, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled @@ -122,7 +122,7 @@ impl CrateDefMap { context, ast, root_file_id, - use_elaborator, + use_legacy, macro_processors, )); 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 55dc22d6c5d0..71fdc6b30d22 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs @@ -5,17 +5,21 @@ pub mod resolution; pub mod scope; pub mod type_check; +use crate::ast::UnresolvedGenerics; use crate::debug::DebugInstrumenter; use crate::graph::{CrateGraph, CrateId}; use crate::hir_def::function::FuncMeta; use crate::node_interner::{FuncId, NodeInterner, StructId}; use crate::parser::ParserError; -use crate::ParsedModule; +use crate::{Generics, Kind, ParsedModule, ResolvedGeneric, Type, TypeVariable}; +use def_collector::dc_crate::CompilationError; use def_map::{Contract, CrateDefMap}; -use fm::FileManager; +use fm::{FileId, FileManager}; +use iter_extended::vecmap; use noirc_errors::Location; use std::borrow::Cow; use std::collections::{BTreeMap, HashMap}; +use std::rc::Rc; use self::def_map::TestFunction; @@ -80,7 +84,7 @@ impl Context<'_, '_> { } } - pub fn parsed_file_results(&self, file_id: fm::FileId) -> (ParsedModule, Vec) { + pub fn parsed_file_results(&self, file_id: FileId) -> (ParsedModule, Vec) { self.parsed_files.get(&file_id).expect("noir file wasn't parsed").clone() } @@ -256,4 +260,34 @@ impl Context<'_, '_> { pub fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { module_id.module(&self.def_maps) } + + /// Generics need to be resolved before elaboration to distinguish + /// between normal and numeric generics. + /// This method is expected to be used during definition collection. + /// Each result is returned in a list rather than returned as a single result as to allow + /// definition collection to provide an error for each ill-formed numeric generic. + pub(crate) fn resolve_generics( + &mut self, + generics: &UnresolvedGenerics, + errors: &mut Vec<(CompilationError, FileId)>, + file_id: FileId, + ) -> Generics { + vecmap(generics, |generic| { + // Map the generic to a fresh type variable + let id = self.def_interner.next_type_variable_id(); + let type_var = TypeVariable::unbound(id); + let ident = generic.ident(); + let span = ident.0.span(); + + // Check for name collisions of this generic + let name = Rc::new(ident.0.contents.clone()); + + let kind = generic.kind().unwrap_or_else(|err| { + errors.push((err.into(), file_id)); + Kind::Numeric(Box::new(Type::Error)) + }); + + ResolvedGeneric { name, type_var, kind, span } + }) + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index 06f6dda71427..bf6de746791a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -98,8 +98,24 @@ pub enum ResolverError { NoPredicatesAttributeOnUnconstrained { ident: Ident }, #[error("#[fold] attribute is only allowed on constrained functions")] FoldAttributeOnUnconstrained { ident: Ident }, + #[error("The only supported types of numeric generics are integers, fields, and booleans")] + UnsupportedNumericGenericType { ident: Ident, typ: Type }, + #[error("Numeric generics should be explicit")] + UseExplicitNumericGeneric { ident: Ident }, + #[error("expected type, found numeric generic parameter")] + NumericGenericUsedForType { name: String, span: Span }, #[error("Invalid array length construction")] ArrayLengthInterpreter { error: InterpreterError }, + #[error("The unquote operator '$' can only be used within a quote expression")] + UnquoteUsedOutsideQuote { span: Span }, + #[error("Invalid syntax in macro call")] + InvalidSyntaxInMacroCall { span: Span }, + #[error("Macros must be comptime functions")] + MacroIsNotComptime { span: Span }, + #[error("Annotation name must refer to a comptime function")] + NonFunctionInAnnotation { span: Span }, + #[error("Unknown annotation")] + UnknownAnnotation { span: Span }, } impl ResolverError { @@ -319,7 +335,7 @@ impl<'a> From<&'a ResolverError> for Diagnostic { "Usage of the `#[foreign]` or `#[builtin]` function attributes are not allowed outside of the Noir standard library".into(), ident.span(), ), - ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_error( + ResolverError::OracleMarkedAsConstrained { ident } => Diagnostic::simple_warning( error.to_string(), "Oracle functions must have the `unconstrained` keyword applied".into(), ident.span(), @@ -390,7 +406,67 @@ impl<'a> From<&'a ResolverError> for Diagnostic { diag.add_note("The `#[fold]` attribute specifies whether a constrained function should be treated as a separate circuit rather than inlined into the program entry point".to_owned()); diag } + ResolverError::UnsupportedNumericGenericType { ident , typ } => { + let name = &ident.0.contents; + + Diagnostic::simple_error( + format!("{name} has a type of {typ}. The only supported types of numeric generics are integers, fields, and booleans."), + "Unsupported numeric generic type".to_string(), + ident.0.span(), + ) + } + ResolverError::UseExplicitNumericGeneric { ident } => { + let name = &ident.0.contents; + + Diagnostic::simple_warning( + String::from("Noir now supports explicit numeric generics. Support for implicit numeric generics will be removed in the following release."), + format!("Numeric generic `{name}` should now be specified with `let {name}: `"), + ident.0.span(), + ) + } + ResolverError::NumericGenericUsedForType { name, span } => { + Diagnostic::simple_error( + format!("expected type, found numeric generic parameter {name}"), + String::from("not a type"), + *span, + ) + } ResolverError::ArrayLengthInterpreter { error } => Diagnostic::from(error), + ResolverError::UnquoteUsedOutsideQuote { span } => { + Diagnostic::simple_error( + "The unquote operator '$' can only be used within a quote expression".into(), + "".into(), + *span, + ) + }, + ResolverError::InvalidSyntaxInMacroCall { span } => { + Diagnostic::simple_error( + "Invalid syntax in macro call".into(), + "Macro calls must call a comptime function directly, they cannot use higher-order functions".into(), + *span, + ) + }, + ResolverError::MacroIsNotComptime { span } => { + Diagnostic::simple_error( + "This macro call is to a non-comptime function".into(), + "Macro calls must be to comptime functions".into(), + *span, + ) + }, + ResolverError::NonFunctionInAnnotation { span } => { + Diagnostic::simple_error( + "Unknown annotation".into(), + "The name of an annotation must refer to a comptime function".into(), + *span, + ) + }, + ResolverError::UnknownAnnotation { span } => { + Diagnostic::simple_warning( + "Unknown annotation".into(), + "No matching comptime function found in scope".into(), + *span, + ) + }, } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/functions.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/functions.rs index e63de9b9173c..fe46796ed24c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/functions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/functions.rs @@ -1,8 +1,7 @@ -use std::{collections::BTreeMap, rc::Rc}; +use std::collections::BTreeMap; use fm::FileId; use iter_extended::vecmap; -use noirc_errors::Span; use crate::{ graph::CrateId, @@ -11,10 +10,10 @@ use crate::{ def_map::{CrateDefMap, ModuleId}, }, node_interner::{FuncId, NodeInterner, TraitImplId}, - Type, TypeVariable, + ResolvedGeneric, Type, }; -use super::{path_resolver::StandardPathResolver, resolver::Resolver}; +use super::{path_resolver::StandardPathResolver, Resolver}; #[allow(clippy::too_many_arguments)] pub(crate) fn resolve_function_set( @@ -24,7 +23,7 @@ pub(crate) fn resolve_function_set( mut unresolved_functions: UnresolvedFunctions, self_type: Option, trait_impl_id: Option, - impl_generics: Vec<(Rc, TypeVariable, Span)>, + impl_generics: Vec, errors: &mut Vec<(CompilationError, FileId)>, ) -> Vec<(FileId, FuncId)> { let file_id = unresolved_functions.file_id; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs index 9a0be775c307..d73130411e46 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/import.rs @@ -38,8 +38,6 @@ pub(crate) type PathResolutionResult = Result From<&'a PathResolutionError> for CustomDiagnostic { PathResolutionError::Unresolved(ident) => { CustomDiagnostic::simple_error(error.to_string(), String::new(), ident.span()) } - PathResolutionError::ExternalContractUsed(ident) => CustomDiagnostic::simple_error( - error.to_string(), - "Contracts may only be referenced from within a contract".to_string(), - ident.span(), - ), // This will be upgraded to an error in future versions PathResolutionError::Private(ident) => CustomDiagnostic::simple_warning( error.to_string(), @@ -140,12 +133,27 @@ fn resolve_path_to_ns( // Resolve from the root of the crate resolve_path_from_crate_root(crate_id, importing_crate, import_path, def_maps) } - crate::ast::PathKind::Dep => { - resolve_external_dep(def_map, import_directive, def_maps, importing_crate) - } crate::ast::PathKind::Plain => { - // Plain paths are only used to import children modules. It's possible to allow import of external deps, but maybe this distinction is better? - // In Rust they can also point to external Dependencies, if no children can be found with the specified name + // There is a possibility that the import path is empty + // In that case, early return + if import_path.is_empty() { + return resolve_name_in_module( + crate_id, + importing_crate, + import_path, + import_directive.module_id, + def_maps, + ); + } + + let current_mod_id = ModuleId { krate: crate_id, local_id: import_directive.module_id }; + let current_mod = &def_map.modules[current_mod_id.local_id.0]; + let first_segment = import_path.first().expect("ice: could not fetch first segment"); + if current_mod.find_name(first_segment).is_none() { + // Resolve externally when first segment is unresolved + return resolve_external_dep(def_map, import_directive, def_maps, importing_crate); + } + resolve_name_in_module( crate_id, importing_crate, @@ -154,6 +162,10 @@ fn resolve_path_to_ns( def_maps, ) } + + crate::ast::PathKind::Dep => { + resolve_external_dep(def_map, import_directive, def_maps, importing_crate) + } } } @@ -271,7 +283,9 @@ fn resolve_external_dep( .ok_or_else(|| PathResolutionError::Unresolved(crate_name.to_owned()))?; // Create an import directive for the dependency crate - let path_without_crate_name = &path[1..]; // XXX: This will panic if the path is of the form `use dep::std` Ideal algorithm will not distinguish between crate and module + // XXX: This will panic if the path is of the form `use std`. Ideal algorithm will not distinguish between crate and module + // See `singleton_import.nr` test case for a check that such cases are handled elsewhere. + let path_without_crate_name = &path[1..]; let path = Path { segments: path_without_crate_name.to_vec(), 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 01f58ba4c275..6d547aaf0b71 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 @@ -23,7 +23,7 @@ use crate::hir_def::expr::{ use crate::hir_def::function::FunctionBody; use crate::hir_def::traits::{Trait, TraitConstraint}; use crate::macros_api::SecondaryAttribute; -use crate::token::{Attributes, FunctionAttribute}; +use crate::token::Attributes; use regex::Regex; use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::rc::Rc; @@ -32,8 +32,9 @@ use crate::ast::{ ArrayLiteral, BinaryOpKind, BlockExpression, Expression, ExpressionKind, ForRange, FunctionDefinition, FunctionKind, FunctionReturnType, Ident, ItemVisibility, LValue, LetStatement, Literal, NoirFunction, NoirStruct, NoirTypeAlias, Param, Path, PathKind, Pattern, - Statement, StatementKind, TraitBound, UnaryOp, UnresolvedGenerics, UnresolvedTraitConstraint, - UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, Visibility, ERROR_IDENT, + Statement, StatementKind, TraitBound, UnaryOp, UnresolvedGeneric, UnresolvedGenerics, + UnresolvedTraitConstraint, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, + Visibility, ERROR_IDENT, }; use crate::graph::CrateId; use crate::hir::def_map::{ModuleDefId, TryFromModuleDefId, MAIN_FUNCTION}; @@ -47,7 +48,10 @@ use crate::node_interner::{ DefinitionId, DefinitionKind, DependencyId, ExprId, FuncId, GlobalId, NodeInterner, StmtId, StructId, TraitId, TraitImplId, TraitMethodId, TypeAliasId, }; -use crate::{Generics, Shared, StructType, Type, TypeAlias, TypeVariable, TypeVariableKind}; +use crate::{ + GenericTypeVars, Generics, Kind, ResolvedGeneric, Shared, StructType, Type, TypeAlias, + TypeVariable, TypeVariableKind, +}; use fm::FileId; use iter_extended::vecmap; use noirc_errors::{Location, Span, Spanned}; @@ -64,6 +68,7 @@ use super::errors::{PubPosition, ResolverError}; use super::import::PathResolution; pub const SELF_TYPE_NAME: &str = "Self"; +pub const WILDCARD_TYPE: &str = "_"; type Scope = GenericScope; type ScopeTree = GenericScopeTree; @@ -130,7 +135,7 @@ pub struct Resolver<'a> { /// unique type variables if we're resolving a struct. Empty otherwise. /// This is a Vec rather than a map to preserve the order a functions generics /// were declared in. - generics: Vec<(Rc, TypeVariable, Span)>, + generics: Vec, /// When resolving lambda expressions, we need to keep track of the variables /// that are captured. We do this in order to create the hidden environment @@ -222,7 +227,8 @@ impl<'a> Resolver<'a> { let mut new_generic_ident: Ident = format!("T{}_impl_{}", func_id, path.as_string()).into(); let mut new_generic_path = Path::from_ident(new_generic_ident.clone()); - while impl_trait_generics.contains(&new_generic_ident) + let new_generic = UnresolvedGeneric::from(new_generic_ident.clone()); + while impl_trait_generics.contains(&new_generic) || self.lookup_generic_or_global_type(&new_generic_path).is_some() { new_generic_ident = @@ -230,7 +236,7 @@ impl<'a> Resolver<'a> { new_generic_path = Path::from_ident(new_generic_ident.clone()); counter += 1; } - impl_trait_generics.insert(new_generic_ident.clone()); + impl_trait_generics.insert(UnresolvedGeneric::from(new_generic_ident.clone())); let is_synthesized = true; let new_generic_type_data = @@ -248,7 +254,7 @@ impl<'a> Resolver<'a> { }; parameter.typ.typ = new_generic_type_data; - func.def.generics.push(new_generic_ident); + func.def.generics.push(new_generic_ident.into()); func.def.where_clause.push(new_trait_constraint); } } @@ -569,7 +575,7 @@ impl<'a> Resolver<'a> { let fields = self.resolve_type_inner(*fields); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } - Code => Type::Code, + Quoted(quoted) => Type::Quoted(quoted), Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, @@ -590,7 +596,7 @@ impl<'a> Resolver<'a> { let env = Box::new(self.resolve_type_inner(*env)); match *env { - Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _) => { + Type::Unit | Type::Tuple(_) | Type::NamedGeneric(_, _, _) => { Type::Function(args, ret, env) } _ => { @@ -606,6 +612,7 @@ impl<'a> Resolver<'a> { Type::MutableReference(Box::new(self.resolve_type_inner(*element))) } Parenthesized(typ) => self.resolve_type_inner(*typ), + Resolved(id) => self.interner.get_quoted_type(id).clone(), }; if let Type::Struct(_, _) = resolved_type { @@ -620,8 +627,8 @@ impl<'a> Resolver<'a> { resolved_type } - fn find_generic(&self, target_name: &str) -> Option<&(Rc, TypeVariable, Span)> { - self.generics.iter().find(|(name, _, _)| name.as_ref() == target_name) + fn find_generic(&self, target_name: &str) -> Option<&ResolvedGeneric> { + self.generics.iter().find(|generic| generic.name.as_ref() == target_name) } fn resolve_named_type(&mut self, path: Path, args: Vec) -> Type { @@ -746,9 +753,15 @@ impl<'a> Resolver<'a> { fn lookup_generic_or_global_type(&mut self, path: &Path) -> Option { if path.segments.len() == 1 { let name = &path.last_segment().0.contents; - if let Some((name, var, _)) = self.find_generic(name) { - return Some(Type::NamedGeneric(var.clone(), name.clone())); - } + if let Some(generic) = self.find_generic(name) { + // We always insert a `TypeKind::Normal` as we do not support explicit numeric generics + // in the resolver + return Some(Type::NamedGeneric( + generic.type_var.clone(), + generic.name.clone(), + Kind::Normal, + )); + }; } // If we cannot find a local generic of the same name, try to look up a global @@ -847,14 +860,14 @@ impl<'a> Resolver<'a> { /// Return the current generics. /// Needed to keep referring to the same type variables across many /// methods in a single impl. - pub fn get_generics(&self) -> &[(Rc, TypeVariable, Span)] { + pub fn get_generics(&self) -> &[ResolvedGeneric] { &self.generics } /// Set the current generics that are in scope. /// Unlike add_generics, this function will not create any new type variables, /// opting to reuse the existing ones it is directly given. - pub fn set_generics(&mut self, generics: Vec<(Rc, TypeVariable, Span)>) { + pub fn set_generics(&mut self, generics: Vec) { self.generics = generics; } @@ -874,48 +887,79 @@ impl<'a> Resolver<'a> { // Map the generic to a fresh type variable let id = self.interner.next_type_variable_id(); let typevar = TypeVariable::unbound(id); - let span = generic.0.span(); + let ident = generic.ident(); + let span = ident.0.span(); // Check for name collisions of this generic - let name = Rc::new(generic.0.contents.clone()); + let name = Rc::new(ident.0.contents.clone()); - if let Some((_, _, first_span)) = self.find_generic(&name) { + let resolved_generic = ResolvedGeneric { + name: name.clone(), + type_var: typevar, + // We only support numeric generics in the elaborator + kind: Kind::Normal, + span, + }; + if let Some(generic) = self.find_generic(&name) { self.errors.push(ResolverError::DuplicateDefinition { - name: generic.0.contents.clone(), - first_span: *first_span, + name: ident.0.contents.clone(), + first_span: generic.span, second_span: span, }); } else { - self.generics.push((name, typevar.clone(), span)); + self.generics.push(resolved_generic.clone()); } - typevar + resolved_generic }) } /// Add the given existing generics to scope. /// This is useful for adding the same generics to many items. E.g. apply impl generics /// to each function in the impl or trait generics to each item in the trait. - pub fn add_existing_generics(&mut self, names: &UnresolvedGenerics, generics: &Generics) { - assert_eq!(names.len(), generics.len()); + pub fn add_existing_generics( + &mut self, + unresolved_generics: &UnresolvedGenerics, + generics: &GenericTypeVars, + ) { + assert_eq!(unresolved_generics.len(), generics.len()); - for (name, typevar) in names.iter().zip(generics) { - self.add_existing_generic(&name.0.contents, name.0.span(), typevar.clone()); + for (unresolved_generic, typevar) in unresolved_generics.iter().zip(generics) { + self.add_existing_generic( + unresolved_generic, + unresolved_generic.span(), + typevar.clone(), + ); } } - pub fn add_existing_generic(&mut self, name: &str, span: Span, typevar: TypeVariable) { + pub fn add_existing_generic( + &mut self, + unresolved_generic: &UnresolvedGeneric, + span: Span, + typevar: TypeVariable, + ) { + let name = &unresolved_generic.ident().0.contents; + // Check for name collisions of this generic - let rc_name = Rc::new(name.to_owned()); + let rc_name = Rc::new(name.clone()); - if let Some((_, _, first_span)) = self.find_generic(&rc_name) { + if let Some(generic) = self.find_generic(&rc_name) { self.errors.push(ResolverError::DuplicateDefinition { - name: name.to_owned(), - first_span: *first_span, + name: name.clone(), + first_span: generic.span, second_span: span, }); } else { - self.generics.push((rc_name, typevar, span)); + let resolved_generic = ResolvedGeneric { + name: rc_name, + type_var: typevar.clone(), + kind: unresolved_generic + .kind() + .expect("ICE: Deprecated code should only support normal kinds"), + span, + }; + self.generics.push(resolved_generic); } } @@ -991,7 +1035,7 @@ impl<'a> Resolver<'a> { // indicate we should code generate in the same way. Thus, we unify the attributes into one flag here. let has_inline_attribute = has_no_predicates_attribute || should_fold; - let generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); + let generics = vecmap(&self.generics, |generic| generic.type_var.clone()); let mut parameters = vec![]; let mut parameter_types = vec![]; @@ -1042,14 +1086,6 @@ impl<'a> Resolver<'a> { }); } - if matches!(attributes.function, Some(FunctionAttribute::Test { .. })) - && !parameters.is_empty() - { - self.push_err(ResolverError::TestFunctionHasParameters { - span: func.name_ident().span(), - }); - } - let mut typ = Type::Function(parameter_types, return_type, Box::new(Type::Unit)); if !generics.is_empty() { @@ -1060,8 +1096,8 @@ impl<'a> Resolver<'a> { let direct_generics = func.def.generics.iter(); let direct_generics = direct_generics - .filter_map(|generic| self.find_generic(&generic.0.contents)) - .map(|(name, typevar, _span)| (name.clone(), typevar.clone())) + .filter_map(|generic| self.find_generic(&generic.ident().0.contents)) + .map(|ResolvedGeneric { name, type_var, .. }| (name.clone(), type_var.clone())) .collect(); FuncMeta { @@ -1078,6 +1114,7 @@ impl<'a> Resolver<'a> { trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), is_entry_point: self.is_entry_point_function(func), has_inline_attribute, + source_crate: self.path_resolver.module_id().krate, // These fields are only used by the elaborator all_generics: Vec::new(), @@ -1114,6 +1151,7 @@ impl<'a> Resolver<'a> { !func.def.is_unconstrained } + // TODO(https://github.com/noir-lang/noir/issues/5156): Remove this method in favor of explicit numeric generics fn declare_numeric_generics(&mut self, params: &[Type], return_type: &Type) { if self.generics.is_empty() { return; @@ -1126,12 +1164,12 @@ impl<'a> Resolver<'a> { // We can fail to find the generic in self.generics if it is an implicit one created // by the compiler. This can happen when, e.g. eliding array lengths using the slice // syntax [T]. - if let Some((name, _, span)) = - self.generics.iter().find(|(name, _, _)| name.as_ref() == &name_to_find) + if let Some(ResolvedGeneric { name, span, .. }) = + self.generics.iter().find(|generic| generic.name.as_ref() == &name_to_find) { let ident = Ident::new(name.to_string(), *span); let definition = DefinitionKind::GenericType(type_variable); - self.add_variable_decl_inner(ident, false, false, false, definition); + self.add_variable_decl_inner(ident.clone(), false, false, false, definition); } } } @@ -1157,8 +1195,8 @@ impl<'a> Resolver<'a> { | Type::Error | Type::TypeVariable(_, _) | Type::Constant(_) - | Type::NamedGeneric(_, _) - | Type::Code + | Type::NamedGeneric(_, _, _) + | Type::Quoted(_) | Type::Forall(_, _) => (), Type::TraitAsType(_, _, args) => { @@ -1168,7 +1206,7 @@ impl<'a> Resolver<'a> { } Type::Array(length, element_type) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } Self::find_numeric_generics_in_type(element_type, found); @@ -1193,7 +1231,7 @@ impl<'a> Resolver<'a> { Type::Struct(struct_type, generics) => { for (i, generic) in generics.iter().enumerate() { - if let Type::NamedGeneric(type_variable, name) = generic { + if let Type::NamedGeneric(type_variable, name, _) = generic { if struct_type.borrow().generic_is_numeric(i) { found.insert(name.to_string(), type_variable.clone()); } @@ -1204,7 +1242,7 @@ impl<'a> Resolver<'a> { } Type::Alias(alias, generics) => { for (i, generic) in generics.iter().enumerate() { - if let Type::NamedGeneric(type_variable, name) = generic { + if let Type::NamedGeneric(type_variable, name, _) = generic { if alias.borrow().generic_is_numeric(i) { found.insert(name.to_string(), type_variable.clone()); } @@ -1215,12 +1253,12 @@ impl<'a> Resolver<'a> { } Type::MutableReference(element) => Self::find_numeric_generics_in_type(element, found), Type::String(length) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } } Type::FmtString(length, fields) => { - if let Type::NamedGeneric(type_variable, name) = length.as_ref() { + if let Type::NamedGeneric(type_variable, name, _) = length.as_ref() { found.insert(name.to_string(), type_variable.clone()); } Self::find_numeric_generics_in_type(fields, found); @@ -1648,6 +1686,10 @@ impl<'a> Resolver<'a> { ExpressionKind::Resolved(_) => unreachable!( "ExpressionKind::Resolved should only be emitted by the comptime interpreter" ), + ExpressionKind::Unquote(_) => { + self.push_err(ResolverError::UnquoteUsedOutsideQuote { span: expr.span }); + HirExpression::Literal(HirLiteral::Unit) + } }; // If these lines are ever changed, make sure to change the early return @@ -1877,7 +1919,9 @@ impl<'a> Resolver<'a> { let constraint = TraitConstraint { typ: self.self_type.clone()?, - trait_generics: Type::from_generics(&the_trait.generics), + trait_generics: Type::from_generics(&vecmap(&the_trait.generics, |generic| { + generic.type_var.clone() + })), trait_id, }; return Some((method, constraint, false)); @@ -1905,7 +1949,9 @@ impl<'a> Resolver<'a> { the_trait.self_type_typevar.clone(), TypeVariableKind::Normal, ), - trait_generics: Type::from_generics(&the_trait.generics), + trait_generics: Type::from_generics(&vecmap(&the_trait.generics, |generic| { + generic.type_var.clone() + })), trait_id, }; return Some((method, constraint, false)); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs index 3d355fd44471..e674a48e779c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -4,7 +4,7 @@ use fm::FileId; use iter_extended::vecmap; use noirc_errors::Location; -use crate::ast::{ItemVisibility, Path, TraitItem}; +use crate::ast::{Ident, ItemVisibility, Path, TraitItem, UnresolvedGeneric}; use crate::{ graph::CrateId, hir::{ @@ -17,7 +17,7 @@ use crate::{ }, hir_def::traits::{TraitConstant, TraitFunction, TraitImpl, TraitType}, node_interner::{FuncId, NodeInterner, TraitId}, - Generics, Shared, Type, TypeVariable, TypeVariableKind, + GenericTypeVars, Shared, Type, TypeVariableKind, }; use super::{ @@ -35,15 +35,18 @@ pub(crate) fn resolve_traits( traits: BTreeMap, crate_id: CrateId, ) -> Vec<(CompilationError, FileId)> { - for (trait_id, unresolved_trait) in &traits { - context.def_interner.push_empty_trait(*trait_id, unresolved_trait); - } let mut all_errors = Vec::new(); for (trait_id, unresolved_trait) in traits { - let generics = vecmap(&unresolved_trait.trait_def.generics, |_| { - TypeVariable::unbound(context.def_interner.next_type_variable_id()) - }); + let file_id = context.def_maps[&crate_id].file_id(unresolved_trait.module_id); + let generics = context.resolve_generics( + &unresolved_trait.trait_def.generics, + &mut all_errors, + file_id, + ); + let generic_type_vars = generics.iter().map(|generic| generic.type_var.clone()).collect(); + + context.def_interner.push_empty_trait(trait_id, &unresolved_trait, generics); // Resolve order // 1. Trait Types ( Trait constants can have a trait type, therefore types before constants) @@ -51,14 +54,18 @@ pub(crate) fn resolve_traits( // 2. Trait Constants ( Trait's methods can use trait types & constants, therefore they should be after) let _ = resolve_trait_constants(context, crate_id, &unresolved_trait); // 3. Trait Methods - let (methods, errors) = - resolve_trait_methods(context, trait_id, crate_id, &unresolved_trait, &generics); + let (methods, errors) = resolve_trait_methods( + context, + trait_id, + crate_id, + &unresolved_trait, + &generic_type_vars, + ); all_errors.extend(errors); context.def_interner.update_trait(trait_id, |trait_def| { trait_def.set_methods(methods); - trait_def.generics = generics; }); // This check needs to be after the trait's methods are set since @@ -93,7 +100,7 @@ fn resolve_trait_methods( trait_id: TraitId, crate_id: CrateId, unresolved_trait: &UnresolvedTrait, - trait_generics: &Generics, + trait_generics: &GenericTypeVars, ) -> (Vec, Vec<(CompilationError, FileId)>) { let interner = &mut context.def_interner; let def_maps = &mut context.def_maps; @@ -126,7 +133,11 @@ fn resolve_trait_methods( resolver.add_generics(generics); resolver.add_existing_generics(&unresolved_trait.trait_def.generics, trait_generics); - resolver.add_existing_generic("Self", name_span, self_typevar); + resolver.add_existing_generic( + &UnresolvedGeneric::Variable(Ident::from("Self")), + name_span, + self_typevar, + ); resolver.set_self_type(Some(self_type.clone())); let func_id = unresolved_trait.method_ids[&name.0.contents]; @@ -143,7 +154,7 @@ fn resolve_trait_methods( let arguments = vecmap(parameters, |param| resolver.resolve_type(param.1.clone())); let return_type = resolver.resolve_type(return_type.get_type().into_owned()); - let generics = vecmap(resolver.get_generics(), |(_, type_var, _)| type_var.clone()); + let generics = vecmap(resolver.get_generics(), |generic| generic.type_var.clone()); let default_impl_list: Vec<_> = unresolved_trait .fns_with_default_impl @@ -300,6 +311,7 @@ fn collect_trait_impl( let file = def_maps[&crate_id].file_id(trait_impl.module_id); let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); resolver.add_generics(&trait_impl.generics); + let typ = resolver.resolve_type(unresolved_type); errors.extend(take_errors(trait_impl.file_id, resolver)); @@ -463,7 +475,7 @@ pub(crate) fn resolve_trait_impls( methods: vecmap(&impl_methods, |(_, func_id)| *func_id), }); - let impl_generics = vecmap(impl_generics, |(_, type_variable, _)| type_variable); + let impl_generics = vecmap(impl_generics, |generic| generic.type_var); if let Err((prev_span, prev_file)) = interner.add_trait_implementation( self_type.clone(), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 0d8a9f3e7171..f18e8a9e843e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -40,6 +40,8 @@ pub enum TypeCheckError { TypeMismatch { expected_typ: String, expr_typ: String, expr_span: Span }, #[error("Expected type {expected} is not the same as {actual}")] TypeMismatchWithSource { expected: Type, actual: Type, span: Span, source: Source }, + #[error("Expected type {expected_kind:?} is not the same as {expr_kind:?}")] + TypeKindMismatch { expected_kind: String, expr_kind: String, expr_span: Span }, #[error("Expected {expected:?} found {found:?}")] ArityMisMatch { expected: usize, found: usize, span: Span }, #[error("Return type in a function cannot be public")] @@ -143,6 +145,8 @@ pub enum TypeCheckError { }, #[error("Strings do not support indexed assignment")] StringIndexAssign { span: Span }, + #[error("Macro calls may only return `Quoted` values")] + MacroReturningNonExpr { typ: Type, span: Span }, } impl TypeCheckError { @@ -176,6 +180,13 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { *expr_span, ) } + TypeCheckError::TypeKindMismatch { expected_kind, expr_kind, expr_span } => { + Diagnostic::simple_error( + format!("Expected kind {expected_kind}, found kind {expr_kind}"), + String::new(), + *expr_span, + ) + } TypeCheckError::TraitMethodParameterTypeMismatch { method_name, expected_typ, actual_typ, parameter_index, parameter_span } => { Diagnostic::simple_error( format!("Parameter #{parameter_index} of method `{method_name}` must be of type {expected_typ}, not {actual_typ}"), @@ -335,6 +346,11 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Expected {expected_count} generic{expected_plural} from this function, but {actual_count} {actual_plural} provided"); Diagnostic::simple_error(msg, "".into(), *span) }, + TypeCheckError::MacroReturningNonExpr { typ, span } => Diagnostic::simple_error( + format!("Expected macro call to return a `Quoted` but found a(n) `{typ}`"), + "Macro calls must return quoted values, otherwise there is no code to insert".into(), + *span, + ), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 50af9dbf34e2..77861a6d8f88 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -307,13 +307,13 @@ impl<'interner> TypeChecker<'interner> { Type::Function(params, Box::new(lambda.return_type), Box::new(env_type)) } - HirExpression::Quote(_) => Type::Code, + HirExpression::Quote(_) => Type::Quoted(crate::QuotedType::Quoted), HirExpression::Comptime(block) => self.check_block(block), // Unquote should be inserted & removed by the comptime interpreter. // Even if we allowed it here, we wouldn't know what type to give to the result. HirExpression::Unquote(block) => { - unreachable!("Unquote remaining during type checking {block}") + unreachable!("Unquote remaining during type checking {block:?}") } }; @@ -340,7 +340,7 @@ impl<'interner> TypeChecker<'interner> { // Check that we are not passing a mutable reference from a constrained runtime to an unconstrained runtime if is_current_func_constrained && is_unconstrained_call { for (typ, _, _) in args.iter() { - if matches!(&typ.follow_bindings(), Type::MutableReference(_)) { + if !typ.is_valid_for_unconstrained_boundary() { self.errors.push(TypeCheckError::ConstrainedReferenceToUnconstrained { span }); } } @@ -404,8 +404,8 @@ impl<'interner> TypeChecker<'interner> { for (param, arg) in the_trait.generics.iter().zip(&constraint.trait_generics) { // Avoid binding t = t - if !arg.occurs(param.id()) { - bindings.insert(param.id(), (param.clone(), arg.clone())); + if !arg.occurs(param.type_var.id()) { + bindings.insert(param.type_var.id(), (param.type_var.clone(), arg.clone())); } } @@ -1025,7 +1025,7 @@ impl<'interner> TypeChecker<'interner> { }); None } - Type::NamedGeneric(_, _) => { + Type::NamedGeneric(_, _, _) => { let func_meta = self.interner.function_meta( &self.current_function.expect("unexpected method outside a function"), ); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 98e1cd9c72a2..1d3c7fcda9b6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -22,7 +22,7 @@ use crate::{ traits::TraitConstraint, }, node_interner::{ExprId, FuncId, GlobalId, NodeInterner}, - Type, TypeBindings, + Kind, Type, TypeBindings, }; pub use self::errors::Source; @@ -263,7 +263,7 @@ pub(crate) fn check_trait_impl_method_matches_declaration( // Substitute each generic on the trait with the corresponding generic on the impl for (generic, arg) in trait_info.generics.iter().zip(&impl_.trait_generics) { - bindings.insert(generic.id(), (generic.clone(), arg.clone())); + bindings.insert(generic.type_var.id(), (generic.type_var.clone(), arg.clone())); } // If this is None, the trait does not have the corresponding function. @@ -284,7 +284,7 @@ pub(crate) fn check_trait_impl_method_matches_declaration( for ((_, trait_fn_generic), (name, impl_fn_generic)) in trait_fn_meta.direct_generics.iter().zip(&meta.direct_generics) { - let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone()); + let arg = Type::NamedGeneric(impl_fn_generic.clone(), name.clone(), Kind::Normal); bindings.insert(trait_fn_generic.id(), (trait_fn_generic.clone(), arg)); } @@ -561,6 +561,7 @@ pub mod test { all_generics: Vec::new(), parameter_idents: Vec::new(), function_body: FunctionBody::Resolved, + source_crate: CrateId::dummy_id(), }; interner.push_fn_meta(func_meta, func_id); @@ -716,13 +717,15 @@ pub mod test { let mut interner = NodeInterner::default(); interner.populate_dummy_operator_traits(); - assert_eq!( - errors.len(), - 0, - "expected 0 parser errors, but got {}, errors: {:?}", - errors.len(), - errors - ); + if !errors.iter().all(|error| error.is_warning()) { + assert_eq!( + errors.len(), + 0, + "expected 0 parser errors, but got {}, errors: {:?}", + errors.len(), + errors + ); + } let func_ids = btree_map(&func_namespace, |name| { (name.to_string(), interner.push_test_function_definition(name.into())) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs index 163ea10ee02f..8de4f118774a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/expr.rs @@ -4,6 +4,7 @@ use noirc_errors::Location; use crate::ast::{BinaryOp, BinaryOpKind, Ident, UnaryOp}; use crate::node_interner::{DefinitionId, ExprId, FuncId, NodeInterner, StmtId, TraitMethodId}; +use crate::token::Tokens; use crate::Shared; use super::stmt::HirPattern; @@ -33,8 +34,8 @@ pub enum HirExpression { If(HirIfExpression), Tuple(Vec), Lambda(HirLambda), - Quote(crate::ast::BlockExpression), - Unquote(crate::ast::BlockExpression), + Quote(Tokens), + Unquote(Tokens), Comptime(HirBlockExpression), Error, } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs index 53eabe210815..a4a9f855c627 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/function.rs @@ -7,9 +7,10 @@ use super::expr::{HirBlockExpression, HirExpression, HirIdent}; use super::stmt::HirPattern; use super::traits::TraitConstraint; use crate::ast::{FunctionKind, FunctionReturnType, Visibility}; +use crate::graph::CrateId; use crate::macros_api::BlockExpression; use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; -use crate::{Type, TypeVariable}; +use crate::{ResolvedGeneric, Type, TypeVariable}; /// A Hir function is a block expression /// with a list of statements @@ -118,7 +119,7 @@ pub struct FuncMeta { /// from outer scopes, such as those introduced by an impl. /// This is stored when the FuncMeta is first created to later be used to set the current /// generics when the function's body is later resolved. - pub all_generics: Vec<(Rc, TypeVariable, Span)>, + pub all_generics: Vec, pub location: Location, @@ -145,6 +146,9 @@ pub struct FuncMeta { pub has_inline_attribute: bool, pub function_body: FunctionBody, + + /// The crate this function was defined in + pub source_crate: CrateId, } #[derive(Debug, Clone)] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs index 1357ea09f941..b529ca17887c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/types.rs @@ -82,7 +82,7 @@ pub enum Type { /// NamedGenerics are the 'T' or 'U' in a user-defined generic function /// like `fn foo(...) {}`. Unlike TypeVariables, they cannot be bound over. - NamedGeneric(TypeVariable, Rc), + NamedGeneric(TypeVariable, Rc, Kind), /// A functions with arguments, a return type and environment. /// the environment should be `Unit` by default, @@ -98,14 +98,14 @@ pub enum Type { /// but it makes handling them both easier. The TypeVariableId should /// never be bound over during type checking, but during monomorphization it /// will be and thus needs the full TypeVariable link. - Forall(Generics, Box), + Forall(GenericTypeVars, Box), /// A type-level integer. Included to let an Array's size type variable /// bind to an integer without special checks to bind it to a non-type. Constant(u32), /// The type of quoted code in macros. This is always a comptime-only type - Code, + Quoted(QuotedType), /// The result of some type error. Remembering type errors as their own type variant lets /// us avoid issuing repeat type errors for the same item. For example, a lambda with @@ -142,12 +142,12 @@ impl Type { | Type::Unit | Type::TypeVariable(_, _) | Type::TraitAsType(..) - | Type::NamedGeneric(_, _) + | Type::NamedGeneric(_, _, _) | Type::Function(_, _, _) | Type::MutableReference(_) | Type::Forall(_, _) | Type::Constant(_) - | Type::Code + | Type::Quoted(_) | Type::Slice(_) | Type::Error => unreachable!("This type cannot exist as a parameter to main"), } @@ -187,6 +187,36 @@ impl Type { } } +/// A Kind is the type of a Type. These are used since only certain kinds of types are allowed in +/// certain positions. +/// +/// For example, the type of a struct field or a function parameter is expected to be +/// a type of kind * (represented here as `Normal`). Types used in positions where a number +/// is expected (such as in an array length position) are expected to be of kind `Kind::Numeric`. +#[derive(PartialEq, Eq, Clone, Hash, Debug)] +pub enum Kind { + Normal, + Numeric(Box), +} + +impl std::fmt::Display for Kind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Kind::Normal => write!(f, "normal"), + Kind::Numeric(typ) => write!(f, "numeric {}", typ), + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub enum QuotedType { + Expr, + Quoted, + TopLevelItem, + Type, + StructDefinition, +} + /// A list of TypeVariableIds to bind to a type. Storing the /// TypeVariable in addition to the matching TypeVariableId allows /// the binding to later be undone if needed. @@ -213,7 +243,22 @@ pub struct StructType { } /// Corresponds to generic lists such as `` in the source program. -pub type Generics = Vec; +/// Used mainly for resolved types which no longer need information such +/// as names or kinds. +pub type GenericTypeVars = Vec; + +/// Corresponds to generic lists such as `` with additional +/// information gathered during name resolution that is necessary +/// correctly resolving types. +pub type Generics = Vec; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ResolvedGeneric { + pub name: Rc, + pub type_var: TypeVariable, + pub kind: Kind, + pub span: Span, +} impl std::hash::Hash for StructType { fn hash(&self, state: &mut H) { @@ -262,7 +307,7 @@ impl StructType { .generics .iter() .zip(generic_args) - .map(|(old, new)| (old.id(), (old.clone(), new.clone()))) + .map(|(old, new)| (old.type_var.id(), (old.type_var.clone(), new.clone()))) .collect(); (typ.substitute(&substitutions), i) @@ -278,7 +323,7 @@ impl StructType { .generics .iter() .zip(generic_args) - .map(|(old, new)| (old.id(), (old.clone(), new.clone()))) + .map(|(old, new)| (old.type_var.id(), (old.type_var.clone(), new.clone()))) .collect(); vecmap(&self.fields, |(name, typ)| { @@ -287,15 +332,33 @@ impl StructType { }) } + /// Returns the name and raw types of each field of this type. + /// This will not substitute any generic arguments so a generic field like `x` + /// in `struct Foo { x: T }` will return a `("x", T)` pair. + /// + /// This method is almost never what is wanted for type checking or monomorphization, + /// prefer to use `get_fields` whenever possible. + pub fn get_fields_as_written(&self) -> Vec<(String, Type)> { + vecmap(&self.fields, |(name, typ)| (name.0.contents.clone(), typ.clone())) + } + pub fn field_names(&self) -> BTreeSet { self.fields.iter().map(|(name, _)| name.clone()).collect() } + /// Search the fields of a struct for any types with a `TypeKind::Numeric` + pub fn find_numeric_generics_in_fields(&self, found_names: &mut Vec) { + for (_, field) in self.fields.iter() { + field.find_numeric_type_vars(found_names); + } + } + /// True if the given index is the same index as a generic type of this struct /// which is expected to be a numeric generic. /// This is needed because we infer type kinds in Noir and don't have extensive kind checking. + /// TODO(https://github.com/noir-lang/noir/issues/5156): This is outdated and we should remove this implicit searching for numeric generics pub fn generic_is_numeric(&self, index_of_generic: usize) -> bool { - let target_id = self.generics[index_of_generic].0; + let target_id = self.generics[index_of_generic].type_var.id(); self.fields.iter().any(|(_, field)| field.contains_numeric_typevar(target_id)) } @@ -364,7 +427,7 @@ impl TypeAlias { .generics .iter() .zip(generic_args) - .map(|(old, new)| (old.id(), (old.clone(), new.clone()))) + .map(|(old, new)| (old.type_var.id(), (old.type_var.clone(), new.clone()))) .collect(); self.typ.substitute(&substitutions) @@ -374,7 +437,7 @@ impl TypeAlias { /// which is expected to be a numeric generic. /// This is needed because we infer type kinds in Noir and don't have extensive kind checking. pub fn generic_is_numeric(&self, index_of_generic: usize) -> bool { - let target_id = self.generics[index_of_generic].0; + let target_id = self.generics[index_of_generic].type_var.id(); self.typ.contains_numeric_typevar(target_id) } } @@ -484,7 +547,7 @@ impl TypeVariable { TypeBinding::Unbound(id) => *id, }; - assert!(!typ.occurs(id)); + assert!(!typ.occurs(id), "{self:?} occurs within {typ:?}"); *self.1.borrow_mut() = TypeBinding::Bound(typ); } @@ -622,7 +685,7 @@ impl Type { fn contains_numeric_typevar(&self, target_id: TypeVariableId) -> bool { // True if the given type is a NamedGeneric with the target_id let named_generic_id_matches_target = |typ: &Type| { - if let Type::NamedGeneric(type_variable, _) = typ { + if let Type::NamedGeneric(type_variable, _, _) = typ { match &*type_variable.borrow() { TypeBinding::Bound(_) => { unreachable!("Named generics should not be bound until monomorphization") @@ -642,9 +705,9 @@ impl Type { | Type::Error | Type::TypeVariable(_, _) | Type::Constant(_) - | Type::NamedGeneric(_, _) + | Type::NamedGeneric(_, _, _) | Type::Forall(_, _) - | Type::Code => false, + | Type::Quoted(_) => false, Type::TraitAsType(_, _, args) => { args.iter().any(|generic| generic.contains_numeric_typevar(target_id)) @@ -686,6 +749,85 @@ impl Type { } } + /// TODO(https://github.com/noir-lang/noir/issues/5156): Remove with explicit numeric generics + pub fn find_numeric_type_vars(&self, found_names: &mut Vec) { + // Return whether the named generic has a TypeKind::Numeric and save its name + let named_generic_is_numeric = |typ: &Type, found_names: &mut Vec| { + if let Type::NamedGeneric(_, name, Kind::Numeric { .. }) = typ { + found_names.push(name.to_string()); + true + } else { + false + } + }; + + match self { + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::Error + | Type::Constant(_) + | Type::Forall(_, _) + | Type::Quoted(_) => {} + + Type::TypeVariable(type_var, _) => { + if let TypeBinding::Bound(typ) = &*type_var.borrow() { + named_generic_is_numeric(typ, found_names); + } + } + + Type::NamedGeneric(_, _, _) => { + named_generic_is_numeric(self, found_names); + } + + Type::TraitAsType(_, _, args) => { + for arg in args.iter() { + arg.find_numeric_type_vars(found_names); + } + } + Type::Array(length, elem) => { + elem.find_numeric_type_vars(found_names); + named_generic_is_numeric(length, found_names); + } + Type::Slice(elem) => elem.find_numeric_type_vars(found_names), + Type::Tuple(fields) => { + for field in fields.iter() { + field.find_numeric_type_vars(found_names); + } + } + Type::Function(parameters, return_type, env) => { + for parameter in parameters.iter() { + parameter.find_numeric_type_vars(found_names); + } + return_type.find_numeric_type_vars(found_names); + env.find_numeric_type_vars(found_names); + } + Type::Struct(_, generics) => { + for generic in generics.iter() { + if !named_generic_is_numeric(generic, found_names) { + generic.find_numeric_type_vars(found_names); + } + } + } + Type::Alias(_, generics) => { + for generic in generics.iter() { + if !named_generic_is_numeric(generic, found_names) { + generic.find_numeric_type_vars(found_names); + } + } + } + Type::MutableReference(element) => element.find_numeric_type_vars(found_names), + Type::String(length) => { + named_generic_is_numeric(length, found_names); + } + Type::FmtString(length, elements) => { + elements.find_numeric_type_vars(found_names); + named_generic_is_numeric(length, found_names); + } + } + } + /// True if this type can be used as a parameter to `main` or a contract function. /// This is only false for unsized types like slices or slices that do not make sense /// as a program input such as named generics or mutable references. @@ -706,11 +848,11 @@ impl Type { Type::FmtString(_, _) | Type::TypeVariable(_, _) - | Type::NamedGeneric(_, _) + | Type::NamedGeneric(_, _, _) | Type::Function(_, _, _) | Type::MutableReference(_) | Type::Forall(_, _) - | Type::Code + | Type::Quoted(_) | Type::Slice(_) | Type::TraitAsType(..) => false, @@ -748,7 +890,7 @@ impl Type { | Type::Unit | Type::Constant(_) | Type::TypeVariable(_, _) - | Type::NamedGeneric(_, _) + | Type::NamedGeneric(_, _, _) | Type::Error => true, Type::FmtString(_, _) @@ -759,7 +901,7 @@ impl Type { | Type::MutableReference(_) | Type::Forall(_, _) // TODO: probably can allow code as it is all compile time - | Type::Code + | Type::Quoted(_) | Type::TraitAsType(..) => false, Type::Alias(alias, generics) => { @@ -780,12 +922,55 @@ impl Type { } } + /// Returns true if a value of this type can safely pass between constrained and + /// unconstrained functions (and vice-versa). + pub(crate) fn is_valid_for_unconstrained_boundary(&self) -> bool { + match self { + Type::FieldElement + | Type::Integer(_, _) + | Type::Bool + | Type::Unit + | Type::Constant(_) + | Type::Slice(_) + | Type::TypeVariable(_, _) + | Type::NamedGeneric(_, _, _) + | Type::Function(_, _, _) + | Type::FmtString(_, _) + | Type::Error => true, + + // Quoted objects only exist at compile-time where the only execution + // environment is the interpreter. In this environment, they are valid. + Type::Quoted(_) => true, + + Type::MutableReference(_) | Type::Forall(_, _) | Type::TraitAsType(..) => false, + + Type::Alias(alias, generics) => { + let alias = alias.borrow(); + alias.get_type(generics).is_valid_for_unconstrained_boundary() + } + + Type::Array(length, element) => { + length.is_valid_for_unconstrained_boundary() + && element.is_valid_for_unconstrained_boundary() + } + Type::String(length) => length.is_valid_for_unconstrained_boundary(), + Type::Tuple(elements) => { + elements.iter().all(|elem| elem.is_valid_for_unconstrained_boundary()) + } + Type::Struct(definition, generics) => definition + .borrow() + .get_fields(generics) + .into_iter() + .all(|(_, field)| field.is_valid_for_unconstrained_boundary()), + } + } + /// Returns the number of `Forall`-quantified type variables on this type. /// Returns 0 if this is not a Type::Forall pub fn generic_count(&self) -> usize { match self { Type::Forall(generics, _) => generics.len(), - Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _) => { + Type::TypeVariable(type_variable, _) | Type::NamedGeneric(type_variable, _, _) => { match &*type_variable.borrow() { TypeBinding::Bound(binding) => binding.generic_count(), TypeBinding::Unbound(_) => 0, @@ -814,12 +999,42 @@ impl Type { /// Return the generics and type within this `Type::Forall`. /// Panics if `self` is not `Type::Forall` - pub fn unwrap_forall(&self) -> (Cow, &Type) { + pub fn unwrap_forall(&self) -> (Cow, &Type) { match self { Type::Forall(generics, typ) => (Cow::Borrowed(generics), typ.as_ref()), - other => (Cow::Owned(Generics::new()), other), + other => (Cow::Owned(GenericTypeVars::new()), other), } } + + // TODO(https://github.com/noir-lang/noir/issues/5156): Bring back this method when we remove implicit numeric generics + // It has been commented out as to not trigger clippy for an unused method + // pub(crate) fn kind(&self) -> Kind { + // match self { + // Type::NamedGeneric(_, _, kind) => kind.clone(), + // Type::Constant(_) => Kind::Numeric(Box::new(Type::Integer( + // Signedness::Unsigned, + // IntegerBitSize::ThirtyTwo, + // ))), + // Type::FieldElement + // | Type::Array(_, _) + // | Type::Slice(_) + // | Type::Integer(_, _) + // | Type::Bool + // | Type::String(_) + // | Type::FmtString(_, _) + // | Type::Unit + // | Type::Tuple(_) + // | Type::Struct(_, _) + // | Type::Alias(_, _) + // | Type::TypeVariable(_, _) + // | Type::TraitAsType(_, _, _) + // | Type::Function(_, _, _) + // | Type::MutableReference(_) + // | Type::Forall(_, _) + // | Type::Quoted(_) + // | Type::Error => Kind::Normal, + // } + // } } impl std::fmt::Display for Type { @@ -899,7 +1114,7 @@ impl std::fmt::Display for Type { } Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), - Type::NamedGeneric(binding, name) => match &*binding.borrow() { + Type::NamedGeneric(binding, name, _) => match &*binding.borrow() { TypeBinding::Bound(binding) => binding.fmt(f), TypeBinding::Unbound(_) if name.is_empty() => write!(f, "_"), TypeBinding::Unbound(_) => write!(f, "{name}"), @@ -922,7 +1137,7 @@ impl std::fmt::Display for Type { Type::MutableReference(element) => { write!(f, "&mut {element}") } - Type::Code => write!(f, "Code"), + Type::Quoted(quoted) => write!(f, "{}", quoted), } } } @@ -954,6 +1169,18 @@ impl std::fmt::Display for TypeBinding { } } +impl std::fmt::Display for QuotedType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + QuotedType::Expr => write!(f, "Expr"), + QuotedType::Quoted => write!(f, "Quoted"), + QuotedType::TopLevelItem => write!(f, "TopLevelItem"), + QuotedType::Type => write!(f, "Type"), + QuotedType::StructDefinition => write!(f, "StructDefinition"), + } + } +} + pub struct UnificationError; impl Type { @@ -1116,8 +1343,7 @@ impl Type { TypeBinding::Unbound(id) => *id, }; - let this = self.substitute(bindings); - + let this = self.substitute(bindings).follow_bindings(); if let Some(binding) = this.get_inner_type_variable() { match &*binding.borrow() { TypeBinding::Bound(typ) => return typ.try_bind_to(var, bindings), @@ -1139,7 +1365,7 @@ impl Type { fn get_inner_type_variable(&self) -> Option> { match self { - Type::TypeVariable(var, _) | Type::NamedGeneric(var, _) => Some(var.1.clone()), + Type::TypeVariable(var, _) | Type::NamedGeneric(var, _, _) => Some(var.1.clone()), _ => None, } } @@ -1250,7 +1476,7 @@ impl Type { } } - (NamedGeneric(binding, _), other) | (other, NamedGeneric(binding, _)) + (NamedGeneric(binding, _, _), other) | (other, NamedGeneric(binding, _, _)) if !binding.borrow().is_unbound() => { if let TypeBinding::Bound(link) = &*binding.borrow() { @@ -1260,7 +1486,7 @@ impl Type { } } - (NamedGeneric(binding_a, name_a), NamedGeneric(binding_b, name_b)) => { + (NamedGeneric(binding_a, name_a, _), NamedGeneric(binding_b, name_b, _)) => { // Bound NamedGenerics are caught by the check above assert!(binding_a.borrow().is_unbound()); assert!(binding_b.borrow().is_unbound()); @@ -1516,6 +1742,15 @@ impl Type { } } + fn type_variable_id(&self) -> Option { + match self { + Type::TypeVariable(variable, _) | Type::NamedGeneric(variable, _, _) => { + Some(variable.0) + } + _ => None, + } + } + /// Substitute any type variables found within this type with the /// given bindings if found. If a type variable is not found within /// the given TypeBindings, it is unchanged. @@ -1550,18 +1785,29 @@ impl Type { return self.clone(); } + let recur_on_binding = |id, replacement: &Type| { + // Prevent recuring forever if there's a `T := T` binding + if replacement.type_variable_id() == Some(id) { + replacement.clone() + } else { + replacement.substitute_helper(type_bindings, substitute_bound_typevars) + } + }; + let substitute_binding = |binding: &TypeVariable| { // Check the id first to allow substituting to // type variables that have already been bound over. // This is needed for monomorphizing trait impl methods. match type_bindings.get(&binding.0) { - Some((_, binding)) if substitute_bound_typevars => binding.clone(), + Some((_, replacement)) if substitute_bound_typevars => { + recur_on_binding(binding.0, replacement) + } _ => match &*binding.borrow() { TypeBinding::Bound(binding) => { binding.substitute_helper(type_bindings, substitute_bound_typevars) } TypeBinding::Unbound(id) => match type_bindings.get(id) { - Some((_, binding)) => binding.clone(), + Some((_, replacement)) => recur_on_binding(binding.0, replacement), None => self.clone(), }, }, @@ -1587,7 +1833,7 @@ impl Type { let fields = fields.substitute_helper(type_bindings, substitute_bound_typevars); Type::FmtString(Box::new(size), Box::new(fields)) } - Type::NamedGeneric(binding, _) | Type::TypeVariable(binding, _) => { + Type::NamedGeneric(binding, _, _) | Type::TypeVariable(binding, _) => { substitute_binding(binding) } // Do not substitute_helper fields, it can lead to infinite recursion @@ -1643,7 +1889,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Code + | Type::Quoted(_) | Type::Unit => self.clone(), } } @@ -1665,7 +1911,7 @@ impl Type { generic_args.iter().any(|arg| arg.occurs(target_id)) } Type::Tuple(fields) => fields.iter().any(|field| field.occurs(target_id)), - Type::NamedGeneric(binding, _) | Type::TypeVariable(binding, _) => { + Type::NamedGeneric(binding, _, _) | Type::TypeVariable(binding, _) => { match &*binding.borrow() { TypeBinding::Bound(binding) => binding.occurs(target_id), TypeBinding::Unbound(id) => *id == target_id, @@ -1686,7 +1932,7 @@ impl Type { | Type::Bool | Type::Constant(_) | Type::Error - | Type::Code + | Type::Quoted(_) | Type::Unit => false, } } @@ -1720,7 +1966,7 @@ impl Type { def.borrow().get_type(args).follow_bindings() } Tuple(args) => Tuple(vecmap(args, |arg| arg.follow_bindings())), - TypeVariable(var, _) | NamedGeneric(var, _) => { + TypeVariable(var, _) | NamedGeneric(var, _, _) => { if let TypeBinding::Bound(typ) = &*var.borrow() { return typ.follow_bindings(); } @@ -1743,11 +1989,13 @@ impl Type { // Expect that this function should only be called on instantiated types Forall(..) => unreachable!(), - FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Code | Error => self.clone(), + FieldElement | Integer(_, _) | Bool | Constant(_) | Unit | Quoted(_) | Error => { + self.clone() + } } } - pub fn from_generics(generics: &Generics) -> Vec { + pub fn from_generics(generics: &GenericTypeVars) -> Vec { vecmap(generics, |var| Type::TypeVariable(var.clone(), TypeVariableKind::Normal)) } } @@ -1878,7 +2126,7 @@ impl From<&Type> for PrintableType { Type::MutableReference(typ) => { PrintableType::MutableReference { typ: Box::new(typ.as_ref().into()) } } - Type::Code => unreachable!(), + Type::Quoted(_) => unreachable!(), } } } @@ -1944,7 +2192,14 @@ impl std::fmt::Debug for Type { } Type::Unit => write!(f, "()"), Type::Error => write!(f, "error"), - Type::NamedGeneric(binding, name) => write!(f, "{}{:?}", name, binding), + Type::NamedGeneric(binding, name, kind) => match kind { + Kind::Normal => { + write!(f, "{} -> {:?}", name, binding) + } + Kind::Numeric(typ) => { + write!(f, "({} : {}) -> {:?}", name, typ, binding) + } + }, Type::Constant(x) => x.fmt(f), Type::Forall(typevars, typ) => { let typevars = vecmap(typevars, |var| format!("{:?}", var)); @@ -1963,7 +2218,7 @@ impl std::fmt::Debug for Type { Type::MutableReference(element) => { write!(f, "&mut {element:?}") } - Type::Code => write!(f, "Code"), + Type::Quoted(quoted) => write!(f, "{}", quoted), } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/errors.rs index 73c75af4cd7b..387ced05258c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/errors.rs @@ -15,6 +15,8 @@ pub enum LexerErrorKind { NotADoubleChar { span: Span, found: Token }, #[error("Invalid integer literal, {:?} is not a integer", found)] InvalidIntegerLiteral { span: Span, found: String }, + #[error("Integer literal is too large")] + IntegerLiteralTooLarge { span: Span, limit: String }, #[error("{:?} is not a valid attribute", found)] MalformedFuncAttribute { span: Span, found: String }, #[error("Logical and used instead of bitwise and")] @@ -27,6 +29,10 @@ pub enum LexerErrorKind { "'\\{escaped}' is not a valid escape sequence. Use '\\' for a literal backslash character." )] InvalidEscape { escaped: char, span: Span }, + #[error("Invalid quote delimiter `{delimiter}`, valid delimiters are `{{`, `[`, and `(`")] + InvalidQuoteDelimiter { delimiter: SpannedToken }, + #[error("Expected `{end_delim}` to close this {start_delim}")] + UnclosedQuote { start_delim: SpannedToken, end_delim: Token }, } impl From for ParserError { @@ -42,11 +48,14 @@ impl LexerErrorKind { LexerErrorKind::UnexpectedCharacter { span, .. } => *span, LexerErrorKind::NotADoubleChar { span, .. } => *span, LexerErrorKind::InvalidIntegerLiteral { span, .. } => *span, + LexerErrorKind::IntegerLiteralTooLarge { span, .. } => *span, LexerErrorKind::MalformedFuncAttribute { span, .. } => *span, LexerErrorKind::LogicalAnd { span } => *span, LexerErrorKind::UnterminatedBlockComment { span } => *span, LexerErrorKind::UnterminatedStringLiteral { span } => *span, LexerErrorKind::InvalidEscape { span, .. } => *span, + LexerErrorKind::InvalidQuoteDelimiter { delimiter } => delimiter.to_span(), + LexerErrorKind::UnclosedQuote { start_delim, .. } => start_delim.to_span(), } } @@ -77,6 +86,11 @@ impl LexerErrorKind { format!(" {found} is not an integer"), *span, ), + LexerErrorKind::IntegerLiteralTooLarge { span, limit } => ( + "Integer literal is too large".to_string(), + format!("value exceeds limit of {limit}"), + *span, + ), LexerErrorKind::MalformedFuncAttribute { span, found } => ( "Malformed function attribute".to_string(), format!(" {found} is not a valid attribute"), @@ -92,6 +106,12 @@ impl LexerErrorKind { ("Unterminated string literal".to_string(), "Unterminated string literal".to_string(), *span), LexerErrorKind::InvalidEscape { escaped, span } => (format!("'\\{escaped}' is not a valid escape sequence. Use '\\' for a literal backslash character."), "Invalid escape sequence".to_string(), *span), + LexerErrorKind::InvalidQuoteDelimiter { delimiter } => { + (format!("Invalid quote delimiter `{delimiter}`"), "Valid delimiters are `{`, `[`, and `(`".to_string(), delimiter.to_span()) + }, + LexerErrorKind::UnclosedQuote { start_delim, end_delim } => { + ("Unclosed `quote` expression".to_string(), format!("Expected a `{end_delim}` to close this `{start_delim}`"), start_delim.to_span()) + } } } } 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 2d1ebf530e3f..0afcb02caac3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -6,9 +6,11 @@ use super::{ token_to_borrowed_token, BorrowedToken, IntType, Keyword, SpannedToken, Token, Tokens, }, }; -use acvm::FieldElement; +use acvm::{AcirField, FieldElement}; use noirc_errors::{Position, Span}; -use std::str::CharIndices; +use num_bigint::BigInt; +use num_traits::{Num, One}; +use std::str::{CharIndices, FromStr}; /// The job of the lexer is to transform an iterator of characters (`char_iter`) /// into an iterator of `SpannedToken`. Each `Token` corresponds roughly to 1 word or operator. @@ -19,6 +21,7 @@ pub struct Lexer<'a> { done: bool, skip_comments: bool, skip_whitespaces: bool, + max_integer: BigInt, } pub type SpannedTokenResult = Result; @@ -61,6 +64,8 @@ impl<'a> Lexer<'a> { done: false, skip_comments: true, skip_whitespaces: true, + max_integer: BigInt::from_biguint(num_bigint::Sign::Plus, FieldElement::modulus()) + - BigInt::one(), } } @@ -141,9 +146,11 @@ impl<'a> Lexer<'a> { Some('}') => self.single_char_token(Token::RightBrace), Some('[') => self.single_char_token(Token::LeftBracket), Some(']') => self.single_char_token(Token::RightBracket), + Some('$') => self.single_char_token(Token::DollarSign), Some('"') => self.eat_string_literal(), Some('f') => self.eat_format_string_or_alpha_numeric(), Some('r') => self.eat_raw_string_or_alpha_numeric(), + Some('q') => self.eat_quote_or_alpha_numeric(), Some('#') => self.eat_attribute(), Some(ch) if ch.is_ascii_alphanumeric() || ch == '_' => self.eat_alpha_numeric(ch), Some(ch) => { @@ -309,14 +316,25 @@ impl<'a> Lexer<'a> { //XXX(low): Can increase performance if we use iterator semantic and utilize some of the methods on String. See below // https://doc.rust-lang.org/stable/std/primitive.str.html#method.rsplit fn eat_word(&mut self, initial_char: char) -> SpannedTokenResult { - let start = self.position; + let (start, word, end) = self.lex_word(initial_char); + self.lookup_word_token(word, start, end) + } + /// Lex the next word in the input stream. Returns (start position, word, end position) + fn lex_word(&mut self, initial_char: char) -> (Position, String, Position) { + let start = self.position; let word = self.eat_while(Some(initial_char), |ch| { ch.is_ascii_alphabetic() || ch.is_numeric() || ch == '_' }); + (start, word, self.position) + } - let end = self.position; - + fn lookup_word_token( + &self, + word: String, + start: Position, + end: Position, + ) -> SpannedTokenResult { // Check if word either an identifier or a keyword if let Some(keyword_token) = Keyword::lookup_keyword(&word) { return Ok(keyword_token.into_span(start, end)); @@ -363,14 +381,28 @@ impl<'a> Lexer<'a> { // Underscores needs to be stripped out before the literal can be converted to a `FieldElement. let integer_str = integer_str.replace('_', ""); - let integer = match FieldElement::try_from_str(&integer_str) { - None => { + let bigint_result = match integer_str.strip_prefix("0x") { + Some(integer_str) => BigInt::from_str_radix(integer_str, 16), + None => BigInt::from_str(&integer_str), + }; + + let integer = match bigint_result { + Ok(bigint) => { + if bigint > self.max_integer { + return Err(LexerErrorKind::IntegerLiteralTooLarge { + span: Span::inclusive(start, end), + limit: self.max_integer.to_string(), + }); + } + let big_uint = bigint.magnitude(); + FieldElement::from_be_bytes_reduce(&big_uint.to_bytes_be()) + } + Err(_) => { return Err(LexerErrorKind::InvalidIntegerLiteral { span: Span::inclusive(start, end), found: integer_str, }) } - Some(integer) => integer, }; let integer_token = Token::Int(integer); @@ -508,6 +540,50 @@ impl<'a> Lexer<'a> { } } + fn eat_quote_or_alpha_numeric(&mut self) -> SpannedTokenResult { + let (start, word, end) = self.lex_word('q'); + if word != "quote" { + return self.lookup_word_token(word, start, end); + } + + let delimiter = self.next_token()?; + let (start_delim, end_delim) = match delimiter.token() { + Token::LeftBrace => (Token::LeftBrace, Token::RightBrace), + Token::LeftBracket => (Token::LeftBracket, Token::RightBracket), + Token::LeftParen => (Token::LeftParen, Token::RightParen), + _ => return Err(LexerErrorKind::InvalidQuoteDelimiter { delimiter }), + }; + + let mut tokens = Vec::new(); + + // Keep track of each nested delimiter we need to close. + let mut nested_delimiters = vec![delimiter]; + + while !nested_delimiters.is_empty() { + let token = self.next_token()?; + + if *token.token() == start_delim { + nested_delimiters.push(token.clone()); + } else if *token.token() == end_delim { + nested_delimiters.pop(); + } else if *token.token() == Token::EOF { + let start_delim = + nested_delimiters.pop().expect("If this were empty, we wouldn't be looping"); + return Err(LexerErrorKind::UnclosedQuote { start_delim, end_delim }); + } + + tokens.push(token); + } + + // Pop the closing delimiter from the token stream + if !tokens.is_empty() { + tokens.pop(); + } + + let end = self.position; + Ok(Token::Quote(Tokens(tokens)).into_span(start, end)) + } + fn parse_comment(&mut self, start: u32) -> SpannedTokenResult { let doc_style = match self.peek_char() { Some('!') => { @@ -603,6 +679,8 @@ impl<'a> Iterator for Lexer<'a> { #[cfg(test)] mod tests { + use iter_extended::vecmap; + use super::*; use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; @@ -840,6 +918,19 @@ mod tests { } } + #[test] + fn test_int_too_large() { + let modulus = FieldElement::modulus(); + let input = modulus.to_string(); + + let mut lexer = Lexer::new(&input); + let token = lexer.next_token(); + assert!( + matches!(token, Err(LexerErrorKind::IntegerLiteralTooLarge { .. })), + "expected {input} to throw error" + ); + } + #[test] fn test_arithmetic_sugar() { let input = "+= -= *= /= %="; @@ -1231,4 +1322,45 @@ mod tests { } } } + + #[test] + fn test_quote() { + // cases is a vector of pairs of (test string, expected # of tokens in token stream) + let cases = vec![ + ("quote {}", 0), + ("quote { a.b }", 3), + ("quote { ) ( }", 2), // invalid syntax is fine in a quote + ("quote { { } }", 2), // Nested `{` and `}` shouldn't close the quote as long as they are matched. + ("quote { 1 { 2 { 3 { 4 { 5 } 4 4 } 3 3 } 2 2 } 1 1 }", 21), + ("quote [ } } ]", 2), // In addition to `{}`, `[]`, and `()` can also be used as delimiters. + ("quote [ } foo[] } ]", 5), + ("quote ( } () } )", 4), + ]; + + for (source, expected_stream_length) in cases { + let mut tokens = vecmap(Lexer::new(source), |result| result.unwrap().into_token()); + + // All examples should be a single TokenStream token followed by an EOF token. + assert_eq!(tokens.len(), 2, "Unexpected token count: {tokens:?}"); + + tokens.pop(); + match tokens.pop().unwrap() { + Token::Quote(stream) => assert_eq!(stream.0.len(), expected_stream_length), + other => panic!("test_quote test failure! Expected a single TokenStream token, got {other} for input `{source}`") + } + } + } + + #[test] + fn test_unclosed_quote() { + let cases = vec!["quote {", "quote { { }", "quote [ []", "quote (((((((())))"]; + + for source in cases { + // `quote` is not itself a keyword so if the token stream fails to + // parse we don't expect any valid tokens from the quote construct + for token in Lexer::new(source) { + assert!(token.is_err(), "Expected Err, found {token:?}"); + } + } + } } 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 d8555b4fbf75..41de13fb17e0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -2,7 +2,10 @@ use acvm::{acir::AcirField, FieldElement}; use noirc_errors::{Position, Span, Spanned}; use std::{fmt, iter::Map, vec::IntoIter}; -use crate::lexer::errors::LexerErrorKind; +use crate::{ + lexer::errors::LexerErrorKind, + node_interner::{ExprId, QuotedTypeId}, +}; /// Represents a token in noir's grammar - a word, number, /// or symbol that can be used in noir's syntax. This is the @@ -23,6 +26,8 @@ pub enum BorrowedToken<'input> { Attribute(Attribute), LineComment(&'input str, Option), BlockComment(&'input str, Option), + Quote(&'input Tokens), + QuotedType(QuotedTypeId), /// < Less, /// <= @@ -85,6 +90,8 @@ pub enum BorrowedToken<'input> { Semicolon, /// ! Bang, + /// $ + DollarSign, /// = Assign, #[allow(clippy::upper_case_acronyms)] @@ -92,6 +99,11 @@ pub enum BorrowedToken<'input> { Whitespace(&'input str), + /// This is an implementation detail on how macros are implemented by quoting token streams. + /// This token marks where an unquote operation is performed. The ExprId argument is the + /// resolved variable which is being unquoted at this position in the token stream. + UnquoteMarker(ExprId), + /// 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 @@ -115,6 +127,13 @@ pub enum Token { Attribute(Attribute), LineComment(String, Option), BlockComment(String, Option), + // A `quote { ... }` along with the tokens in its token stream. + Quote(Tokens), + /// A quoted type resulting from a `Type` object in noir code being + /// spliced into a macro's token stream. We preserve the original type + /// to avoid having to tokenize it, re-parse it, and re-resolve it which + /// may change the underlying type. + QuotedType(QuotedTypeId), /// < Less, /// <= @@ -179,11 +198,18 @@ pub enum Token { Bang, /// = Assign, + /// $ + DollarSign, #[allow(clippy::upper_case_acronyms)] EOF, Whitespace(String), + /// This is an implementation detail on how macros are implemented by quoting token streams. + /// This token marks where an unquote operation is performed. The ExprId argument is the + /// resolved variable which is being unquoted at this position in the token stream. + UnquoteMarker(ExprId), + /// 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 @@ -205,6 +231,8 @@ pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { 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::Quote(stream) => BorrowedToken::Quote(stream), + Token::QuotedType(id) => BorrowedToken::QuotedType(*id), Token::IntType(ref i) => BorrowedToken::IntType(i.clone()), Token::Less => BorrowedToken::Less, Token::LessEqual => BorrowedToken::LessEqual, @@ -238,9 +266,11 @@ pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { Token::Semicolon => BorrowedToken::Semicolon, Token::Assign => BorrowedToken::Assign, Token::Bang => BorrowedToken::Bang, + Token::DollarSign => BorrowedToken::DollarSign, Token::EOF => BorrowedToken::EOF, Token::Invalid(c) => BorrowedToken::Invalid(*c), Token::Whitespace(ref s) => BorrowedToken::Whitespace(s), + Token::UnquoteMarker(id) => BorrowedToken::UnquoteMarker(*id), } } @@ -250,7 +280,7 @@ pub enum DocStyle { Inner, } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct SpannedToken(Spanned); impl PartialEq for Token { @@ -316,6 +346,15 @@ impl fmt::Display for Token { Token::Attribute(ref a) => write!(f, "{a}"), Token::LineComment(ref s, _style) => write!(f, "//{s}"), Token::BlockComment(ref s, _style) => write!(f, "/*{s}*/"), + Token::Quote(ref stream) => { + write!(f, "quote {{")?; + for token in stream.0.iter() { + write!(f, " {token}")?; + } + write!(f, "}}") + } + // Quoted types only have an ID so there is nothing to display + Token::QuotedType(_) => write!(f, "(type)"), Token::IntType(ref i) => write!(f, "{i}"), Token::Less => write!(f, "<"), Token::LessEqual => write!(f, "<="), @@ -349,9 +388,11 @@ impl fmt::Display for Token { Token::Semicolon => write!(f, ";"), Token::Assign => write!(f, "="), Token::Bang => write!(f, "!"), + Token::DollarSign => write!(f, "$"), Token::EOF => write!(f, "end of input"), Token::Invalid(c) => write!(f, "{c}"), Token::Whitespace(ref s) => write!(f, "{s}"), + Token::UnquoteMarker(_) => write!(f, "(UnquoteMarker)"), } } } @@ -364,6 +405,9 @@ pub enum TokenKind { Literal, Keyword, Attribute, + Quote, + QuotedType, + UnquoteMarker, } impl fmt::Display for TokenKind { @@ -374,13 +418,16 @@ impl fmt::Display for TokenKind { TokenKind::Literal => write!(f, "literal"), TokenKind::Keyword => write!(f, "keyword"), TokenKind::Attribute => write!(f, "attribute"), + TokenKind::Quote => write!(f, "quote"), + TokenKind::QuotedType => write!(f, "quoted type"), + TokenKind::UnquoteMarker => write!(f, "macro result"), } } } impl Token { pub fn kind(&self) -> TokenKind { - match *self { + match self { Token::Ident(_) => TokenKind::Ident, Token::Int(_) | Token::Bool(_) @@ -389,7 +436,10 @@ impl Token { | Token::FmtStr(_) => TokenKind::Literal, Token::Keyword(_) => TokenKind::Keyword, Token::Attribute(_) => TokenKind::Attribute, - ref tok => TokenKind::Token(tok.clone()), + Token::UnquoteMarker(_) => TokenKind::UnquoteMarker, + Token::Quote(_) => TokenKind::Quote, + Token::QuotedType(_) => TokenKind::QuotedType, + tok => TokenKind::Token(tok.clone()), } } @@ -454,7 +504,7 @@ impl fmt::Display for IntType { impl IntType { // XXX: Result - // Is not the best API. We could split this into two functions. One that checks if the the + // Is not the best API. We could split this into two functions. One that checks if the // word is a integer, which only returns an Option pub(crate) fn lookup_int_type(word: &str) -> Result, LexerErrorKind> { // Check if the first string is a 'u' or 'i' @@ -840,6 +890,7 @@ pub enum Keyword { Crate, Dep, Else, + Expr, Field, Fn, For, @@ -852,14 +903,17 @@ pub enum Keyword { Mod, Mut, Pub, - Quote, + Quoted, Return, ReturnData, String, Struct, Super, + TopLevelItem, Trait, Type, + TypeType, + StructDefinition, Unchecked, Unconstrained, Use, @@ -884,6 +938,7 @@ impl fmt::Display for Keyword { Keyword::Crate => write!(f, "crate"), Keyword::Dep => write!(f, "dep"), Keyword::Else => write!(f, "else"), + Keyword::Expr => write!(f, "Expr"), Keyword::Field => write!(f, "Field"), Keyword::Fn => write!(f, "fn"), Keyword::For => write!(f, "for"), @@ -896,14 +951,17 @@ impl fmt::Display for Keyword { Keyword::Mod => write!(f, "mod"), Keyword::Mut => write!(f, "mut"), Keyword::Pub => write!(f, "pub"), - Keyword::Quote => write!(f, "quote"), + Keyword::Quoted => write!(f, "Quoted"), Keyword::Return => write!(f, "return"), Keyword::ReturnData => write!(f, "return_data"), Keyword::String => write!(f, "str"), Keyword::Struct => write!(f, "struct"), Keyword::Super => write!(f, "super"), + Keyword::TopLevelItem => write!(f, "TopLevelItem"), Keyword::Trait => write!(f, "trait"), Keyword::Type => write!(f, "type"), + Keyword::TypeType => write!(f, "Type"), + Keyword::StructDefinition => write!(f, "StructDefinition"), Keyword::Unchecked => write!(f, "unchecked"), Keyword::Unconstrained => write!(f, "unconstrained"), Keyword::Use => write!(f, "use"), @@ -931,6 +989,7 @@ impl Keyword { "crate" => Keyword::Crate, "dep" => Keyword::Dep, "else" => Keyword::Else, + "Expr" => Keyword::Expr, "Field" => Keyword::Field, "fn" => Keyword::Fn, "for" => Keyword::For, @@ -943,14 +1002,17 @@ impl Keyword { "mod" => Keyword::Mod, "mut" => Keyword::Mut, "pub" => Keyword::Pub, - "quote" => Keyword::Quote, + "Quoted" => Keyword::Quoted, "return" => Keyword::Return, "return_data" => Keyword::ReturnData, "str" => Keyword::String, "struct" => Keyword::Struct, "super" => Keyword::Super, + "TopLevelItem" => Keyword::TopLevelItem, "trait" => Keyword::Trait, "type" => Keyword::Type, + "Type" => Keyword::TypeType, + "StructDefinition" => Keyword::StructDefinition, "unchecked" => Keyword::Unchecked, "unconstrained" => Keyword::Unconstrained, "use" => Keyword::Use, @@ -966,6 +1028,7 @@ impl Keyword { } } +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Tokens(pub Vec); type TokenMapIter = Map, fn(SpannedToken) -> (Token, Span)>; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs index 2db570540d62..df61c138c021 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/errors.rs @@ -6,6 +6,7 @@ use crate::hir::comptime::InterpreterError; pub enum MonomorphizationError { UnknownArrayLength { location: Location }, TypeAnnotationsNeeded { location: Location }, + InternalError { message: &'static str, location: Location }, InterpreterError(InterpreterError), } @@ -13,6 +14,7 @@ impl MonomorphizationError { fn location(&self) -> Location { match self { MonomorphizationError::UnknownArrayLength { location } + | MonomorphizationError::InternalError { location, .. } | MonomorphizationError::TypeAnnotationsNeeded { location } => *location, MonomorphizationError::InterpreterError(error) => error.get_location(), } @@ -36,6 +38,7 @@ impl MonomorphizationError { } MonomorphizationError::TypeAnnotationsNeeded { .. } => "Type annotations needed", MonomorphizationError::InterpreterError(error) => return (&error).into(), + MonomorphizationError::InternalError { message, .. } => message, }; let location = self.location(); 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 6dfd575d2b22..ebf0503963e0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -612,6 +612,7 @@ impl<'interner> Monomorphizer<'interner> { }) .transpose()? .map(Box::new); + Ok(ast::Expression::Constrain(Box::new(expr), location, assert_message)) } HirStatement::Assign(assign) => self.assign(assign), @@ -891,7 +892,11 @@ impl<'interner> Monomorphizer<'interner> { DefinitionKind::Local(_) => match self.lookup_captured_expr(ident.id) { Some(expr) => expr, None => { - let ident = self.local_ident(&ident)?.unwrap(); + let Some(ident) = self.local_ident(&ident)? else { + let location = self.interner.id_location(expr_id); + let message = "ICE: Variable not found during monomorphization"; + return Err(MonomorphizationError::InternalError { location, message }); + }; ast::Expression::Ident(ident) } }, @@ -943,7 +948,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::TraitAsType(..) => { unreachable!("All TraitAsType should be replaced before calling convert_type"); } - HirType::NamedGeneric(binding, _) => { + HirType::NamedGeneric(binding, _, _) => { if let TypeBinding::Bound(binding) = &*binding.borrow() { return Self::convert_type(binding, location); } @@ -1014,7 +1019,7 @@ impl<'interner> Monomorphizer<'interner> { HirType::Forall(_, _) | HirType::Constant(_) | HirType::Error => { unreachable!("Unexpected type {} found", typ) } - HirType::Code => unreachable!("Tried to translate Code type into runtime code"), + HirType::Quoted(_) => unreachable!("Tried to translate Code type into runtime code"), }) } @@ -1273,19 +1278,19 @@ impl<'interner> Monomorphizer<'interner> { } "modulus_le_bits" => { let bits = FieldElement::modulus().to_radix_le(2); - Some(self.modulus_array_literal(bits, IntegerBitSize::One, location)) + Some(self.modulus_slice_literal(bits, IntegerBitSize::One, location)) } "modulus_be_bits" => { let bits = FieldElement::modulus().to_radix_be(2); - Some(self.modulus_array_literal(bits, IntegerBitSize::One, location)) + Some(self.modulus_slice_literal(bits, IntegerBitSize::One, location)) } "modulus_be_bytes" => { let bytes = FieldElement::modulus().to_bytes_be(); - Some(self.modulus_array_literal(bytes, IntegerBitSize::Eight, location)) + Some(self.modulus_slice_literal(bytes, IntegerBitSize::Eight, location)) } "modulus_le_bytes" => { let bytes = FieldElement::modulus().to_bytes_le(); - Some(self.modulus_array_literal(bytes, IntegerBitSize::Eight, location)) + Some(self.modulus_slice_literal(bytes, IntegerBitSize::Eight, location)) } _ => None, }; @@ -1294,7 +1299,7 @@ impl<'interner> Monomorphizer<'interner> { None } - fn modulus_array_literal( + fn modulus_slice_literal( &self, bytes: Vec, arr_elem_bits: IntegerBitSize, @@ -1308,10 +1313,9 @@ impl<'interner> Monomorphizer<'interner> { Expression::Literal(Literal::Integer((byte as u128).into(), int_type.clone(), location)) }); - let typ = Type::Array(bytes_as_expr.len() as u32, Box::new(int_type)); - + let typ = Type::Slice(Box::new(int_type)); let arr_literal = ArrayLiteral { typ, contents: bytes_as_expr }; - Expression::Literal(Literal::Array(arr_literal)) + Expression::Literal(Literal::Slice(arr_literal)) } fn queue_function( @@ -1815,13 +1819,13 @@ fn unwrap_struct_type(typ: &HirType) -> Vec<(String, HirType)> { } } -fn perform_instantiation_bindings(bindings: &TypeBindings) { +pub fn perform_instantiation_bindings(bindings: &TypeBindings) { for (var, binding) in bindings.values() { var.force_bind(binding.clone()); } } -fn undo_instantiation_bindings(bindings: TypeBindings) { +pub fn undo_instantiation_bindings(bindings: TypeBindings) { for (id, (var, _)) in bindings { var.unbind(id); } 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 cd82685c31e5..17531d09eaca 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -17,6 +17,7 @@ use crate::hir::comptime; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::dc_crate::{UnresolvedStruct, UnresolvedTrait, UnresolvedTypeAlias}; use crate::hir::def_map::{LocalModuleId, ModuleId}; +use crate::QuotedType; use crate::ast::{BinaryOpKind, FunctionDefinition, ItemVisibility}; use crate::hir::resolution::errors::ResolverError; @@ -31,9 +32,9 @@ use crate::hir_def::{ stmt::HirStatement, }; use crate::token::{Attributes, SecondaryAttribute}; -use crate::{ - Generics, Shared, TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind, -}; +use crate::GenericTypeVars; +use crate::Generics; +use crate::{Shared, TypeAlias, TypeBindings, TypeVariable, TypeVariableId, TypeVariableKind}; /// An arbitrary number to limit the recursion depth when searching for trait impls. /// This is needed to stop recursing for cases such as `impl Foo for T where T: Eq` @@ -175,6 +176,12 @@ pub struct NodeInterner { /// Stores the [Location] of a [Type] reference pub(crate) type_ref_locations: Vec<(Type, Location)>, + + /// In Noir's metaprogramming, a noir type has the type `Type`. When these are spliced + /// into `quoted` expressions, we preserve the original type by assigning it a unique id + /// and creating a `Token::QuotedType(id)` from this id. We cannot create a token holding + /// the actual type since types do not implement Send or Sync. + quoted_types: noirc_arena::Arena, } /// A dependency in the dependency graph may be a type or a definition. @@ -302,7 +309,7 @@ impl StmtId { } } -#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)] +#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, PartialOrd, Ord)] pub struct ExprId(Index); impl ExprId { @@ -471,6 +478,9 @@ pub struct GlobalInfo { pub value: Option, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct QuotedTypeId(noirc_arena::Index); + impl Default for NodeInterner { fn default() -> Self { let mut interner = NodeInterner { @@ -505,6 +515,7 @@ impl Default for NodeInterner { primitive_methods: HashMap::new(), type_alias_ref: Vec::new(), type_ref_locations: Vec::new(), + quoted_types: Default::default(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -546,7 +557,12 @@ impl NodeInterner { self.definition_to_type.insert(definition_id, typ); } - pub fn push_empty_trait(&mut self, type_id: TraitId, unresolved_trait: &UnresolvedTrait) { + pub fn push_empty_trait( + &mut self, + type_id: TraitId, + unresolved_trait: &UnresolvedTrait, + generics: Generics, + ) { let self_type_typevar_id = self.next_type_variable_id(); let new_trait = Trait { @@ -554,13 +570,7 @@ impl NodeInterner { name: unresolved_trait.trait_def.name.clone(), crate_id: unresolved_trait.crate_id, location: Location::new(unresolved_trait.trait_def.span, unresolved_trait.file_id), - generics: vecmap(&unresolved_trait.trait_def.generics, |_| { - // Temporary type variable ids before the trait is resolved to its actual ids. - // This lets us record how many arguments the type expects so that other types - // can refer to it with generic arguments before the generic parameters themselves - // are resolved. - TypeVariable::unbound(TypeVariableId(0)) - }), + generics, self_type_typevar_id, self_type_typevar: TypeVariable::unbound(self_type_typevar_id), methods: Vec::new(), @@ -575,6 +585,7 @@ impl NodeInterner { pub fn new_struct( &mut self, typ: &UnresolvedStruct, + generics: Generics, krate: CrateId, local_id: LocalModuleId, file_id: FileId, @@ -584,13 +595,6 @@ impl NodeInterner { // Fields will be filled in later let no_fields = Vec::new(); - let generics = vecmap(&typ.struct_def.generics, |_| { - // Temporary type variable ids before the struct is resolved to its actual ids. - // This lets us record how many arguments the type expects so that other types - // can refer to it with generic arguments before the generic parameters themselves - // are resolved. - TypeVariable::unbound(TypeVariableId(0)) - }); let location = Location::new(typ.struct_def.span, file_id); let new_struct = StructType::new(struct_id, name, location, no_fields, generics); @@ -599,7 +603,11 @@ impl NodeInterner { struct_id } - pub fn push_type_alias(&mut self, typ: &UnresolvedTypeAlias) -> TypeAliasId { + pub fn push_type_alias( + &mut self, + typ: &UnresolvedTypeAlias, + generics: Generics, + ) -> TypeAliasId { let type_id = TypeAliasId(self.type_aliases.len()); self.type_aliases.push(Shared::new(TypeAlias::new( @@ -607,7 +615,7 @@ impl NodeInterner { typ.type_alias_def.name.clone(), Location::new(typ.type_alias_def.span, typ.file_id), Type::Error, - vecmap(&typ.type_alias_def.generics, |_| TypeVariable::unbound(TypeVariableId(0))), + generics, ))); type_id @@ -623,6 +631,11 @@ impl NodeInterner { f(&mut value); } + pub fn update_trait(&mut self, trait_id: TraitId, f: impl FnOnce(&mut Trait)) { + let value = self.traits.get_mut(&trait_id).unwrap(); + f(value); + } + pub fn update_struct_attributes( &mut self, type_id: StructId, @@ -632,11 +645,6 @@ impl NodeInterner { f(value); } - pub fn update_trait(&mut self, trait_id: TraitId, f: impl FnOnce(&mut Trait)) { - let value = self.traits.get_mut(&trait_id).unwrap(); - f(value); - } - pub fn set_type_alias(&mut self, type_id: TypeAliasId, typ: Type, generics: Generics) { let type_alias_type = &mut self.type_aliases[type_id.0]; type_alias_type.borrow_mut().set_type_and_generics(typ, generics); @@ -1415,11 +1423,18 @@ impl NodeInterner { trait_id: TraitId, trait_generics: Vec, impl_id: TraitImplId, - impl_generics: Generics, + impl_generics: GenericTypeVars, trait_impl: Shared, ) -> Result<(), (Span, FileId)> { self.trait_implementations.insert(impl_id, trait_impl.clone()); + // Avoid adding error types to impls since they'll conflict with every other type. + // We don't need to return an error since we expect an error to already be issued when + // the error type is created. + if object_type == Type::Error { + return Ok(()); + } + // Replace each generic with a fresh type variable let substitutions = impl_generics .into_iter() @@ -1475,6 +1490,7 @@ impl NodeInterner { force_type_check: bool, ) -> Option { let methods = self.struct_methods.get(&(id, method_name.to_owned())); + // If there is only one method, just return it immediately. // It will still be typechecked later. if !force_type_check { @@ -1738,6 +1754,14 @@ impl NodeInterner { cycle } + + pub fn push_quoted_type(&mut self, typ: Type) -> QuotedTypeId { + QuotedTypeId(self.quoted_types.insert(typ)) + } + + pub fn get_quoted_type(&self, id: QuotedTypeId) -> &Type { + &self.quoted_types[id.0] + } } impl Methods { @@ -1806,7 +1830,7 @@ enum TypeMethodKey { Tuple, Function, Generic, - Code, + Quoted(QuotedType), } fn get_type_method_key(typ: &Type) -> Option { @@ -1825,8 +1849,8 @@ fn get_type_method_key(typ: &Type) -> Option { Type::Unit => Some(Unit), Type::Tuple(_) => Some(Tuple), Type::Function(_, _, _) => Some(Function), - Type::NamedGeneric(_, _) => Some(Generic), - Type::Code => Some(Code), + Type::NamedGeneric(_, _, _) => Some(Generic), + Type::Quoted(quoted) => Some(Quoted(*quoted)), Type::MutableReference(element) => get_type_method_key(element), Type::Alias(alias, _) => get_type_method_key(&alias.borrow().typ), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop index c6cb788a5a4b..5bf48a764d63 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop +++ b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop @@ -80,7 +80,6 @@ extern { "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), @@ -125,7 +124,7 @@ pub(crate) Path: Path = { }, "dep" "::" => { - let kind = PathKind::Dep; + let kind = PathKind::Plain; let span = Span::from(lo as u32..hi as u32); Path { segments, kind, span } }, 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 af3d4caa1452..41ea9f88c199 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -133,7 +133,7 @@ impl std::fmt::Display for ParserError { } else { let expected = expected.iter().map(ToString::to_string).collect::>().join(", "); - write!(f, "Unexpected {}, expected one of {}{}", self.found, expected, reason_str) + 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 9e60383afee3..d7a282dbfc75 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs @@ -22,10 +22,10 @@ use chumsky::primitive::Container; pub use errors::ParserError; pub use errors::ParserErrorReason; use noirc_errors::Span; -pub use parser::parse_program; +pub use parser::{expression, parse_program, top_level_item}; #[derive(Debug, Clone)] -pub(crate) enum TopLevelStatement { +pub enum TopLevelStatement { Function(NoirFunction), Module(ModuleDeclaration), Import(UseTree), @@ -45,7 +45,7 @@ pub trait NoirParser: Parser + Sized + Clone { impl NoirParser for P where P: Parser + Clone {} // ExprParser just serves as a type alias for NoirParser + Clone -trait ExprParser: NoirParser {} +pub trait ExprParser: NoirParser {} impl

ExprParser for P where P: NoirParser {} fn parenthesized(parser: P) -> impl NoirParser @@ -197,7 +197,7 @@ fn parameter_name_recovery() -> impl NoirParser { } fn top_level_statement_recovery() -> impl NoirParser { - none_of([Token::Semicolon, Token::RightBrace, Token::EOF]) + none_of([Token::RightBrace, Token::EOF]) .repeated() .ignore_then(one_of([Token::Semicolon])) .map(|_| TopLevelStatement::Error) 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 cabc788e07dc..afeee889eded 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -23,7 +23,8 @@ //! prevent other parsers from being tried afterward since there is no longer an error. Thus, they should //! be limited to cases like the above `fn` example where it is clear we shouldn't back out of the //! current parser to try alternative parsers in a `choice` expression. -use self::primitives::{keyword, mutable_reference, variable}; +use self::primitives::{keyword, macro_quote_marker, mutable_reference, variable}; +use self::types::{generic_type_args, maybe_comp_time, parse_type}; use super::{ foldl_with_span, labels::ParsingRuleLabel, parameter_name_recovery, parameter_recovery, @@ -35,8 +36,8 @@ use super::{spanned, Item, ItemKind}; use crate::ast::{ BinaryOp, BinaryOpKind, BlockExpression, ForLoopStatement, ForRange, Ident, IfExpression, InfixExpression, LValue, Literal, ModuleDeclaration, NoirTypeAlias, Param, Path, Pattern, - Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnresolvedTraitConstraint, - UnresolvedTypeExpression, UseTree, UseTreeKind, Visibility, + Recoverable, Statement, TraitBound, TypeImpl, UnaryRhsMemberAccess, UnaryRhsMethodCall, + UnresolvedTraitConstraint, UseTree, UseTreeKind, Visibility, }; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, @@ -59,6 +60,7 @@ mod path; mod primitives; mod structs; mod traits; +mod types; // synthesized by LALRPOP lalrpop_mod!(pub noir_parser); @@ -189,6 +191,11 @@ fn module() -> impl NoirParser { }) } +/// This parser is used for parsing top level statements in macros +pub fn top_level_item() -> impl NoirParser { + top_level_statement(module()) +} + /// top_level_statement: function_definition /// | struct_definition /// | trait_definition @@ -223,11 +230,20 @@ fn implementation() -> impl NoirParser { keyword(Keyword::Impl) .ignore_then(function::generics()) .then(parse_type().map_with_span(|typ, span| (typ, span))) + .then(where_clause()) .then_ignore(just(Token::LeftBrace)) .then(spanned(function::function_definition(true)).repeated()) .then_ignore(just(Token::RightBrace)) - .map(|((generics, (object_type, type_span)), methods)| { - TopLevelStatement::Impl(TypeImpl { generics, object_type, type_span, methods }) + .map(|args| { + let ((other_args, where_clause), methods) = args; + let (generics, (object_type, type_span)) = other_args; + TopLevelStatement::Impl(TypeImpl { + generics, + object_type, + type_span, + where_clause, + methods, + }) }) } @@ -674,41 +690,6 @@ where }) } -fn parse_type<'a>() -> impl NoirParser + 'a { - recursive(parse_type_inner) -} - -fn parse_type_inner<'a>( - recursive_type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - choice(( - field_type(), - int_type(), - bool_type(), - string_type(), - format_string_type(recursive_type_parser.clone()), - named_type(recursive_type_parser.clone()), - named_trait(recursive_type_parser.clone()), - slice_type(recursive_type_parser.clone()), - array_type(recursive_type_parser.clone()), - parenthesized_type(recursive_type_parser.clone()), - tuple_type(recursive_type_parser.clone()), - function_type(recursive_type_parser.clone()), - mutable_reference_type(recursive_type_parser), - )) -} - -fn parenthesized_type( - recursive_type_parser: impl NoirParser, -) -> impl NoirParser { - recursive_type_parser - .delimited_by(just(Token::LeftParen), just(Token::RightParen)) - .map_with_span(|typ, span| UnresolvedType { - typ: UnresolvedTypeData::Parenthesized(Box::new(typ)), - span: span.into(), - }) -} - fn optional_visibility() -> impl NoirParser { keyword(Keyword::Pub) .or(keyword(Keyword::CallData)) @@ -724,188 +705,7 @@ fn optional_visibility() -> impl NoirParser { }) } -fn maybe_comp_time() -> impl NoirParser { - keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { - if opt.is_some() { - emit(ParserError::with_reason( - ParserErrorReason::ExperimentalFeature("Comptime values"), - span, - )); - } - opt.is_some() - }) -} - -fn field_type() -> impl NoirParser { - keyword(Keyword::Field) - .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) -} - -fn bool_type() -> impl NoirParser { - keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) -} - -fn string_type() -> impl NoirParser { - keyword(Keyword::String) - .ignore_then(type_expression().delimited_by(just(Token::Less), just(Token::Greater))) - .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) -} - -fn format_string_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - keyword(Keyword::FormatString) - .ignore_then( - type_expression() - .then_ignore(just(Token::Comma)) - .then(type_parser) - .delimited_by(just(Token::Less), just(Token::Greater)), - ) - .map_with_span(|(size, fields), span| { - UnresolvedTypeData::FormatString(size, Box::new(fields)).with_span(span) - }) -} - -fn int_type() -> impl NoirParser { - filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - }) - .validate(|token, span, emit| { - UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( - |err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }, - ) - }) -} - -fn named_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - path().then(generic_type_args(type_parser)).map_with_span(|(path, args), span| { - UnresolvedTypeData::Named(path, args, false).with_span(span) - }) -} - -fn named_trait<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - keyword(Keyword::Impl).ignore_then(path()).then(generic_type_args(type_parser)).map_with_span( - |(path, args), span| UnresolvedTypeData::TraitAsType(path, args).with_span(span), - ) -} - -fn generic_type_args<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser> + 'a { - type_parser - .clone() - // Without checking for a terminating ',' or '>' here we may incorrectly - // parse a generic `N * 2` as just the type `N` then fail when there is no - // separator afterward. Failing early here ensures we try the `type_expression` - // parser afterward. - .then_ignore(one_of([Token::Comma, Token::Greater]).rewind()) - .or(type_expression() - .map_with_span(|expr, span| UnresolvedTypeData::Expression(expr).with_span(span))) - .separated_by(just(Token::Comma)) - .allow_trailing() - .at_least(1) - .delimited_by(just(Token::Less), just(Token::Greater)) - .or_not() - .map(Option::unwrap_or_default) -} - -fn array_type<'a>( - type_parser: impl NoirParser + 'a, -) -> impl NoirParser + 'a { - just(Token::LeftBracket) - .ignore_then(type_parser) - .then(just(Token::Semicolon).ignore_then(type_expression())) - .then_ignore(just(Token::RightBracket)) - .map_with_span(|(element_type, size), span| { - UnresolvedTypeData::Array(size, Box::new(element_type)).with_span(span) - }) -} - -fn slice_type(type_parser: impl NoirParser) -> impl NoirParser { - just(Token::LeftBracket) - .ignore_then(type_parser) - .then_ignore(just(Token::RightBracket)) - .map_with_span(|element_type, span| { - UnresolvedTypeData::Slice(Box::new(element_type)).with_span(span) - }) -} - -fn type_expression() -> impl NoirParser { - recursive(|expr| { - expression_with_precedence( - Precedence::lowest_type_precedence(), - expr, - nothing(), - nothing(), - true, - false, - ) - }) - .labelled(ParsingRuleLabel::TypeExpression) - .try_map(UnresolvedTypeExpression::from_expr) -} - -fn tuple_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - let fields = type_parser.separated_by(just(Token::Comma)).allow_trailing(); - parenthesized(fields).map_with_span(|fields, span| { - if fields.is_empty() { - UnresolvedTypeData::Unit.with_span(span) - } else { - UnresolvedTypeData::Tuple(fields).with_span(span) - } - }) -} - -fn function_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - let args = parenthesized(type_parser.clone().separated_by(just(Token::Comma)).allow_trailing()); - - let env = just(Token::LeftBracket) - .ignore_then(type_parser.clone()) - .then_ignore(just(Token::RightBracket)) - .or_not() - .map_with_span(|t, span| { - t.unwrap_or_else(|| UnresolvedTypeData::Unit.with_span(Span::empty(span.end()))) - }); - - keyword(Keyword::Fn) - .ignore_then(env) - .then(args) - .then_ignore(just(Token::Arrow)) - .then(type_parser) - .map_with_span(|((env, args), ret), span| { - UnresolvedTypeData::Function(args, Box::new(ret), Box::new(env)).with_span(span) - }) -} - -fn mutable_reference_type(type_parser: T) -> impl NoirParser -where - T: NoirParser, -{ - just(Token::Ampersand) - .ignore_then(keyword(Keyword::Mut)) - .ignore_then(type_parser) - .map_with_span(|element, span| { - UnresolvedTypeData::MutableReference(Box::new(element)).with_span(span) - }) -} - -fn expression() -> impl ExprParser { +pub fn expression() -> impl ExprParser { recursive(|expr| { expression_with_precedence( Precedence::Lowest, @@ -1073,14 +873,18 @@ where S: NoirParser + 'a, { enum UnaryRhs { - Call(Vec), + Call((Option, Vec)), ArrayIndex(Expression), Cast(UnresolvedType), MemberAccess(UnaryRhsMemberAccess), } // `(arg1, ..., argN)` in `my_func(arg1, ..., argN)` - let call_rhs = parenthesized(expression_list(expr_parser.clone())).map(UnaryRhs::Call); + // Optionally accepts a leading `!` for macro calls. + let call_rhs = just(Token::Bang) + .or_not() + .then(parenthesized(expression_list(expr_parser.clone()))) + .map(UnaryRhs::Call); // `[expr]` in `arr[expr]` let array_rhs = expr_parser @@ -1097,11 +901,23 @@ where // A turbofish operator is optional in a method call to specify generic types let turbofish = primitives::turbofish(type_parser); + // `::!(arg1, .., argN)` with the turbofish and macro portions being optional. + let method_call_rhs = turbofish + .then(just(Token::Bang).or_not()) + .then(parenthesized(expression_list(expr_parser.clone()))) + .map(|((turbofish, macro_call), args)| UnaryRhsMethodCall { + turbofish, + macro_call: macro_call.is_some(), + args, + }); + // `.foo` or `.foo(args)` in `atom.foo` or `atom.foo(args)` let member_rhs = just(Token::Dot) .ignore_then(field_name()) - .then(turbofish.then(parenthesized(expression_list(expr_parser.clone()))).or_not()) - .map(UnaryRhs::MemberAccess) + .then(method_call_rhs.or_not()) + .map(|(method_or_field, method_call)| { + UnaryRhs::MemberAccess(UnaryRhsMemberAccess { method_or_field, method_call }) + }) .labelled(ParsingRuleLabel::FieldAccess); let rhs = choice((call_rhs, array_rhs, cast_rhs, member_rhs)); @@ -1110,7 +926,9 @@ where atom(expr_parser, expr_no_constructors, statement, allow_constructors), rhs, |lhs, rhs, span| match rhs { - UnaryRhs::Call(args) => Expression::call(lhs, args, span), + UnaryRhs::Call((is_macro, args)) => { + Expression::call(lhs, is_macro.is_some(), args, span) + } UnaryRhs::ArrayIndex(index) => Expression::index(lhs, index, span), UnaryRhs::Cast(r#type) => Expression::cast(lhs, r#type, span), UnaryRhs::MemberAccess(field) => { @@ -1270,10 +1088,12 @@ where }, lambdas::lambda(expr_parser.clone()), block(statement.clone()).map(ExpressionKind::Block), - comptime_expr(statement.clone()), - quote(statement), + comptime_expr(statement), + quote(), + unquote(expr_parser.clone()), variable(), literal(), + macro_quote_marker(), )) .map_with_span(Expression::new) .or(parenthesized(expr_parser.clone()).map_with_span(|sub_expr, span| { @@ -1296,19 +1116,30 @@ where .labelled(ParsingRuleLabel::Atom) } -fn quote<'a, P>(statement: P) -> impl NoirParser + 'a -where - P: NoirParser + 'a, -{ - keyword(Keyword::Quote).ignore_then(block(statement)).validate(|block, span, emit| { +fn quote() -> impl NoirParser { + token_kind(TokenKind::Quote).validate(|token, span, emit| { + let tokens = match token { + Token::Quote(tokens) => tokens, + _ => unreachable!("token_kind(Quote) should guarantee parsing only a quote token"), + }; emit(ParserError::with_reason( ParserErrorReason::ExperimentalFeature("quoted expressions"), span, )); - ExpressionKind::Quote(block) + ExpressionKind::Quote(tokens) }) } +/// unquote: '$' variable +/// | '$' '(' expression ')' +fn unquote<'a, P>(expr_parser: P) -> impl NoirParser + 'a +where + P: ExprParser + 'a, +{ + let unquote = variable().map_with_span(Expression::new).or(parenthesized(expr_parser)); + just(Token::DollarSign).ignore_then(unquote).map(|expr| ExpressionKind::Unquote(Box::new(expr))) +} + fn tuple

(expr_parser: P) -> impl NoirParser where P: ExprParser, @@ -1452,11 +1283,6 @@ mod test { ); } - #[test] - fn parse_type_expression() { - parse_all(type_expression(), vec!["(123)", "123", "(1 + 1)", "(1 + (1))"]); - } - #[test] fn parse_array_sugar() { let valid = vec!["[0;7]", "[(1, 2); 4]", "[0;Four]", "[2;1+3-a]"]; @@ -1633,7 +1459,7 @@ mod test { "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}", + "use std::{println, bar::baz}", ]; let invalid_use_statements = [ @@ -1735,27 +1561,19 @@ mod test { Case { source: "let = 4 + 3", expect: "let $error: unspecified = (4 + 3)", errors: 1 }, Case { source: "let = ", expect: "let $error: unspecified = Error", errors: 2 }, Case { source: "let", expect: "let $error: unspecified = Error", errors: 3 }, - Case { source: "foo = one two three", expect: "foo = plain::one", errors: 1 }, + Case { source: "foo = one two three", expect: "foo = one", errors: 1 }, Case { source: "constrain", expect: "constrain Error", errors: 2 }, Case { source: "assert", expect: "constrain Error", errors: 1 }, - Case { source: "constrain x ==", expect: "constrain (plain::x == Error)", errors: 2 }, - Case { source: "assert(x ==)", expect: "constrain (plain::x == Error)", errors: 1 }, - Case { - source: "assert(x == x, x)", - expect: "constrain (plain::x == plain::x)", - errors: 0, - }, + Case { source: "constrain x ==", expect: "constrain (x == Error)", errors: 2 }, + Case { source: "assert(x ==)", expect: "constrain (x == Error)", errors: 1 }, + Case { source: "assert(x == x, x)", expect: "constrain (x == x)", errors: 0 }, Case { source: "assert_eq(x,)", expect: "constrain (Error == Error)", errors: 1 }, Case { source: "assert_eq(x, x, x, x)", expect: "constrain (Error == Error)", errors: 1, }, - Case { - source: "assert_eq(x, x, x)", - expect: "constrain (plain::x == plain::x)", - errors: 0, - }, + Case { source: "assert_eq(x, x, x)", expect: "constrain (x == x)", errors: 0 }, ]; check_cases_with_errors(&cases[..], fresh_statement()); @@ -1797,7 +1615,7 @@ mod test { source: "{ if structure { a: 1 } {} }", expect: concat!( "{\n", - " if plain::structure {\n", + " if structure {\n", " Error\n", " }\n", " {\n", @@ -1808,22 +1626,17 @@ mod test { }, Case { source: "{ if ( structure { a: 1 } ) {} }", - expect: concat!("{\n", " if ((plain::structure { a: 1 })) {\n", " }\n", "}",), + expect: concat!("{\n", " if ((structure { a: 1 })) {\n", " }\n", "}",), errors: 0, }, Case { source: "{ if ( structure {} ) {} }", - expect: concat!("{\n", " if ((plain::structure { })) {\n", " }\n", "}"), + expect: concat!("{\n", " if ((structure { })) {\n", " }\n", "}"), errors: 0, }, Case { source: "{ if (a { x: 1 }, b { y: 2 }) {} }", - expect: concat!( - "{\n", - " if ((plain::a { x: 1 }), (plain::b { y: 2 })) {\n", - " }\n", - "}", - ), + expect: concat!("{\n", " if ((a { x: 1 }), (b { y: 2 })) {\n", " }\n", "}",), errors: 0, }, Case { @@ -1831,8 +1644,8 @@ mod test { expect: concat!( "{\n", " if ({\n", - " let foo: unspecified = (plain::bar { baz: 42 })\n", - " (plain::foo == (plain::bar { baz: 42 }))\n", + " let foo: unspecified = (bar { baz: 42 })\n", + " (foo == (bar { baz: 42 }))\n", " }) {\n", " }\n", "}", @@ -1843,4 +1656,19 @@ mod test { check_cases_with_errors(&cases[..], block(fresh_statement())); } + + #[test] + fn test_quote() { + let cases = vec![ + "quote {}", + "quote { a.b }", + "quote { ) ( }", // invalid syntax is fine in a quote + "quote { { } }", // Nested `{` and `}` shouldn't close the quote as long as they are matched. + "quote { 1 { 2 { 3 { 4 { 5 } 4 4 } 3 3 } 2 2 } 1 1 }", + ]; + parse_all(quote(), cases); + + let failing = vec!["quote {}}", "quote a", "quote { { { } } } }"]; + parse_all_failing(quote(), failing); + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs index 4db5637f6a71..3e686ee4c853 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/function.rs @@ -5,11 +5,14 @@ use super::{ self_parameter, where_clause, NoirParser, }; use crate::ast::{ - FunctionDefinition, FunctionReturnType, Ident, ItemVisibility, NoirFunction, Param, Visibility, + FunctionDefinition, FunctionReturnType, ItemVisibility, NoirFunction, Param, Visibility, }; -use crate::parser::labels::ParsingRuleLabel; use crate::parser::spanned; use crate::token::{Keyword, Token}; +use crate::{ + ast::{UnresolvedGeneric, UnresolvedGenerics}, + parser::labels::ParsingRuleLabel, +}; use chumsky::prelude::*; @@ -76,16 +79,31 @@ fn function_modifiers() -> impl NoirParser<(bool, ItemVisibility, bool)> { }) } +pub(super) fn numeric_generic() -> impl NoirParser { + keyword(Keyword::Let) + .ignore_then(ident()) + .then_ignore(just(Token::Colon)) + .then(parse_type()) + .map(|(ident, typ)| UnresolvedGeneric::Numeric { ident, typ }) +} + +pub(super) fn generic_type() -> impl NoirParser { + ident().map(UnresolvedGeneric::Variable) +} + +pub(super) fn generic() -> impl NoirParser { + generic_type().or(numeric_generic()) +} + /// non_empty_ident_list: ident ',' non_empty_ident_list /// | ident /// /// generics: '<' non_empty_ident_list '>' /// | %empty -pub(super) fn generics() -> impl NoirParser> { - ident() +pub(super) fn generics() -> impl NoirParser { + generic() .separated_by(just(Token::Comma)) .allow_trailing() - .at_least(1) .delimited_by(just(Token::Less), just(Token::Greater)) .or_not() .map(|opt| opt.unwrap_or_default()) @@ -193,6 +211,7 @@ mod test { // fn func_name(x: impl Eq) {} with error Expected an end of input but found end of input // "fn func_name(x: impl Eq) {}", "fn func_name(x: impl Eq, y : T) where T: SomeTrait + Eq {}", + "fn func_name(x: [Field; N]) {}", ], ); @@ -209,6 +228,11 @@ mod test { // A leading plus is not allowed. "fn func_name(f: Field, y : T) where T: + SomeTrait {}", "fn func_name(f: Field, y : T) where T: TraitX + {}", + // Test ill-formed numeric generics + "fn func_name(y: T) {}", + "fn func_name(y: T) {}", + "fn func_name(y: T) {}", + "fn func_name(y: T) {}", ], ); } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs index 584224fda462..b25b6acc9e26 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/literals.rs @@ -108,18 +108,18 @@ mod test { #[allow(clippy::needless_raw_string_hashes)] Case { source: r####"r###""###"####, expect: r####"r###""###"####, errors: 0 }, // miscellaneous - Case { source: r##" r#\"foo\"# "##, expect: "plain::r", errors: 2 }, - Case { source: r#" r\"foo\" "#, expect: "plain::r", errors: 1 }, + Case { source: r##" r#\"foo\"# "##, expect: "r", errors: 2 }, + Case { source: r#" r\"foo\" "#, expect: "r", errors: 1 }, Case { source: r##" r##"foo"# "##, expect: "(none)", errors: 2 }, // missing 'r' letter Case { source: r##" ##"foo"# "##, expect: r#""foo""#, errors: 2 }, - Case { source: r#" #"foo" "#, expect: "plain::foo", errors: 2 }, + Case { source: r#" #"foo" "#, expect: "foo", errors: 2 }, // whitespace - Case { source: r##" r #"foo"# "##, expect: "plain::r", errors: 2 }, - Case { source: r##" r# "foo"# "##, expect: "plain::r", errors: 3 }, + Case { source: r##" r #"foo"# "##, expect: "r", errors: 2 }, + Case { source: r##" r# "foo"# "##, expect: "r", errors: 3 }, Case { source: r#" r#"foo" # "#, expect: "(none)", errors: 2 }, // after identifier - Case { source: r##" bar#"foo"# "##, expect: "plain::bar", errors: 2 }, + Case { source: r##" bar#"foo"# "##, expect: "bar", errors: 2 }, // nested Case { source: r###"r##"foo r#"bar"# r"baz" ### bye"##"###, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs index 47bb11991fa2..e40268af4104 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/path.rs @@ -25,7 +25,7 @@ fn empty_path() -> impl NoirParser { let make_path = |kind| move |_, span| Path { segments: Vec::new(), kind, span }; let path_kind = |key, kind| keyword(key).map_with_span(make_path(kind)); - choice((path_kind(Keyword::Crate, PathKind::Crate), path_kind(Keyword::Dep, PathKind::Dep))) + choice((path_kind(Keyword::Crate, PathKind::Crate), path_kind(Keyword::Dep, PathKind::Plain))) } pub(super) fn maybe_empty_path() -> impl NoirParser { @@ -43,7 +43,8 @@ mod test { ("std", vec!["std"]), ("std::hash", vec!["std", "hash"]), ("std::hash::collections", vec!["std", "hash", "collections"]), - ("dep::foo::bar", vec!["foo", "bar"]), + ("foo::bar", vec!["foo", "bar"]), + ("foo::bar", vec!["foo", "bar"]), ("crate::std::hash", vec!["std", "hash"]), ]; @@ -61,7 +62,7 @@ mod test { fn parse_path_kinds() { let cases = vec![ ("std", PathKind::Plain), - ("dep::hash::collections", PathKind::Dep), + ("hash::collections", PathKind::Plain), ("crate::std::hash", PathKind::Crate), ]; @@ -72,7 +73,7 @@ mod test { parse_all_failing( path(), - vec!["dep", "crate", "crate::std::crate", "foo::bar::crate", "foo::dep"], + vec!["crate", "crate::std::crate", "foo::bar::crate", "foo::dep"], ); } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs index 9da19c0a185d..88f9e591aba5 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/primitives.rs @@ -94,6 +94,13 @@ pub(super) fn variable_no_turbofish() -> impl NoirParser { path().map(|path| ExpressionKind::Variable(path, None)) } +pub(super) fn macro_quote_marker() -> impl NoirParser { + token_kind(TokenKind::UnquoteMarker).map(|token| match token { + Token::UnquoteMarker(expr_id) => ExpressionKind::Resolved(expr_id), + other => unreachable!("Non-unquote-marker parsed as an unquote marker: {other:?}"), + }) +} + #[cfg(test)] mod test { use crate::parser::parser::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs index 82dd3dad6815..32929312d541 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/types.rs @@ -1,22 +1,45 @@ +use super::primitives::token_kind; use super::{ - expression_with_precedence, keyword, nothing, parenthesized, NoirParser, ParserError, + expression_with_precedence, keyword, nothing, parenthesized, path, NoirParser, ParserError, ParserErrorReason, Precedence, }; -use crate::ast::{UnresolvedType, UnresolvedTypeData}; +use crate::ast::{Recoverable, UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression}; +use crate::QuotedType; use crate::parser::labels::ParsingRuleLabel; -use crate::token::{Keyword, Token}; -use crate::{Recoverable, UnresolvedTypeExpression}; +use crate::token::{Keyword, Token, TokenKind}; use chumsky::prelude::*; use noirc_errors::Span; -fn maybe_comp_time() -> impl NoirParser<()> { - keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { - if opt.is_some() { - emit(ParserError::with_reason(ParserErrorReason::ComptimeDeprecated, span)); - } - }) +pub(super) fn parse_type<'a>() -> impl NoirParser + 'a { + recursive(parse_type_inner) +} + +pub(super) fn parse_type_inner<'a>( + recursive_type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + choice(( + field_type(), + int_type(), + bool_type(), + string_type(), + expr_type(), + struct_definition_type(), + top_level_item_type(), + type_of_quoted_types(), + quoted_type(), + resolved_type(), + format_string_type(recursive_type_parser.clone()), + named_type(recursive_type_parser.clone()), + named_trait(recursive_type_parser.clone()), + slice_type(recursive_type_parser.clone()), + array_type(recursive_type_parser.clone()), + parenthesized_type(recursive_type_parser.clone()), + tuple_type(recursive_type_parser.clone()), + function_type(recursive_type_parser.clone()), + mutable_reference_type(recursive_type_parser), + )) } pub(super) fn parenthesized_type( @@ -30,29 +53,79 @@ pub(super) fn parenthesized_type( }) } +pub(super) fn maybe_comp_time() -> impl NoirParser { + keyword(Keyword::Comptime).or_not().validate(|opt, span, emit| { + if opt.is_some() { + emit(ParserError::with_reason( + ParserErrorReason::ExperimentalFeature("Comptime values"), + span, + )); + } + opt.is_some() + }) +} + pub(super) fn field_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Field)) + keyword(Keyword::Field) .map_with_span(|_, span| UnresolvedTypeData::FieldElement.with_span(span)) } pub(super) fn bool_type() -> impl NoirParser { - maybe_comp_time() - .then_ignore(keyword(Keyword::Bool)) - .map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) + keyword(Keyword::Bool).map_with_span(|_, span| UnresolvedTypeData::Bool.with_span(span)) +} + +/// This is the type `Expr` - the type of a quoted, untyped expression object used for macros +pub(super) fn expr_type() -> impl NoirParser { + keyword(Keyword::Expr) + .map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::Expr).with_span(span)) +} + +/// This is the type `StructDefinition` - the type of a quoted struct definition +pub(super) fn struct_definition_type() -> impl NoirParser { + keyword(Keyword::StructDefinition).map_with_span(|_, span| { + UnresolvedTypeData::Quoted(QuotedType::StructDefinition).with_span(span) + }) +} + +/// This is the type `TopLevelItem` - the type of a quoted statement in the top level. +/// E.g. a type definition, trait definition, trait impl, function, etc. +fn top_level_item_type() -> impl NoirParser { + keyword(Keyword::TopLevelItem).map_with_span(|_, span| { + UnresolvedTypeData::Quoted(QuotedType::TopLevelItem).with_span(span) + }) +} + +/// This is the type `Type` - the type of a quoted noir type. +fn type_of_quoted_types() -> impl NoirParser { + keyword(Keyword::TypeType) + .map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::Type).with_span(span)) +} + +/// This is the type of a quoted, unparsed token stream. +fn quoted_type() -> impl NoirParser { + keyword(Keyword::Quoted) + .map_with_span(|_, span| UnresolvedTypeData::Quoted(QuotedType::Quoted).with_span(span)) +} + +/// This is the type of an already resolved type. +/// The only way this can appear in the token input is if an already resolved `Type` object +/// was spliced into a macro's token stream via the `$` operator. +fn resolved_type() -> impl NoirParser { + token_kind(TokenKind::QuotedType).map_with_span(|token, span| match token { + Token::QuotedType(id) => UnresolvedTypeData::Resolved(id).with_span(span), + _ => unreachable!("token_kind(QuotedType) guarantees we parse a quoted type"), + }) } pub(super) fn string_type() -> impl NoirParser { keyword(Keyword::String) - .ignore_then( - type_expression().delimited_by(just(Token::Less), just(Token::Greater)).or_not(), - ) + .ignore_then(type_expression().delimited_by(just(Token::Less), just(Token::Greater))) .map_with_span(|expr, span| UnresolvedTypeData::String(expr).with_span(span)) } -pub(super) fn format_string_type( - type_parser: impl NoirParser, -) -> impl NoirParser { +pub(super) fn format_string_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { keyword(Keyword::FormatString) .ignore_then( type_expression() @@ -66,26 +139,61 @@ pub(super) fn format_string_type( } pub(super) fn int_type() -> impl NoirParser { - maybe_comp_time() - .then(filter_map(|span, token: Token| match token { - Token::IntType(int_type) => Ok(int_type), - unexpected => { - Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) - } - })) - .validate(|(_, token), span, emit| { - UnresolvedTypeData::from_int_token(token) - .map(|data| data.with_span(span)) - .unwrap_or_else(|err| { - emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); - UnresolvedType::error(span) - }) - }) + filter_map(|span, token: Token| match token { + Token::IntType(int_type) => Ok(int_type), + unexpected => { + Err(ParserError::expected_label(ParsingRuleLabel::IntegerType, unexpected, span)) + } + }) + .validate(|token, span, emit| { + UnresolvedTypeData::from_int_token(token).map(|data| data.with_span(span)).unwrap_or_else( + |err| { + emit(ParserError::with_reason(ParserErrorReason::InvalidBitSize(err.0), span)); + UnresolvedType::error(span) + }, + ) + }) } -pub(super) fn array_type( - type_parser: impl NoirParser, -) -> impl NoirParser { +pub(super) fn named_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + path().then(generic_type_args(type_parser)).map_with_span(|(path, args), span| { + UnresolvedTypeData::Named(path, args, false).with_span(span) + }) +} + +pub(super) fn named_trait<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { + keyword(Keyword::Impl).ignore_then(path()).then(generic_type_args(type_parser)).map_with_span( + |(path, args), span| UnresolvedTypeData::TraitAsType(path, args).with_span(span), + ) +} + +pub(super) fn generic_type_args<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser> + 'a { + type_parser + .clone() + // Without checking for a terminating ',' or '>' here we may incorrectly + // parse a generic `N * 2` as just the type `N` then fail when there is no + // separator afterward. Failing early here ensures we try the `type_expression` + // parser afterward. + .then_ignore(one_of([Token::Comma, Token::Greater]).rewind()) + .or(type_expression() + .map_with_span(|expr, span| UnresolvedTypeData::Expression(expr).with_span(span))) + .separated_by(just(Token::Comma)) + .allow_trailing() + .at_least(1) + .delimited_by(just(Token::Less), just(Token::Greater)) + .or_not() + .map(Option::unwrap_or_default) +} + +pub(super) fn array_type<'a>( + type_parser: impl NoirParser + 'a, +) -> impl NoirParser + 'a { just(Token::LeftBracket) .ignore_then(type_parser) .then(just(Token::Semicolon).ignore_then(type_expression())) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index 99215c8f173f..9251eb3db6b0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -14,6 +14,7 @@ use fm::FileId; use iter_extended::vecmap; use noirc_errors::Location; +use crate::hir::comptime::InterpreterError; use crate::hir::def_collector::dc_crate::CompilationError; use crate::hir::def_collector::errors::{DefCollectorErrorKind, DuplicateType}; use crate::hir::def_map::ModuleData; @@ -49,7 +50,10 @@ pub(crate) fn remove_experimental_warnings(errors: &mut Vec<(CompilationError, F }); } -pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { +pub(crate) fn get_program( + src: &str, + use_legacy: bool, +) -> (ParsedModule, Context, Vec<(CompilationError, FileId)>) { let root = std::path::Path::new("/"); let fm = FileManager::new(root); @@ -81,7 +85,7 @@ pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(Compilation &mut context, program.clone().into_sorted(), root_file_id, - false, + use_legacy, &[], // No macro processors )); } @@ -89,7 +93,7 @@ pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(Compilation } pub(crate) fn get_program_errors(src: &str) -> Vec<(CompilationError, FileId)> { - get_program(src).2 + get_program(src, false).2 } #[test] @@ -619,7 +623,7 @@ fn check_impl_struct_not_trait() { CompilationError::DefinitionError(DefCollectorErrorKind::NotATrait { not_a_trait_name, }) => { - assert_eq!(not_a_trait_name.to_string(), "plain::Default"); + assert_eq!(not_a_trait_name.to_string(), "Default"); } _ => { panic!("No other errors are expected! Found = {:?}", err); @@ -832,7 +836,7 @@ fn check_trait_as_type_as_two_fn_parameters() { } fn get_program_captures(src: &str) -> Vec> { - let (program, context, _errors) = get_program(src); + let (program, context, _errors) = get_program(src, false); let interner = context.def_interner; let mut all_captures: Vec> = Vec::new(); for func in program.into_sorted().functions { @@ -1194,7 +1198,7 @@ fn resolve_fmt_strings() { } fn check_rewrite(src: &str, expected: &str) { - let (_program, mut context, _errors) = get_program(src); + let (_program, mut context, _errors) = get_program(src, false); let main_func_id = context.def_interner.find_function("main").unwrap(); let program = monomorphize(main_func_id, &mut context.def_interner).unwrap(); assert!(format!("{}", program) == expected); @@ -1325,14 +1329,20 @@ fn for_loop_over_array() { hello(array); } "#; - assert_eq!(get_program_errors(src).len(), 0); + let errors = get_program_errors(src); + assert_eq!(get_program_errors(src).len(), 1); + + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { .. }) + )); } // Regression for #4545 #[test] fn type_aliases_in_main() { let src = r#" - type Outer = [u8; N]; + type Outer = [u8; N]; fn main(_arg: Outer<1>) {} "#; assert_eq!(get_program_errors(src).len(), 0); @@ -1444,3 +1454,445 @@ fn specify_method_types_with_turbofish() { let errors = get_program_errors(src); assert_eq!(errors.len(), 0); } + +#[test] +fn struct_numeric_generic_in_function() { + let src = r#" + struct Foo { + inner: u64 + } + + fn bar() { } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::UnsupportedNumericGenericType { .. }), + )); +} + +#[test] +fn struct_numeric_generic_in_struct() { + let src = r#" + struct Foo { + inner: u64 + } + + struct Bar { } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::DefinitionError( + DefCollectorErrorKind::UnsupportedNumericGenericType { .. } + ), + )); +} + +#[test] +fn bool_numeric_generic() { + let src = r#" + fn read() -> Field { + if N { + 0 + } else { + 1 + } + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::UnsupportedNumericGenericType { .. }), + )); +} + +#[test] +fn numeric_generic_binary_operation_type_mismatch() { + let src = r#" + fn foo() -> bool { + let mut check: bool = true; + check = N; + check + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeMismatchWithSource { .. }), + )); +} + +#[test] +fn bool_generic_as_loop_bound() { + let src = r#" + fn read() { + let mut fields = [0; N]; + for i in 0..N { + fields[i] = i + 1; + } + assert(fields[0] == 1); + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 2); + + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::UnsupportedNumericGenericType { .. }), + )); + + let CompilationError::TypeError(TypeCheckError::TypeMismatch { + expected_typ, expr_typ, .. + }) = &errors[1].0 + else { + panic!("Got an error other than a type mismatch"); + }; + + assert_eq!(expected_typ, "Field"); + assert_eq!(expr_typ, "bool"); +} + +#[test] +fn numeric_generic_in_function_signature() { + let src = r#" + fn foo(arr: [Field; N]) -> [Field; N] { arr } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn numeric_generic_as_struct_field_type() { + let src = r#" + struct Foo { + a: Field, + b: N, + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + )); +} + +#[test] +fn normal_generic_as_array_length() { + let src = r#" + struct Foo { + a: Field, + b: [Field; N], + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + // TODO(https://github.com/noir-lang/noir/issues/5156): This should be switched to a hard type error rather than + // the `UseExplicitNumericGeneric` once implicit numeric generics are removed. + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { .. }), + )); +} + +#[test] +fn numeric_generic_as_param_type() { + let src = r#" + fn foo(x: I) -> I { + let _q: I = 5; + x + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 3); + // Error from the parameter type + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + )); + // Error from the let statement annotated type + assert!(matches!( + errors[1].0, + CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + )); + // Error from the return type + assert!(matches!( + errors[2].0, + CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + )); +} + +#[test] +fn numeric_generic_used_in_nested_type_fail() { + let src = r#" + struct Foo { + a: Field, + b: Bar, + } + struct Bar { + inner: N + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::NumericGenericUsedForType { .. }), + )); +} + +#[test] +fn normal_generic_used_in_nested_array_length_fail() { + let src = r#" + struct Foo { + a: Field, + b: Bar, + } + struct Bar { + inner: [Field; N] + } + "#; + let errors = get_program_errors(src); + // TODO(https://github.com/noir-lang/noir/issues/5156): This should be switched to a hard type error once implicit numeric generics are removed. + assert_eq!(errors.len(), 0); +} + +#[test] +fn numeric_generic_used_in_nested_type_pass() { + // The order of these structs should not be changed to make sure + // that we are accurately resolving all struct generics before struct fields + let src = r#" + struct NestedNumeric { + a: Field, + b: InnerNumeric + } + struct InnerNumeric { + inner: [u64; N], + } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn numeric_generic_used_in_trait() { + let src = r#" + struct MyType { + a: Field, + b: Field, + c: Field, + d: T, + } + + impl Deserialize for MyType { + fn deserialize(fields: [Field; N], other: T) -> Self { + MyType { a: fields[0], b: fields[1], c: fields[2], d: other } + } + } + + trait Deserialize { + fn deserialize(fields: [Field; N], other: T) -> Self; + } + "#; + let errors = get_program_errors(src); + // We want to make sure that `N` in `impl Deserialize` does + // not trigger `expected type, found numeric generic parameter N` as the trait + // does in fact expect a numeric generic. + assert!(errors.is_empty()); +} + +#[test] +fn numeric_generic_in_trait_impl_with_extra_impl_generics() { + let src = r#" + trait Default { + fn default() -> Self; + } + + struct MyType { + a: Field, + b: Field, + c: Field, + d: T, + } + + // Make sure that `T` is placed before `N` as we want to test that the order of the generics is correctly maintained. + // `N` is used first in the trait impl generics (`Deserialize for MyType`). + // We want to make sure that the compiler correctly accounts for that `N` has a numeric kind + // while `T` has a normal kind. + impl Deserialize for MyType where T: Default { + fn deserialize(fields: [Field; N]) -> Self { + MyType { a: fields[0], b: fields[1], c: fields[2], d: T::default() } + } + } + + trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; + } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn numeric_generic_used_in_where_clause() { + let src = r#" + trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; + } + + fn read() -> T where T: Deserialize { + let mut fields: [Field; N] = [0; N]; + for i in 0..N { + fields[i] = i as Field + 1; + } + T::deserialize(fields) + } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn numeric_generic_used_in_turbofish() { + let src = r#" + fn double() -> u32 { + // Used as an expression + N * 2 + } + + fn double_numeric_generics_test() { + // Example usage of a numeric generic arguments. + assert(double::<9>() == 18); + assert(double::<7 + 8>() == 30); + } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn constant_used_with_numeric_generic() { + let src = r#" + struct ValueNote { + value: Field, + } + + trait Serialize { + fn serialize(self) -> [Field; N]; + } + + impl Serialize<1> for ValueNote { + fn serialize(self) -> [Field; 1] { + [self.value] + } + } + "#; + let errors = get_program_errors(src); + assert!(errors.is_empty()); +} + +#[test] +fn normal_generic_used_when_numeric_expected_in_where_clause() { + let src = r#" + trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; + } + + fn read() -> T where T: Deserialize { + T::deserialize([0, 1]) + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::TypeError(TypeCheckError::TypeMismatch { .. }), + )); + + let src = r#" + trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; + } + + fn read() -> T where T: Deserialize { + let mut fields: [Field; N] = [0; N]; + for i in 0..N { + fields[i] = i as Field + 1; + } + T::deserialize(fields) + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + assert!(matches!( + errors[0].0, + CompilationError::ResolverError(ResolverError::VariableNotDeclared { .. }), + )); +} + +// TODO(https://github.com/noir-lang/noir/issues/5156): Remove this test once we ban implicit numeric generics +#[test] +fn implicit_numeric_generics_elaborator() { + let src = r#" + struct BoundedVec { + storage: [T; MaxLen], + len: u64, + } + + impl BoundedVec { + + // Test that we have an implicit numeric generic for "Len" as well as "MaxLen" + pub fn extend_from_bounded_vec(&mut self, _vec: BoundedVec) { + // We do this to avoid an unused variable warning on `self` + let _ = self.len; + for _ in 0..Len { } + } + + pub fn push(&mut self, elem: T) { + assert(self.len < MaxLen, "push out of bounds"); + self.storage[self.len] = elem; + self.len += 1; + } + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 4); + + for error in errors.iter() { + if let CompilationError::ResolverError(ResolverError::UseExplicitNumericGeneric { ident }) = + &errors[0].0 + { + assert!(matches!(ident.0.contents.as_str(), "MaxLen" | "Len")); + } else { + panic!("Expected ResolverError::UseExplicitNumericGeneric but got {:?}", error); + } + } +} + +#[test] +fn quote_code_fragments() { + // This test ensures we can quote (and unquote/splice) code fragments + // which by themselves are not valid code. They only need to be valid + // by the time they are unquoted into the macro's call site. + let src = r#" + fn main() { + comptime { + concat!(quote { assert( }, quote { false); }); + } + } + + comptime fn concat(a: Quoted, b: Quoted) -> Quoted { + quote { $a $b } + } + "#; + let errors = get_program_errors(src); + assert_eq!(errors.len(), 1); + + use InterpreterError::FailingConstraint; + assert!(matches!(&errors[0].0, CompilationError::InterpreterError(FailingConstraint { .. }))); +} diff --git a/noir/noir-repo/compiler/wasm/Cargo.toml b/noir/noir-repo/compiler/wasm/Cargo.toml index 03e59b3e269f..20272dfeecb7 100644 --- a/noir/noir-repo/compiler/wasm/Cargo.toml +++ b/noir/noir-repo/compiler/wasm/Cargo.toml @@ -20,6 +20,7 @@ noirc_driver.workspace = true noirc_frontend = { workspace = true, features = ["bn254"] } noirc_errors.workspace = true noirc_evaluator.workspace = true +noirc_artifacts.workspace = true wasm-bindgen.workspace = true serde.workspace = true js-sys.workspace = true diff --git a/noir/noir-repo/compiler/wasm/package.json b/noir/noir-repo/compiler/wasm/package.json index 0bb9b803ee06..49956d798822 100644 --- a/noir/noir-repo/compiler/wasm/package.json +++ b/noir/noir-repo/compiler/wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.30.0", + "version": "0.31.0", "license": "(MIT OR Apache-2.0)", "main": "dist/main.js", "types": "./dist/types/src/index.d.cts", diff --git a/noir/noir-repo/compiler/wasm/src/compile.rs b/noir/noir-repo/compiler/wasm/src/compile.rs index f1495e0b4383..59b0e00e49f7 100644 --- a/noir/noir-repo/compiler/wasm/src/compile.rs +++ b/noir/noir-repo/compiler/wasm/src/compile.rs @@ -2,10 +2,8 @@ use acvm::acir::circuit::ExpressionWidth; use fm::FileManager; use gloo_utils::format::JsValueSerdeExt; use js_sys::{JsString, Object}; -use nargo::{ - artifacts::{contract::ContractArtifact, program::ProgramArtifact}, - parse_all, -}; +use nargo::parse_all; +use noirc_artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_driver::{ add_dep, file_manager_with_stdlib, prepare_crate, prepare_dependency, CompileOptions, }; diff --git a/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-a/src/lib.nr b/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-a/src/lib.nr index 3f8fa051daf6..c38188d01195 100644 --- a/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-a/src/lib.nr +++ b/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-a/src/lib.nr @@ -1,4 +1,4 @@ -use dep::lib_b::assert_non_zero; +use lib_b::assert_non_zero; pub fn divide(a: u64, b: u64) -> u64 { assert_non_zero(b); diff --git a/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr b/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr index 0376cd4cb871..23b6659b3c56 100644 --- a/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr +++ b/noir/noir-repo/compiler/wasm/test/fixtures/deps/lib-c/src/module/foo.nr @@ -1,3 +1,3 @@ pub fn bar(param: Field) -> Field { - dep::std::hash::pedersen_hash([param]) + std::hash::pedersen_hash([param]) } diff --git a/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr b/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr index fc1dc8a5a17f..6f63850e3a06 100644 --- a/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr +++ b/noir/noir-repo/compiler/wasm/test/fixtures/noir-contract/src/main.nr @@ -1,5 +1,5 @@ contract TestContract { - use dep::test::module::foo; + use test::module::foo; fn constructor(param: Field, pub_param: pub Field) -> pub [Field; 2] { [foo::bar(param), param + pub_param] diff --git a/noir/noir-repo/compiler/wasm/test/fixtures/with-deps/src/main.nr b/noir/noir-repo/compiler/wasm/test/fixtures/with-deps/src/main.nr index 056bcc180b4b..fe9e7f9ca771 100644 --- a/noir/noir-repo/compiler/wasm/test/fixtures/with-deps/src/main.nr +++ b/noir/noir-repo/compiler/wasm/test/fixtures/with-deps/src/main.nr @@ -1,4 +1,4 @@ -use dep::lib_a::divide; +use lib_a::divide; fn main(x: u64, y: pub u64) { divide(x, y); } diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 9eb6e6f92390..2fb20ae2ba49 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -166,6 +166,7 @@ "rfind", "rustc", "rustup", + "sboxed", "schnorr", "sdiv", "secp256k1", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index db7e53cad245..2d6d3e658b5e 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -73,7 +73,7 @@ exceptions = [ { allow = ["CC0-1.0"], name = "tiny-keccak" }, { allow = ["MPL-2.0"], name = "sized-chunks" }, { allow = ["MPL-2.0"], name = "webpki-roots" }, - + { allow = ["CDDL-1.0"], name = "inferno" }, ] [[licenses.clarify]] diff --git a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md index 64d984c8cf99..df41276cfe11 100644 --- a/noir/noir-repo/docs/docs/how_to/how-to-oracles.md +++ b/noir/noir-repo/docs/docs/how_to/how-to-oracles.md @@ -141,10 +141,10 @@ server.addMethod("resolve_function_call", async (params) => { if params.function !== "getSqrt" { throw Error("Unexpected foreign call") }; - const values = params.inputs[0].map((field) => { + const values = params.inputs[0].Array.map((field) => { return `${Math.sqrt(parseInt(field, 16))}`; }); - return { values }; + return { values: [{ Array: values }] }; }); ``` @@ -166,6 +166,10 @@ interface ForeignCallResult { } ``` +::: Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + ::: ## Step 3 - Usage with Nargo 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 16c425bed766..0a128adb2de6 100644 --- a/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx +++ b/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx @@ -12,7 +12,6 @@ Let's walk through an example of a merkle membership proof in Noir that proves t in a merkle tree. ```rust -use dep::std; fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { let leaf = std::hash::hash_to_field(message.as_slice()); diff --git a/noir/noir-repo/docs/docs/noir/concepts/assert.md b/noir/noir-repo/docs/docs/noir/concepts/assert.md index bcff613a6952..2132de42072d 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/assert.md +++ b/noir/noir-repo/docs/docs/noir/concepts/assert.md @@ -1,9 +1,9 @@ --- title: Assert Function description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. + Learn about the `assert` and `static_assert` functions in Noir, which can be used to explicitly + constrain the predicate or comparison expression that follows to be true, and what happens if + the expression is false at runtime or compile-time, respectively. keywords: [Noir programming language, assert statement, predicate expression, comparison expression] sidebar_position: 4 --- @@ -43,3 +43,36 @@ let s = myStruct { myField: y }; assert(s.myField == x, s); ``` +There is also a special `static_assert` function that behaves like `assert`, +but that runs at compile-time. + +```rust +fn main(xs: [Field; 3]) { + let x = 2 + 2; + let y = 4; + static_assert(x == y, "expected 2 + 2 to equal 4"); + + // This passes since the length of `xs` is known at compile-time + static_assert(xs.len() == 3, "expected the input to have 3 elements"); +} +``` + +This function fails when passed a dynamic (run-time) argument: + +```rust +fn main(x : Field, y : Field) { + // this fails because `x` is not known at compile-time + static_assert(x == 2, "expected x to be known at compile-time and equal to 2"); + + let mut example_slice = &[]; + if y == 4 { + example_slice = example_slice.push_back(0); + } + + // This fails because the length of `example_slice` is not known at + // compile-time + let error_message = "expected an empty slice, known at compile-time"; + static_assert(example_slice.len() == 0, error_message); +} +``` + diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md index efce3e95d322..9a4ab5d3c1f2 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` @@ -197,7 +199,7 @@ fn main() { ### reduce -Same as fold, but uses the first element as starting element. +Same as fold, but uses the first element as the starting element. ```rust fn reduce(self, f: fn(T, T) -> T) -> T diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md index 3dcfa836814a..2507af710e71 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/booleans.md @@ -24,5 +24,5 @@ fn main() { ``` The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/index.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/index.md index 357813c147ab..3eadb2dc8a46 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/index.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/index.md @@ -105,6 +105,14 @@ type Bad2 = Bad1; // ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 ``` +## Wildcard Type +Noir can usually infer the type of the variable from the context, so specifying the type of a variable is only required when it cannot be inferred. However, specifying a complex type can be tedious, especially when it has multiple generic arguments. Often some of the generic types can be inferred from the context, and Noir only needs a hint to properly infer the other types. We can partially specify a variable's type by using `_` as a marker, indicating where we still want the compiler to infer the type. + +```rust +let a: [_; 4] = foo(b); +``` + + ### BigInt You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/integers.md index c14fffa71743..a1d59bf31662 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/integers.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/integers.md @@ -149,7 +149,6 @@ fn wrapping_mul(x: T, y: T) -> T; Example of how it is used: ```rust -use dep::std; fn main(x: u8, y: u8) -> pub u8 { std::wrapping_add(x, y) diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx index 4eccc677b80b..d619117b7991 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/slices.mdx @@ -12,9 +12,7 @@ import Experimental from '@site/src/components/Notes/_experimental.mdx'; A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. ```rust -use dep::std::slice; - -fn main() -> pub Field { +fn main() -> pub u32 { let mut slice: [Field] = &[0; 2]; let mut new_slice = slice.push_back(6); @@ -193,3 +191,108 @@ fn main() { assert(array[1] == slice[1]); } ``` + +### map + +Applies a function to each element of the slice, returning a new slice containing the mapped elements. + +```rust +fn map(self, f: fn(T) -> U) -> [U] +``` + +example + +```rust +let a = &[1, 2, 3]; +let b = a.map(|a| a * 2); // b is now &[2, 4, 6] +``` + +### fold + +Applies a function to each element of the slice, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the slice, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = &[1]; +let a2 = &[1, 2]; +let a3 = &[1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let folded = slice.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as the starting element. + +```rust +fn reduce(self, f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let reduced = slice.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 2]; + let all = slice.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let slice = &[2, 2, 2, 2, 5]; + let any = slice.any(|a| a == 5); + assert(any); +} + +``` diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md index 311dfd644168..1fdee42425e5 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md @@ -17,10 +17,9 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust -use dep::std; fn main(message : pub str<11>, hex_as_string : str<4>) { println(message); diff --git a/noir/noir-repo/docs/docs/noir/concepts/generics.md b/noir/noir-repo/docs/docs/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/generics.md +++ b/noir/noir-repo/docs/docs/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/docs/noir/concepts/traits.md b/noir/noir-repo/docs/docs/noir/concepts/traits.md index ef1445a59076..51305b38c16f 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/traits.md +++ b/noir/noir-repo/docs/docs/noir/concepts/traits.md @@ -147,7 +147,7 @@ fn main() { ### Generic Trait Implementations With Where Clauses -Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +Where clauses can be placed on trait implementations themselves to restrict generics in a similar way. For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. For example, here is the implementation for array equality: @@ -169,6 +169,22 @@ impl Eq for [T; N] where T: Eq { } ``` +Where clauses can also be placed on struct implementations. +For example, here is a method utilizing a generic type that implements the equality trait. + +```rust +struct Foo { + a: u32, + b: T, +} + +impl Foo where T: Eq { + fn eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.eq(other.b) + } +} +``` + ## Generic Traits Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in @@ -372,13 +388,13 @@ impls for any trait we need on it. ```rust struct Wrapper { - foo: dep::some_library::Foo, + foo: some_library::Foo, } impl Default for Wrapper { fn default() -> Wrapper { Wrapper { - foo: dep::some_library::Foo::new(), + foo: some_library::Foo::new(), } } } diff --git a/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md b/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/docs/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md index 04c1703d929b..24e02de08fe8 100644 --- a/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/docs/noir/modules_packages_crates/dependencies.md @@ -70,26 +70,26 @@ You can import a dependency to a Noir file using the following syntax. For examp ecrecover-noir library and local lib_a referenced above: ```rust -use dep::ecrecover; -use dep::lib_a; +use ecrecover; +use lib_a; ``` You can also import only the specific parts of dependency that you want to use, like so: ```rust -use dep::std::hash::sha256; -use dep::std::scalar_mul::fixed_base_embedded_curve; +use std::hash::sha256; +use std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; +use std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. @@ -100,7 +100,7 @@ Note that when you import a dependency, you also get access to all of the depend For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: ```rust -use dep::phy_vector; +use phy_vector; fn main(x : Field, y : pub Field) { //... diff --git a/noir/noir-repo/docs/docs/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/docs/noir/modules_packages_crates/modules.md index ae822a1cff4e..9fffd925b7b0 100644 --- a/noir/noir-repo/docs/docs/noir/modules_packages_crates/modules.md +++ b/noir/noir-repo/docs/docs/noir/modules_packages_crates/modules.md @@ -49,6 +49,27 @@ crate ``` +The module filename may also be the name of the module as a directory with the contents in a +file named `mod.nr` within that directory. The above example can alternatively be expressed like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +fn from_foo() {} +``` + +Note that it's an error to have both files `src/foo.nr` and `src/foo/mod.nr` in the filesystem. + ### Importing a module throughout the tree All modules are accessible from the `crate::` namespace. @@ -103,3 +124,28 @@ crate └── bar └── from_bar ``` + +Similar to importing a module in the crate root, modules can be placed in a `mod.nr` file, like this: + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo/mod.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar/mod.nr` + +```rust +fn from_bar() {} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md index eeead5809699..d5694250f052 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md @@ -25,7 +25,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md index ccce62562f81..98b7d584033e 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/boundedvec.md @@ -59,7 +59,7 @@ but for now make sure to use type annotations when using bounded vectors. Otherw ### get ```rust -pub fn get(mut self: Self, index: u64) -> T { +pub fn get(self, index: u64) -> T { ``` Retrieves an element from the vector at the given index, starting from zero. @@ -80,7 +80,7 @@ fn foo(v: BoundedVec) { ### get_unchecked ```rust -pub fn get_unchecked(mut self: Self, index: u64) -> T { +pub fn get_unchecked(self, index: u64) -> T { ``` Retrieves an element from the vector at the given index, starting from zero, without @@ -93,6 +93,42 @@ Example: #include_code get_unchecked_example test_programs/noir_test_success/bounded_vec/src/main.nr rust +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to the vector at the given index, starting from zero, without performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk! + +Example: + +#include_code set_unchecked_example test_programs/noir_test_success/bounded_vec/src/main.nr rust + ### push @@ -210,6 +246,18 @@ Example: let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) ``` +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +#include_code bounded-vec-map-example noir_stdlib/src/collections/bounded_vec.nr rust + ### any ```rust diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md index 2b9f4895722b..651e7f5723bb 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/hashmap.md @@ -21,7 +21,7 @@ Example: ```rust // Create a mapping from Fields to u32s with a maximum length of 12 // using a poseidon2 hasher -use dep::std::hash::poseidon2::Poseidon2Hasher; +use std::hash::poseidon2::Poseidon2Hasher; let mut map: HashMap> = HashMap::default(); map.insert(1, 2); diff --git a/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx index fcfd7e07aa00..475011922f81 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/containers/vec.mdx @@ -84,6 +84,25 @@ let vector: Vec = Vec::from_slice(&[10, 20, 30]); assert(vector.get(1) == 20); ``` +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + ### push Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md index d2b42d67b7cb..f839b4a228ec 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -81,7 +81,7 @@ from the private key. This is a matter of using scalar multiplication. In the ca for example, this code would do: ```rust -use dep::std::ec::tecurve::affine::{Curve, Point}; +use std::ec::tecurve::affine::{Curve, Point}; fn bjj_pub_key(priv_key: Field) -> Point { diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx index 789d26ce426e..1ad42a5ac96b 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -18,7 +18,7 @@ fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify` function by passing a type implementing the Hasher trait with the turbofish operator. For instance, if you want to use Poseidon2 instead, you can do the following: ```rust -use dep::std::hash::poseidon2::Poseidon2Hasher; +use std::hash::poseidon2::Poseidon2Hasher; eddsa_verify::(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg); ``` diff --git a/noir/noir-repo/docs/docs/noir/standard_library/recursion.md b/noir/noir-repo/docs/docs/noir/standard_library/recursion.md index a93894043dce..8cfb37fc52df 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/recursion.md @@ -4,6 +4,8 @@ description: Learn about how to write recursive proofs in Noir. keywords: [recursion, recursive proofs, verification_key, verify_proof] --- +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) @@ -33,16 +35,11 @@ By incorporating this attribute directly in the circuit's definition, tooling li pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} ``` -:::info - -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. - -::: + ## Example usage ```rust -use dep::std; fn main( verification_key : [Field; 114], diff --git a/noir/noir-repo/docs/docs/tooling/debugger.md b/noir/noir-repo/docs/docs/tooling/debugger.md index 7c158d949d19..9b7565ba9ff2 100644 --- a/noir/noir-repo/docs/docs/tooling/debugger.md +++ b/noir/noir-repo/docs/docs/tooling/debugger.md @@ -12,7 +12,7 @@ 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: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/docs/tooling/testing.md b/noir/noir-repo/docs/docs/tooling/testing.md index d3e0c5224730..866677da5679 100644 --- a/noir/noir-repo/docs/docs/tooling/testing.md +++ b/noir/noir-repo/docs/docs/tooling/testing.md @@ -42,7 +42,7 @@ fn test_add() { } ``` -You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: +You can be more specific and make it fail with a specific reason by using `should_fail_with = ""`: ```rust fn main(african_swallow_avg_speed : Field) { @@ -58,5 +58,22 @@ fn test_king_arthur() { fn test_bridgekeeper() { main(32); } - ``` + +The string given to `should_fail_with` doesn't need to exactly match the failure reason, it just needs to be a substring of it: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "airspeed velocity")] +fn test_bridgekeeper() { + main(32); +} +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/docusaurus.config.ts b/noir/noir-repo/docs/docusaurus.config.ts index 29f612b01097..f0c986f1c28c 100644 --- a/noir/noir-repo/docs/docusaurus.config.ts +++ b/noir/noir-repo/docs/docusaurus.config.ts @@ -14,6 +14,7 @@ export default { favicon: 'img/favicon.ico', url: 'https://noir-lang.org', baseUrl: '/', + trailingSlash: true, onBrokenLinks: 'throw', onBrokenMarkdownLinks: 'throw', i18n: { diff --git a/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx b/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx index 9fe9b48fbff1..226017072c88 100644 --- a/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx +++ b/noir/noir-repo/docs/src/components/Notes/_blackbox.mdx @@ -1,5 +1,5 @@ :::info -This is a black box function. Read [this section](../black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](../../black_box_fns) to learn more about black box functions in Noir. -::: \ No newline at end of file +::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md index e7b1f33b3390..8616feee9176 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md index 2d5e6f4454fe..c88aabf0ac1e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands.md#nargo-codegen-verifier) command to create a verifier contract. ### Protocol Developers @@ -96,4 +96,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md index c42f34ec3ade..4360893e9a2a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.17.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md index a412de19d066..b4dedefe4c94 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/black_box_fns.md @@ -26,19 +26,19 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen](./cryptographic_primitives/hashes#pedersen) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen](./cryptographic_primitives/hashes.mdx#pedersen) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md index d28a54a16006..f928370b2e89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md index 380368db0368..e8d86020a201 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md index c42f34ec3ade..4360893e9a2a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.0/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md index d28a54a16006..f928370b2e89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md index 380368db0368..e8d86020a201 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md index c42f34ec3ade..4360893e9a2a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.1/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md index d28a54a16006..f928370b2e89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md index 380368db0368..e8d86020a201 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md index c42f34ec3ade..4360893e9a2a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.2/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md index 7a7fb876c35a..104220296617 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md index 380368db0368..e8d86020a201 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md index c42f34ec3ade..4360893e9a2a 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/03_strings.md @@ -16,7 +16,7 @@ keywords: The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.3/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md index d4daae605a2e..34f8cd96fcd8 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/01_hello_world.md @@ -74,7 +74,7 @@ x : Field, y : pub Field Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the keyword `pub` (e.g. `y`). To learn more about private and public values, check the -[Data Types](../language_concepts/data_types) section. +[Data Types](../language_concepts/data_types.md) section. The next line of the program specifies its body: @@ -84,7 +84,7 @@ assert(x != y); The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. -For more Noir syntax, check the [Language Concepts](../language_concepts/comments) chapter. +For more Noir syntax, check the [Language Concepts](../language_concepts/comments.md) chapter. ## Build In/Output Files diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md index d28a54a16006..f928370b2e89 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/getting_started/02_breakdown.md @@ -51,7 +51,7 @@ license = "MIT" ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} ``` -Nargo.toml for a [workspace](../modules_packages_crates/workspaces) will look a bit different. For example: +Nargo.toml for a [workspace](../modules_packages_crates/workspaces.md) will look a bit different. For example: ```toml [workspace] @@ -74,7 +74,7 @@ The package section requires a number of fields including: #### Dependencies section -This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies) for more info. +This is where you will specify any dependencies for your project. See the [Dependencies page](../modules_packages_crates/dependencies.md)for more info. `./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or verifier contract respectively. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md index 380368db0368..e8d86020a201 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/index.md @@ -34,7 +34,7 @@ Noir can be used for a variety of purposes. ### Solidity Developers Noir currently includes a command to create a Solidity contract which verifies your Noir program. This will -be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier) command to create +be modularized in the future; however, as of the alpha, you can use the [`nargo codegen-verifier`](./nargo/commands#nargo-codegen-verifier.md) command to create a verifier contract. ### Protocol Developers @@ -97,4 +97,4 @@ Some libraries that are available today include: - [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir - [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers -See the section on [dependencies](./modules_packages_crates/dependencies) for more information. +See the section on [dependencies](./modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md index 885db167d837..d353606210a5 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/02_booleans.md @@ -26,5 +26,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md index b4c75942bb80..baa3f2050940 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/03_strings.md @@ -15,7 +15,7 @@ keywords: The string type is a fixed length value defined with `str`. -You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging). +You can use strings in `assert()` functions or print them with `std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md index bdbd1798bef7..1424ca2df14e 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/language_concepts/data_types/04_arrays.md @@ -56,7 +56,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md index e91e73a4c4fd..87a09293ea87 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/dependencies.md @@ -81,14 +81,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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/nargo/01_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md index 65e2bdb44e3b..e2b0af522f43 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/nargo/01_commands.md @@ -213,7 +213,7 @@ you run `nargo test`. To print `println` statements in tests, use the `--show-ou Takes an optional `--exact` flag which allows you to select tests based on an exact name. -See an example on the [testing page](./testing). +See an example on the [testing page](./testing.md). ### Options diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md index ff4c63acaa7d..5e592a2fd895 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d0..d9d21ef0485d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md index e0c6d475c1fe..985bb7c879dc 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/black_box_fns.md @@ -26,20 +26,20 @@ fn sha256(_input : [u8; N]) -> [u8; 32] {} Here is a list of the current black box functions that are supported by UltraPlonk: - AES -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [HashToField128Security](./cryptographic_primitives/hashes#hash_to_field) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) -- [Compute merkle root](./merkle_trees#compute_merkle_root) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [HashToField128Security](./cryptographic_primitives/hashes.mdx#hash_to_field) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) +- [Compute merkle root](./merkle_trees.md#compute_merkle_root) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. To ensure compatibility across backends, the ACVM has fallback implementations of `AND`, `XOR` and `RANGE` defined in its standard library which it can seamlessly fallback to if the backend doesn't support them. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md index 67962082a8f1..4a004fd3664b 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md index 075d39dadd4a..4c80d50ed015 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md index 8d76d4ca654c..dd6c844f6ae9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/syntax/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`std::println()`. See more about [Logging](../../standard_library/logging). +`std::println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md index 7f275a2d771f..d95346454a92 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d0..d9d21ef0485d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.23.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md index eae8744abf00..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/black_box_fns.md @@ -12,19 +12,19 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte Here is a list of the current black box functions: -- [SHA256](./cryptographic_primitives/hashes#sha256) -- [Schnorr signature verification](./cryptographic_primitives/schnorr) -- [Blake2s](./cryptographic_primitives/hashes#blake2s) -- [Blake3](./cryptographic_primitives/hashes#blake3) -- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash) -- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment) -- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification) -- [Fixed base scalar multiplication](./cryptographic_primitives/scalar) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx) - AND - XOR - RANGE -- [Keccak256](./cryptographic_primitives/hashes#keccak256) -- [Recursive proof verification](./recursion) +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md index f252150c8b54..4390bda4a26f 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/standard_library/recursion.md @@ -15,7 +15,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md index a8bd338e736d..ca54d82b26b2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md index a37dc401b7d0..d9d21ef0485d 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.24.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md index 9337499dac89..ed2ed01fceba 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md index a8bd338e736d..ca54d82b26b2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = []; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.25.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md index 9337499dac89..ed2ed01fceba 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ fn verify_proof(_verification_key : [Field], _proof : [Field], _public_input : F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md index efce3e95d322..95d749053e21 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.26.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md index a93894043dce..f33c285cf4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md index efce3e95d322..95d749053e21 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.27.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md index a93894043dce..f33c285cf4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md index efce3e95d322..95d749053e21 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.28.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md index a93894043dce..f33c285cf4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md index 7c158d949d19..9b7565ba9ff2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tooling/debugger.md @@ -12,7 +12,7 @@ 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: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md index 6446e0b2a76f..3dd9fe7d2b02 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.28.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md index efce3e95d322..95d749053e21 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.29.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md index be8c65679c31..e8b62f21d4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/black_box_fns.md @@ -24,7 +24,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md index a93894043dce..f33c285cf4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md index 7c158d949d19..9b7565ba9ff2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tooling/debugger.md @@ -12,7 +12,7 @@ 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: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md index 6446e0b2a76f..3dd9fe7d2b02 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.29.0/tutorials/noirjs_app.md @@ -24,7 +24,7 @@ Before we start, we want to make sure we have Node and Nargo installed. We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). -As for `Nargo`, we can follow the the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: ```sh curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md index efce3e95d322..95d749053e21 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/arrays.md @@ -57,7 +57,7 @@ You can instantiate a new array of a fixed size with the same value repeated for let array: [Field; 32] = [0; 32]; ``` -Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices), you can just call `as_slice` on your array: +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: ```rust let array: [Field; 32] = [0; 32]; @@ -70,7 +70,9 @@ You can define multidimensional arrays: let array : [[Field; 2]; 2]; let element = array[0][0]; ``` + However, multidimensional slices are not supported. For example, the following code will error at compile time: + ```rust let slice : [[Field]] = &[]; ``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md index 69826fcd724f..7211716f63e9 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/booleans.md @@ -27,5 +27,5 @@ fn main() { > `false` in _Verifier.toml_. The boolean type is most commonly used in conditionals like `if` expressions and `assert` -statements. More about conditionals is covered in the [Control Flow](../control_flow) and -[Assert Function](../assert) sections. +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md index 311dfd644168..8ab5825a4c42 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/data_types/strings.md @@ -17,7 +17,7 @@ sidebar_position: 3 The string type is a fixed length value defined with `str`. You can use strings in `assert()` functions or print them with -`println()`. See more about [Logging](../../standard_library/logging). +`println()`. See more about [Logging](../../standard_library/logging.md). ```rust use dep::std; diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md index ddd42bf1f9b7..0c1c27a22211 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/generics.md @@ -73,7 +73,7 @@ impl BigInt { Since a generic type `T` can represent any type, how can we call functions on the underlying type? In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" -This is what [traits](../concepts/traits) are for in Noir. Here's an example of a function generic over +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over any type `T` that implements the `Eq` trait for equality: ```rust @@ -103,4 +103,4 @@ impl Eq for MyStruct { } ``` -You can find more details on traits and trait implementations on the [traits page](../concepts/traits). +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md index b8e71fe65f08..96f824c5e425 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/concepts/unconstrained.md @@ -96,4 +96,4 @@ Generally we want to use brillig whenever there's something that's easy to verif ## Break and Continue -In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow/#break-and-continue) +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md index 04c1703d929b..2c028d858534 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/modules_packages_crates/dependencies.md @@ -82,14 +82,14 @@ use dep::std::scalar_mul::fixed_base_embedded_curve; ``` Lastly, as demonstrated in the -[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives#examples), you +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you can import multiple items in the same line by enclosing them in curly braces: ```rust use dep::std::ec::tecurve::affine::{Curve, Point}; ``` -We don't have a way to consume libraries from inside a [workspace](./workspaces) as external dependencies right now. +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. 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.30.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md index eeead5809699..d5694250f052 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/black_box_fns.md @@ -25,7 +25,7 @@ Here is a list of the current black box functions: - XOR - RANGE - [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) -- [Recursive proof verification](./recursion) +- [Recursive proof verification](./recursion.md) Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md index a93894043dce..f33c285cf4ec 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/noir/standard_library/recursion.md @@ -35,7 +35,7 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [F :::info -This is a black box function. Read [this section](./black_box_fns) to learn more about black box functions in Noir. +This is a black box function. Read [this section](./black_box_fns.md) to learn more about black box functions in Noir. ::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md index 7c158d949d19..9b7565ba9ff2 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.30.0/tooling/debugger.md @@ -12,7 +12,7 @@ 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: +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation/index.md) and vscode-noir: - Noir & Nargo ≥0.28.0 - Noir's VS Code extension ≥0.0.11 diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md new file mode 100644 index 000000000000..b84ca5dd9861 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-oracle.md @@ -0,0 +1,57 @@ +--- +title: Oracles +description: This guide provides an in-depth understanding of how Oracles work in Noir programming. Learn how to use outside calculations in your programs, constrain oracles, and understand their uses and limitations. +keywords: + - Noir Programming + - Oracles + - JSON-RPC + - Foreign Call Handlers + - Constrained Functions + - Blockchain Programming +sidebar_position: 1 +--- + +If you've seen "The Matrix" you may recall "The Oracle" as Gloria Foster smoking cigarettes and baking cookies. While she appears to "know things", she is actually providing a calculation of a pre-determined future. Noir Oracles are similar, in a way. They don't calculate the future (yet), but they allow you to use outside calculations in your programs. + +![matrix oracle prediction](@site/static/img/memes/matrix_oracle.jpeg) + +A Noir program is usually self-contained. You can pass certain inputs to it, and it will generate a deterministic output for those inputs. But what if you wanted to defer some calculation to an outside process or source? + +Oracles are functions that provide this feature. + +## Use cases + +An example usage for Oracles is proving something on-chain. For example, proving that the ETH-USDC quote was below a certain target at a certain block time. Or even making more complex proofs like proving the ownership of an NFT as an anonymous login method. + +Another interesting use case is to defer expensive calculations to be made outside of the Noir program, and then constraining the result; similar to the use of [unconstrained functions](../noir/concepts//unconstrained.md). + +In short, anything that can be constrained in a Noir program but needs to be fetched from an external source is a great candidate to be used in oracles. + +## Constraining oracles + +Just like in The Matrix, Oracles are powerful. But with great power, comes great responsibility. Just because you're using them in a Noir program doesn't mean they're true. Noir has no superpowers. If you want to prove that Portugal won the Euro Cup 2016, you're still relying on potentially untrusted information. + +To give a concrete example, Alice wants to login to the [NounsDAO](https://nouns.wtf/) forum with her username "noir_nouner" by proving she owns a noun without revealing her ethereum address. Her Noir program could have a oracle call like this: + +```rust +#[oracle(getNoun)] +unconstrained fn get_noun(address: Field) -> Field +``` + +This oracle could naively resolve with the number of Nouns she possesses. However, it is useless as a trusted source, as the oracle could resolve to anything Alice wants. In order to make this oracle call actually useful, Alice would need to constrain the response from the oracle, by proving her address and the noun count belongs to the state tree of the contract. + +In short, **Oracles don't prove anything. Your Noir program does.** + +:::danger + +If you don't constrain the return of your oracle, you could be clearly opening an attack vector on your Noir program. Make double-triple sure that the return of an oracle call is constrained! + +::: + +## How to use Oracles + +On CLI, Nargo resolves oracles by making JSON RPC calls, which means it would require an RPC node to be running. + +In JavaScript, NoirJS accepts and resolves arbitrary call handlers (that is, not limited to JSON) as long as they matches the expected types the developer defines. Refer to [Foreign Call Handler](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) to learn more about NoirJS's call handling. + +If you want to build using oracles, follow through to the [oracle guide](../how_to/how-to-oracles.md) for a simple example on how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md new file mode 100644 index 000000000000..18846176ca74 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/explainers/explainer-recursion.md @@ -0,0 +1,176 @@ +--- +title: Recursive proofs +description: Explore the concept of recursive proofs in Zero-Knowledge programming. Understand how recursion works in Noir, a language for writing smart contracts on the EVM blockchain. Learn through practical examples like Alice and Bob's guessing game, Charlie's recursive merkle tree, and Daniel's reusable components. Discover how to use recursive proofs to optimize computational resources and improve efficiency. + +keywords: + [ + "Recursive Proofs", + "Zero-Knowledge Programming", + "Noir", + "EVM Blockchain", + "Smart Contracts", + "Recursion in Noir", + "Alice and Bob Guessing Game", + "Recursive Merkle Tree", + "Reusable Components", + "Optimizing Computational Resources", + "Improving Efficiency", + "Verification Key", + "Aggregation", + "Recursive zkSNARK schemes", + "PLONK", + "Proving and Verification Keys" + ] +sidebar_position: 1 +pagination_next: how_to/how-to-recursion +--- + +In programming, we tend to think of recursion as something calling itself. A classic example would be the calculation of the factorial of a number: + +```js +function factorial(n) { + if (n === 0 || n === 1) { + return 1; + } else { + return n * factorial(n - 1); + } +} +``` + +In this case, while `n` is not `1`, this function will keep calling itself until it hits the base case, bubbling up the result on the call stack: + +```md + Is `n` 1? <--------- + /\ / + / \ n = n -1 + / \ / + Yes No -------- +``` + +In Zero-Knowledge, recursion has some similarities. + +It is not a Noir function calling itself, but a proof being used as an input to another circuit. In short, you verify one proof *inside* another proof, returning the proof that both proofs are valid. + +This means that, given enough computational resources, you can prove the correctness of any arbitrary number of proofs in a single proof. This could be useful to design state channels (for which a common example would be [Bitcoin's Lightning Network](https://en.wikipedia.org/wiki/Lightning_Network)), to save on gas costs by settling one proof on-chain, or simply to make business logic less dependent on a consensus mechanism. + +## Examples + +Let us look at some of these examples + +### Alice and Bob - Guessing game + +Alice and Bob are friends, and they like guessing games. They want to play a guessing game online, but for that, they need a trusted third-party that knows both of their secrets and finishes the game once someone wins. + +So, they use zero-knowledge proofs. Alice tries to guess Bob's number, and Bob will generate a ZK proof stating whether she succeeded or failed. + +This ZK proof can go on a smart contract, revealing the winner and even giving prizes. However, this means every turn needs to be verified on-chain. This incurs some cost and waiting time that may simply make the game too expensive or time-consuming to be worth it. + +As a solution, Alice proposes the following: "what if Bob generates his proof, and instead of sending it on-chain, I verify it *within* my own proof before playing my own turn?". + +She can then generate a proof that she verified his proof, and so on. + +```md + Did you fail? <-------------------------- + / \ / + / \ n = n -1 + / \ / + Yes No / + | | / + | | / + | You win / + | / + | / +Generate proof of that / + + / + my own guess ---------------- +``` + +### Charlie - Recursive merkle tree + +Charlie is a concerned citizen, and wants to be sure his vote in an election is accounted for. He votes with a ZK proof, but he has no way of knowing that his ZK proof was included in the total vote count! + +If the vote collector puts all of the votes into a [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree), everyone can prove the verification of two proofs within one proof, as such: + +```md + abcd + __________|______________ + | | + ab cd + _____|_____ ______|______ + | | | | + alice bob charlie daniel +``` + +Doing this recursively allows us to arrive on a final proof `abcd` which if true, verifies the correctness of all the votes. + +### Daniel - Reusable components + +Daniel has a big circuit and a big headache. A part of his circuit is a setup phase that finishes with some assertions that need to be made. But that section alone takes most of the proving time, and is largely independent of the rest of the circuit. + +He might find it more efficient to generate a proof for that setup phase separately, and verify that proof recursively in the actual business logic section of his circuit. This will allow for parallelization of both proofs, which results in a considerable speedup. + +## What params do I need + +As you can see in the [recursion reference](noir/standard_library/recursion.md), a simple recursive proof requires: + +- The proof to verify +- The Verification Key of the circuit that generated the proof +- A hash of this verification key, as it's needed for some backends +- The public inputs for the proof + +:::info + +Recursive zkSNARK schemes do not necessarily "verify a proof" in the sense that you expect a true or false to be spit out by the verifier. Rather an aggregation object is built over the public inputs. + +So, taking the example of Alice and Bob and their guessing game: + +- Alice makes her guess. Her proof is *not* recursive: it doesn't verify any proof within it! It's just a standard `assert(x != y)` circuit +- Bob verifies Alice's proof and makes his own guess. In this circuit, he doesn't exactly *prove* the verification of Alice's proof. Instead, he *aggregates* his proof to Alice's proof. The actual verification is done when the full proof is verified, for example when using `nargo verify` or through the verifier smart contract. + +We can imagine recursive proofs a [relay race](https://en.wikipedia.org/wiki/Relay_race). The first runner doesn't have to receive the baton from anyone else, as he/she already starts with it. But when his/her turn is over, the next runner needs to receive it, run a bit more, and pass it along. Even though every runner could theoretically verify the baton mid-run (why not? 🏃🔍), only at the end of the race does the referee verify that the whole race is valid. + +::: + +## Some architecture + +As with everything in computer science, there's no one-size-fits all. But there are some patterns that could help understanding and implementing them. To give three examples: + +### Adding some logic to a proof verification + +This would be an approach for something like our guessing game, where proofs are sent back and forth and are verified by each opponent. This circuit would be divided in two sections: + +- A `recursive verification` section, which would be just the call to `std::verify_proof`, and that would be skipped on the first move (since there's no proof to verify) +- A `guessing` section, which is basically the logic part where the actual guessing happens + +In such a situation, and assuming Alice is first, she would skip the first part and try to guess Bob's number. Bob would then verify her proof on the first section of his run, and try to guess Alice's number on the second part, and so on. + +### Aggregating proofs + +In some one-way interaction situations, recursion would allow for aggregation of simple proofs that don't need to be immediately verified on-chain or elsewhere. + +To give a practical example, a barman wouldn't need to verify a "proof-of-age" on-chain every time he serves alcohol to a customer. Instead, the architecture would comprise two circuits: + +- A `main`, non-recursive circuit with some logic +- A `recursive` circuit meant to verify two proofs in one proof + +The customer's proofs would be intermediate, and made on their phones, and the barman could just verify them locally. He would then aggregate them into a final proof sent on-chain (or elsewhere) at the end of the day. + +### Recursively verifying different circuits + +Nothing prevents you from verifying different circuits in a recursive proof, for example: + +- A `circuit1` circuit +- A `circuit2` circuit +- A `recursive` circuit + +In this example, a regulator could verify that taxes were paid for a specific purchase by aggregating both a `payer` circuit (proving that a purchase was made and taxes were paid), and a `receipt` circuit (proving that the payment was received) + +## How fast is it + +At the time of writing, verifying recursive proofs is surprisingly fast. This is because most of the time is spent on generating the verification key that will be used to generate the next proof. So you are able to cache the verification key and reuse it later. + +Currently, Noir JS packages don't expose the functionality of loading proving and verification keys, but that feature exists in the underlying `bb.js` package. + +## How can I try it + +Learn more about using recursion in Nargo and NoirJS in the [how-to guide](../how_to/how-to-recursion.md) and see a full example in [noir-examples](https://github.com/noir-lang/noir-examples). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json new file mode 100644 index 000000000000..5d694210bbf3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/_category_.json new file mode 100644 index 000000000000..27a8e89228de --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 1, + "label": "Install Barretenberg", + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/index.md new file mode 100644 index 000000000000..0102c86770b7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/barretenberg/index.md @@ -0,0 +1,47 @@ +--- +title: Barretenberg Installation +description: bb is a command line tool for interacting with Aztec's proving backend Barretenberg. This page is a quick guide on how to install `bb` +keywords: [ + Barretenberg + bb + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches +] +pagination_next: getting_started/hello_noir/index +--- + +`bb` is the CLI tool for generating and verifying proofs for Noir programs using the Barretenberg proving library. It also allows generating solidity verifier contracts for which you can verify contracts which were constructed using `bb`. + +## Installing `bb` + +Open a terminal on your machine, and write: + +##### macOS (Apple Silicon) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.zshrc +bbup -v 0.41.0 +``` + +##### macOS (Intel) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.zshrc +bbup -v 0.41.0 +``` + +##### Linux (Bash) + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/master/barretenberg/cpp/installation/install | bash +source ~/.bashrc +bbup -v 0.41.0 +``` + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json new file mode 100644 index 000000000000..976a2325de05 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md new file mode 100644 index 000000000000..1ade3f09ae3d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/index.md @@ -0,0 +1,145 @@ +--- +title: Creating a Project +description: + Learn how to create and verify your first Noir program using Nargo, a programming language for + zero-knowledge proofs. +keywords: + [ + Nargo, + Noir, + zero-knowledge proofs, + programming language, + create Noir program, + verify Noir program, + step-by-step guide, + ] +sidebar_position: 1 + +--- + +Now that we have installed Nargo, it is time to make our first hello world program! + +## Create a Project Directory + +Noir code can live anywhere on your computer. Let us create a _projects_ folder in the home +directory to house our Noir programs. + +For Linux, macOS, and Windows PowerShell, create the directory and change directory into it by +running: + +```sh +mkdir ~/projects +cd ~/projects +``` + +## Create Our First Nargo Project + +Now that we are in the projects directory, create a new Nargo project by running: + +```sh +nargo new hello_world +``` + +> **Note:** `hello_world` can be any arbitrary project name, we are simply using `hello_world` for +> demonstration. +> +> In production, the common practice is to name the project folder as `circuits` for better +> identifiability when sitting alongside other folders in the codebase (e.g. `contracts`, `scripts`, +> `test`). + +A `hello_world` folder would be created. Similar to Rust, the folder houses _src/main.nr_ and +_Nargo.toml_ which contain the source code and environmental options of your Noir program +respectively. + +### Intro to Noir Syntax + +Let us take a closer look at _main.nr_. The default _main.nr_ generated should look like this: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +The first line of the program specifies the program's inputs: + +```rust +x : Field, y : pub Field +``` + +Program inputs in Noir are private by default (e.g. `x`), but can be labeled public using the +keyword `pub` (e.g. `y`). To learn more about private and public values, check the +[Data Types](../../noir/concepts/data_types/index.md) section. + +The next line of the program specifies its body: + +```rust +assert(x != y); +``` + +The Noir syntax `assert` can be interpreted as something similar to constraints in other zk-contract languages. + +For more Noir syntax, check the [Language Concepts](../../noir/concepts/comments.md) chapter. + +## Build In/Output Files + +Change directory into _hello_world_ and build in/output files for your Noir program by running: + +```sh +cd hello_world +nargo check +``` + +A _Prover.toml_ file will be generated in your project directory, to allow specifying input values to the program. + +## Execute Our Noir Program + +Now that the project is set up, we can execute our Noir program. + +Fill in input values for execution in the _Prover.toml_ file. For example: + +```toml +x = "1" +y = "2" +``` + +Execute your Noir program: + +```sh +nargo execute witness-name +``` + +The witness corresponding to this execution will then be written to the file `./target/witness-name.gz`. + +## Prove Our Noir Program + +:::info + +Nargo no longer handles communicating with backends in order to generate proofs. In order to prove/verify your Noir programs, you'll need an installation of [bb](../barretenberg/index.md). + +::: + +Prove the valid execution of your Noir program using `bb`: + +```sh +bb prove -b ./target/hello_world.json -w ./target/witness-name.gz -o ./proof +``` + +A new file called `proof` will be generated in your project directory, containing the generated proof for your program. + +## Verify Our Noir Program + +Once a proof is generated, we can verify correct execution of our Noir program by verifying the proof file. + +Verify your proof by running: + +```sh +bb write_vk -b ./target/hello_world.json -o ./target/vk +bb verify -k ./target/vk -p ./proof +``` + +The verification will complete in silence if it is successful. If it fails, it will log the corresponding error instead. + +Congratulations, you have now created and verified a proof for your very first Noir program! + +In the [next section](./project_breakdown.md), we will go into more detail on each step performed. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md new file mode 100644 index 000000000000..29688df148fe --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/hello_noir/project_breakdown.md @@ -0,0 +1,159 @@ +--- +title: Project Breakdown +description: + Learn about the anatomy of a Nargo project, including the purpose of the Prover TOML + file, and how to prove and verify your program. +keywords: + [Nargo, Nargo project, Prover.toml, proof verification, private asset transfer] +sidebar_position: 2 +--- + +This section breaks down our hello world program from the previous section. We elaborate on the project +structure and what the `prove` and `verify` commands did. + +## Anatomy of a Nargo Project + +Upon creating a new project with `nargo new` and building the in/output files with `nargo check` +commands, you would get a minimal Nargo project of the following structure: + + - src + - Prover.toml + - Nargo.toml + +The source directory _src_ holds the source code for your Noir program. By default only a _main.nr_ +file will be generated within it. + +### Prover.toml + +_Prover.toml_ is used for specifying the input values for executing and proving the program. You can specify `toml` files with different names by using the `--prover-name` or `-p` flags, see the [Prover](#provertoml) section below. Optionally you may specify expected output values for prove-time checking as well. + +### Nargo.toml + +_Nargo.toml_ contains the environmental options of your project. It contains a "package" section and a "dependencies" section. + +Example Nargo.toml: + +```toml +[package] +name = "noir_starter" +type = "bin" +authors = ["Alice"] +compiler_version = "0.9.0" +description = "Getting started with Noir" +entry = "circuit/main.nr" +license = "MIT" + +[dependencies] +ecrecover = {tag = "v0.9.0", git = "https://github.com/colinnielsen/ecrecover-noir.git"} +``` + +Nargo.toml for a [workspace](../../noir/modules_packages_crates/workspaces.md) will look a bit different. For example: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +#### Package section + +The package section defines a number of fields including: + +- `name` (**required**) - the name of the package +- `type` (**required**) - can be "bin", "lib", or "contract" to specify whether its a binary, library or Aztec contract +- `authors` (optional) - authors of the project +- `compiler_version` - specifies the version of the compiler to use. This is enforced by the compiler and follow's [Rust's versioning](https://doc.rust-lang.org/cargo/reference/manifest.html#the-version-field), so a `compiler_version = 0.18.0` will enforce Nargo version 0.18.0, `compiler_version = ^0.18.0` will enforce anything above 0.18.0 but below 0.19.0, etc. For more information, see how [Rust handles these operators](https://docs.rs/semver/latest/semver/enum.Op.html) +- `description` (optional) +- `entry` (optional) - a relative filepath to use as the entry point into your package (overrides the default of `src/lib.nr` or `src/main.nr`) +- `backend` (optional) +- `license` (optional) + +#### Dependencies section + +This is where you will specify any dependencies for your project. See the [Dependencies page](../../noir/modules_packages_crates/dependencies.md) for more info. + +`./proofs/` and `./contract/` directories will not be immediately visible until you create a proof or +verifier contract respectively. + +### main.nr + +The _main.nr_ file contains a `main` method, this method is the entry point into your Noir program. + +In our sample program, _main.nr_ looks like this: + +```rust +fn main(x : Field, y : Field) { + assert(x != y); +} +``` + +The parameters `x` and `y` can be seen as the API for the program and must be supplied by the prover. Since neither `x` nor `y` is marked as public, the verifier does not supply any inputs, when verifying the proof. + +The prover supplies the values for `x` and `y` in the _Prover.toml_ file. + +As for the program body, `assert` ensures that the condition to be satisfied (e.g. `x != y`) is constrained by the proof of the execution of said program (i.e. if the condition was not met, the verifier would reject the proof as an invalid proof). + +### Prover.toml + +The _Prover.toml_ file is a file which the prover uses to supply the inputs to the Noir program (both private and public). + +In our hello world program the _Prover.toml_ file looks like this: + +```toml +x = "1" +y = "2" +``` + +When the command `nargo execute` is executed, nargo will execute the Noir program using the inputs specified in `Prover.toml`, aborting if it finds that these do not satisfy the constraints defined by `main`. In this example, `x` and `y` must satisfy the inequality constraint `assert(x != y)`. + +If an output name is specified such as `nargo execute foo`, the witness generated by this execution will be written to `./target/foo.gz`. This can then be used to generate a proof of the execution. + +#### Arrays of Structs + +The following code shows how to pass an array of structs to a Noir program to generate a proof. + +```rust +// main.nr +struct Foo { + bar: Field, + baz: Field, +} + +fn main(foos: [Foo; 3]) -> pub Field { + foos[2].bar + foos[2].baz +} +``` + +Prover.toml: + +```toml +[[foos]] # foos[0] +bar = 0 +baz = 0 + +[[foos]] # foos[1] +bar = 0 +baz = 0 + +[[foos]] # foos[2] +bar = 1 +baz = 2 +``` + +#### Custom toml files + +You can specify a `toml` file with a different name to use for execution by using the `--prover-name` or `-p` flags. + +This command looks for proof inputs in the default **Prover.toml** and generates the witness and saves it at `./target/foo.gz`: + +```bash +nargo execute foo +``` + +This command looks for proof inputs in the custom **OtherProver.toml** and generates the witness and saves it at `./target/bar.gz`: + +```bash +nargo execute -p OtherProver bar +``` + +Now that you understand the concepts, you'll probably want some editor feedback while you are writing more complex code. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json new file mode 100644 index 000000000000..0c02fb5d4d79 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 0, + "label": "Install Nargo", + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md new file mode 100644 index 000000000000..4ef86aa59147 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/index.md @@ -0,0 +1,48 @@ +--- +title: Nargo Installation +description: + nargo is a command line tool for interacting with Noir programs. This page is a quick guide on how to install Nargo through the most common and easy method, noirup +keywords: [ + Nargo + Noir + Rust + Cargo + Noirup + Installation + Terminal Commands + Version Check + Nightlies + Specific Versions + Branches + Noirup Repository +] +pagination_next: getting_started/hello_noir/index +--- + +`nargo` is the one-stop-shop for almost everything related with Noir. The name comes from our love for Rust and its package manager `cargo`. + +With `nargo`, you can start new projects, compile, execute, prove, verify, test, generate solidity contracts, and do pretty much all that is available in Noir. + +Similarly to `rustup`, we also maintain an easy installation method that covers most machines: `noirup`. + +## Installing Noirup + +Open a terminal on your machine, and write: + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Close the terminal, open another one, and run + +```bash +noirup +``` + +Done. That's it. You should have the latest version working. You can check with `nargo --version`. + +You can also install nightlies, specific versions +or branches. Check out the [noirup repository](https://github.com/noir-lang/noirup) for more +information. + +Now we're ready to start working on [our first Noir program!](../hello_noir/index.md) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md new file mode 100644 index 000000000000..3634723562bf --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/installation/other_install_methods.md @@ -0,0 +1,102 @@ +--- +title: Alternative Installations +description: There are different ways to install Nargo, the one-stop shop and command-line tool for developing Noir programs. This guide explains how to specify which version to install when using noirup, and using WSL for windows. +keywords: [ + Installation + Nargo + Noirup + Binaries + Compiling from Source + WSL for Windows + macOS + Linux + Nix + Direnv + Uninstalling Nargo + ] +sidebar_position: 1 +--- + +## Encouraged Installation Method: Noirup + +Noirup is the endorsed method for installing Nargo, streamlining the process of fetching binaries or compiling from source. It supports a range of options to cater to your specific needs, from nightly builds and specific versions to compiling from various sources. + +### Installing Noirup + +First, ensure you have `noirup` installed: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +### Fetching Binaries + +With `noirup`, you can easily switch between different Nargo versions, including nightly builds: + +- **Nightly Version**: Install the latest nightly build. + + ```sh + noirup --version nightly + ``` + +- **Specific Version**: Install a specific version of Nargo. + ```sh + noirup --version + ``` + +### Compiling from Source + +`noirup` also enables compiling Nargo from various sources: + +- **From a Specific Branch**: Install from the latest commit on a branch. + + ```sh + noirup --branch + ``` + +- **From a Fork**: Install from the main branch of a fork. + + ```sh + noirup --repo + ``` + +- **From a Specific Branch in a Fork**: Install from a specific branch in a fork. + + ```sh + noirup --repo --branch + ``` + +- **From a Specific Pull Request**: Install from a specific PR. + + ```sh + noirup --pr + ``` + +- **From a Specific Commit**: Install from a specific commit. + + ```sh + noirup -C + ``` + +- **From Local Source**: Compile and install from a local directory. + ```sh + noirup --path ./path/to/local/source + ``` + +## Installation on Windows + +The default backend for Noir (Barretenberg) doesn't provide Windows binaries at this time. For that reason, Noir cannot be installed natively. However, it is available by using Windows Subsystem for Linux (WSL). + +Step 1: Follow the instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) to install and run WSL. + +step 2: Follow the [Noirup instructions](#encouraged-installation-method-noirup). + +## Uninstalling Nargo + +If you installed Nargo with `noirup`, you can uninstall Nargo by removing the files in `~/.nargo`, `~/nargo`, and `~/noir_cache`. This ensures that all installed binaries, configurations, and cache related to Nargo are fully removed from your system. + +```bash +rm -r ~/.nargo +rm -r ~/nargo +rm -r ~/noir_cache +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md new file mode 100644 index 000000000000..f7505bef7abe --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/getting_started/tooling/noir_codegen.md @@ -0,0 +1,114 @@ +--- +title: Noir Codegen for TypeScript +description: Learn how to use Noir codegen to generate TypeScript bindings +keywords: [Nargo, Noir, compile, TypeScript] +sidebar_position: 3 +--- + +When using TypeScript, it is extra work to interpret Noir program outputs in a type-safe way. Third party libraries may exist for popular Noir programs, but they are either hard to find or unmaintained. + +Now you can generate TypeScript bindings for your Noir programs in two steps: +1. Exporting Noir functions using `nargo export` +2. Using the TypeScript module `noir_codegen` to generate TypeScript binding + +**Note:** you can only export functions from a Noir *library* (not binary or contract program types). + +## Installation + +### Your TypeScript project + +If you don't already have a TypeScript project you can add the module with `yarn` (or `npm`), then initialize it: + +```bash +yarn add typescript -D +npx tsc --init +``` + +### Add TypeScript module - `noir_codegen` + +The following command will add the module to your project's devDependencies: + +```bash +yarn add @noir-lang/noir_codegen -D +``` + +### Nargo library +Make sure you have Nargo, v0.25.0 or greater, installed. If you don't, follow the [installation guide](../installation/index.md). + +If you're in a new project, make a `circuits` folder and create a new Noir library: + +```bash +mkdir circuits && cd circuits +nargo new --lib myNoirLib +``` + +## Usage + +### Export ABI of specified functions + +First go to the `.nr` files in your Noir library, and add the `#[export]` macro to each function that you want to use in TypeScript. + +```rust +#[export] +fn your_function(... +``` + +From your Noir library (where `Nargo.toml` is), run the following command: + +```bash +nargo export +``` + +You will now have an `export` directory with a .json file per exported function. + +You can also specify the directory of Noir programs using `--program-dir`, for example: + +```bash +nargo export --program-dir=./circuits/myNoirLib +``` + +### Generate TypeScript bindings from exported functions + +To use the `noir-codegen` package we added to the TypeScript project: + +```bash +yarn noir-codegen ./export/your_function.json +``` + +This creates an `exports` directory with an `index.ts` file containing all exported functions. + +**Note:** adding `--out-dir` allows you to specify an output dir for your TypeScript bindings to go. Eg: + +```bash +yarn noir-codegen ./export/*.json --out-dir ./path/to/output/dir +``` + +## Example .nr function to .ts output + +Consider a Noir library with this function: + +```rust +#[export] +fn not_equal(x: Field, y: Field) -> bool { + x != y +} +``` + +After the export and codegen steps, you should have an `index.ts` like: + +```typescript +export type Field = string; + + +export const is_equal_circuit: CompiledCircuit = +{"abi":{"parameters":[{"name":"x","type":{"kind":"field"},"visibility":"private"},{"name":"y","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"private"}},"bytecode":"H4sIAAAAAAAA/7WUMQ7DIAxFQ0Krrr2JjSGYLVcpKrn/CaqqDQN12WK+hPBgmWd/wEyHbF1SS923uhOs3pfoChI+wKXMAXzIKyNj4PB0TFTYc0w5RUjoqeAeEu1wqK0F54RGkWvW44LPzExnlkbMEs4JNZmN8PxS42uHv82T8a3Jeyn2Ks+VLPcO558HmyLMCDOXAXXtpPt4R/Rt9T36ss6dS9HGPx/eG17nGegKBQAA"}; + +export async function is_equal(x: Field, y: Field, foreignCallHandler?: ForeignCallHandler): Promise { + const program = new Noir(is_equal_circuit); + const args: InputMap = { x, y }; + const { returnValue } = await program.execute(args, foreignCallHandler); + return returnValue as boolean; +} +``` + +Now the `is_equal()` function and relevant types are readily available for use in TypeScript. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json new file mode 100644 index 000000000000..23b560f610b8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json new file mode 100644 index 000000000000..cc2cbb1c2533 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 000000000000..09e5bae68ad7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/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/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 000000000000..a5858c1a5eb5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/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/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md new file mode 100644 index 000000000000..2d2ed5c94b95 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-oracles.md @@ -0,0 +1,273 @@ +--- +title: How to use Oracles +description: Learn how to use oracles in your Noir program with examples in both Nargo and NoirJS. This guide also covers writing a JSON RPC server and providing custom foreign call handlers for NoirJS. +keywords: + - Noir Programming + - Oracles + - Nargo + - NoirJS + - JSON RPC Server + - Foreign Call Handlers +sidebar_position: 1 +--- + +This guide shows you how to use oracles in your Noir program. For the sake of clarity, it assumes that: + +- You have read the [explainer on Oracles](../explainers/explainer-oracle.md) and are comfortable with the concept. +- You have a Noir program to add oracles to. You can create one using the [vite-hardhat starter](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) as a boilerplate. +- You understand the concept of a JSON-RPC server. Visit the [JSON-RPC website](https://www.jsonrpc.org/) if you need a refresher. +- You are comfortable with server-side JavaScript (e.g. Node.js, managing packages, etc.). + +For reference, you can find the snippets used in this tutorial on the [Aztec DevRel Repository](https://github.com/AztecProtocol/dev-rel/tree/main/code-snippets/how-to-oracles). + +## Rundown + +This guide has 3 major steps: + +1. How to modify our Noir program to make use of oracle calls as unconstrained functions +2. How to write a JSON RPC Server to resolve these oracle calls with Nargo +3. How to use them in Nargo and how to provide a custom resolver in NoirJS + +## Step 1 - Modify your Noir program + +An oracle is defined in a Noir program by defining two methods: + +- An unconstrained method - This tells the compiler that it is executing an [unconstrained functions](../noir/concepts//unconstrained.md). +- A decorated oracle method - This tells the compiler that this method is an RPC call. + +An example of an oracle that returns a `Field` would be: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(number: Field) -> Field { } + +unconstrained fn get_sqrt(number: Field) -> Field { + sqrt(number) +} +``` + +In this example, we're wrapping our oracle function in a unconstrained method, and decorating it with `oracle(getSqrt)`. We can then call the unconstrained function as we would call any other function: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); +} +``` + +In the next section, we will make this `getSqrt` (defined on the `sqrt` decorator) be a method of the RPC server Noir will use. + +:::danger + +As explained in the [Oracle Explainer](../explainers/explainer-oracle.md), this `main` function is unsafe unless you constrain its return value. For example: + +```rust +fn main(input: Field) { + let sqrt = get_sqrt(input); + assert(sqrt.pow_32(2) as u64 == input as u64); // <---- constrain the return of an oracle! +} +``` + +::: + +:::info + +Currently, oracles only work with single params or array params. For example: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt([Field; 2]) -> [Field; 2] { } +``` + +::: + +## Step 2 - Write an RPC server + +Brillig will call *one* RPC server. Most likely you will have to write your own, and you can do it in whatever language you prefer. In this guide, we will do it in Javascript. + +Let's use the above example of an oracle that consumes an array with two `Field` and returns their square roots: + +```rust +#[oracle(getSqrt)] +unconstrained fn sqrt(input: [Field; 2]) -> [Field; 2] { } + +unconstrained fn get_sqrt(input: [Field; 2]) -> [Field; 2] { + sqrt(input) +} + +fn main(input: [Field; 2]) { + let sqrt = get_sqrt(input); + assert(sqrt[0].pow_32(2) as u64 == input[0] as u64); + assert(sqrt[1].pow_32(2) as u64 == input[1] as u64); +} +``` + +:::info + +Why square root? + +In general, computing square roots is computationally more expensive than multiplications, which takes a toll when speaking about ZK applications. In this case, instead of calculating the square root in Noir, we are using our oracle to offload that computation to be made in plain. In our circuit we can simply multiply the two values. + +::: + +Now, we should write the correspondent RPC server, starting with the [default JSON-RPC 2.0 boilerplate](https://www.npmjs.com/package/json-rpc-2.0#example): + +```js +import { JSONRPCServer } from "json-rpc-2.0"; +import express from "express"; +import bodyParser from "body-parser"; + +const app = express(); +app.use(bodyParser.json()); + +const server = new JSONRPCServer(); +app.post("/", (req, res) => { + const jsonRPCRequest = req.body; + server.receive(jsonRPCRequest).then((jsonRPCResponse) => { + if (jsonRPCResponse) { + res.json(jsonRPCResponse); + } else { + res.sendStatus(204); + } + }); +}); + +app.listen(5555); +``` + +Now, we will add our `getSqrt` method, as expected by the `#[oracle(getSqrt)]` decorator in our Noir code. It maps through the params array and returns their square roots: + +```js +server.addMethod("resolve_function_call", async (params) => { + if params.function !== "getSqrt" { + throw Error("Unexpected foreign call") + }; + const values = params.inputs[0].Array.map((field) => { + return `${Math.sqrt(parseInt(field, 16))}`; + }); + return { values: [{ Array: values }] }; +}); +``` + +If you're using Typescript, the following types may be helpful in understanding the expected return value and making sure they're easy to follow: + +```js +interface SingleForeignCallParam { + Single: string, +} + +interface ArrayForeignCallParam { + Array: string[], +} + +type ForeignCallParam = SingleForeignCallParam | ArrayForeignCallParam; + +interface ForeignCallResult { + values: ForeignCallParam[], +} +``` + +::: Multidimensional Arrays + +If the Oracle function is returning an array containing other arrays, such as `[['1','2],['3','4']]`, you need to provide the values in json as flattened values. In the previous example, it would be `['1', '2', '3', '4']`. In the noir program, the Oracle signature can use a nested type, the flattened values will be automatically converted to the nested type. + +::: + +## Step 3 - Usage with Nargo + +Using the [`nargo` CLI tool](../getting_started/installation/index.md), you can use oracles in the `nargo test` and `nargo execute` commands by passing a value to `--oracle-resolver`. For example: + +```bash +nargo test --oracle-resolver http://localhost:5555 +``` + +This tells `nargo` to use your RPC Server URL whenever it finds an oracle decorator. + +## Step 4 - Usage with NoirJS + +In a JS environment, an RPC server is not strictly necessary, as you may want to resolve your oracles without needing any JSON call at all. NoirJS simply expects that you pass a callback function when you generate proofs, and that callback function can be anything. + +For example, if your Noir program expects the host machine to provide CPU pseudo-randomness, you could simply pass it as the `foreignCallHandler`. You don't strictly need to create an RPC server to serve pseudo-randomness, as you may as well get it directly in your app: + +```js +const foreignCallHandler = (name, inputs) => crypto.randomBytes(16) // etc + +await noir.execute(inputs, foreignCallHandler) +``` + +As one can see, in NoirJS, the [`foreignCallHandler`](../reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md) function simply means "a callback function that returns a value of type [`ForeignCallOutput`](../reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md). It doesn't have to be an RPC call like in the case for Nargo. + +:::tip + +Does this mean you don't have to write an RPC server like in [Step #2](#step-2---write-an-rpc-server)? + +You don't technically have to, but then how would you run `nargo test`? To use both `Nargo` and `NoirJS` in your development flow, you will have to write a JSON RPC server. + +::: + +In this case, let's make `foreignCallHandler` call the JSON RPC Server we created in [Step #2](#step-2---write-an-rpc-server), by making it a JSON RPC Client. + +For example, using the same `getSqrt` program in [Step #1](#step-1---modify-your-noir-program) (comments in the code): + +```js +import { JSONRPCClient } from "json-rpc-2.0"; + +// declaring the JSONRPCClient +const client = new JSONRPCClient((jsonRPCRequest) => { +// hitting the same JSON RPC Server we coded above + return fetch("http://localhost:5555", { + method: "POST", + headers: { + "content-type": "application/json", + }, + body: JSON.stringify(jsonRPCRequest), + }).then((response) => { + if (response.status === 200) { + return response + .json() + .then((jsonRPCResponse) => client.receive(jsonRPCResponse)); + } else if (jsonRPCRequest.id !== undefined) { + return Promise.reject(new Error(response.statusText)); + } + }); +}); + +// declaring a function that takes the name of the foreign call (getSqrt) and the inputs +const foreignCallHandler = async (name, input) => { + // notice that the "inputs" parameter contains *all* the inputs + // in this case we to make the RPC request with the first parameter "numbers", which would be input[0] + const oracleReturn = await client.request(name, [ + { Array: input[0].map((i) => i.toString("hex")) }, + ]); + return [oracleReturn.values[0].Array]; +}; + +// the rest of your NoirJS code +const input = { input: [4, 16] }; +const { witness } = await noir.execute(numbers, foreignCallHandler); +``` + +:::tip + +If you're in a NoirJS environment running your RPC server together with a frontend app, you'll probably hit a familiar problem in full-stack development: requests being blocked by [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policy. For development only, you can simply install and use the [`cors` npm package](https://www.npmjs.com/package/cors) to get around the problem: + +```bash +yarn add cors +``` + +and use it as a middleware: + +```js +import cors from "cors"; + +const app = express(); +app.use(cors()) +``` + +::: + +## Conclusion + +Hopefully by the end of this guide, you should be able to: + +- Write your own logic around Oracles and how to write a JSON RPC server to make them work with your Nargo commands. +- Provide custom foreign call handlers for NoirJS. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md new file mode 100644 index 000000000000..aac84e29fac7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-recursion.md @@ -0,0 +1,180 @@ +--- +title: How to use recursion on NoirJS +description: Learn how to implement recursion with NoirJS, a powerful tool for creating smart contracts on the EVM blockchain. This guide assumes familiarity with NoirJS, solidity verifiers, and the Barretenberg proving backend. Discover how to generate both final and intermediate proofs using `noir_js` and `backend_barretenberg`. +keywords: + [ + "NoirJS", + "EVM blockchain", + "smart contracts", + "recursion", + "solidity verifiers", + "Barretenberg backend", + "noir_js", + "backend_barretenberg", + "intermediate proofs", + "final proofs", + "nargo compile", + "json import", + "recursive circuit", + "recursive app" + ] +sidebar_position: 1 +--- + +This guide shows you how to use recursive proofs in your NoirJS app. For the sake of clarity, it is assumed that: + +- You already have a NoirJS app. If you don't, please visit the [NoirJS tutorial](../tutorials/noirjs_app.md) and the [reference](../reference/NoirJS/noir_js/index.md). +- You are familiar with what are recursive proofs and you have read the [recursion explainer](../explainers/explainer-recursion.md) +- You already built a recursive circuit following [the reference](../noir/standard_library/recursion.md), and understand how it works. + +It is also assumed that you're not using `noir_wasm` for compilation, and instead you've used [`nargo compile`](../reference/nargo_commands.md) to generate the `json` you're now importing into your project. However, the guide should work just the same if you're using `noir_wasm`. + +:::info + +As you've read in the [explainer](../explainers/explainer-recursion.md), a recursive proof is an intermediate proof. This means that it doesn't necessarily generate the final step that makes it verifiable in a smart contract. However, it is easy to verify within another circuit. + +While "standard" usage of NoirJS packages abstracts final proofs, it currently lacks the necessary interface to abstract away intermediate proofs. This means that these proofs need to be created by using the backend directly. + +In short: + +- `noir_js` generates *only* final proofs +- `backend_barretenberg` generates both types of proofs + +::: + +In a standard recursive app, you're also dealing with at least two circuits. For the purpose of this guide, we will assume the following: + +- `main`: a circuit of type `assert(x != y)`, where `main` is marked with a `#[recursive]` attribute. This attribute states that the backend should generate proofs that are friendly for verification within another circuit. +- `recursive`: a circuit that verifies `main` + +For a full example on how recursive proofs work, please refer to the [noir-examples](https://github.com/noir-lang/noir-examples) repository. We will *not* be using it as a reference for this guide. + +## Step 1: Setup + +In a common NoirJS app, you need to instantiate a backend with something like `const backend = new Backend(circuit)`. Then you feed it to the `noir_js` interface. + +For recursion, this doesn't happen, and the only need for `noir_js` is only to `execute` a circuit and get its witness and return value. Everything else is not interfaced, so it needs to happen on the `backend` object. + +It is also recommended that you instantiate the backend with as many threads as possible, to allow for maximum concurrency: + +```js +const backend = new Backend(circuit, { threads: 8 }) +``` + +:::tip +You can use the [`os.cpus()`](https://nodejs.org/api/os.html#oscpus) object in `nodejs` or [`navigator.hardwareConcurrency`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/hardwareConcurrency) on the browser to make the most out of those glorious cpu cores +::: + +## Step 2: Generating the witness and the proof for `main` + +After instantiating the backend, you should also instantiate `noir_js`. We will use it to execute the circuit and get the witness. + +```js +const noir = new Noir(circuit) +const { witness } = noir.execute(input) +``` + +With this witness, you are now able to generate the intermediate proof for the main circuit: + +```js +const { proof, publicInputs } = await backend.generateProof(witness) +``` + +:::warning + +Always keep in mind what is actually happening on your development process, otherwise you'll quickly become confused about what circuit we are actually running and why! + +In this case, you can imagine that Alice (running the `main` circuit) is proving something to Bob (running the `recursive` circuit), and Bob is verifying her proof within his proof. + +With this in mind, it becomes clear that our intermediate proof is the one *meant to be verified within another circuit*, so it must be Alice's. Actually, the only final proof in this theoretical scenario would be the last one, sent on-chain. + +::: + +## Step 3 - Verification and proof artifacts + +Optionally, you are able to verify the intermediate proof: + +```js +const verified = await backend.verifyProof({ proof, publicInputs }) +``` + +This can be useful to make sure our intermediate proof was correctly generated. But the real goal is to do it within another circuit. For that, we need to generate recursive proof artifacts that will be passed to the circuit that is verifying the proof we just generated. Instead of passing the proof and verification key as a byte array, we pass them as fields which makes it cheaper to verify in a circuit: + +```js +const { proofAsFields, vkAsFields, vkHash } = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, publicInputsCount) +``` + +This call takes the public inputs and the proof, but also the public inputs count. While this is easily retrievable by simply counting the `publicInputs` length, the backend interface doesn't currently abstract it away. + +:::info + +The `proofAsFields` has a constant size `[Field; 93]` and verification keys in Barretenberg are always `[Field; 114]`. + +::: + +:::warning + +One common mistake is to forget *who* makes this call. + +In a situation where Alice is generating the `main` proof, if she generates the proof artifacts and sends them to Bob, which gladly takes them as true, this would mean Alice could prove anything! + +Instead, Bob needs to make sure *he* extracts the proof artifacts, using his own instance of the `main` circuit backend. This way, Alice has to provide a valid proof for the correct `main` circuit. + +::: + +## Step 4 - Recursive proof generation + +With the artifacts, generating a recursive proof is no different from a normal proof. You simply use the `backend` (with the recursive circuit) to generate it: + +```js +const recursiveInputs = { + verification_key: vkAsFields, // array of length 114 + proof: proofAsFields, // array of length 93 + size of public inputs + publicInputs: [mainInput.y], // using the example above, where `y` is the only public input + key_hash: vkHash, +} + +const { witness, returnValue } = noir.execute(recursiveInputs) // we're executing the recursive circuit now! +const { proof, publicInputs } = backend.generateProof(witness) +const verified = backend.verifyProof({ proof, publicInputs }) +``` + +You can obviously chain this proof into another proof. In fact, if you're using recursive proofs, you're probably interested of using them this way! + +:::tip + +Managing circuits and "who does what" can be confusing. To make sure your naming is consistent, you can keep them in an object. For example: + +```js +const circuits = { + main: mainJSON, + recursive: recursiveJSON +} +const backends = { + main: new BarretenbergBackend(circuits.main), + recursive: new BarretenbergBackend(circuits.recursive) +} +const noir_programs = { + main: new Noir(circuits.main), + recursive: new Noir(circuits.recursive) +} +``` + +This allows you to neatly call exactly the method you want without conflicting names: + +```js +// Alice runs this 👇 +const { witness: mainWitness } = await noir_programs.main.execute(input) +const proof = await backends.main.generateProof(mainWitness) + +// Bob runs this 👇 +const verified = await backends.main.verifyProof(proof) +const { proofAsFields, vkAsFields, vkHash } = await backends.main.generateRecursiveProofArtifacts( + proof, + numPublicInputs, +); +const { witness: recursiveWitness } = await noir_programs.recursive.execute(recursiveInputs) +const recursiveProof = await backends.recursive.generateProof(recursiveWitness); +``` + +::: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md new file mode 100644 index 000000000000..e6ed9abaec61 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/how-to-solidity-verifier.md @@ -0,0 +1,251 @@ +--- +title: Generate a Solidity Verifier +description: + Learn how to run the verifier as a smart contract on the blockchain. Compile a Solidity verifier + contract for your Noir program and deploy it on any EVM blockchain acting as a verifier smart + contract. Read more to find out +keywords: + [ + solidity verifier, + smart contract, + blockchain, + compiler, + plonk_vk.sol, + EVM blockchain, + verifying Noir programs, + proving backend, + Barretenberg, + ] +sidebar_position: 0 +pagination_next: tutorials/noirjs_app +--- + +Noir has the ability to generate a verifier contract in Solidity, which can be deployed in many EVM-compatible blockchains such as Ethereum. + +This allows for a powerful feature set, as one can make use of the conciseness and the privacy provided by Noir in an immutable ledger. Applications can range from simple P2P guessing games, to complex private DeFi interactions. + +This guide shows you how to generate a Solidity Verifier and deploy it on the [Remix IDE](https://remix.ethereum.org/). It is assumed that: + +- You are comfortable with the Solidity programming language and understand how contracts are deployed on the Ethereum network +- You have Noir installed and you have a Noir program. If you don't, [get started](../getting_started/installation/index.md) with Nargo and the example Hello Noir circuit +- You are comfortable navigating RemixIDE. If you aren't or you need a refresher, you can find some video tutorials [here](https://www.youtube.com/channel/UCjTUPyFEr2xDGN6Cg8nKDaA) that could help you. + +## Rundown + +Generating a Solidity Verifier contract is actually a one-command process. However, compiling it and deploying it can have some caveats. Here's the rundown of this guide: + +1. How to generate a solidity smart contract +2. How to compile the smart contract in the RemixIDE +3. How to deploy it to a testnet + +## Step 1 - Generate a contract + +This is by far the most straight-forward step. Just run: + +```sh +nargo compile +``` + +This will compile your source code into a Noir build artifact to be stored in the `./target` directory, you can then generate the smart contract using the commands: + +```sh +# Here we pass the path to the newly generated Noir artifact. +bb write_vk -b ./target/.json +bb contract +``` + +replacing `` with the name of your Noir project. A new `contract` folder would then be generated in your project directory, containing the Solidity +file `contract.sol`. It can be deployed to any EVM blockchain acting as a verifier smart contract. + +:::info + +It is possible to generate verifier contracts of Noir programs for other smart contract platforms as long as the proving backend supplies an implementation. + +Barretenberg, the default proving backend for Nargo, supports generation of verifier contracts, for the time being these are only in Solidity. +::: + +## Step 2 - Compiling + +We will mostly skip the details of RemixIDE, as the UI can change from version to version. For now, we can just open +Remix and create a blank workspace. + +![Create Workspace](@site/static/img/how-tos/solidity_verifier_1.png) + +We will create a new file to contain the contract Nargo generated, and copy-paste its content. + +:::warning + +You'll likely see a warning advising you to not trust pasted code. While it is an important warning, it is irrelevant in the context of this guide and can be ignored. We will not be deploying anywhere near a mainnet. + +::: + +To compile our the verifier, we can navigate to the compilation tab: + +![Compilation Tab](@site/static/img/how-tos/solidity_verifier_2.png) + +Remix should automatically match a suitable compiler version. However, hitting the "Compile" button will most likely generate a "Stack too deep" error: + +![Stack too deep](@site/static/img/how-tos/solidity_verifier_3.png) + +This is due to the verify function needing to put many variables on the stack, but enabling the optimizer resolves the issue. To do this, let's open the "Advanced Configurations" tab and enable optimization. The default 200 runs will suffice. + +:::info + +This time we will see a warning about an unused function parameter. This is expected, as the `verify` function doesn't use the `_proof` parameter inside a solidity block, it is loaded from calldata and used in assembly. + +::: + +![Compilation success](@site/static/img/how-tos/solidity_verifier_4.png) + +## Step 3 - Deploying + +At this point we should have a compiled contract read to deploy. If we navigate to the deploy section in Remix, we will see many different environments we can deploy to. The steps to deploy on each environment would be out-of-scope for this guide, so we will just use the default Remix VM. + +Looking closely, we will notice that our "Solidity Verifier" is actually three contracts working together: + +- An `UltraVerificationKey` library which simply stores the verification key for our circuit. +- An abstract contract `BaseUltraVerifier` containing most of the verifying logic. +- A main `UltraVerifier` contract that inherits from the Base and uses the Key contract. + +Remix will take care of the dependencies for us so we can simply deploy the UltraVerifier contract by selecting it and hitting "deploy": + +![Deploying UltraVerifier](@site/static/img/how-tos/solidity_verifier_5.png) + +A contract will show up in the "Deployed Contracts" section, where we can retrieve the Verification Key Hash. This is particularly useful for double-checking the deployer contract is the correct one. + +:::note + +Why "UltraVerifier"? + +To be precise, the Noir compiler (`nargo`) doesn't generate the verifier contract directly. It compiles the Noir code into an intermediate language (ACIR), which is then executed by the backend. So it is the backend that returns the verifier smart contract, not Noir. + +In this case, the Barretenberg Backend uses the UltraPlonk proving system, hence the "UltraVerifier" name. + +::: + +## Step 4 - Verifying + +To verify a proof using the Solidity verifier contract, we call the `verify` function in this extended contract: + +```solidity +function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool) +``` + +When using the default example in the [Hello Noir](../getting_started/hello_noir/index.md) guide, the easiest way to confirm that the verifier contract is doing its job is by calling the `verify` function via remix with the required parameters. Note that the public inputs must be passed in separately to the rest of the proof so we must split the proof as returned from `bb`. + +First generate a proof with `bb` at the location `./proof` using the steps in [get started](../getting_started/hello_noir/index.md), this proof is in a binary format but we want to convert it into a hex string to pass into Remix, this can be done with the + +```bash +# This value must be changed to match the number of public inputs (including return values!) in your program. +NUM_PUBLIC_INPUTS=1 +PUBLIC_INPUT_BYTES=32*NUM_PUBLIC_INPUTS +HEX_PUBLIC_INPUTS=$(head -c $PUBLIC_INPUT_BYTES ./proof | od -An -v -t x1 | tr -d $' \n') +HEX_PROOF=$(tail -c +$(($PUBLIC_INPUT_BYTES + 1)) ./proof | od -An -v -t x1 | tr -d $' \n') + +echo "Public inputs:" +echo $HEX_PUBLIC_INPUTS + +echo "Proof:" +echo "0x$HEX_PROOF" +``` + +Remix expects that the public inputs will be split into an array of `bytes32` values so `HEX_PUBLIC_INPUTS` needs to be split up into 32 byte chunks which are prefixed with `0x` accordingly. + +A programmatic example of how the `verify` function is called can be seen in the example zk voting application [here](https://github.com/noir-lang/noir-examples/blob/33e598c257e2402ea3a6b68dd4c5ad492bce1b0a/foundry-voting/src/zkVote.sol#L35): + +```solidity +function castVote(bytes calldata proof, uint proposalId, uint vote, bytes32 nullifierHash) public returns (bool) { + // ... + bytes32[] memory publicInputs = new bytes32[](4); + publicInputs[0] = merkleRoot; + publicInputs[1] = bytes32(proposalId); + publicInputs[2] = bytes32(vote); + publicInputs[3] = nullifierHash; + require(verifier.verify(proof, publicInputs), "Invalid proof"); +``` + +:::info[Return Values] + +A circuit doesn't have the concept of a return value. Return values are just syntactic sugar in Noir. + +Under the hood, the return value is passed as an input to the circuit and is checked at the end of the circuit program. + +For example, if you have Noir program like this: + +```rust +fn main( + // Public inputs + pubkey_x: pub Field, + pubkey_y: pub Field, + // Private inputs + priv_key: Field, +) -> pub Field +``` + +the `verify` function will expect the public inputs array (second function parameter) to be of length 3, the two inputs and the return value. + +Passing only two inputs will result in an error such as `PUBLIC_INPUT_COUNT_INVALID(3, 2)`. + +In this case, the inputs parameter to `verify` would be an array ordered as `[pubkey_x, pubkey_y, return`. + +::: + +:::tip[Structs] + +You can pass structs to the verifier contract. They will be flattened so that the array of inputs is 1-dimensional array. + +For example, consider the following program: + +```rust +struct Type1 { + val1: Field, + val2: Field, +} + +struct Nested { + t1: Type1, + is_true: bool, +} + +fn main(x: pub Field, nested: pub Nested, y: pub Field) { + //... +} +``` + +The order of these inputs would be flattened to: `[x, nested.t1.val1, nested.t1.val2, nested.is_true, y]` + +::: + +The other function you can call is our entrypoint `verify` function, as defined above. + +:::tip + +It's worth noticing that the `verify` function is actually a `view` function. A `view` function does not alter the blockchain state, so it doesn't need to be distributed (i.e. it will run only on the executing node), and therefore doesn't cost any gas. + +This can be particularly useful in some situations. If Alice generated a proof and wants Bob to verify its correctness, Bob doesn't need to run Nargo, NoirJS, or any Noir specific infrastructure. He can simply make a call to the blockchain with the proof and verify it is correct without paying any gas. + +It would be incorrect to say that a Noir proof verification costs any gas at all. However, most of the time the result of `verify` is used to modify state (for example, to update a balance, a game state, etc). In that case the whole network needs to execute it, which does incur gas costs (calldata and execution, but not storage). + +::: + +## A Note on EVM chains + +Noir proof verification requires the ecMul, ecAdd and ecPairing precompiles. Not all EVM chains support EC Pairings, notably some of the ZK-EVMs. This means that you won't be able to use the verifier contract in all of them. You can find an incomplete list of which EVM chains support these precompiles [here](https://www.evmdiff.com/features?feature=precompiles). + +For example, chains like `zkSync ERA` and `Polygon zkEVM` do not currently support these precompiles, so proof verification via Solidity verifier contracts won't work. Here's a quick list of EVM chains that have been tested and are known to work: + +- Optimism +- Arbitrum +- Polygon PoS +- Scroll +- Celo + +If you test any other chains, please open a PR on this page to update the list. See [this doc](https://github.com/noir-lang/noir-starter/tree/main/with-foundry#testing-on-chain) for more info about testing verifier contracts on different EVM chains. + +## What's next + +Now that you know how to call a Noir Solidity Verifier on a smart contract using Remix, you should be comfortable with using it with some programmatic frameworks, such as [hardhat](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat) and [foundry](https://github.com/noir-lang/noir-starter/tree/main/with-foundry). + +You can find other tools, examples, boilerplates and libraries in the [awesome-noir](https://github.com/noir-lang/awesome-noir) repository. + +You should also be ready to write and deploy your first NoirJS app and start generating proofs on websites, phones, and NodeJS environments! Head on to the [NoirJS tutorial](../tutorials/noirjs_app.md) to learn how to do that. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx new file mode 100644 index 000000000000..0a128adb2de6 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/merkle-proof.mdx @@ -0,0 +1,48 @@ +--- +title: Prove Merkle Tree Membership +description: + Learn how to use merkle membership proof in Noir to prove that a given leaf is a member of a + merkle tree with a specified root, at a given index. +keywords: + [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 +--- + +Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is +in a merkle tree. + +```rust + +fn main(message : [Field; 62], index : Field, hashpath : [Field; 40], root : Field) { + let leaf = std::hash::hash_to_field(message.as_slice()); + let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); + assert(merkle_root == root); +} + +``` + +The message is hashed using `hash_to_field`. The specific hash function that is being used is chosen +by the backend. The only requirement is that this hash function can heuristically be used as a +random oracle. If only collision resistance is needed, then one can call `std::hash::pedersen_hash` +instead. + +```rust +let leaf = std::hash::hash_to_field(message.as_slice()); +``` + +The leaf is then passed to a compute_merkle_root function with the root, index and hashpath. The returned root can then be asserted to be the same as the provided root. + +```rust +let merkle_root = std::merkle::compute_merkle_root(leaf, index, hashpath); +assert (merkle_root == root); +``` + +> **Note:** It is possible to re-implement the merkle tree implementation without standard library. +> However, for most usecases, it is enough. In general, the standard library will always opt to be +> as conservative as possible, while striking a balance with efficiency. + +An example, the merkle membership proof, only requires a hash function that has collision +resistance, hence a hash function like Pedersen is allowed, which in most cases is more efficient +than the even more conservative sha256. + +[View an example on the starter repo](https://github.com/noir-lang/noir-examples/blob/3ea09545cabfa464124ec2f3ea8e60c608abe6df/stealthdrop/circuits/src/main.nr#L20) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx new file mode 100644 index 000000000000..727ec6ca6672 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/how_to/using-devcontainers.mdx @@ -0,0 +1,110 @@ +--- +title: Developer Containers and Codespaces +description: "Learn how to set up a devcontainer in your GitHub repository for a seamless coding experience with Codespaces. Follow our easy 8-step guide to create your own Noir environment without installing Nargo locally." +keywords: ["Devcontainer", "Codespaces", "GitHub", "Noir Environment", "Docker Image", "Development Environment", "Remote Coding", "GitHub Codespaces", "Noir Programming", "Nargo", "VSCode Extensions", "Noirup"] +sidebar_position: 1 +--- + +Adding a developer container configuration file to your Noir project is one of the easiest way to unlock coding in browser. + +## What's a devcontainer after all? + +A [Developer Container](https://containers.dev/) (devcontainer for short) is a Docker image that comes preloaded with tools, extensions, and other tools you need to quickly get started or continue a project, without having to install Nargo locally. Think of it as a development environment in a box. + +There are many advantages to this: + +- It's platform and architecture agnostic +- You don't need to have an IDE installed, or Nargo, or use a terminal at all +- It's safer for using on a public machine or public network + +One of the best ways of using devcontainers is... not using your machine at all, for maximum control, performance, and ease of use. +Enter Codespaces. + +## Codespaces + +If a devcontainer is just a Docker image, then what stops you from provisioning a `p3dn.24xlarge` AWS EC2 instance with 92 vCPUs and 768 GiB RAM and using it to prove your 10-gate SNARK proof? + +Nothing! Except perhaps the 30-40$ per hour it will cost you. + +The problem is that provisioning takes time, and I bet you don't want to see the AWS console every time you want to code something real quick. + +Fortunately, there's an easy and free way to get a decent remote machine ready and loaded in less than 2 minutes: Codespaces. [Codespaces is a Github feature](https://github.com/features/codespaces) that allows you to code in a remote machine by using devcontainers, and it's pretty cool: + +- You can start coding Noir in less than a minute +- It uses the resources of a remote machine, so you can code on your grandma's phone if needed be +- It makes it easy to share work with your frens +- It's fully reusable, you can stop and restart whenever you need to + +:::info + +Don't take out your wallet just yet. Free GitHub accounts get about [15-60 hours of coding](https://github.com/features/codespaces) for free per month, depending on the size of your provisioned machine. + +::: + +## Tell me it's _actually_ easy + +It is! + +Github comes with a default codespace and you can use it to code your own devcontainer. That's exactly what we will be doing in this guide. + + + +8 simple steps: + +#### 1. Create a new repository on GitHub. + +#### 2. Click "Start coding with Codespaces". This will use the default image. + +#### 3. Create a folder called `.devcontainer` in the root of your repository. + +#### 4. Create a Dockerfile in that folder, and paste the following code: + +```docker +FROM --platform=linux/amd64 node:lts-bookworm-slim +SHELL ["/bin/bash", "-c"] +RUN apt update && apt install -y curl bash git tar gzip libc++-dev +RUN curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +ENV PATH="/root/.nargo/bin:$PATH" +RUN noirup +ENTRYPOINT ["nargo"] +``` +#### 5. Create a file called `devcontainer.json` in the same folder, and paste the following code: + +```json +{ + "name": "Noir on Codespaces", + "build": { + "context": ".", + "dockerfile": "Dockerfile" + }, + "customizations": { + "vscode": { + "extensions": ["noir-lang.vscode-noir"] + } + } +} +``` +#### 6. Commit and push your changes + +This will pull the new image and build it, so it could take a minute or so + +#### 8. Done! +Just wait for the build to finish, and there's your easy Noir environment. + + +Refer to [noir-starter](https://github.com/noir-lang/noir-starter/) as an example of how devcontainers can be used together with codespaces. + + + +## How do I use it? + +Using the codespace is obviously much easier than setting it up. +Just navigate to your repository and click "Code" -> "Open with Codespaces". It should take a few seconds to load, and you're ready to go. + +:::info + +If you really like the experience, you can add a badge to your readme, links to existing codespaces, and more. +Check out the [official docs](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/setting-up-your-repository/facilitating-quick-creation-and-resumption-of-codespaces) for more info. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx new file mode 100644 index 000000000000..a6bd306f91da --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/index.mdx @@ -0,0 +1,67 @@ +--- +title: Noir Lang +hide_title: true +description: + Learn about the public alpha release of Noir, a domain specific language heavily influenced by Rust that compiles to + an intermediate language which can be compiled to an arithmetic circuit or a rank-1 constraint system. +keywords: + [Noir, + Domain Specific Language, + Rust, + Intermediate Language, + Arithmetic Circuit, + Rank-1 Constraint System, + Ethereum Developers, + Protocol Developers, + Blockchain Developers, + Proving System, + Smart Contract Language] +sidebar_position: 0 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Noir Logo + +Noir is an open-source Domain-Specific Language for safe and seamless construction of privacy-preserving Zero-Knowledge programs, requiring no previous knowledge on the underlying mathematics or cryptography. + +ZK programs are programs that can generate short proofs of statements without revealing all inputs to the statements. You can read more about Zero-Knowledge Proofs [here](https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56). + +## What's new about Noir? + +Noir works differently from most ZK languages by taking a two-pronged path. First, it compiles the program to an adaptable intermediate language known as ACIR. From there, depending on a given project's needs, ACIR can be further compiled into an arithmetic circuit for integration with the proving backend. + +:::info + +Noir is backend agnostic, which means it makes no assumptions on which proving backend powers the ZK proof. Being the language that powers [Aztec Contracts](https://docs.aztec.network/developers/contracts/main), it defaults to Aztec's Barretenberg proving backend. + +However, the ACIR output can be transformed to be compatible with other PLONK-based backends, or into a [rank-1 constraint system](https://www.rareskills.io/post/rank-1-constraint-system) suitable for backends such as Arkwork's Marlin. + +::: + +## Who is Noir for? + +Noir can be used both in complex cloud-based backends and in user's smartphones, requiring no knowledge on the underlying math or cryptography. From authorization systems that keep a password in the user's device, to complex on-chain verification of recursive proofs, Noir is designed to abstract away complexity without any significant overhead. Here are some examples of situations where Noir can be used: + + + + Noir Logo + + Aztec Contracts leverage Noir to allow for the storage and execution of private information. Writing an Aztec Contract is as easy as writing Noir, and Aztec developers can easily interact with the network storage and execution through the [Aztec.nr](https://docs.aztec.network/developers/contracts/main) library. + + + Soliditry Verifier Example + Noir can auto-generate Solidity verifier contracts that verify Noir proofs. This allows for non-interactive verification of proofs containing private information in an immutable system. This feature powers a multitude of use-case scenarios, from P2P chess tournaments, to [Aztec Layer-2 Blockchain](https://docs.aztec.network/) + + + Aztec Labs developed NoirJS, an easy interface to generate and verify Noir proofs in a Javascript environment. This allows for Noir to be used in webpages, mobile apps, games, and any other environment supporting JS execution in a standalone manner. + + + + +## Libraries + +Noir is meant to be easy to extend by simply importing Noir libraries just like in Rust. +The [awesome-noir repo](https://github.com/noir-lang/awesome-noir#libraries) is a collection of libraries developed by the Noir community. +Writing a new library is easy and makes code be composable and easy to reuse. See the section on [dependencies](noir/modules_packages_crates/dependencies.md) for more information. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md new file mode 100644 index 000000000000..6bd740024e5b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/migration_notes.md @@ -0,0 +1,105 @@ +--- +title: Migration notes +description: Read about migration notes from previous versions, which could solve problems while updating +keywords: [Noir, notes, migration, updating, upgrading] +--- + +Noir is in full-speed development. Things break fast, wild, and often. This page attempts to leave some notes on errors you might encounter when upgrading and how to resolve them until proper patches are built. + +### `backend encountered an error: libc++.so.1` + +Depending on your OS, you may encounter the following error when running `nargo prove` for the first time: + +```text +The backend encountered an error: "/home/codespace/.nargo/backends/acvm-backend-barretenberg/backend_binary: error while loading shared libraries: libc++.so.1: cannot open shared object file: No such file or directory\n" +``` + +Install the `libc++-dev` library with: + +```bash +sudo apt install libc++-dev +``` + +## ≥0.19 + +### Enforcing `compiler_version` + +From this version on, the compiler will check for the `compiler_version` field in `Nargo.toml`, and will error if it doesn't match the current Nargo version in use. + +To update, please make sure this field in `Nargo.toml` matches the output of `nargo --version`. + +## ≥0.14 + +The index of the [for loops](noir/concepts/control_flow.md#loops) is now of type `u64` instead of `Field`. An example refactor would be: + +```rust +for i in 0..10 { + let i = i as Field; +} +``` + +## ≥v0.11.0 and Nargo backend + +From this version onwards, Nargo starts managing backends through the `nargo backend` command. Upgrading to the versions per usual steps might lead to: + +### `backend encountered an error` + +This is likely due to the existing locally installed version of proving backend (e.g. barretenberg) is incompatible with the version of Nargo in use. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo prove +``` + +with your Noir program. + +This will trigger the download and installation of the latest version of barretenberg compatible with your Nargo in use. + +### `backend encountered an error: illegal instruction` + +On certain Intel-based systems, an `illegal instruction` error may arise due to incompatibility of barretenberg with certain CPU instructions. + +To fix the issue: + +1. Uninstall the existing backend + +```bash +nargo backend uninstall acvm-backend-barretenberg +``` + +You may replace _acvm-backend-barretenberg_ with the name of your backend listed in `nargo backend ls` or in ~/.nargo/backends. + +2. Reinstall a compatible version of the proving backend. + +If you are using the default barretenberg backend, simply run: + +``` +nargo backend install acvm-backend-barretenberg https://github.com/noir-lang/barretenberg-js-binary/raw/master/run-bb.tar.gz +``` + +This downloads and installs a specific bb.js based version of barretenberg binary from GitHub. + +The gzipped file is running [this bash script](https://github.com/noir-lang/barretenberg-js-binary/blob/master/run-bb-js.sh), where we need to gzip it as the Nargo currently expect the backend to be zipped up. + +Then run: + +``` +DESIRED_BINARY_VERSION=0.8.1 nargo info +``` + +This overrides the bb native binary with a bb.js node application instead, which should be compatible with most if not all hardware. This does come with the drawback of being generally slower than native binary. + +0.8.1 indicates bb.js version 0.8.1, so if you change that it will update to a different version or the default version in the script if none was supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json new file mode 100644 index 000000000000..7da08f8a8c5d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Concepts", + "position": 0, + "collapsible": true, + "collapsed": true +} \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md new file mode 100644 index 000000000000..bcff613a6952 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/assert.md @@ -0,0 +1,45 @@ +--- +title: Assert Function +description: + Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or + comparison expression that follows to be true, and what happens if the expression is false at + runtime. +keywords: [Noir programming language, assert statement, predicate expression, comparison expression] +sidebar_position: 4 +--- + +Noir includes a special `assert` function which will explicitly constrain the predicate/comparison +expression that follows to be true. If this expression is false at runtime, the program will fail to +be proven. Example: + +```rust +fn main(x : Field, y : Field) { + assert(x == y); +} +``` + +> Assertions only work for predicate operations, such as `==`. If there's any ambiguity on the operation, the program will fail to compile. For example, it is unclear if `assert(x + y)` would check for `x + y == 0` or simply would return `true`. + +You can optionally provide a message to be logged when the assertion fails: + +```rust +assert(x == y, "x and y are not equal"); +``` + +Aside string literals, the optional message can be a format string or any other type supported as input for Noir's [print](../standard_library/logging.md) functions. This feature lets you incorporate runtime variables into your failed assertion logs: + +```rust +assert(x == y, f"Expected x == y, but got {x} == {y}"); +``` + +Using a variable as an assertion message directly: + +```rust +struct myStruct { + myField: Field +} + +let s = myStruct { myField: y }; +assert(s.myField == x, s); +``` + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md new file mode 100644 index 000000000000..b51a85f5c949 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/comments.md @@ -0,0 +1,33 @@ +--- +title: Comments +description: + Learn how to write comments in Noir programming language. A comment is a line of code that is + ignored by the compiler, but it can be read by programmers. Single-line and multi-line comments + are supported in Noir. +keywords: [Noir programming language, comments, single-line comments, multi-line comments] +sidebar_position: 10 +--- + +A comment is a line in your codebase which the compiler ignores, however it can be read by +programmers. + +Here is a single line comment: + +```rust +// This is a comment and is ignored +``` + +`//` is used to tell the compiler to ignore the rest of the line. + +Noir also supports multi-line block comments. Start a block comment with `/*` and end the block with `*/`. + +Noir does not natively support doc comments. You may be able to use [Rust doc comments](https://doc.rust-lang.org/reference/comments.html) in your code to leverage some Rust documentation build tools with Noir code. + +```rust +/* + This is a block comment describing a complex function. +*/ +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md new file mode 100644 index 000000000000..045d3c3a5f58 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/control_flow.md @@ -0,0 +1,77 @@ +--- +title: Control Flow +description: + Learn how to use loops and if expressions in the Noir programming language. Discover the syntax + and examples for for loops and if-else statements. +keywords: [Noir programming language, loops, for loop, if-else statements, Rust syntax] +sidebar_position: 2 +--- + +## If Expressions + +Noir supports `if-else` statements. The syntax is most similar to Rust's where it is not required +for the statement's conditional to be surrounded by parentheses. + +```rust +let a = 0; +let mut x: u32 = 0; + +if a == 0 { + if a != 0 { + x = 6; + } else { + x = 2; + } +} else { + x = 5; + assert(x == 5); +} +assert(x == 2); +``` + +## Loops + +Noir has one kind of loop: the `for` loop. `for` loops allow you to repeat a block of code multiple +times. + +The following block of code between the braces is run 10 times. + +```rust +for i in 0..10 { + // do something +} +``` + +The index for loops is of type `u64`. + +### Break and Continue + +In unconstrained code, `break` and `continue` are also allowed in `for` loops. These are only allowed +in unconstrained code since normal constrained code requires that Noir knows exactly how many iterations +a loop may have. `break` and `continue` can be used like so: + +```rust +for i in 0 .. 10 { + println("Iteration start") + + if i == 2 { + continue; + } + + if i == 5 { + break; + } + + println(i); +} +println("Loop end") +``` + +When used, `break` will end the current loop early and jump to the statement after the for loop. In the example +above, the `break` will stop the loop and jump to the `println("Loop end")`. + +`continue` will stop the current iteration of the loop, and jump to the start of the next iteration. In the example +above, `continue` will jump to `println("Iteration start")` when used. Note that the loop continues as normal after this. +The iteration variable `i` is still increased by one as normal when `continue` is used. + +`break` and `continue` cannot currently be used to jump out of more than a single loop at a time. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md new file mode 100644 index 000000000000..e54fc861257b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_bus.md @@ -0,0 +1,21 @@ +--- +title: Data Bus +sidebar_position: 13 +--- +**Disclaimer** this feature is experimental, do not use it! + +The data bus is an optimization that the backend can use to make recursion more efficient. +In order to use it, you must define some inputs of the program entry points (usually the `main()` +function) with the `call_data` modifier, and the return values with the `return_data` modifier. +These modifiers are incompatible with `pub` and `mut` modifiers. + +## Example + +```rust +fn main(mut x: u32, y: call_data u32, z: call_data [u32;4] ) -> return_data u32 { + let a = z[x]; + a+y +} +``` + +As a result, both call_data and return_data will be treated as private inputs and encapsulated into a read-only array each, for the backend to process. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json new file mode 100644 index 000000000000..5d694210bbf3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md new file mode 100644 index 000000000000..95d749053e21 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/arrays.md @@ -0,0 +1,253 @@ +--- +title: Arrays +description: + Dive into the Array data type in Noir. Grasp its methods, practical examples, and best practices for efficiently using Arrays in your Noir code. +keywords: + [ + noir, + array type, + methods, + examples, + indexing, + ] +sidebar_position: 4 +--- + +An array is one way of grouping together values into one compound type. Array types can be inferred +or explicitly specified via the syntax `[; ]`: + +```rust +fn main(x : Field, y : Field) { + let my_arr = [x, y]; + let your_arr: [Field; 2] = [x, y]; +} +``` + +Here, both `my_arr` and `your_arr` are instantiated as an array containing two `Field` elements. + +Array elements can be accessed using indexing: + +```rust +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; + let second = a[1]; +} +``` + +All elements in an array must be of the same type (i.e. homogeneous). That is, an array cannot group +a `Field` value and a `u8` value together for example. + +You can write mutable arrays, like: + +```rust +fn main() { + let mut arr = [1, 2, 3, 4, 5]; + assert(arr[0] == 1); + + arr[0] = 42; + assert(arr[0] == 42); +} +``` + +You can instantiate a new array of a fixed size with the same value repeated for each element. The following example instantiates an array of length 32 where each element is of type Field and has the value 0. + +```rust +let array: [Field; 32] = [0; 32]; +``` + +Like in Rust, arrays in Noir are a fixed size. However, if you wish to convert an array to a [slice](./slices.mdx), you can just call `as_slice` on your array: + +```rust +let array: [Field; 32] = [0; 32]; +let sl = array.as_slice() +``` + +You can define multidimensional arrays: + +```rust +let array : [[Field; 2]; 2]; +let element = array[0][0]; +``` + +However, multidimensional slices are not supported. For example, the following code will error at compile time: + +```rust +let slice : [[Field]] = &[]; +``` + +## Types + +You can create arrays of primitive types or structs. There is not yet support for nested arrays +(arrays of arrays) or arrays of structs that contain arrays. + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for arrays. +Each of these functions are located within the generic impl `impl [T; N] {`. +So anywhere `self` appears, it refers to the variable `self: [T; N]`. + +### len + +Returns the length of an array + +```rust +fn len(self) -> Field +``` + +example + +```rust +fn main() { + let array = [42, 42]; + assert(array.len() == 2); +} +``` + +### sort + +Returns a new sorted array. The original array remains untouched. Notice that this function will +only work for arrays of fields or integers, not for any arbitrary type. This is because the sorting +logic it uses internally is optimized specifically for these values. If you need a sort function to +sort any type, you should use the function `sort_via` described below. + +```rust +fn sort(self) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32]; + let sorted = arr.sort(); + assert(sorted == [32, 42]); +} +``` + +### sort_via + +Sorts the array with a custom comparison function + +```rust +fn sort_via(self, ordering: fn(T, T) -> bool) -> [T; N] +``` + +example + +```rust +fn main() { + let arr = [42, 32] + let sorted_ascending = arr.sort_via(|a, b| a < b); + assert(sorted_ascending == [32, 42]); // verifies + + let sorted_descending = arr.sort_via(|a, b| a > b); + assert(sorted_descending == [32, 42]); // does not verify +} +``` + +### map + +Applies a function to each element of the array, returning a new array containing the mapped elements. + +```rust +fn map(self, f: fn(T) -> U) -> [U; N] +``` + +example + +```rust +let a = [1, 2, 3]; +let b = a.map(|a| a * 2); // b is now [2, 4, 6] +``` + +### fold + +Applies a function to each element of the array, returning the final accumulated value. The first +parameter is the initial value. + +```rust +fn fold(self, mut accumulator: U, f: fn(U, T) -> U) -> U +``` + +This is a left fold, so the given function will be applied to the accumulator and first element of +the array, then the second, and so on. For a given call the expected result would be equivalent to: + +```rust +let a1 = [1]; +let a2 = [1, 2]; +let a3 = [1, 2, 3]; + +let f = |a, b| a - b; +a1.fold(10, f) //=> f(10, 1) +a2.fold(10, f) //=> f(f(10, 1), 2) +a3.fold(10, f) //=> f(f(f(10, 1), 2), 3) +``` + +example: + +```rust + +fn main() { + let arr = [2, 2, 2, 2, 2]; + let folded = arr.fold(0, |a, b| a + b); + assert(folded == 10); +} + +``` + +### reduce + +Same as fold, but uses the first element as starting element. + +```rust +fn reduce(self, f: fn(T, T) -> T) -> T +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let reduced = arr.reduce(|a, b| a + b); + assert(reduced == 10); +} +``` + +### all + +Returns true if all the elements satisfy the given predicate + +```rust +fn all(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 2]; + let all = arr.all(|a| a == 2); + assert(all); +} +``` + +### any + +Returns true if any of the elements satisfy the given predicate + +```rust +fn any(self, predicate: fn(T) -> bool) -> bool +``` + +example: + +```rust +fn main() { + let arr = [2, 2, 2, 2, 5]; + let any = arr.any(|a| a == 5); + assert(any); +} + +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md new file mode 100644 index 000000000000..2507af710e71 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/booleans.md @@ -0,0 +1,28 @@ +--- +title: Booleans +description: + Delve into the Boolean data type in Noir. Understand its methods, practical examples, and best practices for using Booleans in your Noir programs. +keywords: + [ + noir, + boolean type, + methods, + examples, + logical operations, + ] +sidebar_position: 2 +--- + + +The `bool` type in Noir has two possible values: `true` and `false`: + +```rust +fn main() { + let t = true; + let f: bool = false; +} +``` + +The boolean type is most commonly used in conditionals like `if` expressions and `assert` +statements. More about conditionals is covered in the [Control Flow](../control_flow.md) and +[Assert Function](../assert.md) sections. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md new file mode 100644 index 000000000000..a10a48107883 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/fields.md @@ -0,0 +1,192 @@ +--- +title: Fields +description: + Dive deep into the Field data type in Noir. Understand its methods, practical examples, and best practices to effectively use Fields in your Noir programs. +keywords: + [ + noir, + field type, + methods, + examples, + best practices, + ] +sidebar_position: 0 +--- + +The field type corresponds to the native field type of the proving backend. + +The size of a Noir field depends on the elliptic curve's finite field for the proving backend +adopted. For example, a field would be a 254-bit integer when paired with the default backend that +spans the Grumpkin curve. + +Fields support integer arithmetic and are often used as the default numeric type in Noir: + +```rust +fn main(x : Field, y : Field) { + let z = x + y; +} +``` + +`x`, `y` and `z` are all private fields in this example. Using the `let` keyword we defined a new +private value `z` constrained to be equal to `x + y`. + +If proving efficiency is of priority, fields should be used as a default for solving problems. +Smaller integer types (e.g. `u64`) incur extra range constraints. + +## Methods + +After declaring a Field, you can use these common methods on it: + +### to_le_bits + +Transforms the field into an array of bits, Little Endian. + +```rust +fn to_le_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_le_bits(32); +} +``` + +### to_be_bits + +Transforms the field into an array of bits, Big Endian. + +```rust +fn to_be_bits(_x : Field, _bit_size: u32) -> [u1] +``` + +example: + +```rust +fn main() { + let field = 2; + let bits = field.to_be_bits(32); +} +``` + +### to_le_bytes + +Transforms into an array of bytes, Little Endian + +```rust +fn to_le_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_le_bytes(4); +} +``` + +### to_be_bytes + +Transforms into an array of bytes, Big Endian + +```rust +fn to_be_bytes(_x : Field, byte_size: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let bytes = field.to_be_bytes(4); +} +``` + +### to_le_radix + +Decomposes into a vector over the specified base, Little Endian + +```rust +fn to_le_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_le_radix(256, 4); +} +``` + +### to_be_radix + +Decomposes into a vector over the specified base, Big Endian + +```rust +fn to_be_radix(_x : Field, _radix: u32, _result_len: u32) -> [u8] +``` + +example: + +```rust +fn main() { + let field = 2; + let radix = field.to_be_radix(256, 4); +} +``` + +### pow_32 + +Returns the value to the power of the specified exponent + +```rust +fn pow_32(self, exponent: Field) -> Field +``` + +example: + +```rust +fn main() { + let field = 2 + let pow = field.pow_32(4); + assert(pow == 16); +} +``` + +### assert_max_bit_size + +Adds a constraint to specify that the field can be represented with `bit_size` number of bits + +```rust +fn assert_max_bit_size(self, bit_size: u32) +``` + +example: + +```rust +fn main() { + let field = 2 + field.assert_max_bit_size(32); +} +``` + +### sgn0 + +Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ \{0, ..., p-1\} is even, otherwise sgn0(x mod p) = 1. + +```rust +fn sgn0(self) -> u1 +``` + + +### lt + +Returns true if the field is less than the other field + +```rust +pub fn lt(self, another: Field) -> bool +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md new file mode 100644 index 000000000000..f6121af17e24 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/function_types.md @@ -0,0 +1,26 @@ +--- +title: Function types +sidebar_position: 10 +--- + +Noir supports higher-order functions. The syntax for a function type is as follows: + +```rust +fn(arg1_type, arg2_type, ...) -> return_type +``` + +Example: + +```rust +fn assert_returns_100(f: fn() -> Field) { // f takes no args and returns a Field + assert(f() == 100); +} + +fn main() { + assert_returns_100(|| 100); // ok + assert_returns_100(|| 150); // fails +} +``` + +A function type also has an optional capture environment - this is necessary to support closures. +See [Lambdas](../lambdas.md) for more details. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md new file mode 100644 index 000000000000..357813c147ab --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/index.md @@ -0,0 +1,110 @@ +--- +title: Data Types +description: + Get a clear understanding of the two categories of Noir data types - primitive types and compound + types. Learn about their characteristics, differences, and how to use them in your Noir + programming. +keywords: + [ + noir, + data types, + primitive types, + compound types, + private types, + public types, + ] +--- + +Every value in Noir has a type, which determines which operations are valid for it. + +All values in Noir are fundamentally composed of `Field` elements. For a more approachable +developing experience, abstractions are added on top to introduce different data types in Noir. + +Noir has two category of data types: primitive types (e.g. `Field`, integers, `bool`) and compound +types that group primitive types (e.g. arrays, tuples, structs). Each value can either be private or +public. + +## Private & Public Types + +A **private value** is known only to the Prover, while a **public value** is known by both the +Prover and Verifier. Mark values as `private` when the value should only be known to the prover. All +primitive types (including individual fields of compound types) in Noir are private by default, and +can be marked public when certain values are intended to be revealed to the Verifier. + +> **Note:** For public values defined in Noir programs paired with smart contract verifiers, once +> the proofs are verified on-chain the values can be considered known to everyone that has access to +> that blockchain. + +Public data types are treated no differently to private types apart from the fact that their values +will be revealed in proofs generated. Simply changing the value of a public type will not change the +circuit (where the same goes for changing values of private types as well). + +_Private values_ are also referred to as _witnesses_ sometimes. + +> **Note:** The terms private and public when applied to a type (e.g. `pub Field`) have a different +> meaning than when applied to a function (e.g. `pub fn foo() {}`). +> +> The former is a visibility modifier for the Prover to interpret if a value should be made known to +> the Verifier, while the latter is a visibility modifier for the compiler to interpret if a +> function should be made accessible to external Noir programs like in other languages. + +### pub Modifier + +All data types in Noir are private by default. Types are explicitly declared as public using the +`pub` modifier: + +```rust +fn main(x : Field, y : pub Field) -> pub Field { + x + y +} +``` + +In this example, `x` is **private** while `y` and `x + y` (the return value) are **public**. Note +that visibility is handled **per variable**, so it is perfectly valid to have one input that is +private and another that is public. + +> **Note:** Public types can only be declared through parameters on `main`. + +## Type Aliases + +A type alias is a new name for an existing type. Type aliases are declared with the keyword `type`: + +```rust +type Id = u8; + +fn main() { + let id: Id = 1; + let zero: u8 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can also be used with [generics](../generics.md): + +```rust +type Id = Size; + +fn main() { + let id: Id = 1; + let zero: u32 = 0; + assert(zero + 1 == id); +} +``` + +Type aliases can even refer to other aliases. An error will be issued if they form a cycle: + +```rust +// Ok! +type A = B; +type B = Field; + +type Bad1 = Bad2; + +// error: Dependency cycle found +type Bad2 = Bad1; +// ^^^^^^^^^^^ 'Bad2' recursively depends on itself: Bad2 -> Bad1 -> Bad2 +``` + +### BigInt + +You can achieve BigInt functionality using the [Noir BigInt](https://github.com/shuklaayush/noir-bigint) library. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md new file mode 100644 index 000000000000..a1d59bf31662 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/integers.md @@ -0,0 +1,156 @@ +--- +title: Integers +description: Explore the Integer data type in Noir. Learn about its methods, see real-world examples, and grasp how to efficiently use Integers in your Noir code. +keywords: [noir, integer types, methods, examples, arithmetic] +sidebar_position: 1 +--- + +An integer type is a range constrained field type. +The Noir frontend supports both unsigned and signed integer types. +The allowed sizes are 1, 8, 16, 32 and 64 bits. + +:::info + +When an integer is defined in Noir without a specific type, it will default to `Field`. + +The one exception is for loop indices which default to `u64` since comparisons on `Field`s are not possible. + +::: + +## Unsigned Integers + +An unsigned integer type is specified first with the letter `u` (indicating its unsigned nature) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: u8 = 1; + let y: u8 = 1; + let z = x + y; + assert (z == 2); +} +``` + +The bit size determines the maximum value the integer type can store. For example, a `u8` variable can store a value in the range of 0 to 255 (i.e. $\\2^{8}-1\\$). + +## Signed Integers + +A signed integer type is specified first with the letter `i` (which stands for integer) followed by its bit size (e.g. `8`): + +```rust +fn main() { + let x: i8 = -1; + let y: i8 = -1; + let z = x + y; + assert (z == -2); +} +``` + +The bit size determines the maximum and minimum range of value the integer type can store. For example, an `i8` variable can store a value in the range of -128 to 127 (i.e. $\\-2^{7}\\$ to $\\2^{7}-1\\$). + +## 128 bits Unsigned Integers + +The built-in structure `U128` allows you to use 128-bit unsigned integers almost like a native integer type. However, there are some differences to keep in mind: +- You cannot cast between a native integer and `U128` +- There is a higher performance cost when using `U128`, compared to a native type. + +Conversion between unsigned integer types and U128 are done through the use of `from_integer` and `to_integer` functions. `from_integer` also accepts the `Field` type as input. + +```rust +fn main() { + let x = U128::from_integer(23); + let y = U128::from_hex("0x7"); + let z = x + y; + assert(z.to_integer() == 30); +} +``` + +`U128` is implemented with two 64 bits limbs, representing the low and high bits, which explains the performance cost. You should expect `U128` to be twice more costly for addition and four times more costly for multiplication. +You can construct a U128 from its limbs: +```rust +fn main(x: u64, y: u64) { + let x = U128::from_u64s_be(x,y); + assert(z.hi == x as Field); + assert(z.lo == y as Field); +} +``` + +Note that the limbs are stored as Field elements in order to avoid unnecessary conversions. +Apart from this, most operations will work as usual: + +```rust +fn main(x: U128, y: U128) { + // multiplication + let c = x * y; + // addition and subtraction + let c = c - x + y; + // division + let c = x / y; + // bit operation; + let c = x & y | y; + // bit shift + let c = x << y; + // comparisons; + let c = x < y; + let c = x == y; +} +``` + +## Overflows + +Computations that exceed the type boundaries will result in overflow errors. This happens with both signed and unsigned integers. For example, attempting to prove: + +```rust +fn main(x: u8, y: u8) { + let z = x + y; +} +``` + +With: + +```toml +x = "255" +y = "1" +``` + +Would result in: + +``` +$ nargo execute +error: Assertion failed: 'attempt to add with overflow' +┌─ ~/src/main.nr:9:13 +│ +│ let z = x + y; +│ ----- +│ += Call stack: + ... +``` + +A similar error would happen with signed integers: + +```rust +fn main() { + let x: i8 = -118; + let y: i8 = -11; + let z = x + y; +} +``` + +### Wrapping methods + +Although integer overflow is expected to error, some use-cases rely on wrapping. For these use-cases, the standard library provides `wrapping` variants of certain common operations: + +```rust +fn wrapping_add(x: T, y: T) -> T; +fn wrapping_sub(x: T, y: T) -> T; +fn wrapping_mul(x: T, y: T) -> T; +``` + +Example of how it is used: + +```rust + +fn main(x: u8, y: u8) -> pub u8 { + std::wrapping_add(x, y) +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md new file mode 100644 index 000000000000..a5293d11cfb9 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/references.md @@ -0,0 +1,23 @@ +--- +title: References +sidebar_position: 9 +--- + +Noir supports first-class references. References are a bit like pointers: they point to a specific address that can be followed to access the data stored at that address. You can use Rust-like syntax to use pointers in Noir: the `&` operator references the variable, the `*` operator dereferences it. + +Example: + +```rust +fn main() { + let mut x = 2; + + // you can reference x as &mut and pass it to multiplyBy2 + multiplyBy2(&mut x); +} + +// you can access &mut here +fn multiplyBy2(x: &mut Field) { + // and dereference it with * + *x = *x * 2; +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx new file mode 100644 index 000000000000..dff08d63ffb8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/slices.mdx @@ -0,0 +1,193 @@ +--- +title: Slices +description: Explore the Slice data type in Noir. Understand its methods, see real-world examples, and learn how to effectively use Slices in your Noir programs. +keywords: [noir, slice type, methods, examples, subarrays] +sidebar_position: 5 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A slice is a dynamically-sized view into a sequence of elements. They can be resized at runtime, but because they don't own the data, they cannot be returned from a circuit. You can treat slices as arrays without a constrained size. + +```rust +fn main() -> pub u32 { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +To write a slice literal, use a preceeding ampersand as in: `&[0; 2]` or +`&[1, 2, 3]`. + +It is important to note that slices are not references to arrays. In Noir, +`&[..]` is more similar to an immutable, growable vector. + +View the corresponding test file [here][test-file]. + +[test-file]: https://github.com/noir-lang/noir/blob/f387ec1475129732f72ba294877efdf6857135ac/crates/nargo_cli/tests/test_data_ssa_refactor/slices/src/main.nr + +## Methods + +For convenience, the STD provides some ready-to-use, common methods for slices: + +### push_back + +Pushes a new element to the end of the slice, returning a new slice with a length one greater than the original unmodified slice. + +```rust +fn push_back(_self: [T], _elem: T) -> [T] +``` + +example: + +```rust +fn main() -> pub Field { + let mut slice: [Field] = &[0; 2]; + + let mut new_slice = slice.push_back(6); + new_slice.len() +} +``` + +View the corresponding test file [here][test-file]. + +### push_front + +Returns a new array with the specified element inserted at index 0. The existing elements indexes are incremented by 1. + +```rust +fn push_front(_self: Self, _elem: T) -> Self +``` + +Example: + +```rust +let mut new_slice: [Field] = &[]; +new_slice = new_slice.push_front(20); +assert(new_slice[0] == 20); // returns true +``` + +View the corresponding test file [here][test-file]. + +### pop_front + +Returns a tuple of two items, the first element of the array and the rest of the array. + +```rust +fn pop_front(_self: Self) -> (T, Self) +``` + +Example: + +```rust +let (first_elem, rest_of_slice) = slice.pop_front(); +``` + +View the corresponding test file [here][test-file]. + +### pop_back + +Returns a tuple of two items, the beginning of the array with the last element omitted and the last element. + +```rust +fn pop_back(_self: Self) -> (Self, T) +``` + +Example: + +```rust +let (popped_slice, last_elem) = slice.pop_back(); +``` + +View the corresponding test file [here][test-file]. + +### append + +Loops over a slice and adds it to the end of another. + +```rust +fn append(mut self, other: Self) -> Self +``` + +Example: + +```rust +let append = &[1, 2].append(&[3, 4, 5]); +``` + +### insert + +Inserts an element at a specified index and shifts all following elements by 1. + +```rust +fn insert(_self: Self, _index: Field, _elem: T) -> Self +``` + +Example: + +```rust +new_slice = rest_of_slice.insert(2, 100); +assert(new_slice[2] == 100); +``` + +View the corresponding test file [here][test-file]. + +### remove + +Remove an element at a specified index, shifting all elements after it to the left, returning the altered slice and the removed element. + +```rust +fn remove(_self: Self, _index: Field) -> (Self, T) +``` + +Example: + +```rust +let (remove_slice, removed_elem) = slice.remove(3); +``` + +### len + +Returns the length of a slice + +```rust +fn len(self) -> Field +``` + +Example: + +```rust +fn main() { + let slice = &[42, 42]; + assert(slice.len() == 2); +} +``` + +### as_array + +Converts this slice into an array. + +Make sure to specify the size of the resulting array. +Panics if the resulting array length is different than the slice's length. + +```rust +fn as_array(self) -> [T; N] +``` + +Example: + +```rust +fn main() { + let slice = &[5, 6]; + + // Always specify the length of the resulting array! + let array: [Field; 2] = slice.as_array(); + + assert(array[0] == slice[0]); + assert(array[1] == slice[1]); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md new file mode 100644 index 000000000000..1fdee42425e5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/strings.md @@ -0,0 +1,79 @@ +--- +title: Strings +description: + Discover the String data type in Noir. Learn about its methods, see real-world examples, and understand how to effectively manipulate and use Strings in Noir. +keywords: + [ + noir, + string type, + methods, + examples, + concatenation, + ] +sidebar_position: 3 +--- + + +The string type is a fixed length value defined with `str`. + +You can use strings in `assert()` functions or print them with +`println()`. See more about [Logging](../../standard_library/logging.md). + +```rust + +fn main(message : pub str<11>, hex_as_string : str<4>) { + println(message); + assert(message == "hello world"); + assert(hex_as_string == "0x41"); +} +``` + +You can convert a `str` to a byte array by calling `as_bytes()` +or a vector by calling `as_bytes_vec()`. + +```rust +fn main() { + let message = "hello world"; + let message_bytes = message.as_bytes(); + let mut message_vec = message.as_bytes_vec(); + assert(message_bytes.len() == 11); + assert(message_bytes[0] == 104); + assert(message_bytes[0] == message_vec.get(0)); +} +``` + +## Escape characters + +You can use escape characters for your strings: + +| Escape Sequence | Description | +|-----------------|-----------------| +| `\r` | Carriage Return | +| `\n` | Newline | +| `\t` | Tab | +| `\0` | Null Character | +| `\"` | Double Quote | +| `\\` | Backslash | + +Example: + +```rust +let s = "Hello \"world" // prints "Hello "world" +let s = "hey \tyou"; // prints "hey you" +``` + +## Raw strings + +A raw string begins with the letter `r` and is optionally delimited by a number of hashes `#`. + +Escape characters are *not* processed within raw strings. All contents are interpreted literally. + +Example: + +```rust +let s = r"Hello world"; +let s = r#"Simon says "hello world""#; + +// Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes +let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md new file mode 100644 index 000000000000..dbf68c99813c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/structs.md @@ -0,0 +1,70 @@ +--- +title: Structs +description: + Explore the Struct data type in Noir. Learn about its methods, see real-world examples, and grasp how to effectively define and use Structs in your Noir programs. +keywords: + [ + noir, + struct type, + methods, + examples, + data structures, + ] +sidebar_position: 8 +--- + +A struct also allows for grouping multiple values of different types. Unlike tuples, we can also +name each field. + +> **Note:** The usage of _field_ here refers to each element of the struct and is unrelated to the +> field type of Noir. + +Defining a struct requires giving it a name and listing each field within as `: ` pairs: + +```rust +struct Animal { + hands: Field, + legs: Field, + eyes: u8, +} +``` + +An instance of a struct can then be created with actual values in `: ` pairs in any +order. Struct fields are accessible using their given names: + +```rust +fn main() { + let legs = 4; + + let dog = Animal { + eyes: 2, + hands: 0, + legs, + }; + + let zero = dog.hands; +} +``` + +Structs can also be destructured in a pattern, binding each field to a new variable: + +```rust +fn main() { + let Animal { hands, legs: feet, eyes } = get_octopus(); + + let ten = hands + feet + eyes as u8; +} + +fn get_octopus() -> Animal { + let octopus = Animal { + hands: 0, + legs: 8, + eyes: 2, + }; + + octopus +} +``` + +The new variables can be bound with names different from the original struct field names, as +showcased in the `legs --> feet` binding in the example above. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md new file mode 100644 index 000000000000..2ec5c9c41135 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/data_types/tuples.md @@ -0,0 +1,48 @@ +--- +title: Tuples +description: + Dive into the Tuple data type in Noir. Understand its methods, practical examples, and best practices for efficiently using Tuples in your Noir code. +keywords: + [ + noir, + tuple type, + methods, + examples, + multi-value containers, + ] +sidebar_position: 7 +--- + +A tuple collects multiple values like an array, but with the added ability to collect values of +different types: + +```rust +fn main() { + let tup: (u8, u64, Field) = (255, 500, 1000); +} +``` + +One way to access tuple elements is via destructuring using pattern matching: + +```rust +fn main() { + let tup = (1, 2); + + let (one, two) = tup; + + let three = one + two; +} +``` + +Another way to access tuple elements is via direct member access, using a period (`.`) followed by +the index of the element we want to access. Index `0` corresponds to the first tuple element, `1` to +the second and so on: + +```rust +fn main() { + let tup = (5, 6, 7, 8); + + let five = tup.0; + let eight = tup.3; +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md new file mode 100644 index 000000000000..f656cdfd97a1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/functions.md @@ -0,0 +1,226 @@ +--- +title: Functions +description: + Learn how to declare functions and methods in Noir, a programming language with Rust semantics. + This guide covers parameter declaration, return types, call expressions, and more. +keywords: [Noir, Rust, functions, methods, parameter declaration, return types, call expressions] +sidebar_position: 1 +--- + +Functions in Noir follow the same semantics of Rust, though Noir does not support early returns. + +To declare a function the `fn` keyword is used. + +```rust +fn foo() {} +``` + +By default, functions are visible only within the package they are defined. To make them visible outside of that package (for example, as part of a [library](../modules_packages_crates/crates_and_packages.md#libraries)), you should mark them as `pub`: + +```rust +pub fn foo() {} +``` + +You can also restrict the visibility of the function to only the crate it was defined in, by specifying `pub(crate)`: + +```rust +pub(crate) fn foo() {} //foo can only be called within its crate +``` + +All parameters in a function must have a type and all types are known at compile time. The parameter +is pre-pended with a colon and the parameter type. Multiple parameters are separated using a comma. + +```rust +fn foo(x : Field, y : Field){} +``` + +The return type of a function can be stated by using the `->` arrow notation. The function below +states that the foo function must return a `Field`. If the function returns no value, then the arrow +is omitted. + +```rust +fn foo(x : Field, y : Field) -> Field { + x + y +} +``` + +Note that a `return` keyword is unneeded in this case - the last expression in a function's body is +returned. + +## Main function + +If you're writing a binary, the `main` function is the starting point of your program. You can pass all types of expressions to it, as long as they have a fixed size at compile time: + +```rust +fn main(x : Field) // this is fine: passing a Field +fn main(x : [Field; 2]) // this is also fine: passing a Field with known size at compile-time +fn main(x : (Field, bool)) // 👌: passing a (Field, bool) tuple means size 2 +fn main(x : str<5>) // this is fine, as long as you pass a string of size 5 + +fn main(x : Vec) // can't compile, has variable size +fn main(x : [Field]) // can't compile, has variable size +fn main(....// i think you got it by now +``` + +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: + +```rust +fn main(x : [Field]) { + assert(x[0] == 1); +} + +#[test] +fn test_one() { + main(&[1, 2]); +} +``` + +```bash +$ nargo test +[testing] Running 1 test functions +[testing] Testing test_one... ok +[testing] All tests passed + +$ nargo check +The application panicked (crashed). +Message: Cannot have variable sized arrays as a parameter to main +``` + +## Call Expressions + +Calling a function in Noir is executed by using the function name and passing in the necessary +arguments. + +Below we show how to call the `foo` function from the `main` function using a call expression: + +```rust +fn main(x : Field, y : Field) { + let z = foo(x); +} + +fn foo(x : Field) -> Field { + x + x +} +``` + +## Methods + +You can define methods in Noir on any struct type in scope. + +```rust +struct MyStruct { + foo: Field, + bar: Field, +} + +impl MyStruct { + fn new(foo: Field) -> MyStruct { + MyStruct { + foo, + bar: 2, + } + } + + fn sum(self) -> Field { + self.foo + self.bar + } +} + +fn main() { + let s = MyStruct::new(40); + assert(s.sum() == 42); +} +``` + +Methods are just syntactic sugar for functions, so if we wanted to we could also call `sum` as +follows: + +```rust +assert(MyStruct::sum(s) == 42); +``` + +It is also possible to specialize which method is chosen depending on the [generic](./generics.md) type that is used. In this example, the `foo` function returns different values depending on its type: + +```rust +struct Foo {} + +impl Foo { + fn foo(self) -> Field { 1 } +} + +impl Foo { + fn foo(self) -> Field { 2 } +} + +fn main() { + let f1: Foo = Foo{}; + let f2: Foo = Foo{}; + assert(f1.foo() + f2.foo() == 3); +} +``` + +Also note that impls with the same method name defined in them cannot overlap. For example, if we already have `foo` defined for `Foo` and `Foo` like we do above, we cannot also define `foo` in an `impl Foo` since it would be ambiguous which version of `foo` to choose. + +```rust +// Including this impl in the same project as the above snippet would +// cause an overlapping impls error +impl Foo { + fn foo(self) -> Field { 3 } +} +``` + +## Lambdas + +Lambdas are anonymous functions. They follow the syntax of Rust - `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +See [Lambdas](./lambdas.md) for more details. + +## Attributes + +Attributes are metadata that can be applied to a function, using the following syntax: `#[attribute(value)]`. + +Supported attributes include: + +- **builtin**: the function is implemented by the compiler, for efficiency purposes. +- **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` +- **field**: Used to enable conditional compilation of code depending on the field size. See below for more details +- **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details + +### Field Attribute + +The field attribute defines which field the function is compatible for. The function is conditionally compiled, under the condition that the field attribute matches the Noir native field. +The field can be defined implicitly, by using the name of the elliptic curve usually associated to it - for instance bn254, bls12_381 - or explicitly by using the field (prime) order, in decimal or hexadecimal form. +As a result, it is possible to define multiple versions of a function with each version specialized for a different field attribute. This can be useful when a function requires different parameters depending on the underlying elliptic curve. + +Example: we define the function `foo()` three times below. Once for the default Noir bn254 curve, once for the field $\mathbb F_{23}$, which will normally never be used by Noir, and once again for the bls12_381 curve. + +```rust +#[field(bn254)] +fn foo() -> u32 { + 1 +} + +#[field(23)] +fn foo() -> u32 { + 2 +} + +// This commented code would not compile as foo would be defined twice because it is the same field as bn254 +// #[field(21888242871839275222246405745257275088548364400416034343698204186575808495617)] +// fn foo() -> u32 { +// 2 +// } + +#[field(bls12_381)] +fn foo() -> u32 { + 3 +} +``` + +If the field name is not known to Noir, it will discard the function. Field names are case insensitive. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md new file mode 100644 index 000000000000..0c1c27a22211 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/generics.md @@ -0,0 +1,106 @@ +--- +title: Generics +description: Learn how to use Generics in Noir +keywords: [Noir, Rust, generics, functions, structs] +sidebar_position: 7 +--- + +Generics allow you to use the same functions with multiple different concrete data types. You can +read more about the concept of generics in the Rust documentation +[here](https://doc.rust-lang.org/book/ch10-01-syntax.html). + +Here is a trivial example showing the identity function that supports any type. In Rust, it is +common to refer to the most general type as `T`. We follow the same convention in Noir. + +```rust +fn id(x: T) -> T { + x +} +``` + +## In Structs + +Generics are useful for specifying types in structs. For example, we can specify that a field in a +struct will be of a certain generic type. In this case `value` is of type `T`. + +```rust +struct RepeatedValue { + value: T, + count: Field, +} + +impl RepeatedValue { + fn print(self) { + for _i in 0 .. self.count { + println(self.value); + } + } +} + +fn main() { + let repeated = RepeatedValue { value: "Hello!", count: 2 }; + repeated.print(); +} +``` + +The `print` function will print `Hello!` an arbitrary number of times, twice in this case. + +If we want to be generic over array lengths (which are type-level integers), we can use numeric +generics. Using these looks just like using regular generics, but these generics can resolve to +integers at compile-time, rather than resolving to types. Here's an example of a struct that is +generic over the size of the array it contains internally: + +```rust +struct BigInt { + limbs: [u32; N], +} + +impl BigInt { + // `N` is in scope of all methods in the impl + fn first(first: BigInt, second: BigInt) -> Self { + assert(first.limbs != second.limbs); + first + + fn second(first: BigInt, second: Self) -> Self { + assert(first.limbs != second.limbs); + second + } +} +``` + +## Calling functions on generic parameters + +Since a generic type `T` can represent any type, how can we call functions on the underlying type? +In other words, how can we go from "any type `T`" to "any type `T` that has certain methods available?" + +This is what [traits](../concepts/traits.md) are for in Noir. Here's an example of a function generic over +any type `T` that implements the `Eq` trait for equality: + +```rust +fn first_element_is_equal(array1: [T; N], array2: [T; N]) -> bool + where T: Eq +{ + if (array1.len() == 0) | (array2.len() == 0) { + true + } else { + array1[0] == array2[0] + } +} + +fn main() { + assert(first_element_is_equal([1, 2, 3], [1, 5, 6])); + + // We can use first_element_is_equal for arrays of any type + // as long as we have an Eq impl for the types we pass in + let array = [MyStruct::new(), MyStruct::new()]; + assert(array_eq(array, array, MyStruct::eq)); +} + +impl Eq for MyStruct { + fn eq(self, other: MyStruct) -> bool { + self.foo == other.foo + } +} +``` + +You can find more details on traits and trait implementations on the [traits page](../concepts/traits.md). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md new file mode 100644 index 000000000000..063a3d89248d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/globals.md @@ -0,0 +1,72 @@ +--- +title: Global Variables +description: + Learn about global variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, globals, global variables, constants] +sidebar_position: 8 +--- + +## Globals + + +Noir supports global variables. The global's type can be inferred by the compiler entirely: + +```rust +global N = 5; // Same as `global N: Field = 5` + +global TUPLE = (3, 2); + +fn main() { + assert(N == 5); + assert(N == TUPLE.0 + TUPLE.1); +} +``` + +:::info + +Globals can be defined as any expression, so long as they don't depend on themselves - otherwise there would be a dependency cycle! For example: + +```rust +global T = foo(T); // dependency error +``` + +::: + + +If they are initialized to a literal integer, globals can be used to specify an array's length: + +```rust +global N: Field = 2; + +fn main(y : [Field; N]) { + assert(y[0] == y[1]) +} +``` + +A global from another module can be imported or referenced externally like any other name: + +```rust +global N = 20; + +fn main() { + assert(my_submodule::N != N); +} + +mod my_submodule { + global N: Field = 10; +} +``` + +When a global is used, Noir replaces the name with its definition on each occurrence. +This means globals defined using function calls will repeat the call each time they're used: + +```rust +global RESULT = foo(); + +fn foo() -> [Field; 100] { ... } +``` + +This is usually fine since Noir will generally optimize any function call that does not +refer to a program input into a constant. It should be kept in mind however, if the called +function performs side-effects like `println`, as these will still occur on each use. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md new file mode 100644 index 000000000000..be3c7e0b5caa --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/lambdas.md @@ -0,0 +1,81 @@ +--- +title: Lambdas +description: Learn how to use anonymous functions in Noir programming language. +keywords: [Noir programming language, lambda, closure, function, anonymous function] +sidebar_position: 9 +--- + +## Introduction + +Lambdas are anonymous functions. The syntax is `|arg1, arg2, ..., argN| return_expression`. + +```rust +let add_50 = |val| val + 50; +assert(add_50(100) == 150); +``` + +A block can be used as the body of a lambda, allowing you to declare local variables inside it: + +```rust +let cool = || { + let x = 100; + let y = 100; + x + y +} + +assert(cool() == 200); +``` + +## Closures + +Inside the body of a lambda, you can use variables defined in the enclosing function. Such lambdas are called **closures**. In this example `x` is defined inside `main` and is accessed from within the lambda: + +```rust +fn main() { + let x = 100; + let closure = || x + 150; + assert(closure() == 250); +} +``` + +## Passing closures to higher-order functions + +It may catch you by surprise that the following code fails to compile: + +```rust +fn foo(f: fn () -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // error :( +} +``` + +The reason is that the closure's capture environment affects its type - we have a closure that captures two Fields and `foo` +expects a regular function as an argument - those are incompatible. +:::note + +Variables contained within the `||` are the closure's parameters, and the expression that follows it is the closure's body. The capture environment is comprised of any variables used in the closure's body that are not parameters. + +E.g. in |x| x + y, y would be a captured variable, but x would not be, since it is a parameter of the closure. + +::: +The syntax for the type of a closure is `fn[env](args) -> ret_type`, where `env` is the capture environment of the closure - +in this example that's `(Field, Field)`. + +The best solution in our case is to make `foo` generic over the environment type of its parameter, so that it can be called +with closures with any environment, as well as with regular functions: + +```rust +fn foo(f: fn[Env]() -> Field) -> Field { + f() +} + +fn main() { + let (x, y) = (50, 50); + assert(foo(|| x + y) == 100); // compiles fine + assert(foo(|| 60) == 60); // compiles fine +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md new file mode 100644 index 000000000000..fdeef6a87c53 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/mutability.md @@ -0,0 +1,121 @@ +--- +title: Mutability +description: + Learn about mutable variables in Noir. Discover how + to declare, modify, and use them in your programs. +keywords: [noir programming language, mutability in noir, mutable variables] +sidebar_position: 8 +--- + +Variables in noir can be declared mutable via the `mut` keyword. Mutable variables can be reassigned +to via an assignment expression. + +```rust +let x = 2; +x = 3; // error: x must be mutable to be assigned to + +let mut y = 3; +let y = 4; // OK +``` + +The `mut` modifier can also apply to patterns: + +```rust +let (a, mut b) = (1, 2); +a = 11; // error: a must be mutable to be assigned to +b = 12; // OK + +let mut (c, d) = (3, 4); +c = 13; // OK +d = 14; // OK + +// etc. +let MyStruct { x: mut y } = MyStruct { x: a }; +// y is now in scope +``` + +Note that mutability in noir is local and everything is passed by value, so if a called function +mutates its parameters then the parent function will keep the old value of the parameters. + +```rust +fn main() -> pub Field { + let x = 3; + helper(x); + x // x is still 3 +} + +fn helper(mut x: i32) { + x = 4; +} +``` + +## Non-local mutability + +Non-local mutability can be achieved through the mutable reference type `&mut T`: + +```rust +fn set_to_zero(x: &mut Field) { + *x = 0; +} + +fn main() { + let mut y = 42; + set_to_zero(&mut y); + assert(*y == 0); +} +``` + +When creating a mutable reference, the original variable being referred to (`y` in this +example) must also be mutable. Since mutable references are a reference type, they must +be explicitly dereferenced via `*` to retrieve the underlying value. Note that this yields +a copy of the value, so mutating this copy will not change the original value behind the +reference: + +```rust +fn main() { + let mut x = 1; + let x_ref = &mut x; + + let mut y = *x_ref; + let y_ref = &mut y; + + x = 2; + *x_ref = 3; + + y = 4; + *y_ref = 5; + + assert(x == 3); + assert(*x_ref == 3); + assert(y == 5); + assert(*y_ref == 5); +} +``` + +Note that types in Noir are actually deeply immutable so the copy that occurs when +dereferencing is only a conceptual copy - no additional constraints will occur. + +Mutable references can also be stored within structs. Note that there is also +no lifetime parameter on these unlike rust. This is because the allocated memory +always lasts the entire program - as if it were an array of one element. + +```rust +struct Foo { + x: &mut Field +} + +impl Foo { + fn incr(mut self) { + *self.x += 1; + } +} + +fn main() { + let foo = Foo { x: &mut 0 }; + foo.incr(); + assert(*foo.x == 1); +} +``` + +In general, you should avoid non-local & shared mutability unless it is needed. Sticking +to only local mutability will improve readability and potentially improve compiler optimizations as well. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md new file mode 100644 index 000000000000..c35c36c38a90 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/ops.md @@ -0,0 +1,98 @@ +--- +title: Logical Operations +description: + Learn about the supported arithmetic and logical operations in the Noir programming language. + Discover how to perform operations on private input types, integers, and booleans. +keywords: + [ + Noir programming language, + supported operations, + arithmetic operations, + logical operations, + predicate operators, + bitwise operations, + short-circuiting, + backend, + ] +sidebar_position: 3 +--- + +# Operations + +## Table of Supported Operations + +| Operation | Description | Requirements | +| :-------- | :------------------------------------------------------------: | -------------------------------------: | +| + | Adds two private input types together | Types must be private input | +| - | Subtracts two private input types together | Types must be private input | +| \* | Multiplies two private input types together | Types must be private input | +| / | Divides two private input types together | Types must be private input | +| ^ | XOR two private input types together | Types must be integer | +| & | AND two private input types together | Types must be integer | +| \| | OR two private input types together | Types must be integer | +| \<\< | Left shift an integer by another integer amount | Types must be integer, shift must be u8 | +| >> | Right shift an integer by another integer amount | Types must be integer, shift must be u8 | +| ! | Bitwise not of a value | Type must be integer or boolean | +| \< | returns a bool if one value is less than the other | Upper bound must have a known bit size | +| \<= | returns a bool if one value is less than or equal to the other | Upper bound must have a known bit size | +| > | returns a bool if one value is more than the other | Upper bound must have a known bit size | +| >= | returns a bool if one value is more than or equal to the other | Upper bound must have a known bit size | +| == | returns a bool if one value is equal to the other | Both types must not be constants | +| != | returns a bool if one value is not equal to the other | Both types must not be constants | + +### Predicate Operators + +`<,<=, !=, == , >, >=` are known as predicate/comparison operations because they compare two values. +This differs from the operations such as `+` where the operands are used in _computation_. + +### Bitwise Operations Example + +```rust +fn main(x : Field) { + let y = x as u32; + let z = y & y; +} +``` + +`z` is implicitly constrained to be the result of `y & y`. The `&` operand is used to denote bitwise +`&`. + +> `x & x` would not compile as `x` is a `Field` and not an integer type. + +### Logical Operators + +Noir has no support for the logical operators `||` and `&&`. This is because encoding the +short-circuiting that these operators require can be inefficient for Noir's backend. Instead you can +use the bitwise operators `|` and `&` which operate identically for booleans, just without the +short-circuiting. + +```rust +let my_val = 5; + +let mut flag = 1; +if (my_val > 6) | (my_val == 0) { + flag = 0; +} +assert(flag == 1); + +if (my_val != 10) & (my_val < 50) { + flag = 0; +} +assert(flag == 0); +``` + +### Shorthand operators + +Noir shorthand operators for most of the above operators, namely `+=, -=, *=, /=, %=, &=, |=, ^=, <<=`, and `>>=`. These allow for more concise syntax. For example: + +```rust +let mut i = 0; +i = i + 1; +``` + +could be written as: + +```rust +let mut i = 0; +i += 1; +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md new file mode 100644 index 000000000000..aa380b5f7b87 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/oracles.md @@ -0,0 +1,31 @@ +--- +title: Oracles +description: Dive into how Noir supports Oracles via RPC calls, and learn how to declare an Oracle in Noir with our comprehensive guide. +keywords: + - Noir + - Oracles + - RPC Calls + - Unconstrained Functions + - Programming + - Blockchain +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) + +You can declare an Oracle through the `#[oracle()]` flag. Example: + +```rust +#[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/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md new file mode 100644 index 000000000000..5ce6130d2011 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/shadowing.md @@ -0,0 +1,44 @@ +--- +title: Shadowing +sidebar_position: 12 +--- + +Noir allows for inheriting variables' values and re-declaring them with the same name similar to Rust, known as shadowing. + +For example, the following function is valid in Noir: + +```rust +fn main() { + let x = 5; + + { + let x = x * 2; + assert (x == 10); + } + + assert (x == 5); +} +``` + +In this example, a variable x is first defined with the value 5. + +The local scope that follows shadows the original x, i.e. creates a local mutable x based on the value of the original x. It is given a value of 2 times the original x. + +When we return to the main scope, x once again refers to just the original x, which stays at the value of 5. + +## Temporal mutability + +One way that shadowing is useful, in addition to ergonomics across scopes, is for temporarily mutating variables. + +```rust +fn main() { + let age = 30; + // age = age + 5; // Would error as `age` is immutable by default. + + let mut age = age + 5; // Temporarily mutates `age` with a new value. + + let age = age; // Locks `age`'s mutability again. + + assert (age == 35); +} +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md new file mode 100644 index 000000000000..df7cb9ebda02 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/traits.md @@ -0,0 +1,389 @@ +--- +title: Traits +description: + Traits in Noir can be used to abstract out a common interface for functions across + several data types. +keywords: [noir programming language, traits, interfaces, generic, protocol] +sidebar_position: 14 +--- + +## Overview + +Traits in Noir are a useful abstraction similar to interfaces or protocols in other languages. Each trait defines +the interface of several methods contained within the trait. Types can then implement this trait by providing +implementations for these methods. For example in the program: + +```rust +struct Rectangle { + width: Field, + height: Field, +} + +impl Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +fn log_area(r: Rectangle) { + println(r.area()); +} +``` + +We have a function `log_area` to log the area of a `Rectangle`. Now how should we change the program if we want this +function to work on `Triangle`s as well?: + +```rust +struct Triangle { + width: Field, + height: Field, +} + +impl Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Making `log_area` generic over all types `T` would be invalid since not all types have an `area` method. Instead, we can +introduce a new `Area` trait and make `log_area` generic over all types `T` that implement `Area`: + +```rust +trait Area { + fn area(self) -> Field; +} + +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +We also need to explicitly implement `Area` for `Rectangle` and `Triangle`. We can do that by changing their existing +impls slightly. Note that the parameter types and return type of each of our `area` methods must match those defined +by the `Area` trait. + +```rust +impl Area for Rectangle { + fn area(self) -> Field { + self.width * self.height + } +} + +impl Area for Triangle { + fn area(self) -> Field { + self.width * self.height / 2 + } +} +``` + +Now we have a working program that is generic over any type of Shape that is used! Others can even use this program +as a library with their own types - such as `Circle` - as long as they also implement `Area` for these types. + +## Where Clauses + +As seen in `log_area` above, when we want to create a function or method that is generic over any type that implements +a trait, we can add a where clause to the generic function. + +```rust +fn log_area(shape: T) where T: Area { + println(shape.area()); +} +``` + +It is also possible to apply multiple trait constraints on the same variable at once by combining traits with the `+` +operator. Similarly, we can have multiple trait constraints by separating each with a comma: + +```rust +fn foo(elements: [T], thing: U) where + T: Default + Add + Eq, + U: Bar, +{ + let mut sum = T::default(); + + for element in elements { + sum += element; + } + + if sum == T::default() { + thing.bar(); + } +} +``` + +## Generic Implementations + +You can add generics to a trait implementation by adding the generic list after the `impl` keyword: + +```rust +trait Second { + fn second(self) -> Field; +} + +impl Second for (T, Field) { + fn second(self) -> Field { + self.1 + } +} +``` + +You can also implement a trait for every type this way: + +```rust +trait Debug { + fn debug(self); +} + +impl Debug for T { + fn debug(self) { + println(self); + } +} + +fn main() { + 1.debug(); +} +``` + +### Generic Trait Implementations With Where Clauses + +Where clauses can also be placed on trait implementations themselves to restrict generics in a similar way. +For example, while `impl Foo for T` implements the trait `Foo` for every type, `impl Foo for T where T: Bar` +will implement `Foo` only for types that also implement `Bar`. This is often used for implementing generic types. +For example, here is the implementation for array equality: + +```rust +impl Eq for [T; N] where T: Eq { + // Test if two arrays have the same elements. + // Because both arrays must have length N, we know their lengths already match. + fn eq(self, other: Self) -> bool { + let mut result = true; + + for i in 0 .. self.len() { + // The T: Eq constraint is needed to call == on the array elements here + result &= self[i] == other[i]; + } + + result + } +} +``` + +## Generic Traits + +Traits themselves can also be generic by placing the generic arguments after the trait name. These generics are in +scope of every item within the trait. + +```rust +trait Into { + // Convert `self` to type `T` + fn into(self) -> T; +} +``` + +When implementing generic traits the generic arguments of the trait must be specified. This is also true anytime +when referencing a generic trait (e.g. in a `where` clause). + +```rust +struct MyStruct { + array: [Field; 2], +} + +impl Into<[Field; 2]> for MyStruct { + fn into(self) -> [Field; 2] { + self.array + } +} + +fn as_array(x: T) -> [Field; 2] + where T: Into<[Field; 2]> +{ + x.into() +} + +fn main() { + let array = [1, 2]; + let my_struct = MyStruct { array }; + + assert_eq(as_array(my_struct), array); +} +``` + +## Trait Methods With No `self` + +A trait can contain any number of methods, each of which have access to the `Self` type which represents each type +that eventually implements the trait. Similarly, the `self` variable is available as well but is not required to be used. +For example, we can define a trait to create a default value for a type. This trait will need to return the `Self` type +but doesn't need to take any parameters: + +```rust +trait Default { + fn default() -> Self; +} +``` + +Implementing this trait can be done similarly to any other trait: + +```rust +impl Default for Field { + fn default() -> Field { + 0 + } +} + +struct MyType {} + +impl Default for MyType { + fn default() -> Field { + MyType {} + } +} +``` + +However, since there is no `self` parameter, we cannot call it via the method call syntax `object.method()`. +Instead, we'll need to refer to the function directly. This can be done either by referring to the +specific impl `MyType::default()` or referring to the trait itself `Default::default()`. In the later +case, type inference determines the impl that is selected. + +```rust +let my_struct = MyStruct::default(); + +let x: Field = Default::default(); +let result = x + Default::default(); +``` + +:::warning + +```rust +let _ = Default::default(); +``` + +If type inference cannot select which impl to use because of an ambiguous `Self` type, an impl will be +arbitrarily selected. This occurs most often when the result of a trait function call with no parameters +is unused. To avoid this, when calling a trait function with no `self` or `Self` parameters or return type, +always refer to it via the implementation type's namespace - e.g. `MyType::default()`. +This is set to change to an error in future Noir versions. + +::: + +## Default Method Implementations + +A trait can also have default implementations of its methods by giving a body to the desired functions. +Note that this body must be valid for all types that may implement the trait. As a result, the only +valid operations on `self` will be operations valid for any type or other operations on the trait itself. + +```rust +trait Numeric { + fn add(self, other: Self) -> Self; + + // Default implementation of double is (self + self) + fn double(self) -> Self { + self.add(self) + } +} +``` + +When implementing a trait with default functions, a type may choose to implement only the required functions: + +```rust +impl Numeric for Field { + fn add(self, other: Field) -> Field { + self + other + } +} +``` + +Or it may implement the optional methods as well: + +```rust +impl Numeric for u32 { + fn add(self, other: u32) -> u32 { + self + other + } + + fn double(self) -> u32 { + self * 2 + } +} +``` + +## Impl Specialization + +When implementing traits for a generic type it is possible to implement the trait for only a certain combination +of generics. This can be either as an optimization or because those specific generics are required to implement the trait. + +```rust +trait Sub { + fn sub(self, other: Self) -> Self; +} + +struct NonZero { + value: T, +} + +impl Sub for NonZero { + fn sub(self, other: Self) -> Self { + let value = self.value - other.value; + assert(value != 0); + NonZero { value } + } +} +``` + +## Overlapping Implementations + +Overlapping implementations are disallowed by Noir to ensure Noir's decision on which impl to select is never ambiguous. +This means if a trait `Foo` is already implemented +by a type `Bar` for all `T`, then we cannot also have a separate impl for `Bar` (or any other +type argument). Similarly, if there is an impl for all `T` such as `impl Debug for T`, we cannot create +any more impls to `Debug` for other types since it would be ambiguous which impl to choose for any given +method call. + +```rust +trait Trait {} + +// Previous impl defined here +impl Trait for (A, B) {} + +// error: Impl for type `(Field, Field)` overlaps with existing impl +impl Trait for (Field, Field) {} +``` + +## Trait Coherence + +Another restriction on trait implementations is coherence. This restriction ensures other crates cannot create +impls that may overlap with other impls, even if several unrelated crates are used as dependencies in the same +program. + +The coherence restriction is: to implement a trait, either the trait itself or the object type must be declared +in the crate the impl is in. + +In practice this often comes up when using types provided by libraries. If a library provides a type `Foo` that does +not implement a trait in the standard library such as `Default`, you may not `impl Default for Foo` in your own crate. +While restrictive, this prevents later issues or silent changes in the program if the `Foo` library later added its +own impl for `Default`. If you are a user of the `Foo` library in this scenario and need a trait not implemented by the +library your choices are to either submit a patch to the library or use the newtype pattern. + +### The Newtype Pattern + +The newtype pattern gets around the coherence restriction by creating a new wrapper type around the library type +that we cannot create `impl`s for. Since the new wrapper type is defined in our current crate, we can create +impls for any trait we need on it. + +```rust +struct Wrapper { + foo: some_library::Foo, +} + +impl Default for Wrapper { + fn default() -> Wrapper { + Wrapper { + foo: some_library::Foo::new(), + } + } +} +``` + +Since we have an impl for our own type, the behavior of this code will not change even if `some_library` is updated +to provide its own `impl Default for Foo`. The downside of this pattern is that it requires extra wrapping and +unwrapping of values when converting to and from the `Wrapper` and `Foo` types. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md new file mode 100644 index 000000000000..96f824c5e425 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/concepts/unconstrained.md @@ -0,0 +1,99 @@ +--- +title: Unconstrained Functions +description: "Learn about what unconstrained functions in Noir are, how to use them and when you'd want to." + +keywords: [Noir programming language, unconstrained, open] +sidebar_position: 5 +--- + +Unconstrained functions are functions which do not constrain any of the included computation and allow for non-deterministic computation. + +## Why? + +Zero-knowledge (ZK) domain-specific languages (DSL) enable developers to generate ZK proofs from their programs by compiling code down to the constraints of an NP complete language (such as R1CS or PLONKish languages). However, the hard bounds of a constraint system can be very limiting to the functionality of a ZK DSL. + +Enabling a circuit language to perform unconstrained execution is a powerful tool. Said another way, unconstrained execution lets developers generate witnesses from code that does not generate any constraints. Being able to execute logic outside of a circuit is critical for both circuit performance and constructing proofs on information that is external to a circuit. + +Fetching information from somewhere external to a circuit can also be used to enable developers to improve circuit efficiency. + +A ZK DSL does not just prove computation, but proves that some computation was handled correctly. Thus, it is necessary that when we switch from performing some operation directly inside of a circuit to inside of an unconstrained environment that the appropriate constraints are still laid down elsewhere in the circuit. + +## Example + +An in depth example might help drive the point home. This example comes from the excellent [post](https://discord.com/channels/1113924620781883405/1124022445054111926/1128747641853972590) by Tom in the Noir Discord. + +Let's look at how we can optimize a function to turn a `u72` into an array of `u8`s. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u72 & 0xff) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 91 +Backend circuit size: 3619 +``` + +A lot of the operations in this function are optimized away by the compiler (all the bit-shifts turn into divisions by constants). However we can save a bunch of gates by casting to u8 a bit earlier. This automatically truncates the bit-shifted value to fit in a u8 which allows us to remove the AND against 0xff. This saves us ~480 gates in total. + +```rust +fn main(num: u72) -> pub [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8)) as u8; + } + + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 75 +Backend circuit size: 3143 +``` + +Those are some nice savings already but we can do better. This code is all constrained so we're proving every step of calculating out using num, but we don't actually care about how we calculate this, just that it's correct. This is where brillig comes in. + +It turns out that truncating a u72 into a u8 is hard to do inside a snark, each time we do as u8 we lay down 4 ACIR opcodes which get converted into multiple gates. It's actually much easier to calculate num from out than the other way around. All we need to do is multiply each element of out by a constant and add them all together, both relatively easy operations inside a snark. + +We can then run u72_to_u8 as unconstrained brillig code in order to calculate out, then use that result in our constrained function and assert that if we were to do the reverse calculation we'd get back num. This looks a little like the below: + +```rust +fn main(num: u72) -> pub [u8; 8] { + let out = u72_to_u8(num); + + let mut reconstructed_num: u72 = 0; + for i in 0..8 { + reconstructed_num += (out[i] as u72 << (56 - (8 * i))); + } + assert(num == reconstructed_num); + out +} + +unconstrained fn u72_to_u8(num: u72) -> [u8; 8] { + let mut out: [u8; 8] = [0; 8]; + for i in 0..8 { + out[i] = (num >> (56 - (i * 8))) as u8; + } + out +} +``` + +``` +Total ACIR opcodes generated for language PLONKCSat { width: 3 }: 78 +Backend circuit size: 2902 +``` + +This ends up taking off another ~250 gates from our circuit! We've ended up with more ACIR opcodes than before but they're easier for the backend to prove (resulting in fewer gates). + +Generally we want to use brillig whenever there's something that's easy to verify but hard to compute within the circuit. For example, if you wanted to calculate a square root of a number it'll be a much better idea to calculate this in brillig and then assert that if you square the result you get back your number. + +## Break and Continue + +In addition to loops over runtime bounds, `break` and `continue` are also available in unconstrained code. See [break and continue](../concepts/control_flow.md#break-and-continue) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json new file mode 100644 index 000000000000..1debcfe76753 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Modules, Packages and Crates", + "position": 2, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md new file mode 100644 index 000000000000..95ee9f52ab21 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/crates_and_packages.md @@ -0,0 +1,43 @@ +--- +title: Crates and Packages +description: Learn how to use Crates and Packages in your Noir project +keywords: [Nargo, dependencies, package management, crates, package] +sidebar_position: 0 +--- + +## Crates + +A crate is the smallest amount of code that the Noir compiler considers at a time. +Crates can contain modules, and the modules may be defined in other files that get compiled with the crate, as we’ll see in the coming sections. + +### Crate Types + +A Noir crate can come in several forms: binaries, libraries or contracts. + +#### Binaries + +_Binary crates_ are programs which you can compile to an ACIR circuit which you can then create proofs against. Each must have a function called `main` that defines the ACIR circuit which is to be proved. + +#### Libraries + +_Library crates_ don't have a `main` function and they don't compile down to ACIR. Instead they define functionality intended to be shared with multiple projects, and eventually included in a binary crate. + +#### Contracts + +Contract crates are similar to binary crates in that they compile to ACIR which you can create proofs against. They are different in that they do not have a single `main` function, but are a collection of functions to be deployed to the [Aztec network](https://aztec.network). You can learn more about the technical details of Aztec in the [monorepo](https://github.com/AztecProtocol/aztec-packages) or contract [examples](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts). + +### Crate Root + +Every crate has a root, which is the source file that the compiler starts, this is also known as the root module. The Noir compiler does not enforce any conditions on the name of the file which is the crate root, however if you are compiling via Nargo the crate root must be called `lib.nr` or `main.nr` for library or binary crates respectively. + +## Packages + +A Nargo _package_ is a collection of one of more crates that provides a set of functionality. A package must include a Nargo.toml file. + +A package _must_ contain either a library or a binary crate, but not both. + +### Differences from Cargo Packages + +One notable difference between Rust's Cargo and Noir's Nargo is that while Cargo allows a package to contain an unlimited number of binary crates and a single library crate, Nargo currently only allows a package to contain a single crate. + +In future this restriction may be lifted to allow a Nargo package to contain both a binary and library crate or multiple binary crates. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md new file mode 100644 index 000000000000..24e02de08fe8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/dependencies.md @@ -0,0 +1,124 @@ +--- +title: Dependencies +description: + Learn how to specify and manage dependencies in Nargo, allowing you to upload packages to GitHub + and use them easily in your project. +keywords: [Nargo, dependencies, GitHub, package management, versioning] +sidebar_position: 1 +--- + +Nargo allows you to upload packages to GitHub and use them as dependencies. + +## Specifying a dependency + +Specifying a dependency requires a tag to a specific commit and the git url to the url containing +the package. + +Currently, there are no requirements on the tag contents. If requirements are added, it would follow +semver 2.0 guidelines. + +> Note: Without a `tag` , there would be no versioning and dependencies would change each time you +> compile your project. + +For example, to add the [ecrecover-noir library](https://github.com/colinnielsen/ecrecover-noir) to your project, add it to `Nargo.toml`: + +```toml +# Nargo.toml + +[dependencies] +ecrecover = {tag = "v0.8.0", git = "https://github.com/colinnielsen/ecrecover-noir"} +``` + +If the module is in a subdirectory, you can define a subdirectory in your git repository, for example: + +```toml +# Nargo.toml + +[dependencies] +easy_private_token_contract = {tag ="v0.1.0-alpha62", git = "https://github.com/AztecProtocol/aztec-packages", directory = "noir-contracts/contracts/easy_private_token_contract"} +``` + +## Specifying a local dependency + +You can also specify dependencies that are local to your machine. + +For example, this file structure has a library and binary crate + +```tree +├── binary_crate +│   ├── Nargo.toml +│   └── src +│   └── main.nr +└── lib_a + ├── Nargo.toml + └── src + └── lib.nr +``` + +Inside of the binary crate, you can specify: + +```toml +# Nargo.toml + +[dependencies] +lib_a = { path = "../lib_a" } +``` + +## Importing dependencies + +You can import a dependency to a Noir file using the following syntax. For example, to import the +ecrecover-noir library and local lib_a referenced above: + +```rust +use ecrecover; +use lib_a; +``` + +You can also import only the specific parts of dependency that you want to use, like so: + +```rust +use std::hash::sha256; +use std::scalar_mul::fixed_base_embedded_curve; +``` + +Lastly, as demonstrated in the +[elliptic curve example](../standard_library/cryptographic_primitives/ec_primitives.md#examples), you +can import multiple items in the same line by enclosing them in curly braces: + +```rust +use std::ec::tecurve::affine::{Curve, Point}; +``` + +We don't have a way to consume libraries from inside a [workspace](./workspaces.md) as external dependencies right now. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +## Dependencies of Dependencies + +Note that when you import a dependency, you also get access to all of the dependencies of that package. + +For example, the [phy_vector](https://github.com/resurgencelabs/phy_vector) library imports an [fraction](https://github.com/resurgencelabs/fraction) library. If you're importing the phy_vector library, then you can access the functions in fractions library like so: + +```rust +use phy_vector; + +fn main(x : Field, y : pub Field) { + //... + let f = phy_vector::fraction::toFraction(true, 2, 1); + //... +} +``` + +## Available Libraries + +Noir does not currently have an official package manager. You can find a list of available Noir libraries in the [awesome-noir repo here](https://github.com/noir-lang/awesome-noir#libraries). + +Some libraries that are available today include: + +- [Standard Library](https://github.com/noir-lang/noir/tree/master/noir_stdlib) - the Noir Standard Library +- [Ethereum Storage Proof Verification](https://github.com/aragonzkresearch/noir-trie-proofs) - a library that contains the primitives necessary for RLP decoding (in the form of look-up table construction) and Ethereum state and storage proof verification (or verification of any trie proof involving 32-byte long keys) +- [BigInt](https://github.com/shuklaayush/noir-bigint) - a library that provides a custom BigUint56 data type, allowing for computations on large unsigned integers +- [ECrecover](https://github.com/colinnielsen/ecrecover-noir/tree/main) - a library to verify an ECDSA signature and return the source Ethereum address +- [Sparse Merkle Tree Verifier](https://github.com/vocdoni/smtverifier-noir/tree/main) - a library for verification of sparse Merkle trees +- [Signed Int](https://github.com/resurgencelabs/signed_int) - a library for accessing a custom Signed Integer data type, allowing access to negative numbers on Noir +- [Fraction](https://github.com/resurgencelabs/fraction) - a library for accessing fractional number data type in Noir, allowing results that aren't whole numbers diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md new file mode 100644 index 000000000000..ae822a1cff4e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/modules.md @@ -0,0 +1,105 @@ +--- +title: Modules +description: + Learn how to organize your files using modules in Noir, following the same convention as Rust's + module system. Examples included. +keywords: [Noir, Rust, modules, organizing files, sub-modules] +sidebar_position: 2 +--- + +Noir's module system follows the same convention as the _newer_ version of Rust's module system. + +## Purpose of Modules + +Modules are used to organize files. Without modules all of your code would need to live in a single +file. In Noir, the compiler does not automatically scan all of your files to detect modules. This +must be done explicitly by the developer. + +## Examples + +### Importing a module in the crate root + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::hello_world(); +} +``` + +Filename : `src/foo.nr` + +```rust +fn from_foo() {} +``` + +In the above snippet, the crate root is the `src/main.nr` file. The compiler sees the module +declaration `mod foo` which prompts it to look for a foo.nr file. + +Visually this module hierarchy looks like the following : + +``` +crate + ├── main + │ + └── foo + └── from_foo + +``` + +### Importing a module throughout the tree + +All modules are accessible from the `crate::` namespace. + +``` +crate + ├── bar + ├── foo + └── main + +``` + +In the above snippet, if `bar` would like to use functions in `foo`, it can do so by `use crate::foo::function_name`. + +### Sub-modules + +Filename : `src/main.nr` + +```rust +mod foo; + +fn main() { + foo::from_foo(); +} +``` + +Filename : `src/foo.nr` + +```rust +mod bar; +fn from_foo() {} +``` + +Filename : `src/foo/bar.nr` + +```rust +fn from_bar() {} +``` + +In the above snippet, we have added an extra module to the module tree; `bar`. `bar` is a submodule +of `foo` hence we declare bar in `foo.nr` with `mod bar`. Since `foo` is not the crate root, the +compiler looks for the file associated with the `bar` module in `src/foo/bar.nr` + +Visually the module hierarchy looks as follows: + +``` +crate + ├── main + │ + └── foo + ├── from_foo + └── bar + └── from_bar +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md new file mode 100644 index 000000000000..513497f12bf7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/modules_packages_crates/workspaces.md @@ -0,0 +1,42 @@ +--- +title: Workspaces +sidebar_position: 3 +--- + +Workspaces are a feature of nargo that allow you to manage multiple related Noir packages in a single repository. A workspace is essentially a group of related projects that share common build output directories and configurations. + +Each Noir project (with it's own Nargo.toml file) can be thought of as a package. Each package is expected to contain exactly one "named circuit", being the "name" defined in Nargo.toml with the program logic defined in `./src/main.nr`. + +For a project with the following structure: + +```tree +├── crates +│ ├── a +│ │ ├── Nargo.toml +│ │ └── 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: + +```toml +[workspace] +members = ["crates/a", "crates/b"] +default-member = "crates/a" +``` + +`members` indicates which packages are included in the workspace. As such, all member packages of a workspace will be processed when the `--workspace` flag is used with various commands or if a `default-member` is not specified. + +`default-member` indicates which package various commands process by default. + +Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. + +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json new file mode 100644 index 000000000000..af04c0933fdb --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Standard Library", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md new file mode 100644 index 000000000000..2bfdeec6631d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bigint.md @@ -0,0 +1,122 @@ +--- +title: Big Integers +description: How to use big integers from Noir standard library +keywords: + [ + Big Integer, + Noir programming language, + Noir libraries, + ] +--- + +The BigInt module in the standard library exposes some class of integers which do not fit (well) into a Noir native field. It implements modulo arithmetic, modulo a 'big' prime number. + +:::note + +The module can currently be considered as `Field`s with fixed modulo sizes used by a set of elliptic curves, in addition to just the native curve. [More work](https://github.com/noir-lang/noir/issues/510) is needed to achieve arbitrarily sized big integers. + +::: + +Currently 6 classes of integers (i.e 'big' prime numbers) are available in the module, namely: + +- BN254 Fq: Bn254Fq +- BN254 Fr: Bn254Fr +- Secp256k1 Fq: Secpk1Fq +- Secp256k1 Fr: Secpk1Fr +- Secp256r1 Fr: Secpr1Fr +- Secp256r1 Fq: Secpr1Fq + +Where XXX Fq and XXX Fr denote respectively the order of the base and scalar field of the (usual) elliptic curve XXX. +For instance the big integer 'Secpk1Fq' in the standard library refers to integers modulo $2^{256}-2^{32}-977$. + +Feel free to explore the source code for the other primes: + +```rust title="big_int_definition" showLineNumbers +struct BigInt { + pointer: u32, + modulus: u32, +} +``` +> Source code: noir_stdlib/src/bigint.nr#L14-L19 + + +## Example usage + +A common use-case is when constructing a big integer from its bytes representation, and performing arithmetic operations on it: + +```rust title="big_int_example" showLineNumbers +fn big_int_example(x: u8, y: u8) { + let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + let b = Secpk1Fq::from_le_bytes(&[y, x, 9]); + let c = (a + b) * b / a; + let d = c.to_le_bytes(); + println(d[0]); +} +``` +> Source code: test_programs/execution_success/bigint/src/main.nr#L70-L78 + + +## Methods + +The available operations for each big integer are: + +### from_le_bytes + +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: + +### to_le_bytes + +Return the little-endian bytes representation of a big integer. Example: + +```rust +let bytes = a.to_le_bytes(); +``` + +### add + +Add two big integers. Example: + +```rust +let sum = a + b; +``` + +### sub + +Subtract two big integers. Example: + +```rust +let difference = a - b; +``` + +### mul + +Multiply two big integers. Example: + +```rust +let product = a * b; +``` + +### div + +Divide two big integers. Note that division is field division and not euclidean division. Example: + +```rust +let quotient = a / b; +``` + +### eq + +Compare two big integers. Example: + +```rust +let are_equal = a == b; +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md new file mode 100644 index 000000000000..d5694250f052 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/black_box_fns.md @@ -0,0 +1,32 @@ +--- +title: Black Box Functions +description: Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. +keywords: [noir, black box functions] +--- + +Black box functions are functions in Noir that rely on backends implementing support for specialized constraints. This makes certain zk-snark unfriendly computations cheaper than if they were implemented in Noir. + +The ACVM spec defines a set of blackbox functions which backends will be expected to implement. This allows backends to use optimized implementations of these constraints if they have them, however they may also fallback to less efficient naive implementations if not. + +## Function list + +Here is a list of the current black box functions: + +- [AES128](./cryptographic_primitives/ciphers.mdx#aes128) +- [SHA256](./cryptographic_primitives/hashes.mdx#sha256) +- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx) +- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s) +- [Blake3](./cryptographic_primitives/hashes.mdx#blake3) +- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash) +- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment) +- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx) +- [Embedded curve operations (MSM, addition, ...)](./cryptographic_primitives/embedded_curve_ops.mdx) +- AND +- XOR +- RANGE +- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256) +- [Recursive proof verification](./recursion.md) + +Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function. + +You can view the black box functions defined in the ACVM code [here](https://github.com/noir-lang/noir/blob/master/acvm-repo/acir/src/circuit/black_box_functions.rs). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md new file mode 100644 index 000000000000..3294f005dbb4 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/bn254.md @@ -0,0 +1,46 @@ +--- +title: Bn254 Field Library +--- + +Noir provides a module in standard library with some optimized functions for bn254 Fr in `std::field::bn254`. + +## decompose + +```rust +fn decompose(x: Field) -> (Field, Field) {} +``` + +Decomposes a single field into two fields, low and high. The low field contains the lower 16 bytes of the input field and the high field contains the upper 16 bytes of the input field. Both field results are range checked to 128 bits. + + +## assert_gt + +```rust +fn assert_gt(a: Field, b: Field) {} +``` + +Asserts that a > b. This will generate less constraints than using `assert(gt(a, b))`. + +## assert_lt + +```rust +fn assert_lt(a: Field, b: Field) {} +``` + +Asserts that a < b. This will generate less constraints than using `assert(lt(a, b))`. + +## gt + +```rust +fn gt(a: Field, b: Field) -> bool {} +``` + +Returns true if a > b. + +## lt + +```rust +fn lt(a: Field, b: Field) -> bool {} +``` + +Returns true if a < b. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md new file mode 100644 index 000000000000..4349eab67c53 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/boundedvec.md @@ -0,0 +1,419 @@ +--- +title: Bounded Vectors +keywords: [noir, vector, bounded vector, slice] +sidebar_position: 1 +--- + +A `BoundedVec` is a growable storage similar to a `Vec` except that it +is bounded with a maximum possible length. Unlike `Vec`, `BoundedVec` is not implemented +via slices and thus is not subject to the same restrictions slices are (notably, nested +slices - and thus nested vectors as well - are disallowed). + +Since a BoundedVec is backed by a normal array under the hood, growing the BoundedVec by +pushing an additional element is also more efficient - the length only needs to be increased +by one. + +For these reasons `BoundedVec` should generally be preferred over `Vec` when there +is a reasonable maximum bound that can be placed on the vector. + +Example: + +```rust +let mut vector: BoundedVec = BoundedVec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +assert(vector.max_len() == 10); +``` + +## Methods + +### new + +```rust +pub fn new() -> Self +``` + +Creates a new, empty vector of length zero. + +Since this container is backed by an array internally, it still needs an initial value +to give each element. To resolve this, each element is zeroed internally. This value +is guaranteed to be inaccessible unless `get_unchecked` is used. + +Example: + +```rust +let empty_vector: BoundedVec = BoundedVec::new(); +assert(empty_vector.len() == 0); +``` + +Note that whenever calling `new` the maximum length of the vector should always be specified +via a type signature: + +```rust title="new_example" showLineNumbers +fn foo() -> BoundedVec { + // Ok! MaxLen is specified with a type annotation + let v1: BoundedVec = BoundedVec::new(); + let v2 = BoundedVec::new(); + + // Ok! MaxLen is known from the type of foo's return value + v2 +} + +fn bad() { + let mut v3 = BoundedVec::new(); + + // Not Ok! We don't know if v3's MaxLen is at least 1, and the compiler often infers 0 by default. + v3.push(5); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L11-L27 + + +This defaulting of `MaxLen` (and numeric generics in general) to zero may change in future noir versions +but for now make sure to use type annotations when using bounded vectors. Otherwise, you will receive a constraint failure at runtime when the vec is pushed to. + +### get + +```rust +pub fn get(self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this +will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + let last = v.get(v.len() - 1); + assert(first != last); +} +``` + +### get_unchecked + +```rust +pub fn get_unchecked(self, index: u64) -> T { +``` + +Retrieves an element from the vector at the given index, starting from zero, without +performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, +it is unsafe! Use at your own risk! + +Example: + +```rust title="get_unchecked_example" showLineNumbers +fn sum_of_first_three(v: BoundedVec) -> u32 { + // Always ensure the length is larger than the largest + // index passed to get_unchecked + assert(v.len() > 2); + let first = v.get_unchecked(0); + let second = v.get_unchecked(1); + let third = v.get_unchecked(2); + first + second + third +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L54-L64 + + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +If the given index is equal to or greater than the length of the vector, this will issue a constraint failure. + +Example: + +```rust +fn foo(v: BoundedVec) { + let first = v.get(0); + assert(first != 42); + v.set(0, 42); + let new_first = v.get(0); + assert(new_first == 42); +} +``` + +### set_unchecked + +```rust +pub fn set_unchecked(&mut self: Self, index: u64, value: T) -> T { +``` + +Writes an element to the vector at the given index, starting from zero, without performing a bounds check. + +Since this function does not perform a bounds check on length before accessing the element, it is unsafe! Use at your own risk! + +Example: + +```rust title="set_unchecked_example" showLineNumbers +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L67-L91 + + + +### push + +```rust +pub fn push(&mut self, elem: T) { +``` + +Pushes an element to the end of the vector. This increases the length +of the vector by one. + +Panics if the new length of the vector will be greater than the max length. + +Example: + +```rust title="bounded-vec-push-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + v.push(1); + v.push(2); + + // Panics with failed assertion "push out of bounds" + v.push(3); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L95-L103 + + +### pop + +```rust +pub fn pop(&mut self) -> T +``` + +Pops the element at the end of the vector. This will decrease the length +of the vector by one. + +Panics if the vector is empty. + +Example: + +```rust title="bounded-vec-pop-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.push(1); + v.push(2); + + let two = v.pop(); + let one = v.pop(); + + assert(two == 2); + assert(one == 1); + // error: cannot pop from an empty vector + // let _ = v.pop(); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L108-L120 + + +### len + +```rust +pub fn len(self) -> u64 { +``` + +Returns the current length of this vector + +Example: + +```rust title="bounded-vec-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + assert(v.len() == 0); + + v.push(100); + assert(v.len() == 1); + + v.push(200); + v.push(300); + v.push(400); + assert(v.len() == 4); + + let _ = v.pop(); + let _ = v.pop(); + assert(v.len() == 2); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L125-L140 + + +### max_len + +```rust +pub fn max_len(_self: BoundedVec) -> u64 { +``` + +Returns the maximum length of this vector. This is always +equal to the `MaxLen` parameter this vector was initialized with. + +Example: + +```rust title="bounded-vec-max-len-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.max_len() == 5); + v.push(10); + assert(v.max_len() == 5); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L145-L151 + + +### storage + +```rust +pub fn storage(self) -> [T; MaxLen] { +``` + +Returns the internal array within this vector. +Since arrays in Noir are immutable, mutating the returned storage array will not mutate +the storage held internally by this vector. + +Note that uninitialized elements may be zeroed out! + +Example: + +```rust title="bounded-vec-storage-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + + assert(v.storage() == [0, 0, 0, 0, 0]); + + v.push(57); + assert(v.storage() == [57, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L156-L163 + + +### extend_from_array + +```rust +pub fn extend_from_array(&mut self, array: [T; Len]) +``` + +Pushes each element from the given array to this vector. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-array-example" showLineNumbers +let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([2, 4]); + + assert(vec.len == 2); + assert(vec.get(0) == 2); + assert(vec.get(1) == 4); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L168-L175 + + +### extend_from_bounded_vec + +```rust +pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) +``` + +Pushes each element from the other vector to this vector. The length of +the other vector is left unchanged. + +Panics if pushing each element would cause the length of this vector +to exceed the maximum length. + +Example: + +```rust title="bounded-vec-extend-from-bounded-vec-example" showLineNumbers +let mut v1: BoundedVec = BoundedVec::new(); + let mut v2: BoundedVec = BoundedVec::new(); + + v2.extend_from_array([1, 2, 3]); + v1.extend_from_bounded_vec(v2); + + assert(v1.storage() == [1, 2, 3, 0, 0]); + assert(v2.storage() == [1, 2, 3, 0, 0, 0, 0]); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L180-L189 + + +### from_array + +```rust +pub fn from_array(array: [T; Len]) -> Self +``` + +Creates a new vector, populating it with values derived from an array input. +The maximum length of the vector is determined based on the type signature. + +Example: +```rust +let bounded_vec: BoundedVec = BoundedVec::from_array([1, 2, 3]) +``` + +### map + +```rust +pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec +``` + +Creates a new vector of equal size by calling a closure on each element in this vector. + +Example: + +```rust title="bounded-vec-map-example" showLineNumbers +let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); +``` +> Source code: noir_stdlib/src/collections/bounded_vec.nr#L214-L217 + + +### any + +```rust +pub fn any(self, predicate: fn[Env](T) -> bool) -> bool +``` + +Returns true if the given predicate returns true for any element +in this vector. + +Example: + +```rust title="bounded-vec-any-example" showLineNumbers +let mut v: BoundedVec = BoundedVec::new(); + v.extend_from_array([2, 4, 6]); + + let all_even = !v.any(|elem: u32| elem % 2 != 0); + assert(all_even); +``` +> Source code: test_programs/noir_test_success/bounded_vec/src/main.nr#L256-L262 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md new file mode 100644 index 000000000000..408b6ba9da7d --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/hashmap.md @@ -0,0 +1,570 @@ +--- +title: HashMap +keywords: [noir, map, hash, hashmap] +sidebar_position: 1 +--- + +`HashMap` is used to efficiently store and look up key-value pairs. + +`HashMap` is a bounded type which can store anywhere from zero to `MaxLen` total elements. +Note that due to hash collisions, the actual maximum number of elements stored by any particular +hashmap is likely lower than `MaxLen`. This is true even with cryptographic hash functions since +every hash value will be performed modulo `MaxLen`. + +When creating `HashMap`s, the `MaxLen` generic should always be specified if it is not already +known. Otherwise, the compiler may infer a different value for `MaxLen` (such as zero), which +will likely change the result of the program. This behavior is set to become an error in future +versions instead. + +Example: + +```rust +// Create a mapping from Fields to u32s with a maximum length of 12 +// using a poseidon2 hasher +use std::hash::poseidon2::Poseidon2Hasher; +let mut map: HashMap> = HashMap::default(); + +map.insert(1, 2); +map.insert(3, 4); + +let two = map.get(1).unwrap(); +``` + +## Methods + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Creates a fresh, empty HashMap. + +When using this function, always make sure to specify the maximum size of the hash map. + +This is the same `default` from the `Default` implementation given further below. It is +repeated here for convenience since it is the recommended way to create a hashmap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +Because `HashMap` has so many generic arguments that are likely to be the same throughout +your program, it may be helpful to create a type alias: + +```rust title="type_alias" showLineNumbers +type MyMap = HashMap>; +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L196-L198 + + +### with_hasher + +```rust title="with_hasher" showLineNumbers +pub fn with_hasher(_build_hasher: B) -> Self + where + B: BuildHasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L82-L86 + + +Creates a hashmap with an existing `BuildHasher`. This can be used to ensure multiple +hashmaps are created with the same hasher instance. + +Example: + +```rust title="with_hasher_example" showLineNumbers +let my_hasher: BuildHasherDefault = Default::default(); + let hashmap: HashMap> = HashMap::with_hasher(my_hasher); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L207-L211 + + +### get + +```rust title="get" showLineNumbers +pub fn get( + self, + key: K + ) -> Option + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L278-L287 + + +Retrieves a value from the hashmap, returning `Option::none()` if it was not found. + +Example: + +```rust title="get_example" showLineNumbers +fn get_example(map: HashMap>) { + let x = map.get(12); + + if x.is_some() { + assert(x.unwrap() == 42); + } +} +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L299-L307 + + +### insert + +```rust title="insert" showLineNumbers +pub fn insert( + &mut self, + key: K, + value: V + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L313-L323 + + +Inserts a new key-value pair into the map. If the key was already in the map, its +previous value will be overridden with the newly provided one. + +Example: + +```rust title="insert_example" showLineNumbers +let mut map: HashMap> = HashMap::default(); + map.insert(12, 42); + assert(map.len() == 1); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L213-L217 + + +### remove + +```rust title="remove" showLineNumbers +pub fn remove( + &mut self, + key: K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L356-L365 + + +Removes the given key-value pair from the map. If the key was not already present +in the map, this does nothing. + +Example: + +```rust title="remove_example" showLineNumbers +map.remove(12); + assert(map.is_empty()); + + // If a key was not present in the map, remove does nothing + map.remove(12); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L221-L228 + + +### is_empty + +```rust title="is_empty" showLineNumbers +pub fn is_empty(self) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L115-L117 + + +True if the length of the hash map is empty. + +Example: + +```rust title="is_empty_example" showLineNumbers +assert(map.is_empty()); + + map.insert(1, 2); + assert(!map.is_empty()); + + map.remove(1); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L230-L238 + + +### len + +```rust title="len" showLineNumbers +pub fn len(self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L264-L266 + + +Returns the current length of this hash map. + +Example: + +```rust title="len_example" showLineNumbers +// This is equivalent to checking map.is_empty() + assert(map.len() == 0); + + map.insert(1, 2); + map.insert(3, 4); + map.insert(5, 6); + assert(map.len() == 3); + + // 3 was already present as a key in the hash map, so the length is unchanged + map.insert(3, 7); + assert(map.len() == 3); + + map.remove(1); + assert(map.len() == 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L240-L255 + + +### capacity + +```rust title="capacity" showLineNumbers +pub fn capacity(_self: Self) -> u32 { +``` +> Source code: noir_stdlib/src/collections/map.nr#L271-L273 + + +Returns the maximum capacity of this hashmap. This is always equal to the capacity +specified in the hashmap's type. + +Unlike hashmaps in general purpose programming languages, hashmaps in Noir have a +static capacity that does not increase as the map grows larger. Thus, this capacity +is also the maximum possible element count that can be inserted into the hashmap. +Due to hash collisions (modulo the hashmap length), it is likely the actual maximum +element count will be lower than the full capacity. + +Example: + +```rust title="capacity_example" showLineNumbers +let empty_map: HashMap> = HashMap::default(); + assert(empty_map.len() == 0); + assert(empty_map.capacity() == 42); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L257-L261 + + +### clear + +```rust title="clear" showLineNumbers +pub fn clear(&mut self) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L93-L95 + + +Clears the hashmap, removing all key-value pairs from it. + +Example: + +```rust title="clear_example" showLineNumbers +assert(!map.is_empty()); + map.clear(); + assert(map.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L263-L267 + + +### contains_key + +```rust title="contains_key" showLineNumbers +pub fn contains_key( + self, + key: K + ) -> bool + where + K: Hash + Eq, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L101-L110 + + +True if the hashmap contains the given key. Unlike `get`, this will not also return +the value associated with the key. + +Example: + +```rust title="contains_key_example" showLineNumbers +if map.contains_key(7) { + let value = map.get(7); + assert(value.is_some()); + } else { + println("No value for key 7!"); + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L269-L276 + + +### entries + +```rust title="entries" showLineNumbers +pub fn entries(self) -> BoundedVec<(K, V), N> { +``` +> Source code: noir_stdlib/src/collections/map.nr#L123-L125 + + +Returns a vector of each key-value pair present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="entries_example" showLineNumbers +let entries = map.entries(); + + // The length of a hashmap may not be compile-time known, so we + // need to loop over its capacity instead + for i in 0..map.capacity() { + if i < entries.len() { + let (key, value) = entries.get(i); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L310-L321 + + +### keys + +```rust title="keys" showLineNumbers +pub fn keys(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L144-L146 + + +Returns a vector of each key present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="keys_example" showLineNumbers +let keys = map.keys(); + + for i in 0..keys.max_len() { + if i < keys.len() { + let key = keys.get_unchecked(i); + let value = map.get(key).unwrap_unchecked(); + println(f"{key} -> {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L323-L333 + + +### values + +```rust title="values" showLineNumbers +pub fn values(self) -> BoundedVec { +``` +> Source code: noir_stdlib/src/collections/map.nr#L164-L166 + + +Returns a vector of each value present in the hashmap. + +The length of the returned vector is always equal to the length of the hashmap. + +Example: + +```rust title="values_example" showLineNumbers +let values = map.values(); + + for i in 0..values.max_len() { + if i < values.len() { + let value = values.get_unchecked(i); + println(f"Found value {value}"); + } + } +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L335-L344 + + +### iter_mut + +```rust title="iter_mut" showLineNumbers +pub fn iter_mut( + &mut self, + f: fn(K, V) -> (K, V) + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L183-L192 + + +Iterates through each key-value pair of the HashMap, setting each key-value pair to the +result returned from the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If this is not desired, use `iter_values_mut` if only values need to be mutated, +or `entries` if neither keys nor values need to be mutated. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_mut_example" showLineNumbers +// Add 1 to each key in the map, and double the value associated with that key. + map.iter_mut(|k, v| (k + 1, v * 2)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L348-L351 + + +### iter_keys_mut + +```rust title="iter_keys_mut" showLineNumbers +pub fn iter_keys_mut( + &mut self, + f: fn(K) -> K + ) + where + K: Eq + Hash, + B: BuildHasher, + H: Hasher { +``` +> Source code: noir_stdlib/src/collections/map.nr#L208-L217 + + +Iterates through the HashMap, mutating each key to the result returned from +the given function. + +Note that since keys can be mutated, the HashMap needs to be rebuilt as it is iterated +through. If only iteration is desired and the keys are not intended to be mutated, +prefer using `entries` instead. + +The iteration order is left unspecified. As a result, if two keys are mutated to become +equal, which of the two values that will be present for the key in the resulting map is also unspecified. + +Example: + +```rust title="iter_keys_mut_example" showLineNumbers +// Double each key, leaving the value associated with that key untouched + map.iter_keys_mut(|k| k * 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L353-L356 + + +### iter_values_mut + +```rust title="iter_values_mut" showLineNumbers +pub fn iter_values_mut(&mut self, f: fn(V) -> V) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L233-L235 + + +Iterates through the HashMap, applying the given function to each value and mutating the +value to equal the result. This function is more efficient than `iter_mut` and `iter_keys_mut` +because the keys are untouched and the underlying hashmap thus does not need to be reordered. + +Example: + +```rust title="iter_values_mut_example" showLineNumbers +// Halve each value + map.iter_values_mut(|v| v / 2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L358-L361 + + +### retain + +```rust title="retain" showLineNumbers +pub fn retain(&mut self, f: fn(K, V) -> bool) { +``` +> Source code: noir_stdlib/src/collections/map.nr#L247-L249 + + +Retains only the key-value pairs for which the given function returns true. +Any key-value pairs for which the function returns false will be removed from the map. + +Example: + +```rust title="retain_example" showLineNumbers +map.retain(|k, v| (k != 0) & (v != 0)); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L281-L283 + + +## Trait Implementations + +### default + +```rust title="default" showLineNumbers +impl Default for HashMap +where + B: BuildHasher + Default, + H: Hasher + Default +{ + fn default() -> Self { +``` +> Source code: noir_stdlib/src/collections/map.nr#L462-L469 + + +Constructs an empty HashMap. + +Example: + +```rust title="default_example" showLineNumbers +let hashmap: HashMap> = HashMap::default(); + assert(hashmap.is_empty()); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L202-L205 + + +### eq + +```rust title="eq" showLineNumbers +impl Eq for HashMap +where + K: Eq + Hash, + V: Eq, + B: BuildHasher, + H: Hasher +{ + fn eq(self, other: HashMap) -> bool { +``` +> Source code: noir_stdlib/src/collections/map.nr#L426-L435 + + +Checks if two HashMaps are equal. + +Example: + +```rust title="eq_example" showLineNumbers +let mut map1: HashMap> = HashMap::default(); + let mut map2: HashMap> = HashMap::default(); + + map1.insert(1, 2); + map1.insert(3, 4); + + map2.insert(3, 4); + map2.insert(1, 2); + + assert(map1 == map2); +``` +> Source code: test_programs/execution_success/hashmap/src/main.nr#L285-L296 + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md new file mode 100644 index 000000000000..ea84c6d5c21e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/index.md @@ -0,0 +1,5 @@ +--- +title: Containers +description: Container types provided by Noir's standard library for storing and retrieving data +keywords: [containers, data types, vec, hashmap] +--- diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx new file mode 100644 index 000000000000..475011922f81 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/containers/vec.mdx @@ -0,0 +1,170 @@ +--- +title: Vectors +description: Delve into the Vec data type in Noir. Learn about its methods, practical examples, and best practices for using Vectors in your Noir code. +keywords: [noir, vector type, methods, examples, dynamic arrays] +sidebar_position: 6 +--- + +import Experimental from '@site/src/components/Notes/_experimental.mdx'; + + + +A vector is a collection type similar to Rust's `Vec` type. In Noir, it is a convenient way to use slices as mutable arrays. + +Example: + +```rust +let mut vector: Vec = Vec::new(); +for i in 0..5 { + vector.push(i); +} +assert(vector.len() == 5); +``` + +## Methods + +### new + +Creates a new, empty vector. + +```rust +pub fn new() -> Self +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### from_slice + +Creates a vector containing each element from a given slice. Mutations to the resulting vector will not affect the original slice. + +```rust +pub fn from_slice(slice: [T]) -> Self +``` + +Example: + +```rust +let slice: [Field] = &[1, 2, 3]; +let vector_from_slice = Vec::from_slice(slice); +assert(vector_from_slice.len() == 3); +``` + +### len + +Returns the number of elements in the vector. + +```rust +pub fn len(self) -> Field +``` + +Example: + +```rust +let empty_vector: Vec = Vec::new(); +assert(empty_vector.len() == 0); +``` + +### get + +Retrieves an element from the vector at a given index. Panics if the index points beyond the vector's end. + +```rust +pub fn get(self, index: Field) -> T +``` + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +``` + +### set + +```rust +pub fn set(&mut self: Self, index: u64, value: T) { +``` + +Writes an element to the vector at the given index, starting from zero. + +Panics if the index points beyond the vector's end. + +Example: + +```rust +let vector: Vec = Vec::from_slice(&[10, 20, 30]); +assert(vector.get(1) == 20); +vector.set(1, 42); +assert(vector.get(1) == 42); +``` + +### push + +Adds a new element to the vector's end, returning a new vector with a length one greater than the original unmodified vector. + +```rust +pub fn push(&mut self, elem: T) +``` + +Example: + +```rust +let mut vector: Vec = Vec::new(); +vector.push(10); +assert(vector.len() == 1); +``` + +### pop + +Removes an element from the vector's end, returning a new vector with a length one less than the original vector, along with the removed element. Panics if the vector's length is zero. + +```rust +pub fn pop(&mut self) -> T +``` + +Example: + +```rust +let mut vector = Vec::from_slice(&[10, 20]); +let popped_elem = vector.pop(); +assert(popped_elem == 20); +assert(vector.len() == 1); +``` + +### insert + +Inserts an element at a specified index, shifting subsequent elements to the right. + +```rust +pub fn insert(&mut self, index: Field, elem: T) +``` + +Example: + +```rust +let mut vector = Vec::from_slice(&[10, 30]); +vector.insert(1, 20); +assert(vector.get(1) == 20); +``` + +### remove + +Removes an element at a specified index, shifting subsequent elements to the left, and returns the removed element. + +```rust +pub fn remove(&mut self, index: Field) -> T +``` + +Example: + +```rust +let mut vector = Vec::from_slice(&[10, 20, 30]); +let removed_elem = vector.remove(1); +assert(removed_elem == 20); +assert(vector.len() == 2); +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json new file mode 100644 index 000000000000..5d694210bbf3 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 0, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx new file mode 100644 index 000000000000..e83e26efb973 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ciphers.mdx @@ -0,0 +1,32 @@ +--- +title: Ciphers +description: + Learn about the implemented ciphers ready to use for any Noir project +keywords: + [ciphers, Noir project, aes128, encrypt] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## aes128 + +Given a plaintext as an array of bytes, returns the corresponding aes128 ciphertext (CBC mode). Input padding is automatically performed using PKCS#7, so that the output length is `input.len() + (16 - input.len() % 16)`. + +```rust title="aes128" showLineNumbers +pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} +``` +> Source code: noir_stdlib/src/aes128.nr#L2-L4 + + +```rust +fn main() { + let input: [u8; 4] = [0, 12, 3, 15] // Random bytes, will be padded to 16 bytes. + let iv: [u8; 16] = [0; 16]; // Initialisation vector + let key: [u8; 16] = [0; 16] // AES key + let ciphertext = std::aes128::aes128_encrypt(inputs.as_bytes(), iv.as_bytes(), key.as_bytes()); // In this case, the output length will be 16 bytes. +} +``` + + + \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md new file mode 100644 index 000000000000..f839b4a228ec --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -0,0 +1,102 @@ +--- +title: Elliptic Curve Primitives +keywords: [cryptographic primitives, Noir project] +sidebar_position: 4 +--- + +Data structures and methods on them that allow you to carry out computations involving elliptic +curves over the (mathematical) field corresponding to `Field`. For the field currently at our +disposal, applications would involve a curve embedded in BN254, e.g. the +[Baby Jubjub curve](https://eips.ethereum.org/EIPS/eip-2494). + +## Data structures + +### Elliptic curve configurations + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Curve`), i.e. the specific elliptic +curve you want to use, which would be specified using any one of the methods +`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the +defining equation together with a generator point as parameters. You can find more detail in the +comments in +[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +the gist of it is that the elliptic curves of interest are usually expressed in one of the standard +forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, +you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly +together with a point at infinity) or `curvegroup` coordinates (some form of projective coordinates +requiring more coordinates but allowing for more efficient implementations of elliptic curve +operations). Conversions between all of these forms are provided, and under the hood these +conversions are done whenever an operation is more efficient in a different representation (or a +mixed coordinate representation is employed). + +### Points + +(`std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::Point`), i.e. points lying on the +elliptic curve. For a curve configuration `c` and a point `p`, it may be checked that `p` +does indeed lie on `c` by calling `c.contains(p1)`. + +## Methods + +(given a choice of curve representation, e.g. use `std::ec::tecurve::affine::Curve` and use +`std::ec::tecurve::affine::Point`) + +- The **zero element** is given by `Point::zero()`, and we can verify whether a point `p: Point` is + zero by calling `p.is_zero()`. +- **Equality**: Points `p1: Point` and `p2: Point` may be checked for equality by calling + `p1.eq(p2)`. +- **Addition**: For `c: Curve` and points `p1: Point` and `p2: Point` on the curve, adding these two + points is accomplished by calling `c.add(p1,p2)`. +- **Negation**: For a point `p: Point`, `p.negate()` is its negation. +- **Subtraction**: For `c` and `p1`, `p2` as above, subtracting `p2` from `p1` is accomplished by + calling `c.subtract(p1,p2)`. +- **Scalar multiplication**: For `c` as above, `p: Point` a point on the curve and `n: Field`, + scalar multiplication is given by `c.mul(n,p)`. If instead `n :: [u1; N]`, i.e. `n` is a bit + array, the `bit_mul` method may be used instead: `c.bit_mul(n,p)` +- **Multi-scalar multiplication**: For `c` as above and arrays `n: [Field; N]` and `p: [Point; N]`, + multi-scalar multiplication is given by `c.msm(n,p)`. +- **Coordinate representation conversions**: The `into_group` method converts a point or curve + configuration in the affine representation to one in the CurveGroup representation, and + `into_affine` goes in the other direction. +- **Curve representation conversions**: `tecurve` and `montcurve` curves and points are equivalent + and may be converted between one another by calling `into_montcurve` or `into_tecurve` on their + configurations or points. `swcurve` is more general and a curve c of one of the other two types + may be converted to this representation by calling `c.into_swcurve()`, whereas a point `p` lying + on the curve given by `c` may be mapped to its corresponding `swcurve` point by calling + `c.map_into_swcurve(p)`. +- **Map-to-curve methods**: The Elligator 2 method of mapping a field element `n: Field` into a + `tecurve` or `montcurve` with configuration `c` may be called as `c.elligator2_map(n)`. For all of + the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where + `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to + satisfy are specified in the comments + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + +## Examples + +The +[ec_baby_jubjub test](https://github.com/noir-lang/noir/blob/master/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr) +illustrates all of the above primitives on various forms of the Baby Jubjub curve. A couple of more +interesting examples in Noir would be: + +Public-key cryptography: Given an elliptic curve and a 'base point' on it, determine the public key +from the private key. This is a matter of using scalar multiplication. In the case of Baby Jubjub, +for example, this code would do: + +```rust +use std::ec::tecurve::affine::{Curve, Point}; + +fn bjj_pub_key(priv_key: Field) -> Point +{ + + let bjj = Curve::new(168700, 168696, G::new(995203441582195749578291179787384436505546430278305826713579947235728471134,5472060717959818805561601436314318772137091100104008585924551046643952123905)); + + let base_pt = Point::new(5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203); + + bjj.mul(priv_key,base_pt) +} +``` + +This would come in handy in a Merkle proof. + +- EdDSA signature verification: This is a matter of combining these primitives with a suitable hash + function. See + [feat(stdlib): EdDSA sig verification noir#1136](https://github.com/noir-lang/noir/pull/1136) for + the case of Baby Jubjub and the Poseidon hash function. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx new file mode 100644 index 000000000000..4394b48f9073 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/ecdsa_sig_verification.mdx @@ -0,0 +1,98 @@ +--- +title: ECDSA Signature Verification +description: Learn about the cryptographic primitives regarding ECDSA over the secp256k1 and secp256r1 curves +keywords: [cryptographic primitives, Noir project, ecdsa, secp256k1, secp256r1, signatures] +sidebar_position: 3 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports ECDSA signatures verification over the secp256k1 and secp256r1 curves. + +## ecdsa_secp256k1::verify_signature + +Verifier for ECDSA Secp256k1 signatures. +See ecdsa_secp256k1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256k1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L2-L9 + + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256k1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + + +## ecdsa_secp256k1::verify_signature_slice + +Verifier for ECDSA Secp256k1 signatures where the message is a slice. + +```rust title="ecdsa_secp256k1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256k1.nr#L13-L20 + + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures. +See ecdsa_secp256r1::verify_signature_slice for a version that accepts slices directly. + +```rust title="ecdsa_secp256r1" showLineNumbers +pub fn verify_signature( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L2-L9 + + +example: + +```rust +fn main(hashed_message : [u8;32], pub_key_x : [u8;32], pub_key_y : [u8;32], signature : [u8;64]) { + let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); + assert(valid_signature); +} +``` + + + +## ecdsa_secp256r1::verify_signature + +Verifier for ECDSA Secp256r1 signatures where the message is a slice. + +```rust title="ecdsa_secp256r1_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: [u8; 32], + public_key_y: [u8; 32], + signature: [u8; 64], + message_hash: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/ecdsa_secp256r1.nr#L13-L20 + + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx new file mode 100644 index 000000000000..1ad42a5ac96b --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/eddsa.mdx @@ -0,0 +1,37 @@ +--- +title: EdDSA Verification +description: Learn about the cryptographic primitives regarding EdDSA +keywords: [cryptographic primitives, Noir project, eddsa, signatures] +sidebar_position: 5 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## eddsa::eddsa_poseidon_verify + +Verifier for EdDSA signatures + +```rust +fn eddsa_poseidon_verify(public_key_x : Field, public_key_y : Field, signature_s: Field, signature_r8_x: Field, signature_r8_y: Field, message: Field) -> bool +``` + +It is also possible to specify the hash algorithm used for the signature by using the `eddsa_verify` function by passing a type implementing the Hasher trait with the turbofish operator. +For instance, if you want to use Poseidon2 instead, you can do the following: +```rust +use std::hash::poseidon2::Poseidon2Hasher; + +eddsa_verify::(pub_key_a.x, pub_key_a.y, s_a, r8_a.x, r8_a.y, msg); +``` + + + +## eddsa::eddsa_to_pub + +Private to public key conversion. + +Returns `(pub_key_x, pub_key_y)` + +```rust +fn eddsa_to_pub(secret : Field) -> (Field, Field) +``` + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx new file mode 100644 index 000000000000..14d7dda7f0d9 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/embedded_curve_ops.mdx @@ -0,0 +1,98 @@ +--- +title: Scalar multiplication +description: See how you can perform scalar multiplication in Noir +keywords: [cryptographic primitives, Noir project, scalar multiplication] +sidebar_position: 1 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +The following functions perform operations over the embedded curve whose coordinates are defined by the configured noir field. +For the BN254 scalar field, this is BabyJubJub or Grumpkin. + +:::note +Suffixes `_low` and `_high` denote low and high limbs of a scalar. +::: + +## embedded_curve_ops::multi_scalar_mul + +Performs multi scalar multiplication over the embedded curve. +The function accepts arbitrary amount of point-scalar pairs on the input, it multiplies the individual pairs over +the curve and returns a sum of the resulting points. + +Points represented as x and y coordinates [x1, y1, x2, y2, ...], scalars as low and high limbs [low1, high1, low2, high2, ...]. + +```rust title="multi_scalar_mul" showLineNumbers +pub fn multi_scalar_mul( + points: [EmbeddedCurvePoint; N], + scalars: [EmbeddedCurveScalar; N] +) -> [Field; 3] +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L62-L67 + + +example + +```rust +fn main(point_x: Field, point_y: Field, scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::multi_scalar_mul([point_x, point_y], [scalar_low, scalar_high]); + println(point); +} +``` + +## embedded_curve_ops::fixed_base_scalar_mul + +Performs fixed base scalar multiplication over the embedded curve (multiplies input scalar with a generator point). +The function accepts a single scalar on the input represented as 2 fields. + +```rust title="fixed_base_scalar_mul" showLineNumbers +pub fn fixed_base_scalar_mul( + scalar_low: Field, + scalar_high: Field +) -> [Field; 3] +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L70-L75 + + +example + +```rust +fn main(scalar_low: Field, scalar_high: Field) { + let point = std::embedded_curve_ops::fixed_base_scalar_mul(scalar_low, scalar_high); + println(point); +} +``` + +## embedded_curve_ops::embedded_curve_add + +Adds two points on the embedded curve. +This function takes two `EmbeddedCurvePoint` structures as parameters, representing points on the curve, and returns a new `EmbeddedCurvePoint` structure that represents their sum. + +### Parameters: +- `point1` (`EmbeddedCurvePoint`): The first point to add. +- `point2` (`EmbeddedCurvePoint`): The second point to add. + +### Returns: +- `EmbeddedCurvePoint`: The resulting point after the addition of `point1` and `point2`. + +```rust title="embedded_curve_add" showLineNumbers +fn embedded_curve_add( + point1: EmbeddedCurvePoint, + point2: EmbeddedCurvePoint +) -> EmbeddedCurvePoint +``` +> Source code: noir_stdlib/src/embedded_curve_ops.nr#L84-L89 + + +example + +```rust +fn main() { + let point1 = EmbeddedCurvePoint { x: 1, y: 2 }; + let point2 = EmbeddedCurvePoint { x: 3, y: 4 }; + let result = std::embedded_curve_ops::embedded_curve_add(point1, point2); + println!("Resulting Point: ({}, {})", result.x, result.y); +} +``` + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx new file mode 100644 index 000000000000..18132b9a4dcd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -0,0 +1,246 @@ +--- +title: Hash methods +description: + Learn about the cryptographic primitives ready to use for any Noir project, including sha256, + blake2s, pedersen, mimc_bn254 and mimc +keywords: + [cryptographic primitives, Noir project, sha256, blake2s, pedersen, mimc_bn254, mimc, hash] +sidebar_position: 0 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## sha256 + +Given an array of bytes, returns the resulting sha256 hash. +Specify a message_size to hash only the first `message_size` bytes of the input. + +```rust title="sha256" showLineNumbers +pub fn sha256(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L11-L13 + + +example: +```rust title="sha256_var" showLineNumbers +let digest = std::hash::sha256_var([x as u8], 1); +``` +> Source code: test_programs/execution_success/sha256/src/main.nr#L16-L18 + + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::sha256::sha256_var(x, 4); +} +``` + + + + +## blake2s + +Given an array of bytes, returns an array with the Blake2 hash + +```rust title="blake2s" showLineNumbers +pub fn blake2s(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L17-L19 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake2s(x); +} +``` + + + +## blake3 + +Given an array of bytes, returns an array with the Blake3 hash + +```rust title="blake3" showLineNumbers +pub fn blake3(input: [u8; N]) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L23-L25 + + +example: + +```rust +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::blake3(x); +} +``` + + + +## pedersen_hash + +Given an array of Fields, returns the Pedersen hash. + +```rust title="pedersen_hash" showLineNumbers +pub fn pedersen_hash(input: [Field; N]) -> Field +``` +> Source code: noir_stdlib/src/hash.nr#L42-L44 + + +example: + +```rust title="pedersen-hash" showLineNumbers +fn main(x: Field, y: Field, expected_hash: Field) { + let hash = std::hash::pedersen_hash([x, y]); + assert_eq(hash, expected_hash); +} +``` +> Source code: test_programs/execution_success/pedersen_hash/src/main.nr#L1-L7 + + + + +## pedersen_commitment + +Given an array of Fields, returns the Pedersen commitment. + +```rust title="pedersen_commitment" showLineNumbers +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +``` +> Source code: noir_stdlib/src/hash.nr#L28-L30 + + +example: + +```rust title="pedersen-commitment" showLineNumbers +fn main(x: Field, y: Field, expected_commitment: std::embedded_curve_ops::EmbeddedCurvePoint) { + let commitment = std::hash::pedersen_commitment([x, y]); + assert_eq(commitment.x, expected_commitment.x); + assert_eq(commitment.y, expected_commitment.y); +} +``` +> Source code: test_programs/execution_success/pedersen_commitment/src/main.nr#L1-L8 + + + + +## keccak256 + +Given an array of bytes (`u8`), returns the resulting keccak hash as an array of +32 bytes (`[u8; 32]`). Specify a message_size to hash only the first +`message_size` bytes of the input. + +```rust title="keccak256" showLineNumbers +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +``` +> Source code: noir_stdlib/src/hash.nr#L64-L66 + + +example: + +```rust title="keccak256" showLineNumbers +fn main(x: Field, result: [u8; 32]) { + // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field + // The padding is taken care of by the program + let digest = std::hash::keccak256([x as u8], 1); + assert(digest == result); + + //#1399: variable message size + let message_size = 4; + let hash_a = std::hash::keccak256([1, 2, 3, 4], message_size); + let hash_b = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size); + + assert(hash_a == hash_b); + + let message_size_big = 8; + let hash_c = std::hash::keccak256([1, 2, 3, 4, 0, 0, 0, 0], message_size_big); + + assert(hash_a != hash_c); +} +``` +> Source code: test_programs/execution_success/keccak256/src/main.nr#L1-L21 + + + + +## poseidon + +Given an array of Fields, returns a new Field with the Poseidon Hash. Mind that you need to specify +how many inputs are there to your Poseidon function. + +```rust +// example for hash_1, hash_2 accepts an array of length 2, etc +fn hash_1(input: [Field; 1]) -> Field +``` + +example: + +```rust title="poseidon" showLineNumbers +use std::hash::poseidon; +use std::hash::poseidon2; + +fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { + let hash1 = poseidon::bn254::hash_2(x1); + assert(hash1 == y1); + + let hash2 = poseidon::bn254::hash_4(x2); + assert(hash2 == y2); + + let hash3 = poseidon2::Poseidon2::hash(x3, x3.len()); + assert(hash3 == y3); +} +``` +> Source code: test_programs/execution_success/poseidon_bn254_hash/src/main.nr#L1-L15 + + +## poseidon 2 + +Given an array of Fields, returns a new Field with the Poseidon2 Hash. Contrary to the Poseidon +function, there is only one hash and you can specify a message_size to hash only the first +`message_size` bytes of the input, + +```rust +// example for hashing the first three elements of the input +Poseidon2::hash(input, 3); +``` + +The above example for Poseidon also includes Poseidon2. + +## mimc_bn254 and mimc + +`mimc_bn254` is `mimc`, but with hardcoded parameters for the BN254 curve. You can use it by +providing an array of Fields, and it returns a Field with the hash. You can use the `mimc` method if +you're willing to input your own constants: + +```rust +fn mimc(x: Field, k: Field, constants: [Field; N], exp : Field) -> Field +``` + +otherwise, use the `mimc_bn254` method: + +```rust +fn mimc_bn254(array: [Field; N]) -> Field +``` + +example: + +```rust + +fn main() { + let x = [163, 117, 178, 149]; // some random bytes + let hash = std::hash::mimc::mimc_bn254(x); +} +``` + +## hash_to_field + +```rust +fn hash_to_field(_input : [Field]) -> Field {} +``` + +Calculates the `blake2s` hash of the inputs and returns the hash modulo the field modulus to return +a value which can be represented as a `Field`. + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md new file mode 100644 index 000000000000..650f30165d56 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/index.md @@ -0,0 +1,14 @@ +--- +title: Cryptographic Primitives +description: + Learn about the cryptographic primitives ready to use for any Noir project +keywords: + [ + cryptographic primitives, + Noir project, + ] +--- + +The Noir team is progressively adding new cryptographic primitives to the standard library. Reach out for news or if you would be interested in adding more of these calculations in Noir. + +Some methods are available thanks to the Aztec backend, not being performed using Noir. When using other backends, these methods may or may not be supplied. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx new file mode 100644 index 000000000000..b59e69c8f07f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/cryptographic_primitives/schnorr.mdx @@ -0,0 +1,64 @@ +--- +title: Schnorr Signatures +description: Learn how you can verify Schnorr signatures using Noir +keywords: [cryptographic primitives, Noir project, schnorr, signatures] +sidebar_position: 2 +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +## schnorr::verify_signature + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin). +See schnorr::verify_signature_slice for a version that works directly on slices. + +```rust title="schnorr_verify" showLineNumbers +pub fn verify_signature( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8; N] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L2-L9 + + +where `_signature` can be generated like so using the npm package +[@noir-lang/barretenberg](https://www.npmjs.com/package/@noir-lang/barretenberg) + +```js +const { BarretenbergWasm } = require('@noir-lang/barretenberg/dest/wasm'); +const { Schnorr } = require('@noir-lang/barretenberg/dest/crypto/schnorr'); + +... + +const barretenberg = await BarretenbergWasm.new(); +const schnorr = new Schnorr(barretenberg); +const pubKey = schnorr.computePublicKey(privateKey); +const message = ... +const signature = Array.from( + schnorr.constructSignature(hash, privateKey).toBuffer() +); + +... +``` + + + +## schnorr::verify_signature_slice + +Verifier for Schnorr signatures over the embedded curve (for BN254 it is Grumpkin) +where the message is a slice. + +```rust title="schnorr_verify_slice" showLineNumbers +pub fn verify_signature_slice( + public_key_x: Field, + public_key_y: Field, + signature: [u8; 64], + message: [u8] +) -> bool +``` +> Source code: noir_stdlib/src/schnorr.nr#L13-L20 + + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md new file mode 100644 index 000000000000..bb157e719dca --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/is_unconstrained.md @@ -0,0 +1,59 @@ +--- +title: Is Unconstrained Function +description: + The is_unconstrained function returns wether the context at that point of the program is unconstrained or not. +keywords: + [ + unconstrained + ] +--- + +It's very common for functions in circuits to take unconstrained hints of an expensive computation and then verify it. This is done by running the hint in an unconstrained context and then verifying the result in a constrained context. + +When a function is marked as unconstrained, any subsequent functions that it calls will also be run in an unconstrained context. However, if we are implementing a library function, other users might call it within an unconstrained context or a constrained one. Generally, in an unconstrained context we prefer just computing the result instead of taking a hint of it and verifying it, since that'd mean doing the same computation twice: + +```rust + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + my_expensive_computation_hint(); + // verify my_expensive_computation: If external_interface is called from unconstrained, this is redundant + ... +} + +``` + +In order to improve the performance in an unconstrained context you can use the function at `std::runtime::is_unconstrained() -> bool`: + + +```rust +use dep::std::runtime::is_unconstrained; + +fn my_expensive_computation(){ + ... +} + +unconstrained fn my_expensive_computation_hint(){ + my_expensive_computation() +} + +pub fn external_interface(){ + if is_unconstrained() { + my_expensive_computation(); + } else { + my_expensive_computation_hint(); + // verify my_expensive_computation + ... + } +} + +``` + +The is_unconstrained result is resolved at compile time, so in unconstrained contexts the compiler removes the else branch, and in constrained contexts the compiler removes the if branch, reducing the amount of compute necessary to run external_interface. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md new file mode 100644 index 000000000000..db75ef9f86fa --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/logging.md @@ -0,0 +1,78 @@ +--- +title: Logging +description: + Learn how to use the println statement for debugging in Noir with this tutorial. Understand the + basics of logging in Noir and how to implement it in your code. +keywords: + [ + noir logging, + println statement, + print statement, + debugging in noir, + noir std library, + logging tutorial, + basic logging in noir, + noir logging implementation, + noir debugging techniques, + rust, + ] +--- + +The standard library provides two familiar statements you can use: `println` and `print`. Despite being a limited implementation of rust's `println!` and `print!` macros, these constructs can be useful for debugging. + +You can print the output of both statements in your Noir code by using the `nargo execute` command or the `--show-output` flag when using `nargo test` (provided there are print statements in your tests). + +It is recommended to use `nargo execute` if you want to debug failing constraints with `println` or `print` statements. This is due to every input in a test being a constant rather than a witness, so we issue an error during compilation while we only print during execution (which comes after compilation). Neither `println`, nor `print` are callable for failed constraints caught at compile time. + +Both `print` and `println` are generic functions which can work on integers, fields, strings, and even structs or expressions. Note however, that slices are currently unsupported. For example: + +```rust +struct Person { + age: Field, + height: Field, +} + +fn main(age: Field, height: Field) { + let person = Person { + age: age, + height: height, + }; + println(person); + println(age + height); + println("Hello world!"); +} +``` + +You can print different types in the same statement (including strings) with a type called `fmtstr`. It can be specified in the same way as a normal string, just prepended with an "f" character: + +```rust + let fmt_str = f"i: {i}, j: {j}"; + println(fmt_str); + + let s = myStruct { y: x, x: y }; + println(s); + + println(f"i: {i}, s: {s}"); + + println(x); + println([x, y]); + + let foo = fooStruct { my_struct: s, foo: 15 }; + println(f"s: {s}, foo: {foo}"); + + println(15); // prints 0x0f, implicit Field + println(-1 as u8); // prints 255 + println(-1 as i8); // prints -1 +``` + +Examples shown above are interchangeable between the two `print` statements: + +```rust +let person = Person { age : age, height : height }; + +println(person); +print(person); + +println("Hello world!"); // Prints with a newline at the end of the input +print("Hello world!"); // Prints the input and keeps cursor on the same line +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md new file mode 100644 index 000000000000..6a9ebf72ada0 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/merkle_trees.md @@ -0,0 +1,58 @@ +--- +title: Merkle Trees +description: Learn about Merkle Trees in Noir with this tutorial. Explore the basics of computing a merkle root using a proof, with examples. +keywords: + [ + Merkle trees in Noir, + Noir programming language, + check membership, + computing root from leaf, + Noir Merkle tree implementation, + Merkle tree tutorial, + Merkle tree code examples, + Noir libraries, + pedersen hash., + ] +--- + +## compute_merkle_root + +Returns the root of the tree from the provided leaf and its hash path, using a [Pedersen hash](./cryptographic_primitives/hashes.mdx#pedersen_hash). + +```rust +fn compute_merkle_root(leaf : Field, index : Field, hash_path: [Field]) -> Field +``` + +example: + +```rust +/** + // these values are for this example only + index = "0" + priv_key = "0x000000000000000000000000000000000000000000000000000000616c696365" + secret = "0x1929ea3ab8d9106a899386883d9428f8256cfedb3c4f6b66bf4aa4d28a79988f" + note_hash_path = [ + "0x1e61bdae0f027b1b2159e1f9d3f8d00fa668a952dddd822fda80dc745d6f65cc", + "0x0e4223f3925f98934393c74975142bd73079ab0621f4ee133cee050a3c194f1a", + "0x2fd7bb412155bf8693a3bd2a3e7581a679c95c68a052f835dddca85fa1569a40" + ] + */ +fn main(index: Field, priv_key: Field, secret: Field, note_hash_path: [Field; 3]) { + + let pubkey = std::scalar_mul::fixed_base_embedded_curve(priv_key); + let pubkey_x = pubkey[0]; + let pubkey_y = pubkey[1]; + let note_commitment = std::hash::pedersen(&[pubkey_x, pubkey_y, secret]); + + let root = std::merkle::compute_merkle_root(note_commitment[0], index, note_hash_path.as_slice()); + println(root); +} +``` + +To check merkle tree membership: + +1. Include a merkle root as a program input. +2. Compute the merkle root of a given leaf, index and hash path. +3. Assert the merkle roots are equal. + +For more info about merkle trees, see the Wikipedia [page](https://en.wikipedia.org/wiki/Merkle_tree). diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md new file mode 100644 index 000000000000..a1bd4e1de5fd --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/options.md @@ -0,0 +1,101 @@ +--- +title: Option Type +--- + +The `Option` type is a way to express that a value might be present (`Some(T))` or absent (`None`). It's a safer way to handle potential absence of values, compared to using nulls in many other languages. + +```rust +struct Option { + None, + Some(T), +} +``` + +The `Option` type, already imported into your Noir program, can be used directly: + +```rust +fn main() { + let none = Option::none(); + let some = Option::some(3); +} +``` + +See [this test](https://github.com/noir-lang/noir/blob/5cbfb9c4a06c8865c98ff2b594464b037d821a5c/crates/nargo_cli/tests/test_data/option/src/main.nr) for a more comprehensive set of examples of each of the methods described below. + +## Methods + +### none + +Constructs a none value. + +### some + +Constructs a some wrapper around a given value. + +### is_none + +Returns true if the Option is None. + +### is_some + +Returns true of the Option is Some. + +### unwrap + +Asserts `self.is_some()` and returns the wrapped value. + +### unwrap_unchecked + +Returns the inner value without asserting `self.is_some()`. This method can be useful within an if condition when we already know that `option.is_some()`. If the option is None, there is no guarantee what value will be returned, only that it will be of type T for an `Option`. + +### unwrap_or + +Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. + +### unwrap_or_else + +Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return a default value. + +### expect + +Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value. The custom message is expected to be a format string. + +### map + +If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. + +### map_or + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. + +### map_or_else + +If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. + +### and + +Returns None if self is None. Otherwise, this returns `other`. + +### and_then + +If self is None, this returns None. Otherwise, this calls the given function with the Some value contained within self, and returns the result of that call. In some languages this function is called `flat_map` or `bind`. + +### or + +If self is Some, return self. Otherwise, return `other`. + +### or_else + +If self is Some, return self. Otherwise, return `default()`. + +### xor + +If only one of the two Options is Some, return that option. Otherwise, if both options are Some or both are None, None is returned. + +### filter + +Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. Otherwise, this returns `None`. + +### flatten + +Flattens an `Option>` into a `Option`. This returns `None` if the outer Option is None. Otherwise, this returns the inner Option. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md new file mode 100644 index 000000000000..8cfb37fc52df --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/recursion.md @@ -0,0 +1,85 @@ +--- +title: Recursive Proofs +description: Learn about how to write recursive proofs in Noir. +keywords: [recursion, recursive proofs, verification_key, verify_proof] +--- + +import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; + +Noir supports recursively verifying proofs, meaning you verify the proof of a Noir program in another Noir program. This enables creating proofs of arbitrary size by doing step-wise verification of smaller components of a large proof. + +Read [the explainer on recursion](../../explainers/explainer-recursion.md) to know more about this function and the [guide on how to use it.](../../how_to/how-to-recursion.md) + +## The `#[recursive]` Attribute + +In Noir, the `#[recursive]` attribute is used to indicate that a circuit is designed for recursive proof generation. When applied, it informs the compiler and the tooling that the circuit should be compiled in a way that makes its proofs suitable for recursive verification. This attribute eliminates the need for manual flagging of recursion at the tooling level, streamlining the proof generation process for recursive circuits. + +### Example usage with `#[recursive]` + +```rust +#[recursive] +fn main(x: Field, y: pub Field) { + assert(x == y, "x and y are not equal"); +} + +// This marks the circuit as recursion-friendly and indicates that proofs generated from this circuit +// are intended for recursive verification. +``` + +By incorporating this attribute directly in the circuit's definition, tooling like Nargo and NoirJS can automatically execute recursive-specific duties for Noir programs (e.g. recursive-friendly proof artifact generation) without additional flags or configurations. + +## Verifying Recursive Proofs + +```rust +#[foreign(recursive_aggregation)] +pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: [Field], key_hash: Field) {} +``` + + + +## Example usage + +```rust + +fn main( + verification_key : [Field; 114], + proof : [Field; 93], + public_inputs : [Field; 1], + key_hash : Field, + proof_b : [Field; 93], +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); + + std::verify_proof( + verification_key.as_slice(), + proof_b.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} +``` + +You can see a full example of recursive proofs in [this example recursion demo repo](https://github.com/noir-lang/noir-examples/tree/master/recursion). + +## Parameters + +### `verification_key` + +The verification key for the zk program that is being verified. + +### `proof` + +The proof for the zk program that is being verified. + +### `public_inputs` + +These represent the public inputs of the proof we are verifying. + +### `key_hash` + +A key hash is used to check the validity of the verification key. The circuit implementing this opcode can use this hash to ensure that the key provided to the circuit matches the key produced by the circuit creator. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md new file mode 100644 index 000000000000..a14312d27920 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/traits.md @@ -0,0 +1,464 @@ +--- +title: Traits +description: Noir's stdlib provides a few commonly used traits. +keywords: [traits, trait, interface, protocol, default, add, eq] +--- + +## `std::default` + +### `std::default::Default` + +```rust title="default-trait" showLineNumbers +trait Default { + fn default() -> Self; +} +``` +> Source code: noir_stdlib/src/default.nr#L1-L5 + + +Constructs a default value of a type. + +Implementations: +```rust +impl Default for Field { .. } + +impl Default for i8 { .. } +impl Default for i16 { .. } +impl Default for i32 { .. } +impl Default for i64 { .. } + +impl Default for u8 { .. } +impl Default for u16 { .. } +impl Default for u32 { .. } +impl Default for u64 { .. } + +impl Default for () { .. } +impl Default for bool { .. } + +impl Default for [T; N] + where T: Default { .. } + +impl Default for [T] { .. } + +impl Default for (A, B) + where A: Default, B: Default { .. } + +impl Default for (A, B, C) + where A: Default, B: Default, C: Default { .. } + +impl Default for (A, B, C, D) + where A: Default, B: Default, C: Default, D: Default { .. } + +impl Default for (A, B, C, D, E) + where A: Default, B: Default, C: Default, D: Default, E: Default { .. } +``` + +For primitive integer types, the return value of `default` is `0`. Container +types such as arrays are filled with default values of their element type, +except slices whose length is unknown and thus defaulted to zero. + + +## `std::convert` + +### `std::convert::From` + +```rust title="from-trait" showLineNumbers +trait From { + fn from(input: T) -> Self; +} +``` +> Source code: noir_stdlib/src/convert.nr#L1-L5 + + +The `From` trait defines how to convert from a given type `T` to the type on which the trait is implemented. + +The Noir standard library provides a number of implementations of `From` between primitive types. +```rust title="from-impls" showLineNumbers +// Unsigned integers + +impl From for u32 { fn from(value: u8) -> u32 { value as u32 } } + +impl From for u64 { fn from(value: u8) -> u64 { value as u64 } } +impl From for u64 { fn from(value: u32) -> u64 { value as u64 } } + +impl From for Field { fn from(value: u8) -> Field { value as Field } } +impl From for Field { fn from(value: u32) -> Field { value as Field } } +impl From for Field { fn from(value: u64) -> Field { value as Field } } + +// Signed integers + +impl From for i32 { fn from(value: i8) -> i32 { value as i32 } } + +impl From for i64 { fn from(value: i8) -> i64 { value as i64 } } +impl From for i64 { fn from(value: i32) -> i64 { value as i64 } } + +// Booleans +impl From for u8 { fn from(value: bool) -> u8 { value as u8 } } +impl From for u32 { fn from(value: bool) -> u32 { value as u32 } } +impl From for u64 { fn from(value: bool) -> u64 { value as u64 } } +impl From for i8 { fn from(value: bool) -> i8 { value as i8 } } +impl From for i32 { fn from(value: bool) -> i32 { value as i32 } } +impl From for i64 { fn from(value: bool) -> i64 { value as i64 } } +impl From for Field { fn from(value: bool) -> Field { value as Field } } +``` +> Source code: noir_stdlib/src/convert.nr#L25-L52 + + +#### When to implement `From` + +As a general rule of thumb, `From` may be implemented in the [situations where it would be suitable in Rust](https://doc.rust-lang.org/std/convert/trait.From.html#when-to-implement-from): + +- The conversion is *infallible*: Noir does not provide an equivalent to Rust's `TryFrom`, if the conversion can fail then provide a named method instead. +- The conversion is *lossless*: semantically, it should not lose or discard information. For example, `u32: From` can losslessly convert any `u16` into a valid `u32` such that the original `u16` can be recovered. On the other hand, `u16: From` should not be implemented as `2**16` is a `u32` which cannot be losslessly converted into a `u16`. +- The conversion is *value-preserving*: the conceptual kind and meaning of the resulting value is the same, even though the Noir type and technical representation might be different. While it's possible to infallibly and losslessly convert a `u8` into a `str<2>` hex representation, `4u8` and `"04"` are too different for `str<2>: From` to be implemented. +- The conversion is *obvious*: it's the only reasonable conversion between the two types. If there's ambiguity on how to convert between them such that the same input could potentially map to two different values then a named method should be used. For instance rather than implementing `U128: From<[u8; 16]>`, the methods `U128::from_le_bytes` and `U128::from_be_bytes` are used as otherwise the endianness of the array would be ambiguous, resulting in two potential values of `U128` from the same byte array. + +One additional recommendation specific to Noir is: +- The conversion is *efficient*: it's relatively cheap to convert between the two types. Due to being a ZK DSL, it's more important to avoid unnecessary computation compared to Rust. If the implementation of `From` would encourage users to perform unnecessary conversion, resulting in additional proving time, then it may be preferable to expose functionality such that this conversion may be avoided. + +### `std::convert::Into` + +The `Into` trait is defined as the reciprocal of `From`. It should be easy to convince yourself that if we can convert to type `A` from type `B`, then it's possible to convert type `B` into type `A`. + +For this reason, implementing `From` on a type will automatically generate a matching `Into` implementation. One should always prefer implementing `From` over `Into` as implementing `Into` will not generate a matching `From` implementation. + +```rust title="into-trait" showLineNumbers +trait Into { + fn into(self) -> T; +} + +impl Into for U where T: From { + fn into(self) -> T { + T::from(self) + } +} +``` +> Source code: noir_stdlib/src/convert.nr#L13-L23 + + +`Into` is most useful when passing function arguments where the types don't quite match up with what the function expects. In this case, the compiler has enough type information to perform the necessary conversion by just appending `.into()` onto the arguments in question. + + +## `std::cmp` + +### `std::cmp::Eq` + +```rust title="eq-trait" showLineNumbers +trait Eq { + fn eq(self, other: Self) -> bool; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L1-L5 + + +Returns `true` if `self` is equal to `other`. Implementing this trait on a type +allows the type to be used with `==` and `!=`. + +Implementations: +```rust +impl Eq for Field { .. } + +impl Eq for i8 { .. } +impl Eq for i16 { .. } +impl Eq for i32 { .. } +impl Eq for i64 { .. } + +impl Eq for u8 { .. } +impl Eq for u16 { .. } +impl Eq for u32 { .. } +impl Eq for u64 { .. } + +impl Eq for () { .. } +impl Eq for bool { .. } + +impl Eq for [T; N] + where T: Eq { .. } + +impl Eq for [T] + where T: Eq { .. } + +impl Eq for (A, B) + where A: Eq, B: Eq { .. } + +impl Eq for (A, B, C) + where A: Eq, B: Eq, C: Eq { .. } + +impl Eq for (A, B, C, D) + where A: Eq, B: Eq, C: Eq, D: Eq { .. } + +impl Eq for (A, B, C, D, E) + where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq { .. } +``` + +### `std::cmp::Ord` + +```rust title="ord-trait" showLineNumbers +trait Ord { + fn cmp(self, other: Self) -> Ordering; +} +``` +> Source code: noir_stdlib/src/cmp.nr#L102-L106 + + +`a.cmp(b)` compares two values returning `Ordering::less()` if `a < b`, +`Ordering::equal()` if `a == b`, or `Ordering::greater()` if `a > b`. +Implementing this trait on a type allows `<`, `<=`, `>`, and `>=` to be +used on values of the type. + +`std::cmp` also provides `max` and `min` functions for any type which implements the `Ord` trait. + +Implementations: + +```rust +impl Ord for u8 { .. } +impl Ord for u16 { .. } +impl Ord for u32 { .. } +impl Ord for u64 { .. } + +impl Ord for i8 { .. } +impl Ord for i16 { .. } +impl Ord for i32 { .. } + +impl Ord for i64 { .. } + +impl Ord for () { .. } +impl Ord for bool { .. } + +impl Ord for [T; N] + where T: Ord { .. } + +impl Ord for [T] + where T: Ord { .. } + +impl Ord for (A, B) + where A: Ord, B: Ord { .. } + +impl Ord for (A, B, C) + where A: Ord, B: Ord, C: Ord { .. } + +impl Ord for (A, B, C, D) + where A: Ord, B: Ord, C: Ord, D: Ord { .. } + +impl Ord for (A, B, C, D, E) + where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord { .. } +``` + +## `std::ops` + +### `std::ops::Add`, `std::ops::Sub`, `std::ops::Mul`, and `std::ops::Div` + +These traits abstract over addition, subtraction, multiplication, and division respectively. +Implementing these traits for a given type will also allow that type to be used with the corresponding operator +for that trait (`+` for Add, etc) in addition to the normal method names. + +```rust title="add-trait" showLineNumbers +trait Add { + fn add(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L1-L5 + +```rust title="sub-trait" showLineNumbers +trait Sub { + fn sub(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L19-L23 + +```rust title="mul-trait" showLineNumbers +trait Mul { + fn mul(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L37-L41 + +```rust title="div-trait" showLineNumbers +trait Div { + fn div(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L55-L59 + + +The implementations block below is given for the `Add` trait, but the same types that implement +`Add` also implement `Sub`, `Mul`, and `Div`. + +Implementations: +```rust +impl Add for Field { .. } + +impl Add for i8 { .. } +impl Add for i16 { .. } +impl Add for i32 { .. } +impl Add for i64 { .. } + +impl Add for u8 { .. } +impl Add for u16 { .. } +impl Add for u32 { .. } +impl Add for u64 { .. } +``` + +### `std::ops::Rem` + +```rust title="rem-trait" showLineNumbers +trait Rem{ + fn rem(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L73-L77 + + +`Rem::rem(a, b)` is the remainder function returning the result of what is +left after dividing `a` and `b`. Implementing `Rem` allows the `%` operator +to be used with the implementation type. + +Unlike other numeric traits, `Rem` is not implemented for `Field`. + +Implementations: +```rust +impl Rem for u8 { fn rem(self, other: u8) -> u8 { self % other } } +impl Rem for u16 { fn rem(self, other: u16) -> u16 { self % other } } +impl Rem for u32 { fn rem(self, other: u32) -> u32 { self % other } } +impl Rem for u64 { fn rem(self, other: u64) -> u64 { self % other } } + +impl Rem for i8 { fn rem(self, other: i8) -> i8 { self % other } } +impl Rem for i16 { fn rem(self, other: i16) -> i16 { self % other } } +impl Rem for i32 { fn rem(self, other: i32) -> i32 { self % other } } +impl Rem for i64 { fn rem(self, other: i64) -> i64 { self % other } } +``` + +### `std::ops::Neg` + +```rust title="neg-trait" showLineNumbers +trait Neg { + fn neg(self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/arith.nr#L89-L93 + + +`Neg::neg` is equivalent to the unary negation operator `-`. + +Implementations: +```rust title="neg-trait-impls" showLineNumbers +impl Neg for Field { fn neg(self) -> Field { -self } } + +impl Neg for i8 { fn neg(self) -> i8 { -self } } +impl Neg for i16 { fn neg(self) -> i16 { -self } } +impl Neg for i32 { fn neg(self) -> i32 { -self } } +impl Neg for i64 { fn neg(self) -> i64 { -self } } +``` +> Source code: noir_stdlib/src/ops/arith.nr#L95-L102 + + +### `std::ops::Not` + +```rust title="not-trait" showLineNumbers +trait Not { + fn not(self: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L1-L5 + + +`Not::not` is equivalent to the unary bitwise NOT operator `!`. + +Implementations: +```rust title="not-trait-impls" showLineNumbers +impl Not for bool { fn not(self) -> bool { !self } } + +impl Not for u64 { fn not(self) -> u64 { !self } } +impl Not for u32 { fn not(self) -> u32 { !self } } +impl Not for u16 { fn not(self) -> u16 { !self } } +impl Not for u8 { fn not(self) -> u8 { !self } } +impl Not for u1 { fn not(self) -> u1 { !self } } + +impl Not for i8 { fn not(self) -> i8 { !self } } +impl Not for i16 { fn not(self) -> i16 { !self } } +impl Not for i32 { fn not(self) -> i32 { !self } } +impl Not for i64 { fn not(self) -> i64 { !self } } +``` +> Source code: noir_stdlib/src/ops/bit.nr#L7-L20 + + +### `std::ops::{ BitOr, BitAnd, BitXor }` + +```rust title="bitor-trait" showLineNumbers +trait BitOr { + fn bitor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L22-L26 + +```rust title="bitand-trait" showLineNumbers +trait BitAnd { + fn bitand(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L40-L44 + +```rust title="bitxor-trait" showLineNumbers +trait BitXor { + fn bitxor(self, other: Self) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L58-L62 + + +Traits for the bitwise operations `|`, `&`, and `^`. + +Implementing `BitOr`, `BitAnd` or `BitXor` for a type allows the `|`, `&`, or `^` operator respectively +to be used with the type. + +The implementations block below is given for the `BitOr` trait, but the same types that implement +`BitOr` also implement `BitAnd` and `BitXor`. + +Implementations: +```rust +impl BitOr for bool { fn bitor(self, other: bool) -> bool { self | other } } + +impl BitOr for u8 { fn bitor(self, other: u8) -> u8 { self | other } } +impl BitOr for u16 { fn bitor(self, other: u16) -> u16 { self | other } } +impl BitOr for u32 { fn bitor(self, other: u32) -> u32 { self | other } } +impl BitOr for u64 { fn bitor(self, other: u64) -> u64 { self | other } } + +impl BitOr for i8 { fn bitor(self, other: i8) -> i8 { self | other } } +impl BitOr for i16 { fn bitor(self, other: i16) -> i16 { self | other } } +impl BitOr for i32 { fn bitor(self, other: i32) -> i32 { self | other } } +impl BitOr for i64 { fn bitor(self, other: i64) -> i64 { self | other } } +``` + +### `std::ops::{ Shl, Shr }` + +```rust title="shl-trait" showLineNumbers +trait Shl { + fn shl(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L76-L80 + +```rust title="shr-trait" showLineNumbers +trait Shr { + fn shr(self, other: u8) -> Self; +} +``` +> Source code: noir_stdlib/src/ops/bit.nr#L93-L97 + + +Traits for a bit shift left and bit shift right. + +Implementing `Shl` for a type allows the left shift operator (`<<`) to be used with the implementation type. +Similarly, implementing `Shr` allows the right shift operator (`>>`) to be used with the type. + +Note that bit shifting is not currently implemented for signed types. + +The implementations block below is given for the `Shl` trait, but the same types that implement +`Shl` also implement `Shr`. + +Implementations: +```rust +impl Shl for u8 { fn shl(self, other: u8) -> u8 { self << other } } +impl Shl for u16 { fn shl(self, other: u16) -> u16 { self << other } } +impl Shl for u32 { fn shl(self, other: u32) -> u32 { self << other } } +impl Shl for u64 { fn shl(self, other: u64) -> u64 { self << other } } +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md new file mode 100644 index 000000000000..f450fecdd364 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/noir/standard_library/zeroed.md @@ -0,0 +1,26 @@ +--- +title: Zeroed Function +description: + The zeroed function returns a zeroed value of any type. +keywords: + [ + zeroed + ] +--- + +Implements `fn zeroed() -> T` to return a zeroed value of any type. This function is generally unsafe to use as the zeroed bit pattern is not guaranteed to be valid for all types. It can however, be useful in cases when the value is guaranteed not to be used such as in a BoundedVec library implementing a growable vector, up to a certain length, backed by an array. The array can be initialized with zeroed values which are guaranteed to be inaccessible until the vector is pushed to. Similarly, enumerations in noir can be implemented using this method by providing zeroed values for the unused variants. + +You can access the function at `std::unsafe::zeroed`. + +This function currently supports the following types: + +- Field +- Bool +- Uint +- Array +- Slice +- String +- Tuple +- Function + +Using it on other types could result in unexpected behavior. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll new file mode 100644 index 000000000000..e2ac6616addc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md new file mode 100644 index 000000000000..d7249d243306 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend.md @@ -0,0 +1,160 @@ +# BarretenbergBackend + +## Extends + +- `BarretenbergVerifierBackend` + +## Implements + +- [`Backend`](../index.md#backend) + +## Constructors + +### new BarretenbergBackend(acirCircuit, options) + +```ts +new BarretenbergBackend(acirCircuit, options): BarretenbergBackend +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `acirCircuit` | `CompiledCircuit` | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergBackend`](BarretenbergBackend.md) + +#### Inherited from + +BarretenbergVerifierBackend.constructor + +## Properties + +| Property | Type | Description | Inheritance | +| :------ | :------ | :------ | :------ | +| `acirComposer` | `any` | - | BarretenbergVerifierBackend.acirComposer | +| `acirUncompressedBytecode` | `Uint8Array` | - | BarretenbergVerifierBackend.acirUncompressedBytecode | +| `api` | `Barretenberg` | - | BarretenbergVerifierBackend.api | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | - | BarretenbergVerifierBackend.options | + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +#### Inherited from + +BarretenbergVerifierBackend.destroy + +*** + +### generateProof() + +```ts +generateProof(compressedWitness): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `compressedWitness` | `Uint8Array` | + +#### Returns + +`Promise`\<`ProofData`\> + +#### Description + +Generates a proof + +*** + +### generateRecursiveProofArtifacts() + +```ts +generateRecursiveProofArtifacts(proofData, numOfPublicInputs): Promise +``` + +Generates artifacts that will be passed to a circuit that will verify this proof. + +Instead of passing the proof and verification key as a byte array, we pass them +as fields which makes it cheaper to verify in a circuit. + +The proof that is passed here will have been created using a circuit +that has the #[recursive] attribute on its `main` method. + +The number of public inputs denotes how many public inputs are in the inner proof. + +#### Parameters + +| Parameter | Type | Default value | +| :------ | :------ | :------ | +| `proofData` | `ProofData` | `undefined` | +| `numOfPublicInputs` | `number` | `0` | + +#### Returns + +`Promise`\<`object`\> + +#### Example + +```typescript +const artifacts = await backend.generateRecursiveProofArtifacts(proof, numOfPublicInputs); +``` + +*** + +### getVerificationKey() + +```ts +getVerificationKey(): Promise +``` + +#### Returns + +`Promise`\<`Uint8Array`\> + +#### Inherited from + +BarretenbergVerifierBackend.getVerificationKey + +*** + +### verifyProof() + +```ts +verifyProof(proofData): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Inherited from + +BarretenbergVerifierBackend.verifyProof + +#### Description + +Verifies a proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md new file mode 100644 index 000000000000..500276ea7480 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier.md @@ -0,0 +1,58 @@ +# BarretenbergVerifier + +## Constructors + +### new BarretenbergVerifier(options) + +```ts +new BarretenbergVerifier(options): BarretenbergVerifier +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `options` | [`BackendOptions`](../type-aliases/BackendOptions.md) | + +#### Returns + +[`BarretenbergVerifier`](BarretenbergVerifier.md) + +## Methods + +### destroy() + +```ts +destroy(): Promise +``` + +#### Returns + +`Promise`\<`void`\> + +*** + +### verifyProof() + +```ts +verifyProof(proofData, verificationKey): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `proofData` | `ProofData` | +| `verificationKey` | `Uint8Array` | + +#### Returns + +`Promise`\<`boolean`\> + +#### Description + +Verifies a proof + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md new file mode 100644 index 000000000000..14dfac681d40 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/index.md @@ -0,0 +1,40 @@ +# backend_barretenberg + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [BarretenbergBackend](classes/BarretenbergBackend.md) | - | +| [BarretenbergVerifier](classes/BarretenbergVerifier.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [BackendOptions](type-aliases/BackendOptions.md) | - | + +## References + +### CompiledCircuit + +Renames and re-exports [Backend](index.md#backend) + +*** + +### ProofData + +Renames and re-exports [Backend](index.md#backend) + +## Variables + +### Backend + +```ts +Backend: any; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md new file mode 100644 index 000000000000..b49a479f4f46 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions.md @@ -0,0 +1,21 @@ +# BackendOptions + +```ts +type BackendOptions: object; +``` + +## Description + +An options object, currently only used to specify the number of threads to use. + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `memory` | `object` | - | +| `memory.maximum` | `number` | - | +| `threads` | `number` | **Description**

Number of threads | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs new file mode 100644 index 000000000000..d7d5128f9e3c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/backend_barretenberg/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergBackend","label":"BarretenbergBackend"},{"type":"doc","id":"reference/NoirJS/backend_barretenberg/classes/BarretenbergVerifier","label":"BarretenbergVerifier"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/backend_barretenberg/type-aliases/BackendOptions","label":"BackendOptions"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll new file mode 100644 index 000000000000..e2ac6616addc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md new file mode 100644 index 000000000000..ead255bc5047 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/classes/Noir.md @@ -0,0 +1,52 @@ +# Noir + +## Constructors + +### new Noir(circuit) + +```ts +new Noir(circuit): Noir +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `circuit` | `CompiledCircuit` | + +#### Returns + +[`Noir`](Noir.md) + +## Methods + +### execute() + +```ts +execute(inputs, foreignCallHandler?): Promise +``` + +#### Parameters + +| Parameter | Type | +| :------ | :------ | +| `inputs` | `InputMap` | +| `foreignCallHandler`? | [`ForeignCallHandler`](../type-aliases/ForeignCallHandler.md) | + +#### Returns + +`Promise`\<`object`\> + +#### Description + +Allows to execute a circuit to get its witness and return value. + +#### Example + +```typescript +async execute(inputs) +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md new file mode 100644 index 000000000000..c783283e3965 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/and.md @@ -0,0 +1,22 @@ +# and() + +```ts +and(lhs, rhs): string +``` + +Performs a bitwise AND operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md new file mode 100644 index 000000000000..7882d0da8d50 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/blake2s256.md @@ -0,0 +1,21 @@ +# blake2s256() + +```ts +blake2s256(inputs): Uint8Array +``` + +Calculates the Blake2s256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md new file mode 100644 index 000000000000..5e3cd53e9d36 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256k1\_verify() + +```ts +ecdsa_secp256k1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256k1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md new file mode 100644 index 000000000000..0b20ff689575 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify.md @@ -0,0 +1,28 @@ +# ecdsa\_secp256r1\_verify() + +```ts +ecdsa_secp256r1_verify( + hashed_msg, + public_key_x_bytes, + public_key_y_bytes, + signature): boolean +``` + +Verifies a ECDSA signature over the secp256r1 curve. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `hashed_msg` | `Uint8Array` | | +| `public_key_x_bytes` | `Uint8Array` | | +| `public_key_y_bytes` | `Uint8Array` | | +| `signature` | `Uint8Array` | | + +## Returns + +`boolean` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md new file mode 100644 index 000000000000..d10f155ce86f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/keccak256.md @@ -0,0 +1,21 @@ +# keccak256() + +```ts +keccak256(inputs): Uint8Array +``` + +Calculates the Keccak256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md new file mode 100644 index 000000000000..6ba4ecac0229 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/sha256.md @@ -0,0 +1,21 @@ +# sha256() + +```ts +sha256(inputs): Uint8Array +``` + +Calculates the SHA256 hash of the input bytes + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `inputs` | `Uint8Array` | | + +## Returns + +`Uint8Array` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md new file mode 100644 index 000000000000..8d762b895d30 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/functions/xor.md @@ -0,0 +1,22 @@ +# xor() + +```ts +xor(lhs, rhs): string +``` + +Performs a bitwise XOR operation between `lhs` and `rhs` + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `lhs` | `string` | | +| `rhs` | `string` | | + +## Returns + +`string` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md new file mode 100644 index 000000000000..166508f71244 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/index.md @@ -0,0 +1,49 @@ +# noir_js + +## Exports + +### Classes + +| Class | Description | +| :------ | :------ | +| [Noir](classes/Noir.md) | - | + +### Type Aliases + +| Type alias | Description | +| :------ | :------ | +| [ErrorWithPayload](type-aliases/ErrorWithPayload.md) | - | +| [ForeignCallHandler](type-aliases/ForeignCallHandler.md) | A callback which performs an foreign call and returns the response. | +| [ForeignCallInput](type-aliases/ForeignCallInput.md) | - | +| [ForeignCallOutput](type-aliases/ForeignCallOutput.md) | - | +| [WitnessMap](type-aliases/WitnessMap.md) | - | + +### Functions + +| Function | Description | +| :------ | :------ | +| [and](functions/and.md) | Performs a bitwise AND operation between `lhs` and `rhs` | +| [blake2s256](functions/blake2s256.md) | Calculates the Blake2s256 hash of the input bytes | +| [ecdsa\_secp256k1\_verify](functions/ecdsa_secp256k1_verify.md) | Verifies a ECDSA signature over the secp256k1 curve. | +| [ecdsa\_secp256r1\_verify](functions/ecdsa_secp256r1_verify.md) | Verifies a ECDSA signature over the secp256r1 curve. | +| [keccak256](functions/keccak256.md) | Calculates the Keccak256 hash of the input bytes | +| [sha256](functions/sha256.md) | Calculates the SHA256 hash of the input bytes | +| [xor](functions/xor.md) | Performs a bitwise XOR operation between `lhs` and `rhs` | + +## References + +### CompiledCircuit + +Renames and re-exports [InputMap](index.md#inputmap) + +## Variables + +### InputMap + +```ts +InputMap: any; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md new file mode 100644 index 000000000000..e8c2f4aef3d5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ErrorWithPayload.md @@ -0,0 +1,15 @@ +# ErrorWithPayload + +```ts +type ErrorWithPayload: ExecutionError & object; +``` + +## Type declaration + +| Member | Type | Description | +| :------ | :------ | :------ | +| `decodedAssertionPayload` | `any` | - | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md new file mode 100644 index 000000000000..812b8b164818 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallHandler.md @@ -0,0 +1,24 @@ +# ForeignCallHandler + +```ts +type ForeignCallHandler: (name, inputs) => Promise; +``` + +A callback which performs an foreign call and returns the response. + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | The identifier for the type of foreign call being performed. | +| `inputs` | [`ForeignCallInput`](ForeignCallInput.md)[] | An array of hex encoded inputs to the foreign call. | + +## Returns + +`Promise`\<[`ForeignCallOutput`](ForeignCallOutput.md)[]\> + +outputs - An array of hex encoded outputs containing the results of the foreign call. + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md new file mode 100644 index 000000000000..dd95809186a2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallInput.md @@ -0,0 +1,9 @@ +# ForeignCallInput + +```ts +type ForeignCallInput: string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md new file mode 100644 index 000000000000..b71fb78a9469 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/ForeignCallOutput.md @@ -0,0 +1,9 @@ +# ForeignCallOutput + +```ts +type ForeignCallOutput: string | string[]; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md new file mode 100644 index 000000000000..258c46f9d0c9 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/type-aliases/WitnessMap.md @@ -0,0 +1,9 @@ +# WitnessMap + +```ts +type WitnessMap: Map; +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs new file mode 100644 index 000000000000..b3156097df61 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_js/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"category","label":"Classes","items":[{"type":"doc","id":"reference/NoirJS/noir_js/classes/Noir","label":"Noir"}]},{"type":"category","label":"Type Aliases","items":[{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ErrorWithPayload","label":"ErrorWithPayload"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallHandler","label":"ForeignCallHandler"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallInput","label":"ForeignCallInput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/ForeignCallOutput","label":"ForeignCallOutput"},{"type":"doc","id":"reference/NoirJS/noir_js/type-aliases/WitnessMap","label":"WitnessMap"}]},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_js/functions/and","label":"and"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/blake2s256","label":"blake2s256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256k1_verify","label":"ecdsa_secp256k1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/ecdsa_secp256r1_verify","label":"ecdsa_secp256r1_verify"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/keccak256","label":"keccak256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/sha256","label":"sha256"},{"type":"doc","id":"reference/NoirJS/noir_js/functions/xor","label":"xor"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll new file mode 100644 index 000000000000..e2ac6616addc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md new file mode 100644 index 000000000000..6faf763b37f7 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile.md @@ -0,0 +1,51 @@ +# compile() + +```ts +compile( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ProgramCompilationArtifacts`](../index.md#programcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_program(fm); +``` + +```typescript +// Browser + +import { compile_program, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_program(fm); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md new file mode 100644 index 000000000000..7d0b39a43ef8 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/compile_contract.md @@ -0,0 +1,51 @@ +# compile\_contract() + +```ts +compile_contract( + fileManager, + projectPath?, + logFn?, +debugLogFn?): Promise +``` + +Compiles a Noir project + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `fileManager` | `FileManager` | The file manager to use | +| `projectPath`? | `string` | The path to the project inside the file manager. Defaults to the root of the file manager | +| `logFn`? | `LogFn` | A logging function. If not provided, console.log will be used | +| `debugLogFn`? | `LogFn` | A debug logging function. If not provided, logFn will be used | + +## Returns + +`Promise`\<[`ContractCompilationArtifacts`](../index.md#contractcompilationartifacts)\> + +## Example + +```typescript +// Node.js + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager(myProjectPath); +const myCompiledCode = await compile_contract(fm); +``` + +```typescript +// Browser + +import { compile_contract, createFileManager } from '@noir-lang/noir_wasm'; + +const fm = createFileManager('/'); +for (const path of files) { + await fm.writeFile(path, await getFileAsStream(path)); +} +const myCompiledCode = await compile_contract(fm); +``` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md new file mode 100644 index 000000000000..7e65c1d69c7e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/createFileManager.md @@ -0,0 +1,21 @@ +# createFileManager() + +```ts +createFileManager(dataDir): FileManager +``` + +Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `dataDir` | `string` | root of the file system | + +## Returns + +`FileManager` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md new file mode 100644 index 000000000000..fcea92753412 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/functions/inflateDebugSymbols.md @@ -0,0 +1,21 @@ +# inflateDebugSymbols() + +```ts +inflateDebugSymbols(debugSymbols): any +``` + +Decompresses and decodes the debug symbols + +## Parameters + +| Parameter | Type | Description | +| :------ | :------ | :------ | +| `debugSymbols` | `string` | The base64 encoded debug symbols | + +## Returns + +`any` + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md new file mode 100644 index 000000000000..b6e0f9d1bc0e --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/index.md @@ -0,0 +1,49 @@ +# noir_wasm + +## Exports + +### Functions + +| Function | Description | +| :------ | :------ | +| [compile](functions/compile.md) | Compiles a Noir project | +| [compile\_contract](functions/compile_contract.md) | Compiles a Noir project | +| [createFileManager](functions/createFileManager.md) | Creates a new FileManager instance based on fs in node and memfs in the browser (via webpack alias) | +| [inflateDebugSymbols](functions/inflateDebugSymbols.md) | Decompresses and decodes the debug symbols | + +## References + +### compile\_program + +Renames and re-exports [compile](functions/compile.md) + +## Interfaces + +### ContractCompilationArtifacts + +The compilation artifacts of a given contract. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `contract` | `ContractArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +### ProgramCompilationArtifacts + +The compilation artifacts of a given program. + +#### Properties + +| Property | Type | Description | +| :------ | :------ | :------ | +| `name` | `string` | not part of the compilation output, injected later | +| `program` | `ProgramArtifact` | The compiled contract. | +| `warnings` | `unknown`[] | Compilation warnings. | + +*** + +Generated using [typedoc-plugin-markdown](https://www.npmjs.com/package/typedoc-plugin-markdown) and [TypeDoc](https://typedoc.org/) diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs new file mode 100644 index 000000000000..e0870710349c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/NoirJS/noir_wasm/typedoc-sidebar.cjs @@ -0,0 +1,4 @@ +// @ts-check +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const typedocSidebar = { items: [{"type":"doc","id":"reference/NoirJS/noir_wasm/index","label":"API"},{"type":"category","label":"Functions","items":[{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile","label":"compile"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/compile_contract","label":"compile_contract"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/createFileManager","label":"createFileManager"},{"type":"doc","id":"reference/NoirJS/noir_wasm/functions/inflateDebugSymbols","label":"inflateDebugSymbols"}]}]}; +module.exports = typedocSidebar.items; \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json new file mode 100644 index 000000000000..5b6a20a609af --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 4, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json new file mode 100644 index 000000000000..27869205ad3c --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugger", + "position": 1, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_known_limitations.md new file mode 100644 index 000000000000..936d416ac4bc --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/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/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_repl.md new file mode 100644 index 000000000000..46e2011304e5 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/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/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/debugger/debugger_vscode.md new file mode 100644 index 000000000000..c027332b3b04 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/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/versioned_docs/version-v0.31.0/reference/nargo_commands.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md new file mode 100644 index 000000000000..ab9dd879d858 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/reference/nargo_commands.md @@ -0,0 +1,244 @@ +--- +title: Nargo +description: + Noir CLI Commands for Noir Prover and Verifier to create, execute, prove and verify programs, + generate Solidity verifier smart contract and compile into JSON file containing ACIR + representation and ABI of circuit. +keywords: + [ + Nargo, + Noir CLI, + Noir Prover, + Noir Verifier, + generate Solidity verifier, + compile JSON file, + ACIR representation, + ABI of circuit, + TypeScript, + ] +sidebar_position: 0 +--- + +# Command-Line Help for `nargo` + +This document contains the help content for the `nargo` command-line program. + +**Command Overview:** + +* [`nargo`↴](#nargo) +* [`nargo check`↴](#nargo-check) +* [`nargo fmt`↴](#nargo-fmt) +* [`nargo compile`↴](#nargo-compile) +* [`nargo new`↴](#nargo-new) +* [`nargo init`↴](#nargo-init) +* [`nargo execute`↴](#nargo-execute) +* [`nargo test`↴](#nargo-test) +* [`nargo info`↴](#nargo-info) +* [`nargo lsp`↴](#nargo-lsp) + +## `nargo` + +Noir's package manager + +**Usage:** `nargo ` + +###### **Subcommands:** + +* `check` — Checks the constraint system for errors +* `fmt` — Format the Noir files in a workspace +* `compile` — Compile the program and its secret execution trace into ACIR format +* `new` — Create a Noir project in a new directory +* `init` — Create a Noir project in the current directory +* `execute` — Executes a circuit to calculate its return value +* `test` — Run the tests for this program +* `info` — Provides detailed information on each of a program's function (represented by a single circuit) +* `lsp` — Starts the Noir LSP server + +###### **Options:** + + + + +## `nargo check` + +Checks the constraint system for errors + +**Usage:** `nargo check [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to check +* `--workspace` — Check all packages in the workspace +* `--overwrite` — Force overwrite of existing files +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo fmt` + +Format the Noir files in a workspace + +**Usage:** `nargo fmt [OPTIONS]` + +###### **Options:** + +* `--check` — Run noirfmt in check mode + + + +## `nargo compile` + +Compile the program and its secret execution trace into ACIR format + +**Usage:** `nargo compile [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to compile +* `--workspace` — Compile all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo new` + +Create a Noir project in a new directory + +**Usage:** `nargo new [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to save the new project + +###### **Options:** + +* `--name ` — Name of the package [default: package directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo init` + +Create a Noir project in the current directory + +**Usage:** `nargo init [OPTIONS]` + +###### **Options:** + +* `--name ` — Name of the package [default: current directory name] +* `--lib` — Use a library template +* `--bin` — Use a binary template [default] +* `--contract` — Use a contract template + + + +## `nargo execute` + +Executes a circuit to calculate its return value + +**Usage:** `nargo execute [OPTIONS] [WITNESS_NAME]` + +###### **Arguments:** + +* `` — Write the execution witness to named file + +###### **Options:** + +* `-p`, `--prover-name ` — The name of the toml file which contains the inputs for the prover + + Default value: `Prover` +* `--package ` — The name of the package to execute +* `--workspace` — Execute all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo test` + +Run the tests for this program + +**Usage:** `nargo test [OPTIONS] [TEST_NAME]` + +###### **Arguments:** + +* `` — If given, only tests with names containing this string will be run + +###### **Options:** + +* `--show-output` — Display output of `println` statements +* `--exact` — Only run tests that match exactly +* `--package ` — The name of the package to test +* `--workspace` — Test all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings +* `--oracle-resolver ` — JSON RPC url to solve oracle calls + + + +## `nargo info` + +Provides detailed information on each of a program's function (represented by a single circuit) + +Current information provided per circuit: 1. The number of ACIR opcodes 2. Counts the final number gates in the circuit used by a backend + +**Usage:** `nargo info [OPTIONS]` + +###### **Options:** + +* `--package ` — The name of the package to detail +* `--workspace` — Detail all packages in the workspace +* `--expression-width ` — Override the expression width requested by the backend + + Default value: `4` +* `--force` — Force a full recompilation +* `--print-acir` — Display the ACIR for compiled circuit +* `--deny-warnings` — Treat all warnings as errors +* `--silence-warnings` — Suppress warnings + + + +## `nargo lsp` + +Starts the Noir LSP server + +Starts an LSP server which allows IDEs such as VS Code to display diagnostics in Noir source. + +VS Code Noir Language Support: https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir + +**Usage:** `nargo lsp` + + + +
+ + + This document was generated automatically by + clap-markdown. + + diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md new file mode 100644 index 000000000000..9b7565ba9ff2 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/debugger.md @@ -0,0 +1,26 @@ +--- +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/index.md) and vscode-noir: + +- Noir & Nargo ≥0.28.0 +- Noir's VS Code extension ≥0.0.11 + +:::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/versioned_docs/version-v0.31.0/tooling/language_server.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md new file mode 100644 index 000000000000..81e0356ef8a1 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/language_server.md @@ -0,0 +1,43 @@ +--- +title: Language Server +description: Learn about the Noir Language Server, how to install the components, and configuration that may be required. +keywords: [Nargo, Language Server, LSP, VSCode, Visual Studio Code] +sidebar_position: 0 +--- + +This section helps you install and configure the Noir Language Server. + +The Language Server Protocol (LSP) has two components, the [Server](#language-server) and the [Client](#language-client). Below we describe each in the context of Noir. + +## Language Server + +The Server component is provided by the Nargo command line tool that you installed at the beginning of this guide. +As long as Nargo is installed and you've used it to run other commands in this guide, it should be good to go! + +If you'd like to verify that the `nargo lsp` command is available, you can run `nargo --help` and look for `lsp` in the list of commands. If you see it, you're using a version of Noir with LSP support. + +## Language Client + +The Client component is usually an editor plugin that launches the Server. It communicates LSP messages between the editor and the Server. For example, when you save a file, the Client will alert the Server, so it can try to compile the project and report any errors. + +Currently, Noir provides a Language Client for Visual Studio Code via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). + +> **Note:** Noir's Language Server Protocol support currently assumes users' VSCode workspace root to be the same as users' Noir project root (i.e. where Nargo.toml lies). +> +> If LSP features seem to be missing / malfunctioning, make sure you are opening your Noir project directly (instead of as a sub-folder) in your VSCode instance. + +When your language server is running correctly and the VSCode plugin is installed, you should see handy codelens buttons for compilation, measuring circuit size, execution, and tests: + +![Compile and Execute](@site/static/img/codelens_compile_execute.png) +![Run test](@site/static/img/codelens_run_test.png) + +You should also see your tests in the `testing` panel: + +![Testing panel](@site/static/img/codelens_testing_panel.png) + +### Configuration + +- **Noir: Enable LSP** - If checked, the extension will launch the Language Server via `nargo lsp` and communicate with it. +- **Noir: Nargo Flags** - Additional flags may be specified if you require them to be added when the extension calls `nargo lsp`. +- **Noir: Nargo Path** - An absolute path to a Nargo binary with the `lsp` command. This may be useful if Nargo is not within the `PATH` of your editor. +- **Noir > Trace: Server** - Setting this to `"messages"` or `"verbose"` will log LSP messages between the Client and Server. Useful for debugging. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md new file mode 100644 index 000000000000..d3e0c5224730 --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tooling/testing.md @@ -0,0 +1,62 @@ +--- +title: Testing in Noir +description: Learn how to use Nargo to test your Noir program in a quick and easy way +keywords: [Nargo, testing, Noir, compile, test] +sidebar_position: 1 +--- + +You can test your Noir programs using Noir circuits. + +Nargo will automatically compile and run any functions which have the decorator `#[test]` on them if +you run `nargo test`. + +For example if you have a program like: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test] +fn test_add() { + assert(add(2,2) == 4); + assert(add(0,1) == 1); + assert(add(1,0) == 1); +} +``` + +Running `nargo test` will test that the `test_add` function can be executed while satisfying all +the constraints which allows you to test that add returns the expected values. Test functions can't +have any arguments currently. + +### Test fail + +You can write tests that are expected to fail by using the decorator `#[test(should_fail)]`. For example: + +```rust +fn add(x: u64, y: u64) -> u64 { + x + y +} +#[test(should_fail)] +fn test_add() { + assert(add(2,2) == 5); +} +``` + +You can be more specific and make it fail with a specific reason by using `should_fail_with = "`: + +```rust +fn main(african_swallow_avg_speed : Field) { + assert(african_swallow_avg_speed == 65, "What is the airspeed velocity of an unladen swallow"); +} + +#[test] +fn test_king_arthur() { + main(65); +} + +#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")] +fn test_bridgekeeper() { + main(32); +} + +``` diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md new file mode 100644 index 000000000000..cbb1938a5c6f --- /dev/null +++ b/noir/noir-repo/docs/versioned_docs/version-v0.31.0/tutorials/noirjs_app.md @@ -0,0 +1,327 @@ +--- +title: Building a web app with NoirJS +description: Learn how to setup a new app that uses Noir to generate and verify zero-knowledge SNARK proofs in a typescript or javascript environment. +keywords: [how to, guide, javascript, typescript, noir, barretenberg, zero-knowledge, proofs, app] +sidebar_position: 0 +pagination_next: noir/concepts/data_types/index +--- + +NoirJS is a set of packages meant to work both in a browser and a server environment. In this tutorial, we will build a simple web app using them. From here, you should get an idea on how to proceed with your own Noir projects! + +You can find the complete app code for this guide [here](https://github.com/noir-lang/tiny-noirjs-app). + +## Setup + +:::note + +Feel free to use whatever versions, just keep in mind that Nargo and the NoirJS packages are meant to be in sync. For example, Nargo 0.27.x matches `noir_js@0.27.x`, etc. + +In this guide, we will be pinned to 0.27.0. + +::: + +Before we start, we want to make sure we have Node and Nargo installed. + +We start by opening a terminal and executing `node --version`. If we don't get an output like `v20.10.0`, that means node is not installed. Let's do that by following the handy [nvm guide](https://github.com/nvm-sh/nvm?tab=readme-ov-file#install--update-script). + +As for `Nargo`, we can follow the [Nargo guide](../getting_started/installation/index.md) to install it. If you're lazy, just paste this on a terminal and run `noirup`: + +```sh +curl -L https://raw.githubusercontent.com/noir-lang/noirup/main/install | bash +``` + +Easy enough. Onwards! + +## Our project + +ZK is a powerful technology. An app that doesn't reveal one of the inputs to _anyone_ is almost unbelievable, yet Noir makes it as easy as a single line of code. + +In fact, it's so simple that it comes nicely packaged in `nargo`. Let's do that! + +### Nargo + +Run: + +`nargo new circuit` + +And... That's about it. Your program is ready to be compiled and run. + +To compile, let's `cd` into the `circuit` folder to enter our project, and call: + +`nargo compile` + +This compiles our circuit into `json` format and add it to a new `target` folder. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit <---- our working directory + ├── Nargo.toml + ├── src + │ └── main.nr + └── target + └── circuit.json +``` + +::: + +### Node and Vite + +If you want to explore Nargo, feel free to go on a side-quest now and follow the steps in the +[getting started](../getting_started/hello_noir/index.md) guide. However, we want our app to run on the browser, so we need Vite. + +Vite is a powerful tool to generate static websites. While it provides all kinds of features, let's just go barebones with some good old vanilla JS. + +To do this this, go back to the previous folder (`cd ..`) and create a new vite project by running `npm create vite` and choosing "Vanilla" and "Javascript". + +A wild `vite-project` directory should now appear in your root folder! Let's not waste any time and dive right in: + +```bash +cd vite-project +``` + +### Setting Up Vite and Configuring the Project + +Before we proceed with any coding, let's get our environment tailored for Noir. We'll start by laying down the foundations with a `vite.config.js` file. This little piece of configuration is our secret sauce for making sure everything meshes well with the NoirJS libraries and other special setups we might need, like handling WebAssembly modules. Here’s how you get that going: + +#### Creating the vite.config.js + +In your freshly minted `vite-project` folder, create a new file named `vite.config.js` and open it in your code editor. Paste the following to set the stage: + +```javascript +import { defineConfig } from "vite"; +import copy from "rollup-plugin-copy"; + +export default defineConfig({ + esbuild: { + target: "esnext", + }, + optimizeDeps: { + esbuildOptions: { + target: "esnext", + }, + }, + plugins: [ + copy({ + targets: [ + { src: "node_modules/**/*.wasm", dest: "node_modules/.vite/dist" }, + ], + copySync: true, + hook: "buildStart", + }), + ], + server: { + port: 3000, + }, +}); +``` + +#### Install Dependencies + +Now that our stage is set, install the necessary NoirJS packages along with our other dependencies: + +```bash +npm install && npm install @noir-lang/backend_barretenberg@0.27.0 @noir-lang/noir_js@0.27.0 +npm install rollup-plugin-copy --save-dev +``` + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...etc... +└── vite-project <---- our working directory + └── ...etc... +``` + +::: + +#### Some cleanup + +`npx create vite` is amazing but it creates a bunch of files we don't really need for our simple example. Actually, let's just delete everything except for `vite.config.js`, `index.html`, `main.js` and `package.json`. I feel lighter already. + +![my heart is ready for you, noir.js](@site/static/img/memes/titanic.jpeg) + +## HTML + +Our app won't run like this, of course. We need some working HTML, at least. Let's open our broken-hearted `index.html` and replace everything with this code snippet: + +```html + + + + + + +

Noir app

+
+ + +
+
+

Logs

+

Proof

+
+ + +``` + +It _could_ be a beautiful UI... Depending on which universe you live in. + +## Some good old vanilla Javascript + +Our love for Noir needs undivided attention, so let's just open `main.js` and delete everything (this is where the romantic scenery becomes a bit creepy). + +Start by pasting in this boilerplate code: + +```js +const setup = async () => { + await Promise.all([ + import('@noir-lang/noirc_abi').then((module) => + module.default(new URL('@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm', import.meta.url).toString()), + ), + import('@noir-lang/acvm_js').then((module) => + module.default(new URL('@noir-lang/acvm_js/web/acvm_js_bg.wasm', import.meta.url).toString()), + ), + ]); +}; + +function display(container, msg) { + const c = document.getElementById(container); + const p = document.createElement('p'); + p.textContent = msg; + c.appendChild(p); +} + +document.getElementById('submitGuess').addEventListener('click', async () => { + try { + // here's where love happens + } catch (err) { + display('logs', 'Oh 💔 Wrong guess'); + } +}); +``` + +The display function doesn't do much. We're simply manipulating our website to see stuff happening. For example, if the proof fails, it will simply log a broken heart 😢 + +As for the `setup` function, it's just a sad reminder that dealing with `wasm` on the browser is not as easy as it should. Just copy, paste, and forget. + +:::info + +At this point in the tutorial, your folder structure should look like this: + +```tree +. +└── circuit + └── ...same as above +└── vite-project + ├── vite.config.js + ├── main.js + ├── package.json + └── index.html +``` + +You'll see other files and folders showing up (like `package-lock.json`, `node_modules`) but you shouldn't have to care about those. + +::: + +## Some NoirJS + +We're starting with the good stuff now. If you've compiled the circuit as described above, you should have a `json` file we want to import at the very top of our `main.js` file: + +```ts +import circuit from '../circuit/target/circuit.json'; +``` + +[Noir is backend-agnostic](../index.mdx#whats-new-about-noir). We write Noir, but we also need a proving backend. That's why we need to import and instantiate the two dependencies we installed above: `BarretenbergBackend` and `Noir`. Let's import them right below: + +```js +import { BarretenbergBackend, BarretenbergVerifier as Verifier } from '@noir-lang/backend_barretenberg'; +import { Noir } from '@noir-lang/noir_js'; +``` + +And instantiate them inside our try-catch block: + +```ts +// try { +const backend = new BarretenbergBackend(circuit); +const noir = new Noir(circuit); +// } +``` + +:::note + +For the remainder of the tutorial, everything will be happening inside the `try` block + +::: + +## Our app + +Now for the app itself. We're capturing whatever is in the input when people press the submit button. Just add this: + +```js +const x = parseInt(document.getElementById('guessInput').value); +const input = { x, y: 2 }; +``` + +Now we're ready to prove stuff! Let's feed some inputs to our circuit and calculate the proof: + +```js +await setup(); // let's squeeze our wasm inits here + +display('logs', 'Generating proof... ⌛'); +const { witness } = await noir.execute(input); +const proof = await backend.generateProof(witness); +display('logs', 'Generating proof... ✅'); +display('results', proof.proof); +``` + +You're probably eager to see stuff happening, so go and run your app now! + +From your terminal, run `npm run dev`. If it doesn't open a browser for you, just visit `localhost:5173`. You should now see the worst UI ever, with an ugly input. + +![Getting Started 0](@site/static/img/noir_getting_started_1.png) + +Now, our circuit says `fn main(x: Field, y: pub Field)`. This means only the `y` value is public, and it's hardcoded above: `input = { x, y: 2 }`. In other words, you won't need to send your secret`x` to the verifier! + +By inputting any number other than 2 in the input box and clicking "submit", you should get a valid proof. Otherwise the proof won't even generate correctly. By the way, if you're human, you shouldn't be able to understand anything on the "proof" box. That's OK. We like you, human ❤️. + +## Verifying + +Time to celebrate, yes! But we shouldn't trust machines so blindly. Let's add these lines to see our proof being verified: + +```js +display('logs', 'Verifying proof... ⌛'); +const verificationKey = await backend.getVerificationKey(); +const verifier = new Verifier(); +const isValid = await verifier.verifyProof(proof, verificationKey); +if (isValid) display('logs', 'Verifying proof... ✅'); +``` + +You have successfully generated a client-side Noir web app! + +![coded app without math knowledge](@site/static/img/memes/flextape.jpeg) + +## Further Reading + +You can see how noirjs is used in a full stack Next.js hardhat application in the [noir-starter repo here](https://github.com/noir-lang/noir-starter/tree/main/vite-hardhat). The example shows how to calculate a proof in the browser and verify it with a deployed Solidity verifier contract from noirjs. + +You should also check out the more advanced examples in the [noir-examples repo](https://github.com/noir-lang/noir-examples), where you'll find reference usage for some cool apps. diff --git a/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json b/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json new file mode 100644 index 000000000000..b9ad026f69ff --- /dev/null +++ b/noir/noir-repo/docs/versioned_sidebars/version-v0.31.0-sidebars.json @@ -0,0 +1,93 @@ +{ + "sidebar": [ + { + "type": "doc", + "id": "index" + }, + { + "type": "category", + "label": "Getting Started", + "items": [ + { + "type": "autogenerated", + "dirName": "getting_started" + } + ] + }, + { + "type": "category", + "label": "The Noir Language", + "items": [ + { + "type": "autogenerated", + "dirName": "noir" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "category", + "label": "How To Guides", + "items": [ + { + "type": "autogenerated", + "dirName": "how_to" + } + ] + }, + { + "type": "category", + "label": "Explainers", + "items": [ + { + "type": "autogenerated", + "dirName": "explainers" + } + ] + }, + { + "type": "category", + "label": "Tutorials", + "items": [ + { + "type": "autogenerated", + "dirName": "tutorials" + } + ] + }, + { + "type": "category", + "label": "Reference", + "items": [ + { + "type": "autogenerated", + "dirName": "reference" + } + ] + }, + { + "type": "category", + "label": "Tooling", + "items": [ + { + "type": "autogenerated", + "dirName": "tooling" + } + ] + }, + { + "type": "html", + "value": "
", + "defaultStyle": true + }, + { + "type": "doc", + "id": "migration_notes", + "label": "Migration notes" + } + ] +} diff --git a/noir/noir-repo/examples/.gitignore b/noir/noir-repo/examples/.gitignore new file mode 100644 index 000000000000..c4fdcad6719b --- /dev/null +++ b/noir/noir-repo/examples/.gitignore @@ -0,0 +1,2 @@ +target +proofs \ No newline at end of file diff --git a/noir/noir-repo/examples/codegen_verifier/.gitignore b/noir/noir-repo/examples/codegen_verifier/.gitignore index c0d62c447d3c..ae13a24752c2 100644 --- a/noir/noir-repo/examples/codegen_verifier/.gitignore +++ b/noir/noir-repo/examples/codegen_verifier/.gitignore @@ -1,4 +1,3 @@ out cache -target src/contract.sol \ No newline at end of file diff --git a/noir/noir-repo/examples/prove_and_verify/proofs/proof b/noir/noir-repo/examples/prove_and_verify/proofs/proof deleted file mode 100644 index 01d5ad276865ced1d94c7e1be9a84e09e0d6cb50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2176 zcmV-`2!Hng000000000000000000000000000000000000006J0S8cdAa>aDI1er` zD|x|5vMZ?MQTBMo$;s!NqkKRF(GdPwXbO6bcBHP4(CLcGZ{3r7QLt zaWO0Zhf%!!=``aT_Ngbft_>T+6XBD6%_RL2=Nb|XZKh8$=o?+MNSMEld2+}qL|YqH zLv37TBiqvfn7o4__bhJ|M<8>FmMP<3Sen_18u;RyI*DdwZ_hvTws2jpcP8bGBZ^e3)Jn6=g9>4a&jMY3YvROW7@1uygo z;5@Y@!u0*#UO#;c$)lIBLj70Kdl)i$`9uWor`4HW4^9?RD2x4cYsS-=KY2m(_GRbXxLd`oyO*Z)%l*L|x zv-CZ8>9svulPJHe7Fxx>8C!H#UbE;2(0fM-gegT@y=e-H?)xt_#D9X$wMVOf>DFaK z0%FYk?xNKLWKuV8By z9xl$MPJ!&4KjFIO(;;Z(vbJ*pWgkp2C< &3u_voM;b zOtM%%_fQ{^&wAJfZ;GiN0p9qKBout>sXkPL)2W#Jx`<}s)UUqDwXxO`peHgLbtXEi zA}QV2A5Y-kA}enoMoM3VRp`w6Y)0a8ZZH@O!Ts}z*}woW#imU_!aB{?Y1w4 zd~iKsf)fzvxs8$Gq6iEr7lL!+cc7iQiE*bBVf0JiH2S;)RXw_%l4}P~Q)PHJu_p4{*Ru_1m9Dp8)*zYD$!A&?i2~NJxFh-eka_ z5&@JLG^IL)kaSba{Rl?wehG5T^4158geGzaxi$V!E+Cd58w*SZEJDPnAuDv|2SQ2v zD6U)1Jf#xchKQNmnPi0fe{GsY(T|4-SxmAGRYR z!;|O<+&dyFTcx>!{NBfR7#ofvKxi;V`O!!mxJ=Y6>I+}AZGrHbn%qc>U|YtSq617FqhC6+)VddC>J;Cq)J1og5Luo@<-Q12xSbLa zp4H7G58tL4;|ZpwE*GX6ePf%~(6m1I<@^({r+s^J%rvkGB@5*3ayuiQ!Fasr&xbP) zK^aV+8fDOXvjj{o^OVgaZxq-wLO0uf;Uit)e{PD7iO70nerlMaHatF2o1>d1co%5j zw_sTKrNcmFmNe2Vd}^mZ>`6X298oXo2{Ic8E_?0a`h_++3wIRNg(+kP zb-A39b^ZaJVA~p0gnqqRfL<9O+WIHv)7i5Wx6|)VbSDHDJAecE!UA?Iom+~24j~r_ z0o~7H^Q};cpVA~TpTksRgysp2c=}a06gZg`WJGKS3~JRg-RURs=LMFuX7>T#u|qq@ zqW7q6c{6l)ehj4=`-R~qJstJS6W?>-Ks(wKT*z4TN_7gwYUa}5Y-@}e^2-u#-0`N8 zhrUI9DFl3KIvt{UlC9G^Sb2>`aAU|Hah48r%uVBMRlEXl>FO?W8eBWSIGd$9k32Gi zv#M(<)#fWe=Xb3LG@0zy4oWefBzX1!I!VPV*gt~=P#t9w^~deLGAGQZA07Pf|Mif} zddk93$K#e}$j;HZ1L|la>frfIP|MwU9zkTl7mWdCoVt=%Lg1jKVgDRgntNg{1!LxB z5V7Ku@3Sc}26&B|D4S8BB)h7jOK-f&6j@IS-K*efFN6G$90iBbvClb1UX_J6;X{d) z4b5cs8uKU`K;Eh0C;UB?yTPS{8b-r#20xH2mHtQTX?08lgJ97bm3F-#stFrS(n0h9 z4CA}n2txgxH+HlnLO#AneCmV&#-b9mZ@nAn!i#}(}^jL#=8#xmc C5)-Ka diff --git a/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh b/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh index 01ee6c70738d..df3ec3ff97ac 100755 --- a/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh +++ b/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh @@ -11,4 +11,4 @@ $BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz # TODO: backend should automatically generate vk if necessary. $BACKEND write_vk -b ./target/hello_world.json -$BACKEND verify -v ./target/vk -p ./proofs/proof \ No newline at end of file +$BACKEND verify -k ./target/vk -p ./proofs/proof \ No newline at end of file diff --git a/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr b/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr index b6a2b49b219d..4859e84d49eb 100644 --- a/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr +++ b/noir/noir-repo/examples/recursion/recurse_leaf/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - #[recursive] fn main( verification_key: [Field; 114], @@ -17,4 +15,4 @@ fn main( ); // Take output of previous proof and add another number to it. public_inputs[2] as u64 + num -} \ No newline at end of file +} diff --git a/noir/noir-repo/examples/recursion/recurse_node/src/main.nr b/noir/noir-repo/examples/recursion/recurse_node/src/main.nr index 7c983dcf050f..60192493b54f 100644 --- a/noir/noir-repo/examples/recursion/recurse_node/src/main.nr +++ b/noir/noir-repo/examples/recursion/recurse_node/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main( verification_key: [Field; 114], public_inputs: pub [Field; 4], @@ -14,4 +12,4 @@ fn main( key_hash ); public_inputs[3] as u64 -} \ No newline at end of file +} diff --git a/noir/noir-repo/noir_stdlib/src/aes128.nr b/noir/noir-repo/noir_stdlib/src/aes128.nr index e6e2a5e49975..7b0876b86f39 100644 --- a/noir/noir-repo/noir_stdlib/src/aes128.nr +++ b/noir/noir-repo/noir_stdlib/src/aes128.nr @@ -1,4 +1,4 @@ #[foreign(aes128_encrypt)] // docs:start:aes128 -pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} +pub fn aes128_encrypt(input: [u8; N], iv: [u8; 16], key: [u8; 16]) -> [u8] {} // docs:end:aes128 diff --git a/noir/noir-repo/noir_stdlib/src/array.nr b/noir/noir-repo/noir_stdlib/src/array.nr index 6fba197dd050..ad9c7093d070 100644 --- a/noir/noir-repo/noir_stdlib/src/array.nr +++ b/noir/noir-repo/noir_stdlib/src/array.nr @@ -2,7 +2,7 @@ use crate::cmp::Ord; // TODO: Once we fully move to the new SSA pass this module can be removed and replaced // by the methods in the `slice` module -impl [T; N] { +impl [T; N] { #[builtin(array_len)] pub fn len(self) -> u32 {} @@ -110,7 +110,7 @@ impl [T; N] { // helper function used to look up the position of a value in an array of Field // Note that function returns 0 if the value is not found -unconstrained fn find_index(a: [u32; N], find: u32) -> u32 { +unconstrained fn find_index(a: [u32; N], find: u32) -> u32 { let mut result = 0; for i in 0..a.len() { if a[i] == find { diff --git a/noir/noir-repo/noir_stdlib/src/cmp.nr b/noir/noir-repo/noir_stdlib/src/cmp.nr index 457b2cfa1677..bdd5e2bc5ec0 100644 --- a/noir/noir-repo/noir_stdlib/src/cmp.nr +++ b/noir/noir-repo/noir_stdlib/src/cmp.nr @@ -18,7 +18,7 @@ impl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } } impl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } } impl Eq for bool { fn eq(self, other: bool) -> bool { self == other } } -impl Eq for [T; N] where T: Eq { +impl Eq for [T; N] where T: Eq { fn eq(self, other: [T; N]) -> bool { let mut result = true; for i in 0 .. self.len() { @@ -38,7 +38,7 @@ impl Eq for [T] where T: Eq { } } -impl Eq for str { +impl Eq for str { fn eq(self, other: str) -> bool { let self_bytes = self.as_bytes(); let other_bytes = other.as_bytes(); @@ -203,7 +203,7 @@ impl Ord for bool { } } -impl Ord for [T; N] where T: Ord { +impl Ord for [T; N] where T: Ord { // The first non-equal element of both arrays determines // the ordering for the whole array. fn cmp(self, other: [T; N]) -> Ordering { 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 aae96e5943d0..c218ecd23481 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -1,25 +1,45 @@ use crate::{cmp::Eq, convert::From}; -struct BoundedVec { +struct BoundedVec { storage: [T; MaxLen], len: u32, } -impl BoundedVec { +impl BoundedVec { pub fn new() -> Self { let zeroed = crate::unsafe::zeroed(); BoundedVec { storage: [zeroed; MaxLen], len: 0 } } - pub fn get(mut self: Self, index: u32) -> T { + /// Get an element from the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn get(self, index: u32) -> T { assert(index < self.len); - self.storage[index] + self.get_unchecked(index) } - pub fn get_unchecked(mut self: Self, index: u32) -> T { + /// Get an element from the vector at the given index. + /// Responds with undefined data for `index` where `self.len < index < self.max_len()`. + pub fn get_unchecked(self, index: u32) -> T { self.storage[index] } + /// Write an element to the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn set(&mut self, index: u32, value: T) { + assert(index < self.len, "Attempted to write past end of BoundedVec"); + self.set_unchecked(index, value) + } + + /// Write an element to the vector at the given index. + /// Does not check whether the passed `index` is a valid index within the vector. + /// + /// Silently writes past the end of the vector for `index` where `self.len < index < self.max_len()` + /// Panics if the given index points beyond the maximum length of the vector (`self.max_len()`). + pub fn set_unchecked(&mut self, index: u32, value: T) { + self.storage[index] = value; + } + pub fn push(&mut self, elem: T) { assert(self.len < MaxLen, "push out of bounds"); @@ -41,7 +61,7 @@ impl BoundedVec { self.storage } - pub fn extend_from_array(&mut self, array: [T; Len]) { + pub fn extend_from_array(&mut self, array: [T; Len]) { let new_len = self.len + array.len(); assert(new_len <= MaxLen, "extend_from_array out of bounds"); for i in 0..array.len() { @@ -59,7 +79,7 @@ impl BoundedVec { self.len = new_len; } - pub fn extend_from_bounded_vec(&mut self, vec: 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 <= MaxLen, "extend_from_bounded_vec out of bounds"); @@ -74,7 +94,7 @@ impl BoundedVec { self.len = new_len; } - pub fn from_array(array: [T; Len]) -> Self { + pub fn from_array(array: [T; Len]) -> Self { assert(Len <= MaxLen, "from array out of bounds"); let mut vec: BoundedVec = BoundedVec::new(); vec.extend_from_array(array); @@ -101,9 +121,20 @@ impl BoundedVec { } ret } + + pub fn map(self, f: fn[Env](T) -> U) -> BoundedVec { + let mut ret = BoundedVec::new(); + ret.len = self.len(); + for i in 0..MaxLen { + if i < self.len() { + ret.storage[i] = f(self.get_unchecked(i)); + } + } + ret + } } -impl Eq for BoundedVec where T: Eq { +impl Eq for BoundedVec where T: Eq { fn eq(self, other: BoundedVec) -> bool { // TODO: https://github.com/noir-lang/noir/issues/4837 // @@ -114,7 +145,7 @@ impl Eq for BoundedVec where T: Eq { } } -impl From<[T; Len]> for BoundedVec { +impl From<[T; Len]> for BoundedVec { fn from(array: [T; Len]) -> BoundedVec { BoundedVec::from_array(array) } @@ -142,6 +173,73 @@ mod bounded_vec_tests { assert(bounded_vec1 != bounded_vec2); } + mod set { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn set_updates_values_properly() { + let mut vec = BoundedVec::from_array([0, 0, 0, 0, 0]); + + vec.set(0, 42); + assert_eq(vec.storage, [42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.storage, [42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.storage, [42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.storage, [42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.storage, [0, 10, 44, 0, 0]); + } + + #[test(should_fail_with = "Attempted to write past end of BoundedVec")] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } + } + + mod map { + use crate::collections::bounded_vec::BoundedVec; + + #[test] + fn applies_function_correctly() { + // docs:start:bounded-vec-map-example + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| value * 2); + // docs:end:bounded-vec-map-example + let expected = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn applies_function_that_changes_return_type() { + let vec: BoundedVec = BoundedVec::from_array([1, 2, 3, 4]); + let result = vec.map(|value| (value * 2) as Field); + let expected: BoundedVec = BoundedVec::from_array([2, 4, 6, 8]); + + assert_eq(result, expected); + } + + #[test] + fn does_not_apply_function_past_len() { + let vec: BoundedVec = BoundedVec::from_array([0, 1]); + let result = vec.map(|value| if value == 0 { 5 } else { value }); + let expected = BoundedVec::from_array([5, 1]); + + assert_eq(result, expected); + assert_eq(result.storage()[2], 0); + } + } + mod from_array { use crate::collections::bounded_vec::BoundedVec; diff --git a/noir/noir-repo/noir_stdlib/src/collections/map.nr b/noir/noir-repo/noir_stdlib/src/collections/map.nr index 84e941668692..8324583632f8 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/map.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/map.nr @@ -15,7 +15,7 @@ global MAX_LOAD_FACTOR_DEN0MINATOR = 4; // Size of the underlying table must be known at compile time. // It is advised to select capacity N as a power of two, or a prime number // because utilized probing scheme is best tailored for it. -struct HashMap { +struct HashMap { _table: [Slot; N], // Amount of valid elements in the map. @@ -77,7 +77,7 @@ impl Slot { // While conducting lookup, we iterate attempt from 0 to N - 1 due to heuristic, // that if we have went that far without finding desired, // it is very unlikely to be after - performance will be heavily degraded. -impl HashMap { +impl HashMap { // Creates a new instance of HashMap with specified BuildHasher. // docs:start:with_hasher pub fn with_hasher(_build_hasher: B) -> Self @@ -424,7 +424,7 @@ impl HashMap { // equal sets of key-value entries, // thus one is a subset of the other and vice versa. // docs:start:eq -impl Eq for HashMap +impl Eq for HashMap where K: Eq + Hash, V: Eq, @@ -460,7 +460,7 @@ where } // docs:start:default -impl Default for HashMap +impl Default for HashMap where B: BuildHasher + Default, H: Hasher + Default diff --git a/noir/noir-repo/noir_stdlib/src/collections/vec.nr b/noir/noir-repo/noir_stdlib/src/collections/vec.nr index 18aaa8b9b3be..cedae7f5ce19 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/vec.nr @@ -21,6 +21,12 @@ impl Vec { self.slice[index] } + /// Write an element to the vector at the given index. + /// Panics if the given index points beyond the end of the vector (`self.len()`). + pub fn set(&mut self, index: u32, value: T) { + self.slice[index] = value; + } + /// Push a new element to the end of the vector, returning a /// new vector with a length one greater than the /// original unmodified vector. @@ -57,3 +63,36 @@ impl Vec { self.slice.len() } } + +mod tests { + use crate::collections::vec::Vec; + + #[test] + fn set_updates_values_properly() { + let mut vec = Vec { slice: &[0, 0, 0, 0, 0] }; + + vec.set(0, 42); + assert_eq(vec.slice, &[42, 0, 0, 0, 0]); + + vec.set(1, 43); + assert_eq(vec.slice, &[42, 43, 0, 0, 0]); + + vec.set(2, 44); + assert_eq(vec.slice, &[42, 43, 44, 0, 0]); + + vec.set(1, 10); + assert_eq(vec.slice, &[42, 10, 44, 0, 0]); + + vec.set(0, 0); + assert_eq(vec.slice, &[0, 10, 44, 0, 0]); + } + + #[test(should_fail)] + fn panics_when_writing_elements_past_end_of_vec() { + let mut vec = Vec::new(); + vec.set(0, 42); + + // Need to use println to avoid DIE removing the write operation. + crate::println(vec.get(0)); + } +} diff --git a/noir/noir-repo/noir_stdlib/src/compat.nr b/noir/noir-repo/noir_stdlib/src/compat.nr index 5d80c422c331..06da81507671 100644 --- a/noir/noir-repo/noir_stdlib/src/compat.nr +++ b/noir/noir-repo/noir_stdlib/src/compat.nr @@ -1,4 +1,7 @@ +global BN254_MODULUS_BE_BYTES: [u8] = &[ + 48, 100, 78, 114, 225, 49, 160, 41, 184, 80, 69, 182, 129, 129, 88, 93, 40, 51, 232, 72, 121, 185, 112, 145, 67, 225, 245, 147, 240, 0, 0, 1 +]; + pub fn is_bn254() -> bool { - // bn254 truncates its curve order to 0 - 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 + crate::field::modulus_be_bytes() == BN254_MODULUS_BE_BYTES } diff --git a/noir/noir-repo/noir_stdlib/src/default.nr b/noir/noir-repo/noir_stdlib/src/default.nr index bd2f1ce0cd2e..0acb39660343 100644 --- a/noir/noir-repo/noir_stdlib/src/default.nr +++ b/noir/noir-repo/noir_stdlib/src/default.nr @@ -17,7 +17,7 @@ impl Default for i64 { fn default() -> i64 { 0 } } impl Default for () { fn default() -> () { () } } impl Default for bool { fn default() -> bool { false } } -impl Default for [T; N] where T: Default { +impl Default for [T; N] where T: Default { fn default() -> [T; N] { [T::default(); N] } diff --git a/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr b/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr index 7dc756781c09..12b48d66b9d4 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/montcurve.nr @@ -114,7 +114,7 @@ mod affine { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { self.into_tecurve().bit_mul(bits, p.into_tecurve()).into_montcurve() } @@ -124,7 +124,7 @@ mod affine { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { @@ -315,7 +315,7 @@ mod curvegroup { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { self.into_tecurve().bit_mul(bits, p.into_tecurve()).into_montcurve() } @@ -325,7 +325,7 @@ mod curvegroup { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { diff --git a/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr b/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr index 9dd324f30854..3ad3af41cff7 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/swcurve.nr @@ -134,7 +134,7 @@ mod affine { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { self.into_group().bit_mul(bits, p.into_group()).into_affine() } @@ -144,7 +144,7 @@ mod affine { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - pub fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + pub fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { @@ -336,7 +336,7 @@ mod curvegroup { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { let mut out = Point::zero(); for i in 0..N { @@ -363,7 +363,7 @@ mod curvegroup { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { diff --git a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr index 506fe89313a8..aaf66f903cc1 100644 --- a/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr +++ b/noir/noir-repo/noir_stdlib/src/ec/tecurve.nr @@ -132,7 +132,7 @@ mod affine { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { self.into_group().bit_mul(bits, p.into_group()).into_affine() } @@ -142,7 +142,7 @@ mod affine { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { @@ -340,7 +340,7 @@ mod curvegroup { // Scalar multiplication with scalar represented by a bit array (little-endian convention). // If k is the natural number represented by `bits`, then this computes p + ... + p k times. - fn bit_mul(self, bits: [u1; N], p: Point) -> Point { + fn bit_mul(self, bits: [u1; N], p: Point) -> Point { let mut out = Point::zero(); for i in 0..N { @@ -367,7 +367,7 @@ mod curvegroup { } // Multi-scalar multiplication (n[0]*p[0] + ... + n[N]*p[N], where * denotes scalar multiplication) - fn msm(self, n: [Field; N], p: [Point; N]) -> Point { + fn msm(self, n: [Field; N], p: [Point; N]) -> Point { let mut out = Point::zero(); for i in 0..N { diff --git a/noir/noir-repo/noir_stdlib/src/ecdsa_secp256k1.nr b/noir/noir-repo/noir_stdlib/src/ecdsa_secp256k1.nr index f84e2221f574..8a70184dca84 100644 --- a/noir/noir-repo/noir_stdlib/src/ecdsa_secp256k1.nr +++ b/noir/noir-repo/noir_stdlib/src/ecdsa_secp256k1.nr @@ -1,6 +1,6 @@ #[foreign(ecdsa_secp256k1)] // docs:start:ecdsa_secp256k1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], diff --git a/noir/noir-repo/noir_stdlib/src/ecdsa_secp256r1.nr b/noir/noir-repo/noir_stdlib/src/ecdsa_secp256r1.nr index 76e68aeeafa7..8772fa7c2caf 100644 --- a/noir/noir-repo/noir_stdlib/src/ecdsa_secp256r1.nr +++ b/noir/noir-repo/noir_stdlib/src/ecdsa_secp256r1.nr @@ -1,6 +1,6 @@ #[foreign(ecdsa_secp256r1)] // docs:start:ecdsa_secp256r1 -pub fn verify_signature( +pub fn verify_signature( public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], diff --git a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr index cd8c421e1368..c5617094c0a3 100644 --- a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr @@ -52,6 +52,14 @@ struct EmbeddedCurveScalar { hi: Field, } +impl EmbeddedCurveScalar { + #[field(bn254)] + fn from_field(scalar: Field) -> EmbeddedCurveScalar { + let (a,b) = crate::field::bn254::decompose(scalar); + EmbeddedCurveScalar { lo: a, hi: b } + } +} + // Computes a multi scalar multiplication over the embedded curve. // For bn254, We have Grumpkin and Baby JubJub. // For bls12-381, we have JubJub and Bandersnatch. @@ -60,7 +68,7 @@ struct EmbeddedCurveScalar { // underlying proof system. #[foreign(multi_scalar_mul)] // docs:start:multi_scalar_mul -pub fn multi_scalar_mul( +pub fn multi_scalar_mul( points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N] ) -> [Field; 3] diff --git a/noir/noir-repo/noir_stdlib/src/hash.nr b/noir/noir-repo/noir_stdlib/src/hash.nr index 6c295d127ab0..493430c99a44 100644 --- a/noir/noir-repo/noir_stdlib/src/hash.nr +++ b/noir/noir-repo/noir_stdlib/src/hash.nr @@ -5,49 +5,87 @@ mod poseidon2; use crate::default::Default; use crate::uint128::U128; use crate::sha256::{digest, sha256_var}; -use crate::embedded_curve_ops::EmbeddedCurvePoint; +use crate::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; #[foreign(sha256)] // docs:start:sha256 -pub fn sha256(input: [u8; N]) -> [u8; 32] +pub fn sha256(input: [u8; N]) -> [u8; 32] // docs:end:sha256 {} #[foreign(blake2s)] // docs:start:blake2s -pub fn blake2s(input: [u8; N]) -> [u8; 32] +pub fn blake2s(input: [u8; N]) -> [u8; 32] // docs:end:blake2s {} #[foreign(blake3)] // docs:start:blake3 -pub fn blake3(input: [u8; N]) -> [u8; 32] +pub fn blake3(input: [u8; N]) -> [u8; 32] // docs:end:blake3 {} // docs:start:pedersen_commitment -pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { +pub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint { // docs:end:pedersen_commitment - pedersen_commitment_with_separator(input, 0) + let value = pedersen_commitment_with_separator(input, 0); + if (value.x == 0) & (value.y == 0) { + EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true } + } else { + EmbeddedCurvePoint { x: value.x, y: value.y, is_infinite: false } + } } -#[foreign(pedersen_commitment)] -pub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} +fn pedersen_commitment_with_separator_noir(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { + let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N]; + for i in 0..N { + points[i] = EmbeddedCurveScalar::from_field(input[i]); + } + let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); + let values = multi_scalar_mul(generators, points); + EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: values[2] as bool } +} -pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { +pub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint { let values = __pedersen_commitment_with_separator(input, separator); EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false } } // docs:start:pedersen_hash -pub fn pedersen_hash(input: [Field; N]) -> Field +pub fn pedersen_hash(input: [Field; N]) -> Field // docs:end:pedersen_hash { pedersen_hash_with_separator(input, 0) } +#[field(bn254)] +fn derive_generators( + domain_separator_bytes: [u8; M], + starting_index: u32 +) -> [EmbeddedCurvePoint; N] { + crate::assert_constant(domain_separator_bytes); + crate::assert_constant(starting_index); + __derive_generators(domain_separator_bytes, starting_index) +} + +#[builtin(derive_pedersen_generators)] +#[field(bn254)] +fn __derive_generators(domain_separator_bytes: [u8; M], starting_index: u32) -> [EmbeddedCurvePoint; N] {} + +fn pedersen_hash_with_separator_noir(input: [Field; N], separator: u32) -> Field { + let v1 = pedersen_commitment_with_separator(input, separator); + let length_generator : [EmbeddedCurvePoint; 1] = derive_generators("pedersen_hash_length".as_bytes(), 0); + multi_scalar_mul( + [length_generator[0], v1], + [EmbeddedCurveScalar { lo: N as Field, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] + )[0] +} + #[foreign(pedersen_hash)] -pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} +pub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {} + +#[foreign(pedersen_commitment)] +fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {} pub fn hash_to_field(inputs: [Field]) -> Field { let mut sum = 0; @@ -62,12 +100,12 @@ pub fn hash_to_field(inputs: [Field]) -> Field { #[foreign(keccak256)] // docs:start:keccak256 -pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] +pub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] // docs:end:keccak256 {} #[foreign(poseidon2_permutation)] -pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} +pub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {} #[foreign(sha256_compression)] pub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {} @@ -172,7 +210,7 @@ impl Hash for U128 { } } -impl Hash for [T; N] where T: Hash { +impl Hash for [T; N] where T: Hash { fn hash(self, state: &mut H) where H: Hasher{ for elem in self { elem.hash(state); @@ -222,3 +260,11 @@ impl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: self.4.hash(state); } } + +#[test] +fn assert_pedersen_noir() { + // TODO: make this a fuzzer test once fuzzer supports curve-specific blackbox functions. + let input = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + assert_eq(pedersen_hash_with_separator(input, 4), pedersen_hash_with_separator_noir(input, 4)); + assert_eq(pedersen_commitment_with_separator(input, 4), pedersen_commitment_with_separator_noir(input, 4)); +} diff --git a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr index 6c5502c2fbfe..a16a73c5bc55 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mimc.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mimc.nr @@ -6,7 +6,7 @@ use crate::default::Default; // You must use constants generated for the native field // Rounds number should be ~ log(p)/log(exp) // For 254 bit primes, exponent 7 and 91 rounds seems to be recommended -fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { +fn mimc(x: Field, k: Field, constants: [Field; N], exp: Field) -> Field { //round 0 let mut t = x + k; let mut h = t.pow_32(exp); @@ -116,7 +116,7 @@ global MIMC_BN254_CONSTANTS: [Field; MIMC_BN254_ROUNDS] = [ //mimc implementation with hardcoded parameters for BN254 curve. #[field(bn254)] -pub fn mimc_bn254(array: [Field; N]) -> Field { +pub fn mimc_bn254(array: [Field; N]) -> Field { let exponent = 7; let mut r = 0; for elem in array { diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr index c4b5f0fcb6f9..963808f60532 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr @@ -6,7 +6,7 @@ use crate::default::Default; // A config struct defining the parameters of the Poseidon instance to use. // // A thorough writeup of this method (along with an unoptimized method) can be found at: https://spec.filecoin.io/algorithms/crypto/poseidon/ -struct PoseidonConfig { +struct PoseidonConfig { // State width, should be equal to `T` t: Field, // Number of full rounds. should be even @@ -28,7 +28,7 @@ struct PoseidonConfig { sparse_mds: [Field; X], } -pub fn config( +pub fn config( t: Field, rf: u8, rp: u8, @@ -40,14 +40,17 @@ pub fn config( ) -> PoseidonConfig { // Input checks assert_eq(rf & 1, 0); - assert_eq((t as u8) * rf + rp, N); - assert_eq(t, T); + assert_eq((t as u8) * rf + rp, N as u8); + assert_eq(t, T as Field); assert(alpha != 0); PoseidonConfig { t, rf, rp, alpha, round_constants, mds, presparse_mds, sparse_mds } } -pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; T]) -> [Field; T] { +pub fn permute( + pos_conf: PoseidonConfig, + mut state: [Field; T] +) -> [Field; T] { let PoseidonConfig {t, rf, rp, alpha, round_constants, mds, presparse_mds, sparse_mds } = pos_conf; for i in 0..state.len() { @@ -109,7 +112,7 @@ pub fn permute(pos_conf: PoseidonConfig, mut state: [Field; T] } // Performs matrix multiplication on a vector -fn apply_matrix(matrix: [[Field; N]; N], vec: [Field; N]) -> [Field; N] { +fn apply_matrix(matrix: [[Field; N]; N], vec: [Field; N]) -> [Field; N] { let mut out = [0; N]; for i in 0..N { @@ -122,7 +125,7 @@ fn apply_matrix(matrix: [[Field; N]; N], vec: [Field; N]) -> [Field; N] { } // Corresponding absorption. -fn absorb( +fn absorb( pos_conf: PoseidonConfig, // Initial state; usually [0; O] mut state: [Field; T], @@ -152,7 +155,7 @@ fn absorb( state } -fn sigma(x: [Field; O]) -> [Field; O] { +fn sigma(x: [Field; O]) -> [Field; O] { let mut y = x; for i in 0..O { let t = y[i]; diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr index 54f22884e293..0e47ca11e203 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon/bn254.nr @@ -6,7 +6,7 @@ use crate::hash::poseidon::{PoseidonConfig, absorb}; // Variable-length Poseidon-128 sponge as suggested in second bullet point of §3 of https://eprint.iacr.org/2019/458.pdf #[field(bn254)] -pub fn sponge(msg: [Field; N]) -> Field { +pub fn sponge(msg: [Field; N]) -> Field { absorb(consts::x5_5_config(), [0; 5], 4, 1, msg)[1] } diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr index 04d922b581d7..e34992364ab4 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr @@ -11,8 +11,7 @@ struct Poseidon2 { } impl Poseidon2 { - - pub fn hash(input: [Field; N], message_size: u32) -> Field { + pub fn hash(input: [Field; N], message_size: u32) -> Field { if message_size == N { Poseidon2::hash_internal(input, N, false) } else { @@ -95,7 +94,7 @@ impl Poseidon2 { result } - fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field { + fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field { let two_pow_64 = 18446744073709551616; let iv : Field = (in_len as Field) * two_pow_64; let mut sponge = Poseidon2::new(iv); diff --git a/noir/noir-repo/noir_stdlib/src/lib.nr b/noir/noir-repo/noir_stdlib/src/lib.nr index ad47171fa468..65da7e6e9ab4 100644 --- a/noir/noir-repo/noir_stdlib/src/lib.nr +++ b/noir/noir-repo/noir_stdlib/src/lib.nr @@ -26,6 +26,7 @@ mod prelude; mod uint128; mod bigint; mod runtime; +mod meta; // Oracle calls are required to be wrapped in an unconstrained function // Thus, the only argument to the `println` oracle is expected to always be an ident @@ -47,6 +48,11 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: // Useful for debugging for-loop bounds. #[builtin(assert_constant)] pub fn assert_constant(x: T) {} + +// Asserts that the given value is both true and known at compile-time +#[builtin(static_assert)] +pub fn static_assert(predicate: bool, message: str) {} + // from_field and as_field are private since they are not valid for every type. // `as` should be the default for users to cast between primitive types, and in the future // traits can be used to work with generic types. diff --git a/noir/noir-repo/noir_stdlib/src/merkle.nr b/noir/noir-repo/noir_stdlib/src/merkle.nr index 9b15fe7313d1..17e539ab9b73 100644 --- a/noir/noir-repo/noir_stdlib/src/merkle.nr +++ b/noir/noir-repo/noir_stdlib/src/merkle.nr @@ -2,7 +2,7 @@ // Currently we assume that it is a binary tree, so depth k implies a width of 2^k // XXX: In the future we can add an arity parameter // Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function. -pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { +pub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field { let n = hash_path.len(); let index_bits = index.to_le_bits(n as u32); let mut current = leaf; diff --git a/noir/noir-repo/noir_stdlib/src/meta.nr b/noir/noir-repo/noir_stdlib/src/meta.nr new file mode 100644 index 000000000000..1825888130b4 --- /dev/null +++ b/noir/noir-repo/noir_stdlib/src/meta.nr @@ -0,0 +1 @@ +mod type_def; diff --git a/noir/noir-repo/noir_stdlib/src/meta/type_def.nr b/noir/noir-repo/noir_stdlib/src/meta/type_def.nr new file mode 100644 index 000000000000..c01aab4b1413 --- /dev/null +++ b/noir/noir-repo/noir_stdlib/src/meta/type_def.nr @@ -0,0 +1,16 @@ +impl StructDefinition { + /// Return a syntactic version of this struct definition as a type. + /// For example, `as_type(quote { type Foo { ... } })` would return `Foo` + #[builtin(struct_def_as_type)] + fn as_type(self) -> Quoted {} + + /// Return each generic on this struct. The names of these generics are unchanged + /// so users may need to keep name collisions in mind if this is used directly in a macro. + #[builtin(struct_def_generics)] + fn generics(self) -> [Quoted] {} + + /// Returns (name, type) pairs of each field in this struct. Each type is as-is + /// with any generic arguments unchanged. + #[builtin(struct_def_fields)] + fn fields(self) -> [(Quoted, Quoted)] {} +} diff --git a/noir/noir-repo/noir_stdlib/src/option.nr b/noir/noir-repo/noir_stdlib/src/option.nr index c94a1cf836e4..df020e756150 100644 --- a/noir/noir-repo/noir_stdlib/src/option.nr +++ b/noir/noir-repo/noir_stdlib/src/option.nr @@ -57,7 +57,7 @@ impl Option { } /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value - fn expect(self, message: fmtstr) -> T { + fn expect(self, message: fmtstr) -> T { assert(self.is_some(), message); self._value } diff --git a/noir/noir-repo/noir_stdlib/src/schnorr.nr b/noir/noir-repo/noir_stdlib/src/schnorr.nr index c63915061cbf..24ca514025c1 100644 --- a/noir/noir-repo/noir_stdlib/src/schnorr.nr +++ b/noir/noir-repo/noir_stdlib/src/schnorr.nr @@ -1,6 +1,6 @@ #[foreign(schnorr_verify)] // docs:start:schnorr_verify -pub fn verify_signature( +pub fn verify_signature( public_key_x: Field, public_key_y: Field, signature: [u8; 64], diff --git a/noir/noir-repo/noir_stdlib/src/sha256.nr b/noir/noir-repo/noir_stdlib/src/sha256.nr index d856043fcfa8..0161756c1d05 100644 --- a/noir/noir-repo/noir_stdlib/src/sha256.nr +++ b/noir/noir-repo/noir_stdlib/src/sha256.nr @@ -16,8 +16,8 @@ fn msg_u8_to_u32(msg: [u8; 64]) -> [u32; 16] { msg32 } // SHA-256 hash function -pub fn digest(msg: [u8; N]) -> [u8; 32] { - sha256_var(msg, N) +pub fn digest(msg: [u8; N]) -> [u8; 32] { + sha256_var(msg, N as u64) } fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { @@ -38,12 +38,12 @@ fn hash_final_block(msg_block: [u8; 64], mut state: [u32; 8]) -> [u8; 32] { } // Variable size SHA-256 hash -pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { +pub fn sha256_var(msg: [u8; N], message_size: u64) -> [u8; 32] { let mut msg_block: [u8; 64] = [0; 64]; let mut h: [u32; 8] = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; // Intermediate hash, starting with the canonical initial value let mut i: u64 = 0; // Message byte pointer for k in 0..N { - if k < message_size { + if k as u64 < message_size { // Populate msg_block msg_block[i] = msg[k]; i = i + 1; diff --git a/noir/noir-repo/noir_stdlib/src/sha512.nr b/noir/noir-repo/noir_stdlib/src/sha512.nr index 0f8ffcfcb1c7..aed6c2878b3e 100644 --- a/noir/noir-repo/noir_stdlib/src/sha512.nr +++ b/noir/noir-repo/noir_stdlib/src/sha512.nr @@ -87,7 +87,7 @@ fn msg_u8_to_u64(msg: [u8; 128]) -> [u64; 16] { msg64 } // SHA-512 hash function -pub fn digest(msg: [u8; N]) -> [u8; 64] { +pub fn digest(msg: [u8; N]) -> [u8; 64] { let mut msg_block: [u8; 128] = [0; 128]; // noir-fmt:ignore let mut h: [u64; 8] = [7640891576956012808, 13503953896175478587, 4354685564936845355, 11912009170470909681, 5840696475078001361, 11170449401992604703, 2270897969802886507, 6620516959819538809]; // Intermediate hash, starting with the canonical initial value diff --git a/noir/noir-repo/noir_stdlib/src/slice.nr b/noir/noir-repo/noir_stdlib/src/slice.nr index bf05ae0cf64e..1a40abcf704e 100644 --- a/noir/noir-repo/noir_stdlib/src/slice.nr +++ b/noir/noir-repo/noir_stdlib/src/slice.nr @@ -44,7 +44,7 @@ impl [T] { self } - pub fn as_array(self) -> [T; N] { + pub fn as_array(self) -> [T; N] { assert(self.len() == N); let mut array = [crate::unsafe::zeroed(); N]; @@ -53,4 +53,53 @@ impl [T] { } array } + + // Apply a function to each element of the slice, returning a new slice + // containing the mapped elements. + pub fn map(self, f: fn[Env](T) -> U) -> [U] { + let mut ret = &[]; + for elem in self { + ret = ret.push_back(f(elem)); + } + ret + } + + // Apply a function to each element of the slice and an accumulator value, + // returning the final accumulated value. This function is also sometimes + // called `foldl`, `fold_left`, `reduce`, or `inject`. + pub fn fold(self, mut accumulator: U, f: fn[Env](U, T) -> U) -> U { + for elem in self { + accumulator = f(accumulator, elem); + } + accumulator + } + + // Apply a function to each element of the slice and an accumulator value, + // returning the final accumulated value. Unlike fold, reduce uses the first + // element of the given slice as its starting accumulator value. + pub fn reduce(self, f: fn[Env](T, T) -> T) -> T { + let mut accumulator = self[0]; + for i in 1..self.len() { + accumulator = f(accumulator, self[i]); + } + accumulator + } + + // Returns true if all elements in the slice satisfy the predicate + pub fn all(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = true; + for elem in self { + ret &= predicate(elem); + } + ret + } + + // Returns true if any element in the slice satisfies the predicate + pub fn any(self, predicate: fn[Env](T) -> bool) -> bool { + let mut ret = false; + for elem in self { + ret |= predicate(elem); + } + ret + } } diff --git a/noir/noir-repo/noir_stdlib/src/string.nr b/noir/noir-repo/noir_stdlib/src/string.nr index 12b5a1e75ec4..5f8f3de775dc 100644 --- a/noir/noir-repo/noir_stdlib/src/string.nr +++ b/noir/noir-repo/noir_stdlib/src/string.nr @@ -1,5 +1,5 @@ use crate::collections::vec::Vec; -impl str { +impl str { /// Converts the given string into a byte array #[builtin(str_as_bytes)] pub fn as_bytes(self) -> [u8; N] {} diff --git a/noir/noir-repo/noir_stdlib/src/test.nr b/noir/noir-repo/noir_stdlib/src/test.nr index e6a7e03fefcf..f8db60791938 100644 --- a/noir/noir-repo/noir_stdlib/src/test.nr +++ b/noir/noir-repo/noir_stdlib/src/test.nr @@ -1,5 +1,5 @@ #[oracle(create_mock)] -unconstrained fn create_mock_oracle(name: str) -> Field {} +unconstrained fn create_mock_oracle(name: str) -> Field {} #[oracle(set_mock_params)] unconstrained fn set_mock_params_oracle

(id: Field, params: P) {} @@ -21,7 +21,7 @@ struct OracleMock { } impl OracleMock { - unconstrained pub fn mock(name: str) -> Self { + unconstrained pub fn mock(name: str) -> Self { Self { id: create_mock_oracle(name) } } diff --git a/noir/noir-repo/noir_stdlib/src/uint128.nr b/noir/noir-repo/noir_stdlib/src/uint128.nr index 173fa54863aa..e99818bafa0d 100644 --- a/noir/noir-repo/noir_stdlib/src/uint128.nr +++ b/noir/noir-repo/noir_stdlib/src/uint128.nr @@ -66,7 +66,7 @@ impl U128 { bytes } - pub fn from_hex(hex: str) -> U128 { + pub fn from_hex(hex: str) -> U128 { let N = N as u32; let bytes = hex.as_bytes(); // string must starts with "0x" @@ -319,13 +319,12 @@ mod tests { use crate::uint128::{U128, pow64, pow63}; #[test] - fn test_not() { - let num = U128::from_u64s_le(0, 0); + fn test_not(lo: u64, hi: u64) { + let num = U128::from_u64s_le(lo, hi); let not_num = num.not(); - let max_u64: Field = pow64 - 1; - assert_eq(not_num.hi, max_u64); - assert_eq(not_num.lo, max_u64); + assert_eq(not_num.hi, (hi.not() as Field)); + assert_eq(not_num.lo, (lo.not() as Field)); let not_not_num = not_num.not(); assert_eq(num, not_not_num); @@ -493,6 +492,15 @@ mod tests { let end = a.to_integer(); assert_eq(start, end); } + + #[test] + fn integer_conversions_fuzz(lo: u64, hi: u64) { + let start: Field = (lo as Field) + pow64 * (hi as Field); + let a = U128::from_integer(start); + let end = a.to_integer(); + assert_eq(start, end); + } + #[test] fn test_wrapping_mul() { // 1*0==0 diff --git a/noir/noir-repo/scripts/install_bb.sh b/noir/noir-repo/scripts/install_bb.sh index c3ed476200a1..b0d55b6ff1d4 100755 --- a/noir/noir-repo/scripts/install_bb.sh +++ b/noir/noir-repo/scripts/install_bb.sh @@ -1,6 +1,6 @@ #!/bin/bash -VERSION="0.41.0" +VERSION="0.43.0" BBUP_PATH=~/.bb/bbup diff --git a/noir/noir-repo/scripts/redo-typo-pr.sh b/noir/noir-repo/scripts/redo-typo-pr.sh new file mode 100755 index 000000000000..416be65a4496 --- /dev/null +++ b/noir/noir-repo/scripts/redo-typo-pr.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -eux + +# Configuration +ORIGINAL_PR_NUMBER=$1 +REPO='noir-lang/noir' +NEW_BRANCH="chore/typo-redo-$ORIGINAL_PR_NUMBER" +AUTHOR=`gh pr view $ORIGINAL_PR_NUMBER --json author --jq '.author.login'` + +# Step 1: Checkout the PR locally +echo "Checking out PR #$ORIGINAL_PR_NUMBER" +gh pr checkout $ORIGINAL_PR_NUMBER + +# Step 2: Create a new local branch +echo "Creating new local branch $NEW_BRANCH" +git checkout -b $NEW_BRANCH + +# Step 3: Push the new branch to GitHub +echo "Pushing new branch $NEW_BRANCH to GitHub" +git commit --amend --no-edit +git push origin $NEW_BRANCH + +# Step 4: create a new pull request +echo "Creating a new pull request for $NEW_BRANCH" +gh pr create --base master --head $NEW_BRANCH --title "chore: redo typo PR by $AUTHOR" --body "Thanks $AUTHOR for https://github.com/$REPO/pull/$ORIGINAL_PR_NUMBER. Our policy is to redo typo changes to dissuade metric farming. This is an automated script." + +# Step 5: Close the original PR +echo "Closing original PR #$ORIGINAL_PR_NUMBER" +gh pr close $ORIGINAL_PR_NUMBER + +echo "Script completed." diff --git a/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr index 31c2f1f2d13d..cb853e48c30b 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_eddsa_poseidon/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::eddsa::{eddsa_poseidon_verify}; +use std::eddsa::eddsa_poseidon_verify; fn main( msg: pub Field, @@ -9,4 +9,4 @@ fn main( s: Field ) -> pub bool { eddsa_poseidon_verify(pub_key_x, pub_key_y, s, r8_x, r8_y, msg) -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash/src/main.nr index 38adeef6ec75..9900e91c1d73 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::hash::poseidon; +use std::hash::poseidon; fn main(input: [Field; 2]) -> pub Field { poseidon::bn254::hash_2(input) diff --git a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr index fc9a5b7a9705..1c9bbfe61bfe 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_100/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::hash; +use std::hash; global SIZE = 100; @@ -9,4 +9,4 @@ fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr index 4d2d94e49463..3edb47e9f72f 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_poseidon_hash_30/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::hash; +use std::hash; global SIZE = 30; @@ -9,4 +9,4 @@ fn main(input: [[Field; 2]; SIZE]) -> pub [Field; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256/Nargo.toml b/noir/noir-repo/test_programs/benchmarks/bench_sha256/Nargo.toml new file mode 100644 index 000000000000..488b94ca8586 --- /dev/null +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bench_sha256" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_sha256/src/main.nr index fc873fb4afbd..c94d359239dd 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; fn main(input: [u8; 2]) -> pub [u8; 32] { std::hash::sha256(input) diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr index d78ca8002d2d..6df856a83fce 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256_100/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - global SIZE = 100; fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { @@ -9,4 +7,4 @@ fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr b/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr index fa66d6265863..220c1cfbbeda 100644 --- a/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr +++ b/noir/noir-repo/test_programs/benchmarks/bench_sha256_30/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - global SIZE = 30; fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { @@ -9,4 +7,4 @@ fn main(input: [[u8; 2]; SIZE]) -> pub [[u8; 32]; SIZE] { } results -} \ No newline at end of file +} diff --git a/noir/noir-repo/test_programs/compile_failure/array_length_defaulting/src/main.nr b/noir/noir-repo/test_programs/compile_failure/array_length_defaulting/src/main.nr index 216a9ae3f0c1..40543db28705 100644 --- a/noir/noir-repo/test_programs/compile_failure/array_length_defaulting/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/array_length_defaulting/src/main.nr @@ -1,5 +1,5 @@ fn main() { - let x = dep::std::unsafe::zeroed(); + let x = std::unsafe::zeroed(); foo(x); } diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml new file mode 100644 index 000000000000..6171770b62ba --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr new file mode 100644 index 000000000000..43da3ef0eaae --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant([dynamic_one]); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml new file mode 100644 index 000000000000..e5583e531267 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr new file mode 100644 index 000000000000..f8a377092a2a --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(dynamic_one + 1 == 3); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml new file mode 100644 index 000000000000..d1d068a79b8a --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr new file mode 100644 index 000000000000..f07002d7d4c6 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(&[dynamic_one]); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml new file mode 100644 index 000000000000..18781f4d57d4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr new file mode 100644 index 000000000000..b9f4dceafc02 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_array = Foo { field: 0, array: [dynamic_one, 2, 3], slice: &[] }; + assert_constant(foo_dynamic_array); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml new file mode 100644 index 000000000000..173ea44101ae --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_field" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr new file mode 100644 index 000000000000..e7986c93b6ba --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic = Foo { field: dynamic_one, array: [1, 2, 3], slice: &[] }; + assert_constant(foo_dynamic); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml new file mode 100644 index 000000000000..426f4826a0bd --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr new file mode 100644 index 000000000000..c775b5639284 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_slice = Foo { field: 0, array: [1, 2, 3], slice: &[dynamic_one] }; + assert_constant(foo_dynamic_slice); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml new file mode 100644 index 000000000000..de7b2031300e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_tuple" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr new file mode 100644 index 000000000000..579a5a0991f0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant((dynamic_one, 2)); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_fail/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_fail/src/main.nr index cf682607083a..b8d5d255228c 100644 --- a/noir/noir-repo/test_programs/compile_failure/assert_constant_fail/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_fail/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::assert_constant; +use std::assert_constant; fn main(x: Field) { foo(5, x); diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml new file mode 100644 index 000000000000..cb8d59f42935 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_false" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr new file mode 100644 index 000000000000..f4e98cfec370 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr @@ -0,0 +1,3 @@ +fn main() { + std::static_assert(false, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/src/main.nr b/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/src/main.nr index 3d8a6748ccf2..ee61195cf8f5 100644 --- a/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/brillig_nested_slices/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::slice; +use std::slice; // Tests nested slice passing to/from functions unconstrained fn push_back_to_slice(slice: [T], item: T) -> [T] { slice.push_back(item) diff --git a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml index 3835292a6ba8..80312a7aec11 100644 --- a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml @@ -2,6 +2,6 @@ name = "builtin_function_declaration" type = "bin" authors = [""] -compiler_version = ">=0.23.0" +compiler_version = ">=0.31.0" -[dependencies] +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr index ed376557371e..473b5405691e 100644 --- a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr @@ -7,4 +7,4 @@ fn to_le_bits(_x: Field, _bit_size: u32) -> [u1] {} fn main(x: Field) -> pub u1 { let bits = to_le_bits(x, 100); bits[0] -} +} \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/src/main.nr b/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/src/main.nr index e61ae82b62c5..40578574c75a 100644 --- a/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/dep_impl_primitive/src/main.nr @@ -1,4 +1,4 @@ -use dep::bad_impl; +use bad_impl; fn main(x: Field) { x.something(); diff --git a/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml new file mode 100644 index 000000000000..0d5a6221ef2c --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "dep_submodule_overlap" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] +reexporting_lib = { path = "../../test_libraries/reexporting_lib" } diff --git a/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr new file mode 100644 index 000000000000..e2e82b2f5cde --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/lib.nr @@ -0,0 +1,3 @@ +struct MyStruct { + inner: Field +} diff --git a/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/main.nr b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/main.nr new file mode 100644 index 000000000000..c53630c53ca3 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/dep_submodule_overlap/src/main.nr @@ -0,0 +1,9 @@ +use reexporting_lib::{MyStruct, lib}; + +mod lib; +use crate::lib::MyStruct; + +fn main() { + let x = MyStruct { inner: 0 }; + assert(lib::is_struct_zero(x)); +} diff --git a/noir/noir-repo/test_programs/compile_failure/depend_on_bin/src/main.nr b/noir/noir-repo/test_programs/compile_failure/depend_on_bin/src/main.nr index 4e03e8eb41e4..d7aff600fe61 100644 --- a/noir/noir-repo/test_programs/compile_failure/depend_on_bin/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/depend_on_bin/src/main.nr @@ -1,4 +1,4 @@ -use dep::bin_dep; +use bin_dep; fn main(x : Field) { assert(x == 1); diff --git a/noir/noir-repo/test_programs/compile_failure/integer_too_large/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/integer_too_large/Nargo.toml new file mode 100644 index 000000000000..08439d2f02ef --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/integer_too_large/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "integer_too_large" +type = "bin" +authors = [""] +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/integer_too_large/src/main.nr b/noir/noir-repo/test_programs/compile_failure/integer_too_large/src/main.nr new file mode 100644 index 000000000000..a8a2c383fe6c --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/integer_too_large/src/main.nr @@ -0,0 +1,4 @@ +fn main(x: Field) { + let too_large: Field = 233149999999999999999999999999999999999999999999999999999999923314999999999999999999999999999999999999999999999999999999999923314999999999999999999999999999999999999999999999999999999999; + assert(x == too_large); +} \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml new file mode 100644 index 000000000000..12776f477121 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_main_sub_lib" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr new file mode 100644 index 000000000000..4658900a47a0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main.nr @@ -0,0 +1,5 @@ +mod lib; + +use crate::lib::foo; + +fn main() {} diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr new file mode 100644 index 000000000000..0f89316b5bd4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_main_sub_lib/src/main/lib.nr @@ -0,0 +1,3 @@ +pub fn foo() -> bool { + true +} diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml new file mode 100644 index 000000000000..7a93d385c1c4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "invalid_mod_mod_path" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr new file mode 100644 index 000000000000..0f89316b5bd4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/main/lib.nr @@ -0,0 +1,3 @@ +pub fn foo() -> bool { + true +} diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr new file mode 100644 index 000000000000..86fa197360f8 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/main.nr @@ -0,0 +1,4 @@ +mod crate::mod; + +fn main() { +} diff --git a/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr new file mode 100644 index 000000000000..e2f24cb9226e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/invalid_mod_mod_path/src/mod.nr @@ -0,0 +1,3 @@ +pub foo() -> bool { + true +} diff --git a/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr b/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr index db5f9b0820f8..4d3c5abe5a45 100644 --- a/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/negate_unsigned/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { let var = -1 as u8; std::println(var); diff --git a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml new file mode 100644 index 000000000000..8bdefbbbd218 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "non_comptime_local_fn_call" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr new file mode 100644 index 000000000000..d75bb1a922af --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + comptime { + let _a = id(3); + } +} + +fn id(x: Field) -> Field { + x +} diff --git a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr b/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr index dfd88d8f074a..dd04aa454b28 100644 --- a/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/orphaned_trait_impl/src/main.nr @@ -1,4 +1,4 @@ -impl dep::crate1::MyTrait for dep::crate2::MyStruct { +impl crate1::MyTrait for crate2::MyStruct { } fn main(x: Field, y: pub Field) { diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 000000000000..b2c3e5f94be1 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 000000000000..57e704462dbc --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Prover.toml b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/Prover.toml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 000000000000..675e889b7e57 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,12 @@ +fn main() -> pub Field { + assert(foo::bar() + foo::baz() == 3); + assert(foo::bar() == 1); + assert(foo::baz() == 2); + foo::bar() + foo::baz() +} + +mod foo { + pub(crate) fn bar() -> Field { + 1 + } +} diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 000000000000..857d4e722a88 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 000000000000..7834e2c92764 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,3 @@ +pub fn baz() -> Field { + 2 +} diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_mod/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/Nargo.toml new file mode 100644 index 000000000000..c9d59b22a39b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "overlapping_lib_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo.nr b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo.nr new file mode 100644 index 000000000000..f17d7d7cec53 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo.nr @@ -0,0 +1,4 @@ +pub fn bar() -> bool { + true +} + diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr new file mode 100644 index 000000000000..261729b812bb --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/foo/mod.nr @@ -0,0 +1,3 @@ +pub fn bar() -> bool { + true +} diff --git a/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/main.nr b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/main.nr new file mode 100644 index 000000000000..12a3d91f9414 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/overlapping_mod/src/main.nr @@ -0,0 +1,7 @@ +mod foo; + +use foo::bar; + +fn main() { + assert(bar()); +} diff --git a/noir/noir-repo/test_programs/compile_failure/regression_5008/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/regression_5008/Nargo.toml new file mode 100644 index 000000000000..920c00660cf5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/regression_5008/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5008" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/regression_5008/src/main.nr b/noir/noir-repo/test_programs/compile_failure/regression_5008/src/main.nr new file mode 100644 index 000000000000..6d9645ee6eb5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/regression_5008/src/main.nr @@ -0,0 +1,17 @@ +struct Bar { + value: Field, +} + +struct Foo{ + bar: &mut Bar, +} + +impl Foo { + unconstrained fn crash_fn(self) {} +} + +fn main() { + let foo = Foo { bar: &mut Bar { value: 0 } }; + + foo.crash_fn(); +} diff --git a/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr b/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr index 01e72bfcfd70..a3fea13cc3ab 100644 --- a/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/restricted_bit_sizes/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::assert_constant; +use std::assert_constant; fn main() -> pub u63 { 5 diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml new file mode 100644 index 000000000000..1c6c13ce225e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_array_len" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr new file mode 100644 index 000000000000..9e4665f8ad8d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + std::static_assert([1, 2, dynamic_one].len() == 4, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml new file mode 100644 index 000000000000..45e39ae24a8e --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr new file mode 100644 index 000000000000..6621b8a1fb35 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr @@ -0,0 +1,15 @@ +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field, // == 2 +) { + // length unknown at compile time + let mut dynamic_built_slice_pair = &[]; + if dynamic_one == 1 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_one); + } + if dynamic_two == 2 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_two); + } + + std::static_assert(dynamic_built_slice_pair.len() == 3, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml new file mode 100644 index 000000000000..fdb90c0dc1c9 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr new file mode 100644 index 000000000000..2241743ddb00 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let x = 2; + let y = 3; + let xy = x + y; + + std::static_assert(xy == 6, "2 + 3 != 6"); +} diff --git a/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr b/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr index a360641fa15a..4091b2f05810 100644 --- a/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/turbofish_generic_count/src/main.nr @@ -1,4 +1,3 @@ - struct Bar { one: Field, two: Field, @@ -7,7 +6,7 @@ struct Bar { impl Bar { fn zeroed(_self: Self) -> A { - dep::std::unsafe::zeroed() + std::unsafe::zeroed() } } diff --git a/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/Nargo.toml new file mode 100644 index 000000000000..dc90816e16b4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "type_definition_annotation" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/src/main.nr b/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/src/main.nr new file mode 100644 index 000000000000..d4fef84442d0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/type_definition_annotation/src/main.nr @@ -0,0 +1,8 @@ +#[fail_assert] +struct Foo { x: Field } + +comptime fn fail_assert(_typ: StructDefinition) { + assert(false); +} + +fn main() {} diff --git a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml new file mode 100644 index 000000000000..56fa88ccb688 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "abi_attribute" +type = "contract" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr new file mode 100644 index 000000000000..164512b03dbb --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr @@ -0,0 +1,9 @@ +contract Foo { + #[abi(foo)] + global foo: Field = 42; + + #[abi(bar)] + struct Bar { + inner: Field + } +} diff --git a/noir/noir-repo/test_programs/compile_success_contract/recursive_method/Nargo.toml b/noir/noir-repo/test_programs/compile_success_contract/recursive_method/Nargo.toml new file mode 100644 index 000000000000..8142e5b3278d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_contract/recursive_method/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "recursive_method" +type = "contract" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_contract/recursive_method/src/main.nr b/noir/noir-repo/test_programs/compile_success_contract/recursive_method/src/main.nr new file mode 100644 index 000000000000..6fd4bf3338d4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_contract/recursive_method/src/main.nr @@ -0,0 +1,6 @@ +contract Foo { + #[recursive] + fn contract_entrypoint() -> pub Field { + 1 + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml new file mode 100644 index 000000000000..f18d4828fdf4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr new file mode 100644 index 000000000000..6910a2d17b2f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr @@ -0,0 +1,59 @@ +use std::static_assert; + +global GLOBAL_ONE = 1; +global GLOBAL_TWO = 2; +global GLOBAL_THREE = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR = &[GLOBAL_ONE, GLOBAL_TWO]; + +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + assert_constant(true); + assert_constant(false); + + assert_constant(2 == 2); + assert_constant(1 + 1 == 2); + + // assert_constant doesn't check for true + assert_constant(1 + 1 == 3); + + let local_one = 1; + let local_two = 2; + let local_three = local_one + local_two; + let local_array_pair = [local_one, local_two]; + let local_slice_pair = &[local_one, local_two]; + + assert_constant(local_one); + assert_constant(local_three); + assert_constant(local_array_pair); + assert_constant(local_slice_pair); + + assert_constant(GLOBAL_ONE); + assert_constant(GLOBAL_THREE); + assert_constant(GLOBAL_ARRAY_PAIR); + assert_constant(GLOBAL_SLICE_PAIR); + + assert_constant([1, 2, dynamic_one].len() == 4); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + let foo = Foo { field: 0, array: [1, 2, 3], slice: &[] }; + assert_constant(foo); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/impl_with_where_clause/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/Nargo.toml similarity index 62% rename from noir/noir-repo/test_programs/compile_success_empty/impl_with_where_clause/Nargo.toml rename to noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/Nargo.toml index ef9bdce2640e..c07deddc6c52 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/impl_with_where_clause/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "impl_with_where_clause" +name = "comptime_array_len" type = "bin" authors = [""] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/src/main.nr new file mode 100644 index 000000000000..c98a3de01dd0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_array_len/src/main.nr @@ -0,0 +1,6 @@ +fn main() { + comptime + { + assert_eq([1, 2, 3].len(), 3); + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml new file mode 100644 index 000000000000..90c67b07b2b5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "array_to_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.24.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/src/main.nr new file mode 100644 index 000000000000..07c5e344cc24 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_as_slice/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + comptime + { + let ws: [Field; 3] = [1; 3]; + let ws_as_slice: [Field] = ws.as_slice(); + + assert_eq(ws[0], ws_as_slice[0]); + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/Nargo.toml new file mode 100644 index 000000000000..099545a9e719 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_type_definition" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/src/main.nr new file mode 100644 index 000000000000..cdfc9bd6b75b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_type_definition/src/main.nr @@ -0,0 +1,13 @@ +fn main() {} + +#[my_comptime_fn] +struct MyType { + field1: [A; 10], + field2: (B, C), +} + +comptime fn my_comptime_fn(typ: StructDefinition) { + let _ = typ.as_type(); + assert_eq(typ.generics().len(), 3); + assert_eq(typ.fields().len(), 2); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr index 5446cfbb1e41..9b5d95c11bc1 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/conditional_regression_to_bits/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { //Regression for to_le_bits() constant evaluation // binary array representation of u8 1 diff --git a/noir/noir-repo/test_programs/compile_success_empty/derive_impl/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/derive_impl/Nargo.toml new file mode 100644 index 000000000000..26a6020a6b1f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/derive_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "derive_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/derive_impl/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/derive_impl/src/main.nr new file mode 100644 index 000000000000..5463a61d9698 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/derive_impl/src/main.nr @@ -0,0 +1,49 @@ +comptime fn derive_default(typ: StructDefinition) -> Quoted { + let generics: [Quoted] = typ.generics(); + assert_eq( + generics.len(), 0, "derive_default: Deriving Default on generic types is currently unimplemented" + ); + + let type_name = typ.as_type(); + let fields = typ.fields(); + + let fields = join(make_field_exprs(fields)); + + quote { + impl Default for $type_name { + fn default() -> Self { + Self { $fields } + } + } + } +} + +#[derive_default] +struct Foo { + x: Field, + y: Bar, +} + +#[derive_default] +struct Bar {} + +comptime fn make_field_exprs(fields: [(Quoted, Quoted)]) -> [Quoted] { + let mut result = &[]; + for my_field in fields { + let name = my_field.0; + result = result.push_back(quote { $name: Default::default(), }); + } + result +} + +comptime fn join(slice: [Quoted]) -> Quoted { + let mut result = quote {}; + for elem in slice { + result = quote { $result $elem }; + } + result +} + +fn main() { + let _foo: Foo = Default::default(); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr index becd3c8927ac..616ac7ef6ee0 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/ec_baby_jubjub/src/main.nr @@ -1,18 +1,19 @@ // Tests may be checked against https://github.com/cfrg/draft-irtf-cfrg-hash-to-curve/tree/main/poc -use dep::std::ec::tecurve::affine::Curve as AffineCurve; -use dep::std::ec::tecurve::affine::Point as Gaffine; -use dep::std::ec::tecurve::curvegroup::Curve; -use dep::std::ec::tecurve::curvegroup::Point as G; +use std::ec::tecurve::affine::Curve as AffineCurve; +use std::ec::tecurve::affine::Point as Gaffine; +use std::ec::tecurve::curvegroup::Curve; +use std::ec::tecurve::curvegroup::Point as G; -use dep::std::ec::swcurve::affine::Point as SWGaffine; -use dep::std::ec::swcurve::curvegroup::Point as SWG; +use std::ec::swcurve::affine::Point as SWGaffine; +use std::ec::swcurve::curvegroup::Point as SWG; -use dep::std::ec::montcurve::affine::Point as MGaffine; -use dep::std::ec::montcurve::curvegroup::Point as MG; +use std::ec::montcurve::affine::Point as MGaffine; +use std::ec::montcurve::curvegroup::Point as MG; +use std::compat; fn main() { // This test only makes sense if Field is the right prime field. - if 21888242871839275222246405745257275088548364400416034343698204186575808495617 == 0 { + if compat::is_bn254() { // Define Baby Jubjub (ERC-2494) parameters in affine representation let bjj_affine = AffineCurve::new( 168700, diff --git a/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/Nargo.toml new file mode 100644 index 000000000000..7d0d5f3513ed --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "impl_where_clause" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/src/main.nr new file mode 100644 index 000000000000..2f3223efaae5 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/impl_where_clause/src/main.nr @@ -0,0 +1,34 @@ +struct MyStruct { + a: u32, + b: T, +} + +struct InnerStruct { + a: Field, + b: Field, +} + +trait MyEq { + fn my_eq(self, other: Self) -> bool; +} + +impl MyEq for InnerStruct { + fn my_eq(self, other: InnerStruct) -> bool { + (self.a == other.a) & (self.b == other.b) + } +} + +impl MyStruct where T: MyEq { + fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} + +fn main() { + let inner = InnerStruct { a: 1, b: 2 }; + let my_struct = MyStruct { a: 5, b: inner }; + assert(my_struct.my_eq(my_struct)); + + let mut my_struct_new = MyStruct { a: 5, b: InnerStruct { a: 10, b: 15 } }; + assert(my_struct_new.my_eq(my_struct_new)); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/intrinsic_die/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/intrinsic_die/src/main.nr index a6c6d3df9a1d..17aaf02c2835 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/intrinsic_die/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/intrinsic_die/src/main.nr @@ -1,7 +1,5 @@ -use dep::std; // This test checks that we perform dead-instruction-elimination on intrinsic functions. fn main(x: Field) { - let hash = std::hash::pedersen_commitment([x]); let g1_x = 0x0000000000000000000000000000000000000000000000000000000000000001; let g1_y = 0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c; let g1 = std::embedded_curve_ops::EmbeddedCurvePoint { x: g1_x, y: g1_y, is_infinite: false }; diff --git a/noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml new file mode 100644 index 000000000000..e4408e2ee170 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/macros/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "macros" +type = "bin" +authors = [""] +compiler_version = ">=0.30.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr new file mode 100644 index 000000000000..587c2c4c0778 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr @@ -0,0 +1,15 @@ +comptime fn my_macro(x: Field, y: Field) -> Quoted { + // Current version of macros in Noir are not hygienic + // so we can quote a and b here and expect them to resolve + // to the a and b in main at the callsite of my_macro. + quote { + $x + $y + a + b + } +} + +fn main() { + let a = 100; + let b = 200; + let result = my_macro!(1, 2); + assert_eq(result, 1 + 2 + a + b); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/method_call_regression/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/method_call_regression/src/main.nr index 8bb7ebcac45c..88b8dc571968 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/method_call_regression/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/method_call_regression/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { // s: Struct let s = Struct { b: () }; diff --git a/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml new file mode 100644 index 000000000000..b90b73261866 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "mod_nr_entrypoint" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr new file mode 100644 index 000000000000..0bcfe8b02ad4 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/baz.nr @@ -0,0 +1,3 @@ +pub fn in_baz_mod() -> bool { + true +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr new file mode 100644 index 000000000000..f2efe64906de --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/bar.nr @@ -0,0 +1,3 @@ +pub fn in_bar_mod() -> Field { + 2 +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr new file mode 100644 index 000000000000..4eac6cb8514b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/foo/mod.nr @@ -0,0 +1,5 @@ +mod bar; + +pub fn in_foo_mod() -> Field { + 1 +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr new file mode 100644 index 000000000000..620fd99f6eca --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/mod_nr_entrypoint/src/main.nr @@ -0,0 +1,11 @@ +use crate::foo::in_foo_mod; +use crate::foo::bar::in_bar_mod; +use crate::baz::in_baz_mod; + +mod foo; +mod baz; + +fn main() { + assert(in_foo_mod() != in_bar_mod()); + assert(in_baz_mod()); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml new file mode 100644 index 000000000000..2125d475530f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "no_duplicate_methods" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/Prover.toml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr new file mode 100644 index 000000000000..2be1d3fa11e9 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/no_duplicate_methods/src/main.nr @@ -0,0 +1,26 @@ +// Test that declaring several methods & trait methods with the same name +// does not trigger a duplicate method error +trait ToField { + fn to_field(self) -> Field; +} +trait ToField2 { + fn to_field(self) -> Field; +} + +struct Foo { x: Field } + +impl ToField for Foo { + fn to_field(self) -> Field { self.x } +} + +impl ToField2 for Foo { + fn to_field(self) -> Field { self.x } +} + +impl Foo { + fn to_field(self) -> Field { + self.x + } +} + +fn main() {} diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr index 1e03a382fed3..340c18c2a1dc 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics/src/main.nr @@ -36,4 +36,3 @@ fn foo(mut s: MyStruct<2+1>) -> MyStruct<10/2-2> { s.data[0] = s.data[0] + 1; s } - diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml new file mode 100644 index 000000000000..980e5db588ae --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "numeric_generics_explicit" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr new file mode 100644 index 000000000000..7c4f7761ff6f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/src/main.nr @@ -0,0 +1,111 @@ +// Regression that a global of the same name does not trigger a duplicate definition error +global N = 1000; + +fn main() { + let a = id([1, 2]); + let b = id([1, 2, 3]); + + let itWorks1 = MyStruct { data: a }; + assert(itWorks1.data[1] == 2); + let itWorks2 = MyStruct { data: b }; + assert(itWorks2.data[1] == 2); + + let c = [1, 2]; + let itAlsoWorks = MyStruct { data: c }; + assert(itAlsoWorks.data[1] == 2); + + assert(foo(itWorks2).data[0] == itWorks2.data[0] + 1); + + double_numeric_generics_test(); + + let my_type = PublicStorage::read::(); + assert(my_type.a == 1); + assert(my_type.b == 2); + assert(my_type.c == 3); + + let foo = baz::<10>(); + assert(foo.data == [1; 10]); +} + +// Used in the signature of a function +fn id(x: [Field; I]) -> [Field; I] { + x +} + +// Used as a field of a struct +struct MyStruct { + data: [Field; S], +} + +// Used in an impl +impl MyStruct { + fn insert(mut self: Self, index: Field, elem: Field) -> Self { + // Regression test for numeric generics on impls + assert(index as u32 < S); + + self.data[index] = elem; + self + } +} + +fn foo(mut s: MyStruct<2+1>) -> MyStruct<10/2-2> { + s.data[0] = s.data[0] + 1; + s +} + +fn baz() -> MyStruct { + MyStruct { data: [1; N] } +} + +fn double() -> u32 { + // Used as an expression + N * 2 +} + +fn double_numeric_generics_test() { + // Example usage of a numeric generic arguments. + assert(double::<9>() == 18); + assert(double::<123>() == 246); + assert(double::<7 + 8>() == 30); +} + +struct MyType { + a: Field, + b: Field, + c: Field, +} + +impl Deserialize for MyType { + fn deserialize(fields: [Field; N]) -> Self { + MyType { a: fields[0], b: fields[1], c: fields[2] } + } +} + +trait Deserialize { + fn deserialize(fields: [Field; N]) -> Self; +} + +struct PublicStorage {} + +impl PublicStorage { + fn read() -> T where T: Deserialize { + // Used as a type within a function body + let mut fields: [Field; N] = [0; N]; + // Used a loop bound + for i in 0..N { + fields[i] = i as Field + 1; + } + T::deserialize(fields) + } +} + +// Check that we can thread numeric generics into nested structs +// and also that we can handle nested structs with numeric generics +// which are declared after the parent struct +struct NestedNumeric { + a: Field, + b: InnerNumeric +} +struct InnerNumeric { + inner: [u32; N], +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 000000000000..b2c3e5f94be1 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 000000000000..57e704462dbc --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 000000000000..1d9c917d91a0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,9 @@ +fn main() { + let _ = foo::bar() + dep::foo::baz(); +} + +mod foo { + pub(crate) fn bar() -> Field { + 5 + } +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 000000000000..857d4e722a88 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 000000000000..cb8392ed275f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,5 @@ +// foo/lib.nr + +pub fn baz() -> Field { + 6 +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr index ed469ff77d0a..0fd65a335641 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/reexports/src/main.nr @@ -1,4 +1,4 @@ -use dep::reexporting_lib::{FooStruct, MyStruct, lib}; +use reexporting_lib::{FooStruct, MyStruct, lib}; fn main() { let x: FooStruct = MyStruct { inner: 0 }; diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_2099/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/regression_2099/src/main.nr index f92373ce63ae..660f72f56e5d 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/regression_2099/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_2099/src/main.nr @@ -1,13 +1,13 @@ -use dep::std::ec::tecurve::affine::Curve as AffineCurve; -use dep::std::ec::tecurve::affine::Point as Gaffine; -use dep::std::ec::tecurve::curvegroup::Curve; -use dep::std::ec::tecurve::curvegroup::Point as G; +use std::ec::tecurve::affine::Curve as AffineCurve; +use std::ec::tecurve::affine::Point as Gaffine; +use std::ec::tecurve::curvegroup::Curve; +use std::ec::tecurve::curvegroup::Point as G; -use dep::std::ec::swcurve::affine::Point as SWGaffine; -use dep::std::ec::swcurve::curvegroup::Point as SWG; +use std::ec::swcurve::affine::Point as SWGaffine; +use std::ec::swcurve::curvegroup::Point as SWG; -use dep::std::ec::montcurve::affine::Point as MGaffine; -use dep::std::ec::montcurve::curvegroup::Point as MG; +use std::ec::montcurve::affine::Point as MGaffine; +use std::ec::montcurve::curvegroup::Point as MG; fn main() { // Define Baby Jubjub (ERC-2494) parameters in affine representation diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_3635/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/regression_3635/src/main.nr index 97a04f9d93fa..edc6d8690e8e 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/regression_3635/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_3635/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { let x: u8 = 0x61; let y: u8 = "a".as_bytes()[0]; diff --git a/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr index 23918e30785f..350b60ba3f7e 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/regression_4635/src/main.nr @@ -8,7 +8,7 @@ impl FromField for Field { } } -trait Deserialize { +trait Deserialize { fn deserialize(fields: [Field; N]) -> Self; } diff --git a/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml new file mode 100644 index 000000000000..5dabd7803e38 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr new file mode 100644 index 000000000000..e61d9388ceb6 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr @@ -0,0 +1,46 @@ +use std::static_assert; + +global GLOBAL_ONE = 1; +global GLOBAL_TWO = 2; +global GLOBAL_THREE = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR = &[GLOBAL_ONE, GLOBAL_TWO]; + +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + static_assert(true, ""); + + static_assert(1 + 1 == 2, ""); + + let x = 2; + let y = 3; + let xy = x + y; + static_assert(xy == 5, ""); + + static_assert(3 == GLOBAL_THREE, ""); + + static_assert(GLOBAL_ARRAY_PAIR.len() == 2, ""); + static_assert(GLOBAL_SLICE_PAIR.len() == 2, ""); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + assert_constant([1, 2, dynamic_one].len() == 4); + static_assert([1, 2, dynamic_one].len() == 3, ""); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/str_as_bytes/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/str_as_bytes/src/main.nr index 6fdd926ce7fd..1330924e501c 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/str_as_bytes/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/str_as_bytes/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; fn main() { let a = "hello"; let b = a.as_bytes(); diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_default_implementation/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_default_implementation/src/main.nr index 2f5bff8c40cb..90c375b60109 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/trait_default_implementation/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_default_implementation/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - trait MyDefault { fn my_default(x: Field, y: Field) -> Self; diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr index 30b2e79d579f..15591f2f2ead 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr @@ -15,7 +15,7 @@ trait MyInto { fn into(self) -> T; } -impl MyInto<[U; N]> for [T; N] where T: MyInto { +impl MyInto<[U; N]> for [T; N] where T: MyInto { fn into(self) -> [U; N] { self.map(|x: T| x.into()) } @@ -29,7 +29,7 @@ impl MyInto for Field { /// Serialize example -trait Serializable { +trait Serializable { fn serialize(self) -> [Field; N]; } diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml new file mode 100644 index 000000000000..672569634ea0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "trait_impl_with_where_clause" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr similarity index 100% rename from noir/noir-repo/test_programs/compile_success_empty/impl_with_where_clause/src/main.nr rename to noir/noir-repo/test_programs/compile_success_empty/trait_impl_with_where_clause/src/main.nr diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_override_implementation/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_override_implementation/src/main.nr index 855282918704..21d89b1b261e 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/trait_override_implementation/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_override_implementation/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - trait MyDefault { fn my_default(x: Field, y: Field) -> Self; diff --git a/noir/noir-repo/test_programs/compile_success_empty/traits/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/traits/src/main.nr index ed804559fed0..0a5644e75301 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/traits/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/traits/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - trait MyDefault { fn my_default(x: Field, y: Field) -> Self; } diff --git a/noir/noir-repo/test_programs/compile_success_empty/vectors/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/vectors/src/main.nr index d105ceed1809..ac02a4691dde 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/vectors/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/vectors/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::collections::vec::Vec; +use std::collections::vec::Vec; fn main(x: Field, y: pub Field) { let mut vector = Vec::new(); diff --git a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr index ab0ae9a48b87..a4207794a8ab 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/binary/src/main.nr @@ -1,2 +1,2 @@ -use dep::library::ReExportMeFromAnotherLib; +use library::ReExportMeFromAnotherLib; fn main(_x: ReExportMeFromAnotherLib) {} diff --git a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr index 8e84662ed03f..e3a1539ea654 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/workspace_reexport_bug/library/src/lib.nr @@ -1,2 +1,2 @@ // Re-export -use dep::library2::ReExportMeFromAnotherLib; +use library2::ReExportMeFromAnotherLib; diff --git a/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr index 58adc5444b1c..f90b3ef9429a 100644 --- a/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/div_by_zero_constants/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { let a: Field = 3 / 0; std::println(a); diff --git a/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr index f51b26d5ba19..012e823b2975 100644 --- a/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/div_by_zero_numerator_witness/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: Field) { let a: Field = x / 0; std::println(a); diff --git a/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr b/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr index a814f88f3202..eaa3c1f2a726 100644 --- a/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/div_by_zero_witness/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // It is expected that `y` must be equal to 0. fn main(x: Field, y: pub Field) { let a: Field = x / y; diff --git a/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr b/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr index 907c36281426..e95da67a084f 100644 --- a/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr +++ b/noir/noir-repo/test_programs/execution_failure/hashmap_load_factor/src/main.nr @@ -1,6 +1,6 @@ -use dep::std::collections::map::HashMap; -use dep::std::hash::BuildHasherDefault; -use dep::std::hash::poseidon2::Poseidon2Hasher; +use std::collections::map::HashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; struct Entry{ key: Field, diff --git a/noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml new file mode 100644 index 000000000000..dcdc044836e4 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5202" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr b/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr new file mode 100644 index 000000000000..45ffafca4c75 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr @@ -0,0 +1,41 @@ +trait ToField { + fn to_field(self) -> Field; +} + +impl ToField for bool { fn to_field(self) -> Field { self as Field } } + +unconstrained fn get_unconstrained_option() -> Option { + Option::some(13) +} + +unconstrained fn should_i_assert() -> bool { + false +} + +fn get_magical_boolean() -> bool { + let option = get_unconstrained_option(); + + let pre_assert = option.is_some().to_field(); + + if should_i_assert() { + // Note that `should_i_assert` is unconstrained, so Noir should not be able to infer + // any behavior from the contents of this block. In this case it is actually false, so the + // assertion below is not even executed (if it did it'd fail since the values are not equal). + + assert_eq(option, Option::some(42)); /// <- this seems to be the trigger for the bug + } + + // In my testing, the `option` value exhibits weird behavior from this point on, as if it had been mutated + let post_assert = option.is_some().to_field(); + + // The following expression should be true, but I can get it to evaluate to false depending on how I call it + pre_assert == post_assert +} + +fn main() { + let magic = get_magical_boolean(); + + // One of these asserts should fail. Before #5202, they would both pass + assert_eq(magic, true); + assert_eq(magic, false); +} diff --git a/noir/noir-repo/test_programs/execution_success/4_sub/src/main.nr b/noir/noir-repo/test_programs/execution_success/4_sub/src/main.nr index 6aef8e7b2089..2b4fc3957054 100644 --- a/noir/noir-repo/test_programs/execution_success/4_sub/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/4_sub/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Test unsafe integer subtraction with underflow: 12 - 2418266113 = 1876701195 modulo 2^32 fn main(mut x: u32, y: u32, z: u32) { x = std::wrapping_sub(x,y); diff --git a/noir/noir-repo/test_programs/execution_success/5_over/src/main.nr b/noir/noir-repo/test_programs/execution_success/5_over/src/main.nr index 313d580a8d1d..6c4153e4b49b 100644 --- a/noir/noir-repo/test_programs/execution_success/5_over/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/5_over/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Test unsafe integer arithmetic // Test odd bits integer fn main(mut x: u32, y: u32) { diff --git a/noir/noir-repo/test_programs/execution_success/6/src/main.nr b/noir/noir-repo/test_programs/execution_success/6/src/main.nr index 5ecb809e68bb..8657199bd7f9 100644 --- a/noir/noir-repo/test_programs/execution_success/6/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/6/src/main.nr @@ -5,7 +5,6 @@ // If you do not cast, it will take all the bytes from the field element! // Mimc input is an array of field elements // The function is called mimc_bn254 to emphasize its parameters are chosen for bn254 curve, it should be used only with a proving system using the same curve (e.g Plonk from Aztec) -use dep::std; fn main(x: [u8; 5], result: pub [u8; 32]) { let mut digest = std::hash::sha256(x); diff --git a/noir/noir-repo/test_programs/execution_success/6_array/src/main.nr b/noir/noir-repo/test_programs/execution_success/6_array/src/main.nr index 6aa05f58b71a..d7180c260ff2 100644 --- a/noir/noir-repo/test_programs/execution_success/6_array/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/6_array/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; //Basic tests for arrays fn main(x: [u32; 5], y: [u32; 5], mut z: u32, t: u32) { let mut c = 2301; diff --git a/noir/noir-repo/test_programs/execution_success/7/src/main.nr b/noir/noir-repo/test_programs/execution_success/7/src/main.nr index a6bba9786447..ad3fe1aadc89 100644 --- a/noir/noir-repo/test_programs/execution_success/7/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/7/src/main.nr @@ -2,7 +2,6 @@ // // Pre-alpha dependencies must now be prefixed with the word "dep". // The line below indicates that we would like to pull in the standard library dependency. -use dep::std; fn main(x: [u8; 5], result: [u8; 32]) { let digest = std::hash::blake2s(x); diff --git a/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr b/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr index f6ed0f309c32..cd7fb4772e23 100644 --- a/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/aes128_encrypt/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - unconstrained fn decode_ascii(ascii: u8) -> u8 { if ascii < 58 { ascii - 48 diff --git a/noir/noir-repo/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr b/noir/noir-repo/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr index 4cbf1bd8e6df..260d609928b8 100644 --- a/noir/noir-repo/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/array_dynamic_blackbox_input/src/main.nr @@ -18,7 +18,7 @@ fn compute_root(leaf: [u8; 32], path: [u8; 64], _index: u32, root: [u8; 32]) { hash_input[j + b] = path[offset + j]; } - current = dep::std::hash::sha256(hash_input); + current = std::hash::sha256(hash_input); index = index >> 1; } diff --git a/noir/noir-repo/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr b/noir/noir-repo/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr index 8faaf69dfc86..15a2747eaa9d 100644 --- a/noir/noir-repo/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/array_dynamic_nested_blackbox_input/src/main.nr @@ -15,6 +15,6 @@ fn main(mut x: [Foo; 3], y: pub Field, hash_result: pub [u8; 32]) { // Make sure that we are passing a dynamic array to the black box function call // by setting the array using a dynamic index here hash_input[y - 1] = 0; - let hash = dep::std::hash::sha256(hash_input); + let hash = std::hash::sha256(hash_input); assert_eq(hash, hash_result); } diff --git a/noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml b/noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml new file mode 100644 index 000000000000..18f3f99b5b51 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "as_witness" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml b/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml new file mode 100644 index 000000000000..cd8a5b5e03cc --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml @@ -0,0 +1 @@ +a = 42 \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr b/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr new file mode 100644 index 000000000000..a24f4af76694 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr @@ -0,0 +1,5 @@ +// Simple example of checking where two arrays are different +fn main(a: Field) -> pub Field { + std::as_witness(a); + a +} 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 c454c2b66cd4..9385b39e8476 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 @@ -1,5 +1,5 @@ -use dep::std::bigint; -use dep::std::{bigint::Secpk1Fq, println}; +use std::bigint; +use 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]]); @@ -10,8 +10,8 @@ fn main(mut x: [u8; 5], y: [u8; 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); + let a_field = std::field::bytes32_to_field(a_be_bytes); + let b_field = std::field::bytes32_to_field(b_be_bytes); // Regression for issue #4682 let c = if x[0] != 0 { @@ -19,7 +19,7 @@ fn main(mut x: [u8; 5], y: [u8; 5]) { } else { test_unconstrained2(a, b) }; - assert(c.array[0] == dep::std::wrapping_mul(x[0], y[0])); + assert(c.array[0] == std::wrapping_mul(x[0], y[0])); let a_bytes = a.to_le_bytes(); let b_bytes = b.to_le_bytes(); diff --git a/noir/noir-repo/test_programs/execution_success/blake3/src/main.nr b/noir/noir-repo/test_programs/execution_success/blake3/src/main.nr index 3bfea6c5f95e..fb056bfa8482 100644 --- a/noir/noir-repo/test_programs/execution_success/blake3/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/blake3/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: [u8; 5], result: [u8; 32]) { let digest = std::hash::blake3(x); assert(digest == result); diff --git a/noir/noir-repo/test_programs/execution_success/brillig_blake2s/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_blake2s/src/main.nr index 5bd52666ae98..2743e02e920c 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_blake2s/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_blake2s/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is blake2s in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_blake3/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_blake3/src/main.nr index 05a5b31f9364..64852d775f4e 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_blake3/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_blake3/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - unconstrained fn main(x: [u8; 5], result: [u8; 32]) { let digest = std::hash::blake3(x); assert(digest == result); diff --git a/noir/noir-repo/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr index 142290ecbe2d..2809668c574d 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_block_parameter_liveness/src/main.nr @@ -38,11 +38,11 @@ struct Outer { // If we don't take into account block parameter liveness, this function will need 5*500=2500 stack items unconstrained fn main(conditions: [bool; 5]) -> pub Outer { let out0 = if conditions[0] { - let mut outer: Outer = dep::std::unsafe::zeroed(); + let mut outer: Outer = std::unsafe::zeroed(); outer.middle_a.inner_a.a = 1; outer } else { - let mut outer: Outer= dep::std::unsafe::zeroed(); + let mut outer: Outer= std::unsafe::zeroed(); outer.middle_f.inner_c.d = 2; outer }; diff --git a/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr index 1cae9b1ba410..ae3adf6425ca 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_cow_regression/src/main.nr @@ -1,8 +1,8 @@ // Tests a performance regression found in aztec-packages with brillig cow optimization -global MAX_NEW_NOTE_HASHES_PER_TX: u64 = 64; -global MAX_NEW_NULLIFIERS_PER_TX: u64 = 64; -global MAX_NEW_L2_TO_L1_MSGS_PER_TX: u64 = 2; +global MAX_NOTE_HASHES_PER_TX: u64 = 64; +global MAX_NULLIFIERS_PER_TX: u64 = 64; +global MAX_L2_TO_L1_MSGS_PER_TX: u64 = 2; global MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX: u64 = 16; global MAX_NEW_CONTRACTS_PER_TX: u64 = 1; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; @@ -25,15 +25,15 @@ struct NewContractData { impl NewContractData { fn hash(self) -> Field { - dep::std::hash::pedersen_hash([self.contract_address, self.portal_contract_address]) + std::hash::pedersen_hash([self.contract_address, self.portal_contract_address]) } } struct DataToHash { - new_note_hashes: [Field; MAX_NEW_NOTE_HASHES_PER_TX], - new_nullifiers: [Field; MAX_NEW_NULLIFIERS_PER_TX], + new_note_hashes: [Field; MAX_NOTE_HASHES_PER_TX], + new_nullifiers: [Field; MAX_NULLIFIERS_PER_TX], public_data_update_requests: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], - new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], + new_l2_to_l1_msgs: [Field; MAX_L2_TO_L1_MSGS_PER_TX], encrypted_logs_hash: [Field; NUM_FIELDS_PER_SHA256], unencrypted_logs_hash: [Field; NUM_FIELDS_PER_SHA256], new_contracts: [NewContractData; MAX_NEW_CONTRACTS_PER_TX], @@ -104,21 +104,21 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA let new_note_hashes = kernel_data.new_note_hashes; let new_nullifiers = kernel_data.new_nullifiers; let public_data_update_requests = kernel_data.public_data_update_requests; - let newL2ToL1msgs = kernel_data.new_l2_to_l1_msgs; + let l2ToL1Msgs = kernel_data.new_l2_to_l1_msgs; let encryptedLogsHash = kernel_data.encrypted_logs_hash; let unencryptedLogsHash = kernel_data.unencrypted_logs_hash; let mut offset = 0; - for j in 0..MAX_NEW_NOTE_HASHES_PER_TX { + for j in 0..MAX_NOTE_HASHES_PER_TX { tx_effects_hash_inputs[offset + j] = new_note_hashes[j]; } - offset += MAX_NEW_NOTE_HASHES_PER_TX ; + offset += MAX_NOTE_HASHES_PER_TX ; - for j in 0..MAX_NEW_NULLIFIERS_PER_TX { + for j in 0..MAX_NULLIFIERS_PER_TX { tx_effects_hash_inputs[offset + j] = new_nullifiers[j]; } - offset += MAX_NEW_NULLIFIERS_PER_TX ; + offset += MAX_NULLIFIERS_PER_TX ; for j in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { tx_effects_hash_inputs[offset + j * 2] = @@ -128,10 +128,10 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA } offset += MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * 2; - for j in 0..MAX_NEW_L2_TO_L1_MSGS_PER_TX { - tx_effects_hash_inputs[offset + j] = newL2ToL1msgs[j]; + for j in 0..MAX_L2_TO_L1_MSGS_PER_TX { + tx_effects_hash_inputs[offset + j] = l2ToL1Msgs[j]; } - offset += MAX_NEW_L2_TO_L1_MSGS_PER_TX; + offset += MAX_L2_TO_L1_MSGS_PER_TX; let contract_leaf = kernel_data.new_contracts[0]; tx_effects_hash_inputs[offset] = contract_leaf.hash(); @@ -173,6 +173,6 @@ unconstrained fn main(kernel_data: DataToHash) -> pub [Field; NUM_FIELDS_PER_SHA } } - let sha_digest = dep::std::hash::sha256(hash_input_flattened); + let sha_digest = std::hash::sha256(hash_input_flattened); U256::from_bytes32(sha_digest).to_u128_limbs() } diff --git a/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr index 5d84d885567a..78343dcd26c2 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256k1/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is ecdsa in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr index 9da07f531aa5..48debadb0127 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_ecdsa_secp256r1/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is ecdsa in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_fns_as_values/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_fns_as_values/src/main.nr index 9248bff2f4c6..1476c4474318 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_fns_as_values/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_fns_as_values/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - struct MyStruct { operation: fn (u32) -> u32, } diff --git a/noir/noir-repo/test_programs/execution_success/brillig_hash_to_field/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_hash_to_field/src/main.nr index 53ed85b3dddd..78759bd84c67 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_hash_to_field/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_hash_to_field/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is hash_to_field in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr index a300bc18279c..9150e38f2081 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_keccak/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is keccak256 in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_oracle/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_oracle/src/main.nr index 6a9e58066215..0305cb06978c 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_oracle/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_oracle/src/main.nr @@ -1,5 +1,5 @@ -use dep::std::slice; -use dep::std::test::OracleMock; +use std::slice; +use std::test::OracleMock; // Tests oracle usage in brillig/unconstrained functions fn main(_x: Field) { diff --git a/noir/noir-repo/test_programs/execution_success/brillig_pedersen/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_pedersen/src/main.nr index 2379818c4548..17c79f9d0ae9 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_pedersen/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_pedersen/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - unconstrained fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { let res = std::hash::pedersen_commitment_with_separator([x, y], 0); assert(res.x == out_x); diff --git a/noir/noir-repo/test_programs/execution_success/brillig_sha256/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_sha256/src/main.nr index e76109df9c35..fcc01978a0a0 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_sha256/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_sha256/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Tests a very simple program. // // The features being tested is sha256 in brillig diff --git a/noir/noir-repo/test_programs/execution_success/brillig_slices/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_slices/src/main.nr index 2cf1850f1515..89f838a3a574 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_slices/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_slices/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::slice; +use std::slice; unconstrained fn main(x: Field, y: Field) { let mut slice: [Field] = &[y, x]; assert(slice.len() == 2); diff --git a/noir/noir-repo/test_programs/execution_success/conditional_1/src/main.nr b/noir/noir-repo/test_programs/execution_success/conditional_1/src/main.nr index 5064c82bce93..e7d780263b8e 100644 --- a/noir/noir-repo/test_programs/execution_success/conditional_1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/conditional_1/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn sort(mut a: [u32; 4]) -> [u32; 4] { for i in 1..4 { for j in 0..i { diff --git a/noir/noir-repo/test_programs/execution_success/conditional_2/src/main.nr b/noir/noir-repo/test_programs/execution_success/conditional_2/src/main.nr index 5b3f64f6be54..ea23ec3cf3b8 100644 --- a/noir/noir-repo/test_programs/execution_success/conditional_2/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/conditional_2/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn must_be_zero(x: u8) { assert(x == 0); } diff --git a/noir/noir-repo/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr b/noir/noir-repo/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr index d260fa49dc32..de5ad20a6423 100644 --- a/noir/noir-repo/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/conditional_regression_short_circuit/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(a: u32, mut c: [u32; 4], x: [u8; 5], result: pub [u8; 32]) { //regression for short-circuit2 if 35 == a { diff --git a/noir/noir-repo/test_programs/execution_success/databus/src/main.nr b/noir/noir-repo/test_programs/execution_success/databus/src/main.nr index 1cf95be8a22d..7e5c23d508de 100644 --- a/noir/noir-repo/test_programs/execution_success/databus/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/databus/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(mut x: u32, y: call_data u32, z: call_data [u32; 4]) -> return_data u32 { let a = z[x]; a + foo(y) diff --git a/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr b/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr index ca95c6e0aa81..690d6fc9fc83 100644 --- a/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/diamond_deps_0/src/main.nr @@ -1,6 +1,6 @@ -use dep::dep1::call_dep1_then_dep2; -use dep::dep2::call_dep2; -use dep::dep2::RESOLVE_THIS; +use dep1::call_dep1_then_dep2; +use dep2::call_dep2; +use dep2::RESOLVE_THIS; fn main(x: Field, y: pub Field) -> pub Field { call_dep1_then_dep2(x, y) + call_dep2(x, y) + RESOLVE_THIS diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_nested_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/double_verify_nested_proof/src/main.nr index 95d4b6f69958..5f0eb1a5b530 100644 --- a/noir/noir-repo/test_programs/execution_success/double_verify_nested_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/double_verify_nested_proof/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // This circuit aggregates two recursive proofs from `double_verify_proof_recursive`. // Recursive aggregation is a backend-specific process and it is expected for backends diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/double_verify_proof/src/main.nr index d832ce0f0499..d3b909c3fa44 100644 --- a/noir/noir-repo/test_programs/execution_success/double_verify_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/double_verify_proof/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // This circuit aggregates two proofs from `assert_statement_recursive`. fn main( diff --git a/noir/noir-repo/test_programs/execution_success/double_verify_proof_recursive/src/main.nr b/noir/noir-repo/test_programs/execution_success/double_verify_proof_recursive/src/main.nr index 86b4971c3a6d..2555bbc47587 100644 --- a/noir/noir-repo/test_programs/execution_success/double_verify_proof_recursive/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/double_verify_proof_recursive/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // This circuit aggregates two proofs from `assert_statement_recursive`. #[recursive] diff --git a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256k1/src/main.nr b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256k1/src/main.nr index ac0359e4bb8a..7f0999fc3607 100644 --- a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256k1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256k1/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main( message: [u8; 38], hashed_message: [u8; 32], diff --git a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1/src/main.nr b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1/src/main.nr index c64e390d6523..09f427c37d90 100644 --- a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(hashed_message: [u8; 32], pub_key_x: [u8; 32], pub_key_y: [u8; 32], signature: [u8; 64]) { let valid_signature = std::ecdsa_secp256r1::verify_signature(pub_key_x, pub_key_y, signature, hashed_message); assert(valid_signature); diff --git a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr index e7a6be9d47ae..b5bd633915fc 100644 --- a/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/ecdsa_secp256r1_3x/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main( hashed_message: [u8; 32], pub_key_x: [u8; 32], diff --git a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr index ada15d5405c7..407ca049806f 100644 --- a/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/eddsa/src/main.nr @@ -1,9 +1,9 @@ -use dep::std::compat; -use dep::std::ec::consts::te::baby_jubjub; -use dep::std::ec::tecurve::affine::Point as TEPoint; -use dep::std::hash; -use dep::std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify}; -use dep::std::hash::poseidon2::Poseidon2Hasher; +use std::compat; +use std::ec::consts::te::baby_jubjub; +use std::ec::tecurve::affine::Point as TEPoint; +use std::hash; +use std::eddsa::{eddsa_to_pub, eddsa_poseidon_verify, eddsa_verify}; +use std::hash::poseidon2::Poseidon2Hasher; fn main(msg: pub Field, _priv_key_a: Field, _priv_key_b: Field) { // Skip this test for non-bn254 backends diff --git a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr index 46f919e947ae..4eeda39c6aa4 100644 --- a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { let g1_y = 17631683881184975370165255887551781615748388533673675138860; let g1 = std::embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: g1_y, is_infinite: false }; diff --git a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr index f9f3e75789b1..8727b2a23de7 100644 --- a/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/fold_numeric_generic_poseidon/src/main.nr @@ -1,10 +1,10 @@ -use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; +use std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; global NUM_HASHES = 2; global HASH_LENGTH = 10; #[fold] -pub fn poseidon_hash(inputs: [Field; N]) -> Field { +pub fn poseidon_hash(inputs: [Field; N]) -> Field { Poseidon2::hash(inputs, inputs.len()) } diff --git a/noir/noir-repo/test_programs/execution_success/generics/src/main.nr b/noir/noir-repo/test_programs/execution_success/generics/src/main.nr index c8616960559a..f754fb96292f 100644 --- a/noir/noir-repo/test_programs/execution_success/generics/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/generics/src/main.nr @@ -34,7 +34,7 @@ impl Bar { impl Bar { // This is to test that we can use turbofish on methods as well fn zeroed(_self: Self) -> A { - dep::std::unsafe::zeroed() + std::unsafe::zeroed() } } diff --git a/noir/noir-repo/test_programs/execution_success/hash_to_field/src/main.nr b/noir/noir-repo/test_programs/execution_success/hash_to_field/src/main.nr index 242b5ecbc18a..bb4f829ec338 100644 --- a/noir/noir-repo/test_programs/execution_success/hash_to_field/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hash_to_field/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(input: Field) -> pub Field { std::hash::hash_to_field(&[input]) } diff --git a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr index 76daa594a89e..56b13d6779b6 100644 --- a/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/hashmap/src/main.nr @@ -1,9 +1,8 @@ mod utils; -use dep::std::collections::map::HashMap; -use dep::std::hash::BuildHasherDefault; -use dep::std::hash::poseidon2::Poseidon2Hasher; -use dep::std::cmp::Eq; +use std::collections::map::HashMap; +use std::hash::BuildHasherDefault; +use std::hash::poseidon2::Poseidon2Hasher; use utils::cut; diff --git a/noir/noir-repo/test_programs/execution_success/import/src/main.nr b/noir/noir-repo/test_programs/execution_success/import/src/main.nr index 7dcc16fed163..0f5aa7e5460f 100644 --- a/noir/noir-repo/test_programs/execution_success/import/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/import/src/main.nr @@ -2,7 +2,7 @@ mod import; use crate::import::hello; fn main(x: Field, y: Field) { - let _k = dep::std::hash::pedersen_commitment([x]); + let _k = std::hash::pedersen_commitment([x]); let _l = hello(x); assert(x != import::hello(y)); diff --git a/noir/noir-repo/test_programs/execution_success/is_unconstrained/src/main.nr b/noir/noir-repo/test_programs/execution_success/is_unconstrained/src/main.nr index af40af1029fd..ddafc73c5981 100644 --- a/noir/noir-repo/test_programs/execution_success/is_unconstrained/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/is_unconstrained/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::runtime::is_unconstrained; +use std::runtime::is_unconstrained; fn check(should_be_unconstrained: bool) { assert_eq(should_be_unconstrained, is_unconstrained()); diff --git a/noir/noir-repo/test_programs/execution_success/keccak256/src/main.nr b/noir/noir-repo/test_programs/execution_success/keccak256/src/main.nr index eb401fe614cc..ff18cae0c9cc 100644 --- a/noir/noir-repo/test_programs/execution_success/keccak256/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/keccak256/src/main.nr @@ -1,5 +1,4 @@ // docs:start:keccak256 -use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field diff --git a/noir/noir-repo/test_programs/execution_success/merkle_insert/src/main.nr b/noir/noir-repo/test_programs/execution_success/merkle_insert/src/main.nr index ac9a7b34ea32..a08088e847b6 100644 --- a/noir/noir-repo/test_programs/execution_success/merkle_insert/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/merkle_insert/src/main.nr @@ -1,5 +1,4 @@ -use dep::std; -use dep::std::hash::mimc; +use std::hash::mimc; fn main( old_root: Field, diff --git a/noir/noir-repo/test_programs/execution_success/modulus/src/main.nr b/noir/noir-repo/test_programs/execution_success/modulus/src/main.nr index 35f63fdc8c52..1627cc0dba27 100644 --- a/noir/noir-repo/test_programs/execution_success/modulus/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/modulus/src/main.nr @@ -1,10 +1,13 @@ -use dep::std; - fn main(bn254_modulus_be_bytes: [u8; 32], bn254_modulus_be_bits: [u1; 254]) { let modulus_size = std::field::modulus_num_bits(); // NOTE: The constraints used in this circuit will only work when testing nargo with the plonk bn254 backend assert(modulus_size == 254); + assert_reverse( + std::field::modulus_be_bytes(), + std::field::modulus_le_bytes() + ); + let modulus_be_byte_array = std::field::modulus_be_bytes(); for i in 0..32 { assert(modulus_be_byte_array[i] == bn254_modulus_be_bytes[i]); @@ -23,3 +26,9 @@ fn main(bn254_modulus_be_bytes: [u8; 32], bn254_modulus_be_bits: [u1; 254]) { assert(modulus_le_bits[i] == bn254_modulus_be_bits[253 - i]); } } + +fn assert_reverse(forwards: [u8], backwards: [u8]) { + for i in 0..32 { + assert_eq(forwards[i], backwards[31 - i]); + } +} diff --git a/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr b/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr index dcb5e6bc5cad..60a7d2f8d17d 100644 --- a/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr @@ -1,10 +1,10 @@ -use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; +use std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; global NUM_HASHES = 2; global HASH_LENGTH = 10; #[no_predicates] -pub fn poseidon_hash(inputs: [Field; N]) -> Field { +pub fn poseidon_hash(inputs: [Field; N]) -> Field { Poseidon2::hash(inputs, inputs.len()) } diff --git a/noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr b/noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr index 3956ea5c5770..c2c831d0c1e5 100644 --- a/noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/operator_overloading/src/main.nr @@ -1,5 +1,5 @@ -use dep::std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr}; -use dep::std::cmp::Ordering; +use std::ops::{Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr}; +use std::cmp::Ordering; // x = 3, y = 9 fn main(x: u32, y: u32) { diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml new file mode 100644 index 000000000000..b2c3e5f94be1 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/Nargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = [ + "bin", + "foo", +] +default-member = "bin" diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml new file mode 100644 index 000000000000..57e704462dbc --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "overlapping_dep_and_mod" +type = "bin" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] +foo = { path = "../foo" } diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Prover.toml b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/Prover.toml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr new file mode 100644 index 000000000000..16c940f12fc9 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/bin/src/main.nr @@ -0,0 +1,14 @@ +// bin/main.nr + +fn main() -> pub Field { + assert(foo::bar() + dep::foo::bar() == 11); + assert(foo::bar() == 5); + assert(dep::foo::bar() == 6); + foo::bar() + dep::foo::bar() +} + +mod foo { + pub(crate) fn bar() -> Field { + 5 + } +} diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml new file mode 100644 index 000000000000..857d4e722a88 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "foo" +type = "lib" +authors = [""] +compiler_version = ">=0.29.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr new file mode 100644 index 000000000000..09283defed7f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/overlapping_dep_and_mod/foo/src/lib.nr @@ -0,0 +1,5 @@ +// foo/lib.nr + +pub fn bar() -> Field { + 6 +} diff --git a/noir/noir-repo/test_programs/execution_success/pedersen_check/src/main.nr b/noir/noir-repo/test_programs/execution_success/pedersen_check/src/main.nr index 90ef218249b8..c71b2b570da4 100644 --- a/noir/noir-repo/test_programs/execution_success/pedersen_check/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/pedersen_check/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: Field, y: Field, salt: Field, out_x: Field, out_y: Field, out_hash: Field) { let res = std::hash::pedersen_commitment([x, y]); assert(res.x == out_x); diff --git a/noir/noir-repo/test_programs/execution_success/pedersen_commitment/src/main.nr b/noir/noir-repo/test_programs/execution_success/pedersen_commitment/src/main.nr index a3a9aea1cf06..81c605a64dda 100644 --- a/noir/noir-repo/test_programs/execution_success/pedersen_commitment/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/pedersen_commitment/src/main.nr @@ -1,5 +1,4 @@ // docs:start:pedersen-commitment -use dep::std; fn main(x: Field, y: Field, expected_commitment: std::embedded_curve_ops::EmbeddedCurvePoint) { let commitment = std::hash::pedersen_commitment([x, y]); diff --git a/noir/noir-repo/test_programs/execution_success/pedersen_hash/src/main.nr b/noir/noir-repo/test_programs/execution_success/pedersen_hash/src/main.nr index 20c7de12d6c0..f8ec56a9d985 100644 --- a/noir/noir-repo/test_programs/execution_success/pedersen_hash/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/pedersen_hash/src/main.nr @@ -1,5 +1,4 @@ // docs:start:pedersen-hash -use dep::std; fn main(x: Field, y: Field, expected_hash: Field) { let hash = std::hash::pedersen_hash([x, y]); diff --git a/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr b/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr index a16079561908..cf1c190e5c96 100644 --- a/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/poseidon_bn254_hash/src/main.nr @@ -1,6 +1,6 @@ // docs:start:poseidon -use dep::std::hash::poseidon; -use dep::std::hash::poseidon2; +use std::hash::poseidon; +use std::hash::poseidon2; fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field, x3: [Field; 4], y3: Field) { let hash1 = poseidon::bn254::hash_2(x1); diff --git a/noir/noir-repo/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr b/noir/noir-repo/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr index 910a17c8c89d..137f3e5d2a6c 100644 --- a/noir/noir-repo/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/poseidonsponge_x5_254/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::hash::poseidon; +use std::hash::poseidon; fn main(x: [Field; 7]) { // Test optimized sponge diff --git a/noir/noir-repo/test_programs/execution_success/prelude/src/main.nr b/noir/noir-repo/test_programs/execution_success/prelude/src/main.nr index 226341f1e7bd..4fe6080222ee 100644 --- a/noir/noir-repo/test_programs/execution_success/prelude/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/prelude/src/main.nr @@ -8,8 +8,8 @@ fn main() { mod a { // We don't want to give an error due to re-importing elements that are already in the prelude. - use dep::std::collections::vec::Vec; - use dep::std::option::Option; + use std::collections::vec::Vec; + use std::option::Option; fn main() { let _xs = Vec::new(); diff --git a/noir/noir-repo/test_programs/execution_success/regression_3051/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_3051/src/main.nr index 2e7d10fd7b01..90eb652db7a5 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_3051/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_3051/src/main.nr @@ -19,6 +19,6 @@ impl Bar for u64 { } fn main() { - dep::std::println(1.foo()); - dep::std::println(1.bar()); + std::println(1.foo()); + std::println(1.bar()); } diff --git a/noir/noir-repo/test_programs/execution_success/regression_3394/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_3394/src/main.nr index 94b6c818ff20..594942537574 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_3394/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_3394/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { let x : i8 = -128; std::println(x); diff --git a/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr index 9e4d7892fc37..12a7afca68cf 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_4088/src/main.nr @@ -1,4 +1,4 @@ -trait Serialize { +trait Serialize { fn serialize(self) -> [Field; N]; } @@ -12,7 +12,7 @@ impl Serialize<1> for ValueNote { } } -fn check(serialized_note: [Field; N]) { +fn check(serialized_note: [Field; N]) { assert(serialized_note[0] == 0); } diff --git a/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr index 49ff68ee6ad5..6caea017798b 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_4124/src/main.nr @@ -1,6 +1,6 @@ -use dep::std::option::Option; +use std::option::Option; -trait MyDeserialize { +trait MyDeserialize { fn deserialize(fields: [Field; N]) -> Self; } @@ -10,8 +10,8 @@ impl MyDeserialize<1> for Field { } } -pub fn storage_read() -> [Field; N] { - dep::std::unsafe::zeroed() +pub fn storage_read() -> [Field; N] { + std::unsafe::zeroed() } struct PublicMutable { diff --git a/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr index 454a93f5d1ae..66bab2e09f44 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_4449/src/main.nr @@ -1,5 +1,4 @@ // Regression test for issue #4449 -use dep::std; fn main(x: u8, result: [u8; 32]) { let x = x % 31; diff --git a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr index 015fb1b2555d..cf39b2f97e4c 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr @@ -1,5 +1,5 @@ -use dep::std::embedded_curve_ops::EmbeddedCurvePoint; -use dep::std::embedded_curve_ops::EmbeddedCurveScalar; +use std::embedded_curve_ops::EmbeddedCurvePoint; +use std::embedded_curve_ops::EmbeddedCurveScalar; fn main(is_active: bool) { let a = EmbeddedCurvePoint { @@ -11,7 +11,7 @@ fn main(is_active: bool) { if is_active { let bad = EmbeddedCurvePoint { x: 0, y: 5, is_infinite: false }; let d = bad.double(); - let e = dep::std::embedded_curve_ops::multi_scalar_mul( + let e = std::embedded_curve_ops::multi_scalar_mul( [a, bad], [EmbeddedCurveScalar { lo: 1, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] ); diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml b/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml new file mode 100644 index 000000000000..855507dfaf39 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "regression_5252" +version = "0.1.0" +type = "bin" +authors = [""] + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml b/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml new file mode 100644 index 000000000000..82776b4463d4 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/Prover.toml @@ -0,0 +1,6 @@ +to_hash = [[1,5,9,2,24,563,3545,5,52,4244,43,2,7373567,2,286762,7,2457,24,2456,2456], +[2234,2,26,27,24566,132452,3452456344567,657,45674657,4567467,45674,4567456,4567,23454,2345,2345345245,25252345,2435234524366,8678678,67867567], +[9887575467567,5367367243617,46244567783,64673425,67456573456,4673457,46735,745674,6574,567456,7456,84,683,683,8368,38,32,16,7,98], +#[465656,234324,4353,5245246,2567345674567,5634563456,7676474,4747,4567456746,56,4657456,4657,4567,46,7,8,98,87,76,57] +] +enable = [1,1,0] diff --git a/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr new file mode 100644 index 000000000000..4b4d1937c0e2 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/regression_5252/src/main.nr @@ -0,0 +1,23 @@ +use std::hash::{mimc, poseidon, poseidon2::Poseidon2}; + +global NUM_HASHES = 3; +global HASH_LENGTH = 20; + +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES] { + let mut result = [0; NUM_HASHES]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash) + poseidon::bn254::sponge(to_hash) + mimc::mimc_bn254(to_hash); + } + } + result +} diff --git a/noir/noir-repo/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr index 1a6931a6870a..c7db543f1bb2 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_method_cannot_be_found/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; struct Item { id: Field, } diff --git a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr index 1067d9707b2a..5bc0ca9fefbf 100644 --- a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr @@ -1,5 +1,4 @@ -use dep::std; -use dep::std::embedded_curve_ops; +use std::embedded_curve_ops; // Note: If main has any unsized types, then the verifier will never be able // to figure out the circuit instance @@ -37,11 +36,7 @@ fn main( // Meanwhile, you have to use a message with 32 additional bytes: // If you want to verify a signature on a message of 10 bytes, you need to pass a message of length 42, // where the first 10 bytes are the one from the original message (the other bytes are not used) -pub fn verify_signature_noir( - public_key: embedded_curve_ops::EmbeddedCurvePoint, - signature: [u8; 64], - message: [u8; M] -) -> bool { +pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoint, signature: [u8; 64], message: [u8; M]) -> bool { let N = message.len() - 32; //scalar lo/hi from bytes @@ -90,11 +85,7 @@ pub fn bytes_to_scalar(bytes: [u8; 64], offset: u32) -> embedded_curve_ops::Embe sig_s } -pub fn assert_valid_signature( - public_key: embedded_curve_ops::EmbeddedCurvePoint, - signature: [u8; 64], - message: [u8; M] -) { +pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePoint, signature: [u8; 64], message: [u8; M]) { let N = message.len() - 32; //scalar lo/hi from bytes let sig_s = bytes_to_scalar(signature, 0); diff --git a/noir/noir-repo/test_programs/execution_success/sha256/src/main.nr b/noir/noir-repo/test_programs/execution_success/sha256/src/main.nr index d4240ded8b38..4f999d349f03 100644 --- a/noir/noir-repo/test_programs/execution_success/sha256/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/sha256/src/main.nr @@ -9,7 +9,6 @@ // // Not yet here: For R1CS, it is more about manipulating arithmetic gates to get performance // This can be done in ACIR! -use dep::std; fn main(x: Field, result: [u8; 32]) { // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field diff --git a/noir/noir-repo/test_programs/execution_success/sha2_byte/src/main.nr b/noir/noir-repo/test_programs/execution_success/sha2_byte/src/main.nr index fa8ddfbdf69a..aecd9fba2f3f 100644 --- a/noir/noir-repo/test_programs/execution_success/sha2_byte/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/sha2_byte/src/main.nr @@ -1,5 +1,4 @@ // Test Noir implementations of SHA256 and SHA512 on a one-byte message. -use dep::std; fn main(x: Field, result256: [u8; 32], result512: [u8; 64]) { let digest256 = std::sha256::digest([x as u8]); diff --git a/noir/noir-repo/test_programs/execution_success/signed_comparison/src/main.nr b/noir/noir-repo/test_programs/execution_success/signed_comparison/src/main.nr index d020be380fb2..0fe72112f5a4 100644 --- a/noir/noir-repo/test_programs/execution_success/signed_comparison/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/signed_comparison/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(mut x: i8, mut y: i8, z: i8) { let mut s1: i8 = 5; let mut s2: i8 = 8; diff --git a/noir/noir-repo/test_programs/execution_success/signed_division/src/main.nr b/noir/noir-repo/test_programs/execution_success/signed_division/src/main.nr index 6289a2f9ed9d..207ef59986b5 100644 --- a/noir/noir-repo/test_programs/execution_success/signed_division/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/signed_division/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Testing signed integer division: // 7/3 = 2 // -7/3 = -2 diff --git a/noir/noir-repo/test_programs/execution_success/simple_print/src/main.nr b/noir/noir-repo/test_programs/execution_success/simple_print/src/main.nr index 6038b995af0e..3a68f8cc4c38 100644 --- a/noir/noir-repo/test_programs/execution_success/simple_print/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/simple_print/src/main.nr @@ -1,6 +1,5 @@ // Simple program for testing the logging // of single witnesses and witness arrays. -use dep::std; fn main(x: Field, y: pub Field) { std::println(x); diff --git a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr index 548ba17d4620..d84288b9fd6d 100644 --- a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main( // Public key of note // all notes have the same denomination diff --git a/noir/noir-repo/test_programs/execution_success/slice_coercion/src/main.nr b/noir/noir-repo/test_programs/execution_success/slice_coercion/src/main.nr index a7ba0443bd18..4a83b739523b 100644 --- a/noir/noir-repo/test_programs/execution_success/slice_coercion/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/slice_coercion/src/main.nr @@ -23,5 +23,5 @@ fn main(expected: pub Field, first: Field) { fn regression_4967() { let var1: [(i32, u8)] = [(1, 2)]; assert(var1.len() == 1); - dep::std::println(var1); + std::println(var1); } diff --git a/noir/noir-repo/test_programs/execution_success/slices/src/main.nr b/noir/noir-repo/test_programs/execution_success/slices/src/main.nr index b20e34788981..2bd4dbd97b04 100644 --- a/noir/noir-repo/test_programs/execution_success/slices/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/slices/src/main.nr @@ -1,5 +1,4 @@ -use dep::std::slice; -use dep::std; +use std::slice; fn main(x: Field, y: pub Field) { let mut slice = &[0; 2]; @@ -46,6 +45,14 @@ fn main(x: Field, y: pub Field) { assert(append[0] == 1); assert(append[4] == 5); + let mapped = &[1, 2].map(|x| x + 1); + assert_eq(mapped, &[2, 3]); + + assert_eq(&[1, 2, 3].fold(0, |acc, x| acc + x), 6); + assert_eq(&[1, 2, 3].reduce(|acc, x| acc + x), 6); + assert(&[2, 4, 6].all(|x| x > 0)); + assert(&[2, 4, 6].any(|x| x > 5)); + regression_2083(); // The parameters to this function must come from witness values (inputs to main) regression_merge_slices(x, y); diff --git a/noir/noir-repo/test_programs/execution_success/strings/src/main.nr b/noir/noir-repo/test_programs/execution_success/strings/src/main.nr index cff229d368ac..d28a9f483aca 100644 --- a/noir/noir-repo/test_programs/execution_success/strings/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/strings/src/main.nr @@ -1,4 +1,3 @@ -use dep::std; // Test global string literals global HELLO_WORLD = "hello world"; diff --git a/noir/noir-repo/test_programs/execution_success/to_bits/src/main.nr b/noir/noir-repo/test_programs/execution_success/to_bits/src/main.nr index 18f65f0bd668..84ace83903a1 100644 --- a/noir/noir-repo/test_programs/execution_success/to_bits/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/to_bits/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { let field = 1000; let be_bits = field.to_be_bits(16); diff --git a/noir/noir-repo/test_programs/execution_success/to_bytes_integration/src/main.nr b/noir/noir-repo/test_programs/execution_success/to_bytes_integration/src/main.nr index 3c43caf1806c..21c4ad90bfeb 100644 --- a/noir/noir-repo/test_programs/execution_success/to_bytes_integration/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/to_bytes_integration/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: Field, a: Field) { let y: Field = 2040124; let be_byte_array = y.to_be_bytes(31); diff --git a/noir/noir-repo/test_programs/execution_success/trait_method_mut_self/src/main.nr b/noir/noir-repo/test_programs/execution_success/trait_method_mut_self/src/main.nr index fa47fd5d881e..9cc8375b1403 100644 --- a/noir/noir-repo/test_programs/execution_success/trait_method_mut_self/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/trait_method_mut_self/src/main.nr @@ -1,5 +1,5 @@ -use dep::std::hash::Hasher; -use dep::std::hash::poseidon2::Poseidon2Hasher; +use std::hash::Hasher; +use std::hash::poseidon2::Poseidon2Hasher; fn main(x: Field, y: pub Field) { let mut a_mut_ref = AType { x }; diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr index 62dd5a2c111c..e36a263093ae 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/crate1/src/lib.nr @@ -2,7 +2,7 @@ trait MyTrait { fn Add10(&mut self); } -impl MyTrait for dep::crate2::MyStruct { +impl MyTrait for crate2::MyStruct { fn Add10(&mut self) { self.Q += 10; } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr index 7ba2f63c5c0b..2afec29ee1f1 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_1/src/main.nr @@ -1,5 +1,5 @@ fn main(x: Field, y: pub Field) { - let mut V = dep::crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr index 388704891318..fe6a94a4a954 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/crate2/src/lib.nr @@ -2,7 +2,7 @@ struct MyStruct { Q: Field, } -impl dep::crate1::MyTrait for MyStruct { +impl crate1::MyTrait for MyStruct { fn Add10(&mut self) { self.Q += 10; } diff --git a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr index 7ba2f63c5c0b..2afec29ee1f1 100644 --- a/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/traits_in_crates_2/src/main.nr @@ -1,5 +1,5 @@ fn main(x: Field, y: pub Field) { - let mut V = dep::crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct { Q: x }; V.Add10(); assert(V.Q == y); } diff --git a/noir/noir-repo/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr b/noir/noir-repo/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr index b880d3ae047e..36c7d2926c11 100644 --- a/noir/noir-repo/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/turbofish_call_func_diff_types/src/main.nr @@ -1,6 +1,6 @@ -use dep::std::hash::Hasher; -use dep::std::hash::poseidon2::Poseidon2Hasher; -use dep::std::hash::poseidon::PoseidonHasher; +use std::hash::Hasher; +use std::hash::poseidon2::Poseidon2Hasher; +use std::hash::poseidon::PoseidonHasher; fn main(x: Field, y: pub Field) { let mut hasher = PoseidonHasher::default(); diff --git a/noir/noir-repo/test_programs/execution_success/u128/src/main.nr b/noir/noir-repo/test_programs/execution_success/u128/src/main.nr index a403571ea744..d0835ccf30fc 100644 --- a/noir/noir-repo/test_programs/execution_success/u128/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/u128/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(mut x: u32, y: u32, z: u32, big_int: U128, hexa: str<7>) { let a = U128::from_u64s_le(x as u64, x as u64); let b = U128::from_u64s_le(y as u64, x as u64); 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 index f3844e03cf20..a488f267b4c0 100644 --- 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 @@ -1,5 +1,5 @@ fn get_transaction() { - dep::std::unsafe::zeroed() + std::unsafe::zeroed() } fn main() { diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml index d298dabb5601..8fce1bf44b6e 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Nargo.toml @@ -2,6 +2,5 @@ name = "verify_honk_proof" type = "bin" authors = [""] -compiler_version = ">=0.30.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml index 4619fd298dd3..921b69e100ac 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" -proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x0000000000000000000000000000007f36e0b4f59927ebbb2302e76cbe8bd44e","0x00000000000000000000000000000000001b95777c6c98640c80638c195909ca","0x0000000000000000000000000000006d4b1ad71244248cb2070fbbbb0ac9df88","0x00000000000000000000000000000000001abada4d5d816a67b6fc75746cb723","0x000000000000000000000000000000465811089df032ceb5269254547a101e57","0x000000000000000000000000000000000011a4a909c59776a6df9c7615e8e87d","0x000000000000000000000000000000311f6f724e7199351c9774225f15c25f20","0x00000000000000000000000000000000001ddba8eb0ab208ad3d96c70941fcbc","0x0000000000000000000000000000000dfa80bdf5be151b21ad89466b7201b63d","0x000000000000000000000000000000000015ca7dc258adab8ea406d94e00c56d","0x000000000000000000000000000000507ea3454165f92295b6e435c7d30d14f0","0x00000000000000000000000000000000002f522608db7b7d389d1df67eab104d","0x000000000000000000000000000000950102cce743fadb23965fc72e31efd36c","0x000000000000000000000000000000000018b4a7ec90df68dfe97d3c5367d1bf","0x000000000000000000000000000000118d90258b25dba8bc0f99d9f7547c6a62","0x000000000000000000000000000000000012d78638701da6322abbf325693b0f","0x000000000000000000000000000000144743e0d082f35295b51561af65f94c6b","0x00000000000000000000000000000000002322a615615e5405836374bb3c5336","0x000000000000000000000000000000e6f08dd5904ee42f826cde680919b41a96","0x00000000000000000000000000000000002d3f823ea255b68465e4b5360bf864","0x00000000000000000000000000000076d4db93683b6363ae92a5a20d8bb9922e","0x00000000000000000000000000000000002f8a7009cac72c9599b81cb9054308","0x00000000000000000000000000000085c12dd2be9f2b29e54c1a4bc3cbf9b6ce","0x000000000000000000000000000000000024e3688a1f4f50b0c6bd6c068f32b2","0x00000000000000000000000000000023a2015e7ea351e444c9405adfbd81e84d","0x00000000000000000000000000000000001fb3e4228c15dc4380db796925ec49","0x000000000000000000000000000000834ad9406b8ded7208b872373be7445e47","0x0000000000000000000000000000000000267544d6a9f5cc46d10555f2617c65"] +proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] \ No newline at end of file +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] diff --git a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr index c534b07fc77f..ecfd18f38374 100644 --- a/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/verify_honk_proof/src/main.nr @@ -1,12 +1,12 @@ -use dep::std; // This circuit aggregates a single Honk proof from `assert_statement_recursive`. +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; fn main( verification_key: [Field; 103], // This is the proof without public inputs attached. // // This means: the size of this does not change with the number of public inputs. - proof: [Field; 156], + proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], public_inputs: pub [Field; 1], // This is currently not public. It is fine given that the vk is a part of the circuit definition. // I believe we want to eventually make it public too though. diff --git a/noir/noir-repo/test_programs/execution_success/wildcard_type/Nargo.toml b/noir/noir-repo/test_programs/execution_success/wildcard_type/Nargo.toml new file mode 100644 index 000000000000..e3d7fc636afc --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/wildcard_type/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "wildcard_type" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/wildcard_type/Prover.toml b/noir/noir-repo/test_programs/execution_success/wildcard_type/Prover.toml new file mode 100644 index 000000000000..c7c8371dfa48 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/wildcard_type/Prover.toml @@ -0,0 +1 @@ +enable = [4,7] diff --git a/noir/noir-repo/test_programs/execution_success/wildcard_type/src/main.nr b/noir/noir-repo/test_programs/execution_success/wildcard_type/src/main.nr new file mode 100644 index 000000000000..c27f9987c484 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/wildcard_type/src/main.nr @@ -0,0 +1,23 @@ +struct bar { + enable: [bool; 4], + data: [Field; 2], + pad: u32, +} + +fn main(enable: [Field; 2]) -> pub [Field; 4] { + let mut result = [0; 4]; + let a: [_; 4] = foo(enable[1]); + for i in 0..4 { + result[i] = a[i].data[i % 2]; + } + result +} + +fn foo(x: Field) -> [bar; 4] { + [ + bar { enable: [true, true, false, false], data: [x, x + 1], pad: 0 }, + bar { enable: [true, false, false, false], data: [x + 2, x + 7], pad: 0 }, + bar { enable: [true, true, false, true], data: [x + 3, x + 5], pad: 0 }, + bar { enable: [false, false, false, false], data: [x + 4, x - 1], pad: 0 } + ] +} diff --git a/noir/noir-repo/test_programs/execution_success/wrapping_operations/src/main.nr b/noir/noir-repo/test_programs/execution_success/wrapping_operations/src/main.nr index 85fd65b193c8..d8345884c828 100644 --- a/noir/noir-repo/test_programs/execution_success/wrapping_operations/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/wrapping_operations/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: u8, y: u8) { assert(std::wrapping_sub(x, 1) == y); assert(std::wrapping_add(y, 1) == x); diff --git a/noir/noir-repo/test_programs/format.sh b/noir/noir-repo/test_programs/format.sh index 3c679b8689e3..fa63d228752f 100755 --- a/noir/noir-repo/test_programs/format.sh +++ b/noir/noir-repo/test_programs/format.sh @@ -2,7 +2,7 @@ set -e # These tests are incompatible with gas reporting -excluded_dirs=("workspace" "workspace_default_member" "workspace_reexport_bug") +excluded_dirs=("workspace" "overlapping_dep_and_mod" "overlapping_dep_and_mod_fix" "workspace_default_member" "workspace_reexport_bug") # These tests cause failures in CI with a stack overflow for some reason. ci_excluded_dirs=("eddsa") diff --git a/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr b/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr index 253e999ce07c..59b99c85c0bb 100644 --- a/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_failure/should_fail_mismatch/src/main.nr @@ -2,14 +2,9 @@ fn test_different_string() { assert_eq(0, 1, "Different string"); } -// The assert message has a space -#[test(should_fail_with = "Not equal")] -fn test_with_extra_space() { - assert_eq(0, 1, "Not equal "); -} -// The assert message has a space -#[test(should_fail_with = "Not equal")] -fn test_runtime_mismatch() { - // We use a pedersen commitment here so that the assertion failure is only known at runtime. - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal "); + +// The failure reason is a substring of the expected message, but it should be the other way around +#[test(should_fail_with = "Definitely Not equal!")] +fn test_wrong_expectation() { + assert_eq(0, 1, "Not equal"); } diff --git a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr index 22ec291f9d63..e5aa5f88a94c 100644 --- a/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/bounded_vec/src/main.nr @@ -63,6 +63,33 @@ fn sum_of_first_three(v: BoundedVec) -> u32 { } // docs:end:get_unchecked_example +#[test(should_fail)] +// docs:start:set_unchecked_example +fn set_unchecked_example() { + let mut vec: BoundedVec = BoundedVec::new(); + vec.extend_from_array([1, 2]); + + // Here we're safely writing within the valid range of `vec` + // `vec` now has the value [42, 2] + vec.set_unchecked(0, 42); + + // We can then safely read this value back out of `vec`. + // Notice that we use the checked version of `get` which would prevent reading unsafe values. + assert_eq(vec.get(0), 42); + + // We've now written past the end of `vec`. + // As this index is still within the maximum potential length of `v`, + // it won't cause a constraint failure. + vec.set_unchecked(2, 42); + println(vec); + + // This will write past the end of the maximum potential length of `vec`, + // it will then trigger a constraint failure. + vec.set_unchecked(5, 42); + println(vec); +} +// docs:end:set_unchecked_example + #[test(should_fail_with = "push out of bounds")] fn push_docs_example() { // docs:start:bounded-vec-push-example diff --git a/noir/noir-repo/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr index 5d73ef96d492..35a0c44218f7 100644 --- a/noir/noir-repo/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/brillig_overflow_checks/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::field::bn254::{TWO_POW_128, assert_gt}; +use std::field::bn254::{TWO_POW_128, assert_gt}; #[test(should_fail_with = "attempt to add with overflow")] unconstrained fn test_overflow_add() { diff --git a/noir/noir-repo/test_programs/noir_test_success/comptime_globals/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/comptime_globals/src/main.nr index efe9f0742b91..95c54b96609f 100644 --- a/noir/noir-repo/test_programs/noir_test_success/comptime_globals/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/comptime_globals/src/main.nr @@ -5,7 +5,7 @@ comptime global FOO: Field = foo(); // Due to this function's mutability and branching, SSA currently fails // to fold this function into a constant before the assert_constant check // is evaluated before loop unrolling. -fn foo() -> Field { +comptime fn foo() -> Field { let mut three = 3; if three == 3 { 5 } else { 6 } } diff --git a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr index 9e3c5d878745..225e86397fdd 100644 --- a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; +use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}; #[test] diff --git a/noir/noir-repo/test_programs/noir_test_success/field_comparisons/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/field_comparisons/src/main.nr index 105d82ca755f..8613e6d6c4f2 100644 --- a/noir/noir-repo/test_programs/noir_test_success/field_comparisons/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/field_comparisons/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::field::bn254::{TWO_POW_128, assert_gt}; +use std::field::bn254::{TWO_POW_128, assert_gt}; #[test(should_fail)] fn test_assert_gt_should_fail_eq() { diff --git a/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/Nargo.toml b/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/Nargo.toml new file mode 100644 index 000000000000..cd09d0d344d3 --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "fuzzer_checks" +type = "bin" +authors = [""] +[dependencies] diff --git a/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/src/main.nr new file mode 100644 index 000000000000..2b928db092e0 --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/fuzzer_checks/src/main.nr @@ -0,0 +1,6 @@ + +#[test(should_fail_with = "42 is not allowed")] +fn finds_magic_value(x: u32) { + let x = x as u64; + assert(2 * x != 42, "42 is not allowed"); +} diff --git a/noir/noir-repo/test_programs/noir_test_success/mock_oracle/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/mock_oracle/src/main.nr index d840ffaef66a..4d3dd8d030b1 100644 --- a/noir/noir-repo/test_programs/noir_test_success/mock_oracle/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/mock_oracle/src/main.nr @@ -1,4 +1,4 @@ -use dep::std::test::OracleMock; +use std::test::OracleMock; struct Point { x: Field, diff --git a/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml b/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml new file mode 100644 index 000000000000..90deee74640c --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/regression_4561/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "regression_4561" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr new file mode 100644 index 000000000000..ad40941ff51c --- /dev/null +++ b/noir/noir-repo/test_programs/noir_test_success/regression_4561/src/main.nr @@ -0,0 +1,78 @@ +// Regression test for issue #4561 +use std::test::OracleMock; + +type TReturnElem = [Field; 3]; +type TReturn = [TReturnElem; 2]; + +#[oracle(simple_nested_return)] +unconstrained fn simple_nested_return_oracle() -> TReturn {} + +unconstrained fn simple_nested_return_unconstrained() -> TReturn { + simple_nested_return_oracle() +} + +#[test] +fn test_simple_nested_return() { + OracleMock::mock("simple_nested_return").returns([1, 2, 3, 4, 5, 6]); + assert_eq(simple_nested_return_unconstrained(), [[1, 2, 3], [4, 5, 6]]); +} + +#[oracle(nested_with_fields_return)] +unconstrained fn nested_with_fields_return_oracle() -> (Field, TReturn, Field) {} + +unconstrained fn nested_with_fields_return_unconstrained() -> (Field, TReturn, Field) { + nested_with_fields_return_oracle() +} + +#[test] +fn test_nested_with_fields_return() { + OracleMock::mock("nested_with_fields_return").returns((0, [1, 2, 3, 4, 5, 6], 7)); + assert_eq(nested_with_fields_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7)); +} + +#[oracle(two_nested_return)] +unconstrained fn two_nested_return_oracle() -> (Field, TReturn, Field, TReturn) {} + +unconstrained fn two_nested_return_unconstrained() -> (Field, TReturn, Field, TReturn) { + two_nested_return_oracle() +} + +#[test] +fn two_nested_return() { + OracleMock::mock("two_nested_return").returns((0, [1, 2, 3, 4, 5, 6], 7, [1, 2, 3, 4, 5, 6])); + assert_eq(two_nested_return_unconstrained(), (0, [[1, 2, 3], [4, 5, 6]], 7, [[1, 2, 3], [4, 5, 6]])); +} + +#[oracle(foo_return)] +unconstrained fn foo_return() -> (Field, TReturn, TestTypeFoo) {} +unconstrained fn foo_return_unconstrained() -> (Field, TReturn, TestTypeFoo) { + foo_return() +} + +struct TestTypeFoo { + a: Field, + b: [[[Field; 3]; 4]; 2], + c: [TReturnElem; 2], + d: TReturnElem, +} + +#[test] +fn complexe_struct_return() { + OracleMock::mock("foo_return").returns( + ( + 0, [1, 2, 3, 4, 5, 6], 7, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [1, 2, 3, 4, 5, 6] + ) + ); + let foo_x = foo_return_unconstrained(); + assert_eq((foo_x.0, foo_x.1), (0, [[1, 2, 3], [4, 5, 6]])); + assert_eq(foo_x.2.a, 7); + assert_eq( + foo_x.2.b, [ + [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18], [19, 20, 21], [22, 23, 24]] + ] + ); + let a: TReturnElem = [1, 2, 3]; + let b: TReturnElem = [4, 5, 6]; + assert_eq(foo_x.2.c, [a, b]); + assert_eq(foo_x.2.d, a); +} diff --git a/noir/noir-repo/test_programs/noir_test_success/should_fail_with_matches/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/should_fail_with_matches/src/main.nr index 1f5c29e58a2c..42696762ffee 100644 --- a/noir/noir-repo/test_programs/noir_test_success/should_fail_with_matches/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/should_fail_with_matches/src/main.nr @@ -3,6 +3,11 @@ fn test_should_fail_with_match() { assert_eq(0, 1, "Not equal"); } +#[test(should_fail_with = "Not equal")] +fn test_should_fail_with_match_partial_match() { + assert_eq(0, 1, "Definitely Not equal!"); +} + #[test(should_fail)] fn test_should_fail_without_match() { assert_eq(0, 1); @@ -10,21 +15,21 @@ fn test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] fn test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); + assert_eq(std::hash::pedersen_commitment([27]).x, 0, "Not equal"); } #[test(should_fail)] fn test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); + assert_eq(std::hash::pedersen_commitment([27]).x, 0); } struct InvalidPointError { - point: dep::std::embedded_curve_ops::EmbeddedCurvePoint, + point: std::embedded_curve_ops::EmbeddedCurvePoint, } #[test(should_fail_with = "InvalidPointError { point: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false } }")] fn test_should_fail_with_struct() { - let hash = dep::std::hash::pedersen_commitment([27]); + let hash = std::hash::pedersen_commitment([27]); assert_eq(hash.x, 0, InvalidPointError { point: hash }); } @@ -37,7 +42,7 @@ fn test_should_fail_with_basic_type_fmt_string() { #[test(should_fail_with = "Invalid hash: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false }")] fn test_should_fail_with_struct_fmt_string() { - let hash = dep::std::hash::pedersen_commitment([27]); + let hash = std::hash::pedersen_commitment([27]); assert_eq(hash.x, 0, f"Invalid hash: {hash}"); } @@ -48,6 +53,11 @@ unconstrained fn unconstrained_test_should_fail_with_match() { assert_eq(0, 1, "Not equal"); } +#[test(should_fail_with = "Not equal")] +unconstrained fn unconstrained_test_should_fail_with_match_partial_match() { + assert_eq(0, 1, "Definitely Not equal!"); +} + #[test(should_fail)] unconstrained fn unconstrained_test_should_fail_without_match() { assert_eq(0, 1); @@ -55,17 +65,17 @@ unconstrained fn unconstrained_test_should_fail_without_match() { #[test(should_fail_with = "Not equal")] unconstrained fn unconstrained_test_should_fail_with_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0, "Not equal"); + assert_eq(std::hash::pedersen_commitment([27]).x, 0, "Not equal"); } #[test(should_fail)] unconstrained fn unconstrained_test_should_fail_without_runtime_match() { - assert_eq(dep::std::hash::pedersen_commitment([27]).x, 0); + assert_eq(std::hash::pedersen_commitment([27]).x, 0); } #[test(should_fail_with = "InvalidPointError { point: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false } }")] unconstrained fn unconstrained_test_should_fail_with_struct() { - let hash = dep::std::hash::pedersen_commitment([27]); + let hash = std::hash::pedersen_commitment([27]); assert_eq(hash.x, 0, InvalidPointError { point: hash }); } @@ -78,6 +88,6 @@ unconstrained fn unconstrained_test_should_fail_with_basic_type_fmt_string() { #[test(should_fail_with = "Invalid hash: EmbeddedCurvePoint { x: 0x1cea3a116d01eb94d568ef04c3dfbc39f96f015ed801ab8958e360d406503ce0, y: 0x2721b237df87234acc36a238b8f231a3d31d18fe3845fff4cc59f0bd873818f8, is_infinite: false }")] unconstrained fn unconstrained_test_should_fail_with_struct_fmt_string() { - let hash = dep::std::hash::pedersen_commitment([27]); + let hash = std::hash::pedersen_commitment([27]); assert_eq(hash.x, 0, f"Invalid hash: {hash}"); } diff --git a/noir/noir-repo/test_programs/rebuild.sh b/noir/noir-repo/test_programs/rebuild.sh index 2d4147cb08c9..13479f58b4b8 100755 --- a/noir/noir-repo/test_programs/rebuild.sh +++ b/noir/noir-repo/test_programs/rebuild.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash set -e -NO_PARALLEL=${1:-} - process_dir() { local dir=$1 local current_dir=$2 @@ -62,28 +60,6 @@ for dir in $current_dir/benchmarks/*; do dirs_to_process+=("$dir") done -# Process each directory in parallel -pids=() -if [ -z $NO_PARALLEL ]; then -for dir in "${dirs_to_process[@]}"; do - process_dir "$dir" "$current_dir" & - pids+=($!) -done -else -for dir in "${dirs_to_process[@]}"; do - process_dir "$dir" "$current_dir" - pids+=($!) -done -fi - -# Check the exit status of each background job. -for pid in "${pids[@]}"; do - wait $pid || exit_status=$? -done +parallel -j0 process_dir {} "$current_dir" ::: ${dirs_to_process[@]} -# Exit with a failure status if any job failed. -if [ ! -z "$exit_status" ]; then - echo "Rebuild failed!" - exit $exit_status -fi echo "Rebuild Succeeded!" diff --git a/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr b/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr index 60c001ec64e1..d76ce5a05e9f 100644 --- a/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr +++ b/noir/noir-repo/test_programs/test_libraries/diamond_deps_1/src/lib.nr @@ -1,4 +1,4 @@ -use dep::dep2::call_dep2; +use dep2::call_dep2; pub fn call_dep1_then_dep2(x: Field, y: Field) -> Field { call_dep2(x, y) diff --git a/noir/noir-repo/test_programs/test_libraries/exporting_lib/src/lib.nr b/noir/noir-repo/test_programs/test_libraries/exporting_lib/src/lib.nr index bfb1819132a7..fdd9f139d410 100644 --- a/noir/noir-repo/test_programs/test_libraries/exporting_lib/src/lib.nr +++ b/noir/noir-repo/test_programs/test_libraries/exporting_lib/src/lib.nr @@ -4,6 +4,6 @@ struct MyStruct { type FooStruct = MyStruct; -fn is_struct_zero(val: MyStruct) -> bool { +pub fn is_struct_zero(val: MyStruct) -> bool { val.inner == 0 } diff --git a/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr b/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr index f12dfe01ecdb..1bced5483040 100644 --- a/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr +++ b/noir/noir-repo/test_programs/test_libraries/reexporting_lib/src/lib.nr @@ -1,3 +1,3 @@ -use dep::exporting_lib::{MyStruct, FooStruct}; +use exporting_lib::{MyStruct, FooStruct}; -use dep::exporting_lib as lib; +use exporting_lib as lib; diff --git a/noir/noir-repo/tooling/debugger/Cargo.toml b/noir/noir-repo/tooling/debugger/Cargo.toml index a3bf12f53686..05b28f9d95a3 100644 --- a/noir/noir-repo/tooling/debugger/Cargo.toml +++ b/noir/noir-repo/tooling/debugger/Cargo.toml @@ -18,6 +18,7 @@ noirc_frontend.workspace = true noirc_printable_type.workspace = true noirc_errors.workspace = true noirc_driver.workspace = true +noirc_artifacts.workspace = true thiserror.workspace = true codespan-reporting.workspace = true dap.workspace = true diff --git a/noir/noir-repo/tooling/debugger/ignored-tests.txt b/noir/noir-repo/tooling/debugger/ignored-tests.txt index a91938965891..a3971d437fbd 100644 --- a/noir/noir-repo/tooling/debugger/ignored-tests.txt +++ b/noir/noir-repo/tooling/debugger/ignored-tests.txt @@ -11,7 +11,8 @@ fold_distinct_return fold_fibonacci fold_numeric_generic_poseidon is_unconstrained +macros modulus references regression_4709 -to_bytes_integration \ No newline at end of file +to_bytes_integration diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 4436ce0ec3de..cb36988bf0bc 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -10,9 +10,9 @@ use acvm::{BlackBoxFunctionSolver, FieldElement}; use codespan_reporting::files::{Files, SimpleFile}; use fm::FileId; -use nargo::artifacts::debug::{DebugArtifact, StackFrame}; use nargo::errors::{ExecutionError, Location}; use nargo::NargoError; +use noirc_artifacts::debug::{DebugArtifact, StackFrame}; use noirc_driver::DebugFile; use std::collections::BTreeMap; diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index 40b77f0ad2a8..77abf3093cd1 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -24,7 +24,7 @@ use dap::types::{ Breakpoint, DisassembledInstruction, Scope, Source, StackFrame, SteppingGranularity, StoppedEventReason, Thread, Variable, }; -use nargo::artifacts::debug::DebugArtifact; +use noirc_artifacts::debug::DebugArtifact; use fm::FileId; use noirc_driver::CompiledProgram; diff --git a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs index 03b1a35dfa55..62443d4065c6 100644 --- a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs +++ b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs @@ -3,10 +3,8 @@ use acvm::{ pwg::ForeignCallWaitInfo, AcirField, FieldElement, }; -use nargo::{ - artifacts::debug::{DebugArtifact, DebugVars, StackFrame}, - ops::{DefaultForeignCallExecutor, ForeignCallExecutor}, -}; +use nargo::ops::{DefaultForeignCallExecutor, ForeignCallExecutor}; +use noirc_artifacts::debug::{DebugArtifact, DebugVars, StackFrame}; use noirc_errors::debug_info::{DebugFnId, DebugVarId}; use noirc_printable_type::ForeignCallError; diff --git a/noir/noir-repo/tooling/debugger/src/lib.rs b/noir/noir-repo/tooling/debugger/src/lib.rs index 9168a6228f08..9d0059ee495a 100644 --- a/noir/noir-repo/tooling/debugger/src/lib.rs +++ b/noir/noir-repo/tooling/debugger/src/lib.rs @@ -13,7 +13,7 @@ use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; use acvm::{BlackBoxFunctionSolver, FieldElement}; -use nargo::artifacts::debug::DebugArtifact; +use noirc_artifacts::debug::DebugArtifact; use nargo::NargoError; use noirc_driver::CompiledProgram; diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index 07f9333d51cf..7d8c6e0947dc 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -5,9 +5,10 @@ use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::brillig_vm::brillig::Opcode as BrilligOpcode; use acvm::{BlackBoxFunctionSolver, FieldElement}; +use nargo::NargoError; use crate::foreign_calls::DefaultDebugForeignCallExecutor; -use nargo::{artifacts::debug::DebugArtifact, NargoError}; +use noirc_artifacts::debug::DebugArtifact; use easy_repl::{command, CommandStatus, Repl}; use noirc_printable_type::PrintableValueDisplay; diff --git a/noir/noir-repo/tooling/debugger/src/source_code_printer.rs b/noir/noir-repo/tooling/debugger/src/source_code_printer.rs index e298eb8aadd9..e9586b786bd0 100644 --- a/noir/noir-repo/tooling/debugger/src/source_code_printer.rs +++ b/noir/noir-repo/tooling/debugger/src/source_code_printer.rs @@ -1,5 +1,5 @@ use codespan_reporting::files::Files; -use nargo::artifacts::debug::DebugArtifact; +use noirc_artifacts::debug::DebugArtifact; use noirc_errors::Location; use owo_colors::OwoColorize; use std::ops::Range; @@ -143,7 +143,7 @@ fn render_line( // // Consider for example the file (line numbers added to facilitate this doc): // ``` -// 1 use dep::std::hash::poseidon; +// 1 use std::hash::poseidon; // 2 // 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { // 4 let hash1 = poseidon::bn254::hash_2(x1); @@ -157,7 +157,7 @@ fn render_line( // // If the location to render is `poseidon::bn254::hash_2(x1)`, we'll render the file as: // ``` -// 1 use dep::std::hash::poseidon; +// 1 use std::hash::poseidon; // 2 // 3 fn main(x1: [Field; 2], y1: pub Field, x2: [Field; 4], y2: pub Field) { // 4 let hash1 = poseidon::bn254::hash_2(x1); @@ -224,7 +224,7 @@ mod tests { use crate::source_code_printer::PrintedLine::Content; use acvm::acir::circuit::OpcodeLocation; use fm::FileManager; - use nargo::artifacts::debug::DebugArtifact; + use noirc_artifacts::debug::DebugArtifact; use noirc_errors::{debug_info::DebugInfo, Location, Span}; use std::collections::BTreeMap; use std::ops::Range; diff --git a/noir/noir-repo/tooling/fuzzer/Cargo.toml b/noir/noir-repo/tooling/fuzzer/Cargo.toml new file mode 100644 index 000000000000..ef49d707d6a5 --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "noir_fuzzer" +description = "A fuzzer for Noir programs" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +nargo.workspace = true +noirc_artifacts.workspace = true +noirc_abi.workspace = true +proptest.workspace = true +rand.workspace = true diff --git a/noir/noir-repo/tooling/fuzzer/src/dictionary/mod.rs b/noir/noir-repo/tooling/fuzzer/src/dictionary/mod.rs new file mode 100644 index 000000000000..bf2ab87be290 --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/dictionary/mod.rs @@ -0,0 +1,124 @@ +//! This module defines how to build a dictionary of values which are likely to be correspond +//! to significant inputs during fuzzing by inspecting the [Program] being fuzzed. +//! +//! This dictionary can be fed into the fuzzer's [strategy][proptest::strategy::Strategy] in order to bias it towards +//! generating these values to ensure they get proper coverage. +use std::collections::HashSet; + +use acvm::{ + acir::{ + circuit::{ + brillig::{BrilligBytecode, BrilligInputs}, + directives::Directive, + opcodes::{BlackBoxFuncCall, FunctionInput}, + Circuit, Opcode, Program, + }, + native_types::Expression, + }, + brillig_vm::brillig::Opcode as BrilligOpcode, + AcirField, +}; + +/// Constructs a [HashSet] of values pulled from a [Program] which are likely to be correspond +/// to significant inputs during fuzzing. +pub(super) fn build_dictionary_from_program(program: &Program) -> HashSet { + let constrained_dictionaries = program.functions.iter().map(build_dictionary_from_circuit); + let unconstrained_dictionaries = + program.unconstrained_functions.iter().map(build_dictionary_from_unconstrained_function); + let dictionaries = constrained_dictionaries.chain(unconstrained_dictionaries); + + let mut constants: HashSet = HashSet::new(); + for dictionary in dictionaries { + constants.extend(dictionary); + } + constants +} + +fn build_dictionary_from_circuit(circuit: &Circuit) -> HashSet { + let mut constants: HashSet = HashSet::new(); + + fn insert_expr(dictionary: &mut HashSet, expr: &Expression) { + let quad_coefficients = expr.mul_terms.iter().map(|(k, _, _)| *k); + let linear_coefficients = expr.linear_combinations.iter().map(|(k, _)| *k); + let coefficients = linear_coefficients.chain(quad_coefficients); + + dictionary.extend(coefficients.clone()); + dictionary.insert(expr.q_c); + + // We divide the constant term by any coefficients in the expression to aid solving constraints such as `2 * x - 4 == 0`. + let scaled_constants = coefficients.map(|coefficient| expr.q_c / coefficient); + dictionary.extend(scaled_constants); + } + + fn insert_array_len(dictionary: &mut HashSet, array: &[T]) { + let array_length = array.len() as u128; + dictionary.insert(F::from(array_length)); + dictionary.insert(F::from(array_length - 1)); + } + + for opcode in &circuit.opcodes { + match opcode { + Opcode::AssertZero(expr) + | Opcode::Call { predicate: Some(expr), .. } + | Opcode::MemoryOp { predicate: Some(expr), .. } + | Opcode::Directive(Directive::ToLeRadix { a: expr, .. }) => { + insert_expr(&mut constants, expr) + } + + Opcode::MemoryInit { init, .. } => insert_array_len(&mut constants, init), + + Opcode::BrilligCall { inputs, predicate, .. } => { + for input in inputs { + match input { + BrilligInputs::Single(expr) => insert_expr(&mut constants, expr), + BrilligInputs::Array(exprs) => { + exprs.iter().for_each(|expr| insert_expr(&mut constants, expr)); + insert_array_len(&mut constants, exprs); + } + BrilligInputs::MemoryArray(_) => (), + } + } + if let Some(predicate) = predicate { + insert_expr(&mut constants, predicate) + } + } + + Opcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE { + input: FunctionInput { num_bits, .. }, + }) => { + let field = 1u128.wrapping_shl(*num_bits); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + _ => (), + } + } + + constants +} + +fn build_dictionary_from_unconstrained_function( + function: &BrilligBytecode, +) -> HashSet { + let mut constants: HashSet = HashSet::new(); + + for opcode in &function.bytecode { + match opcode { + BrilligOpcode::Cast { bit_size, .. } => { + let field = 1u128.wrapping_shl(*bit_size); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + BrilligOpcode::Const { bit_size, value, .. } => { + constants.insert(*value); + + let field = 1u128.wrapping_shl(*bit_size); + constants.insert(F::from(field)); + constants.insert(F::from(field - 1)); + } + _ => (), + } + } + + constants +} diff --git a/noir/noir-repo/tooling/fuzzer/src/lib.rs b/noir/noir-repo/tooling/fuzzer/src/lib.rs new file mode 100644 index 000000000000..28d7353f35a2 --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/lib.rs @@ -0,0 +1,96 @@ +//! This module has been adapted from Foundry's fuzzing implementation for the EVM. +//! https://github.com/foundry-rs/foundry/blob/6a85dbaa62f1c305f31cab37781232913055ae28/crates/evm/evm/src/executors/fuzz/mod.rs#L40 +//! +//! Code is used under the MIT license. + +use acvm::{blackbox_solver::StubbedBlackBoxSolver, FieldElement}; +use dictionary::build_dictionary_from_program; +use noirc_abi::InputMap; +use proptest::test_runner::{TestCaseError, TestError, TestRunner}; + +mod dictionary; +mod strategies; +mod types; + +use types::{CaseOutcome, CounterExampleOutcome, FuzzOutcome, FuzzTestResult}; + +use noirc_artifacts::program::ProgramArtifact; + +use nargo::ops::{execute_program, DefaultForeignCallExecutor}; + +/// An executor for Noir programs which which provides fuzzing support using [`proptest`]. +/// +/// After instantiation, calling `fuzz` will proceed to hammer the program with +/// inputs, until it finds a counterexample. The provided [`TestRunner`] contains all the +/// configuration which can be overridden via [environment variables](proptest::test_runner::Config) +pub struct FuzzedExecutor { + /// The program to be fuzzed + program: ProgramArtifact, + + /// The fuzzer + runner: TestRunner, +} + +impl FuzzedExecutor { + /// Instantiates a fuzzed executor given a testrunner + pub fn new(program: ProgramArtifact, runner: TestRunner) -> Self { + Self { program, runner } + } + + /// Fuzzes the provided program. + pub fn fuzz(&self) -> FuzzTestResult { + let dictionary = build_dictionary_from_program(&self.program.bytecode); + let strategy = strategies::arb_input_map(&self.program.abi, dictionary); + + let run_result: Result<(), TestError> = + self.runner.clone().run(&strategy, |input_map| { + let fuzz_res = self.single_fuzz(input_map)?; + + match fuzz_res { + FuzzOutcome::Case(_) => Ok(()), + FuzzOutcome::CounterExample(CounterExampleOutcome { + exit_reason: status, + .. + }) => Err(TestCaseError::fail(status)), + } + }); + + match run_result { + Ok(()) => FuzzTestResult { success: true, reason: None, counterexample: None }, + + Err(TestError::Abort(reason)) => FuzzTestResult { + success: false, + reason: Some(reason.to_string()), + counterexample: None, + }, + Err(TestError::Fail(reason, counterexample)) => { + let reason = reason.to_string(); + let reason = if reason.is_empty() { None } else { Some(reason) }; + + FuzzTestResult { success: false, reason, counterexample: Some(counterexample) } + } + } + } + + /// Granular and single-step function that runs only one fuzz and returns either a `CaseOutcome` + /// or a `CounterExampleOutcome` + pub fn single_fuzz(&self, input_map: InputMap) -> Result { + let initial_witness = self.program.abi.encode(&input_map, None).unwrap(); + let result = execute_program( + &self.program.bytecode, + initial_witness, + &StubbedBlackBoxSolver, + &mut DefaultForeignCallExecutor::::new(false, None), + ); + + // TODO: Add handling for `vm.assume` equivalent + + match result { + Ok(_) => Ok(FuzzOutcome::Case(CaseOutcome { case: input_map })), + Err(err) => Ok(FuzzOutcome::CounterExample(CounterExampleOutcome { + exit_reason: err.to_string(), + counterexample: input_map, + })), + } + } +} diff --git a/noir/noir-repo/tooling/fuzzer/src/strategies/int.rs b/noir/noir-repo/tooling/fuzzer/src/strategies/int.rs new file mode 100644 index 000000000000..d11cafcfae5d --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/strategies/int.rs @@ -0,0 +1,83 @@ +use proptest::{ + strategy::{NewTree, Strategy}, + test_runner::TestRunner, +}; +use rand::Rng; + +/// Strategy for signed ints (up to i128). +/// The strategy combines 2 different strategies, each assigned a specific weight: +/// 1. Generate purely random value in a range. This will first choose bit size uniformly (up `bits` +/// param). Then generate a value for this bit size. +/// 2. Generate a random value around the edges (+/- 3 around min, 0 and max possible value) +#[derive(Debug)] +pub struct IntStrategy { + /// Bit size of int (e.g. 128) + bits: usize, + /// The weight for edge cases (+/- 3 around 0 and max possible value) + edge_weight: usize, + /// The weight for purely random values + random_weight: usize, +} + +impl IntStrategy { + /// Create a new strategy. + /// # Arguments + /// * `bits` - Size of int in bits + pub fn new(bits: usize) -> Self { + Self { bits, edge_weight: 10usize, random_weight: 50usize } + } + + fn generate_edge_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + + let offset = rng.gen_range(0..4); + // Choose if we want values around min, -0, +0, or max + let kind = rng.gen_range(0..4); + let start = match kind { + 0 => self.type_min() + offset, + 1 => -offset - 1i128, + 2 => offset, + 3 => self.type_max() - offset, + _ => unreachable!(), + }; + Ok(proptest::num::i128::BinarySearch::new(start)) + } + + fn generate_random_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + + let start: i128 = rng.gen_range(self.type_min()..=self.type_max()); + Ok(proptest::num::i128::BinarySearch::new(start)) + } + + fn type_max(&self) -> i128 { + if self.bits < 128 { + (1i128 << (self.bits - 1)) - 1 + } else { + i128::MAX + } + } + + fn type_min(&self) -> i128 { + if self.bits < 128 { + -(1i128 << (self.bits - 1)) + } else { + i128::MIN + } + } +} + +impl Strategy for IntStrategy { + type Tree = proptest::num::i128::BinarySearch; + type Value = i128; + + fn new_tree(&self, runner: &mut TestRunner) -> NewTree { + let total_weight = self.random_weight + self.edge_weight; + let bias = runner.rng().gen_range(0..total_weight); + // randomly select one of 2 strategies + match bias { + x if x < self.edge_weight => self.generate_edge_tree(runner), + _ => self.generate_random_tree(runner), + } + } +} diff --git a/noir/noir-repo/tooling/fuzzer/src/strategies/mod.rs b/noir/noir-repo/tooling/fuzzer/src/strategies/mod.rs new file mode 100644 index 000000000000..46187a28d5b2 --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/strategies/mod.rs @@ -0,0 +1,99 @@ +use int::IntStrategy; +use prop::collection::vec; +use proptest::prelude::*; + +use acvm::{AcirField, FieldElement}; + +use noirc_abi::{input_parser::InputValue, Abi, AbiType, InputMap, Sign}; +use std::collections::{BTreeMap, HashSet}; +use uint::UintStrategy; + +mod int; +mod uint; + +pub(super) fn arb_value_from_abi_type( + abi_type: &AbiType, + dictionary: HashSet, +) -> SBoxedStrategy { + match abi_type { + AbiType::Field => vec(any::(), 32) + .prop_map(|bytes| InputValue::Field(FieldElement::from_be_bytes_reduce(&bytes))) + .sboxed(), + AbiType::Integer { width, sign } if sign == &Sign::Unsigned => { + UintStrategy::new(*width as usize, dictionary) + .prop_map(|uint| InputValue::Field(uint.into())) + .sboxed() + } + AbiType::Integer { width, .. } => { + let shift = 2i128.pow(*width); + IntStrategy::new(*width as usize) + .prop_map(move |mut int| { + if int < 0 { + int += shift + } + InputValue::Field(int.into()) + }) + .sboxed() + } + AbiType::Boolean => { + any::().prop_map(|val| InputValue::Field(FieldElement::from(val))).sboxed() + } + + AbiType::String { length } => { + // Strings only allow ASCII characters as each character must be able to be represented by a single byte. + let string_regex = format!("[[:ascii:]]{{{length}}}"); + proptest::string::string_regex(&string_regex) + .expect("parsing of regex should always succeed") + .prop_map(InputValue::String) + .sboxed() + } + AbiType::Array { length, typ } => { + let length = *length as usize; + let elements = vec(arb_value_from_abi_type(typ, dictionary), length..=length); + + elements.prop_map(InputValue::Vec).sboxed() + } + + AbiType::Struct { fields, .. } => { + let fields: Vec> = fields + .iter() + .map(|(name, typ)| { + (Just(name.clone()), arb_value_from_abi_type(typ, dictionary.clone())).sboxed() + }) + .collect(); + + fields + .prop_map(|fields| { + let fields: BTreeMap<_, _> = fields.into_iter().collect(); + InputValue::Struct(fields) + }) + .sboxed() + } + + AbiType::Tuple { fields } => { + let fields: Vec<_> = + fields.iter().map(|typ| arb_value_from_abi_type(typ, dictionary.clone())).collect(); + fields.prop_map(InputValue::Vec).sboxed() + } + } +} + +pub(super) fn arb_input_map( + abi: &Abi, + dictionary: HashSet, +) -> BoxedStrategy { + let values: Vec<_> = abi + .parameters + .iter() + .map(|param| { + (Just(param.name.clone()), arb_value_from_abi_type(¶m.typ, dictionary.clone())) + }) + .collect(); + + values + .prop_map(|values| { + let input_map: InputMap = values.into_iter().collect(); + input_map + }) + .boxed() +} diff --git a/noir/noir-repo/tooling/fuzzer/src/strategies/uint.rs b/noir/noir-repo/tooling/fuzzer/src/strategies/uint.rs new file mode 100644 index 000000000000..94610dbc8294 --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/strategies/uint.rs @@ -0,0 +1,98 @@ +use std::collections::HashSet; + +use acvm::{AcirField, FieldElement}; +use proptest::{ + strategy::{NewTree, Strategy}, + test_runner::TestRunner, +}; +use rand::Rng; + +/// Value tree for unsigned ints (up to u128). +/// The strategy combines 2 different strategies, each assigned a specific weight: +/// 1. Generate purely random value in a range. This will first choose bit size uniformly (up `bits` +/// param). Then generate a value for this bit size. +/// 2. Generate a random value around the edges (+/- 3 around 0 and max possible value) +#[derive(Debug)] +pub struct UintStrategy { + /// Bit size of uint (e.g. 128) + bits: usize, + /// A set of fixtures to be generated + fixtures: Vec, + /// The weight for edge cases (+/- 3 around 0 and max possible value) + edge_weight: usize, + /// The weight for fixtures + fixtures_weight: usize, + /// The weight for purely random values + random_weight: usize, +} + +impl UintStrategy { + /// Create a new strategy. + /// # Arguments + /// * `bits` - Size of uint in bits + /// * `fixtures` - Set of `FieldElements` representing values which the fuzzer weight towards testing. + pub fn new(bits: usize, fixtures: HashSet) -> Self { + Self { + bits, + fixtures: fixtures.into_iter().collect(), + edge_weight: 10usize, + fixtures_weight: 40usize, + random_weight: 50usize, + } + } + + fn generate_edge_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + // Choose if we want values around 0 or max + let is_min = rng.gen_bool(0.5); + let offset = rng.gen_range(0..4); + let start = if is_min { offset } else { self.type_max().saturating_sub(offset) }; + Ok(proptest::num::u128::BinarySearch::new(start)) + } + + fn generate_fixtures_tree(&self, runner: &mut TestRunner) -> NewTree { + // generate random cases if there's no fixtures + if self.fixtures.is_empty() { + return self.generate_random_tree(runner); + } + + // Generate value tree from fixture. + let fixture = &self.fixtures[runner.rng().gen_range(0..self.fixtures.len())]; + if fixture.num_bits() <= self.bits as u32 { + return Ok(proptest::num::u128::BinarySearch::new(fixture.to_u128())); + } + + // If fixture is not a valid type, generate random value. + self.generate_random_tree(runner) + } + + fn generate_random_tree(&self, runner: &mut TestRunner) -> NewTree { + let rng = runner.rng(); + let start = rng.gen_range(0..=self.type_max()); + + Ok(proptest::num::u128::BinarySearch::new(start)) + } + + fn type_max(&self) -> u128 { + if self.bits < 128 { + (1 << self.bits) - 1 + } else { + u128::MAX + } + } +} + +impl Strategy for UintStrategy { + type Tree = proptest::num::u128::BinarySearch; + type Value = u128; + fn new_tree(&self, runner: &mut TestRunner) -> NewTree { + let total_weight = self.random_weight + self.fixtures_weight + self.edge_weight; + let bias = runner.rng().gen_range(0..total_weight); + // randomly select one of 3 strategies + match bias { + x if x < self.edge_weight => self.generate_edge_tree(runner), + x if x < self.edge_weight + self.fixtures_weight => self.generate_fixtures_tree(runner), + _ => self.generate_random_tree(runner), + } + } +} diff --git a/noir/noir-repo/tooling/fuzzer/src/types.rs b/noir/noir-repo/tooling/fuzzer/src/types.rs new file mode 100644 index 000000000000..dbd4ba94ec1e --- /dev/null +++ b/noir/noir-repo/tooling/fuzzer/src/types.rs @@ -0,0 +1,42 @@ +use noirc_abi::InputMap; + +type CounterExample = InputMap; + +/// The outcome of a fuzz test +#[derive(Debug)] +pub struct FuzzTestResult { + /// Whether the test case was successful. This means that the program executed + /// properly, or that there was a constraint failure and that the test was expected to fail + /// (has the `should_fail` attribute) + pub success: bool, + + /// If there was a constraint failure, this field will be populated. Note that the test can + /// still be successful (i.e self.success == true) when it's expected to fail. + pub reason: Option, + + /// Minimal reproduction test case for failing fuzz tests + pub counterexample: Option, +} + +/// Returned by a single fuzz in the case of a successful run +#[derive(Debug)] +pub struct CaseOutcome { + /// Data of a single fuzz test case + pub case: InputMap, +} + +/// Returned by a single fuzz when a counterexample has been discovered +#[derive(Debug)] +pub struct CounterExampleOutcome { + /// Minimal reproduction test case for failing test + pub counterexample: CounterExample, + /// The status of the call + pub exit_reason: String, +} + +/// Outcome of a single fuzz +#[derive(Debug)] +pub enum FuzzOutcome { + Case(CaseOutcome), + CounterExample(CounterExampleOutcome), +} diff --git a/noir/noir-repo/tooling/lsp/Cargo.toml b/noir/noir-repo/tooling/lsp/Cargo.toml index a599b096e527..ac3e3b1d30a0 100644 --- a/noir/noir-repo/tooling/lsp/Cargo.toml +++ b/noir/noir-repo/tooling/lsp/Cargo.toml @@ -19,6 +19,7 @@ nargo_toml.workspace = true noirc_driver.workspace = true noirc_errors.workspace = true noirc_frontend.workspace = true +noirc_artifacts.workspace = true serde.workspace = true serde_json.workspace = true tower.workspace = true 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 7d06bc87c851..57bc32994557 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs @@ -5,11 +5,9 @@ use std::{ use acvm::acir::circuit::ExpressionWidth; use async_lsp::{ErrorCode, ResponseError}; -use nargo::{ - artifacts::debug::DebugArtifact, insert_all_files_for_workspace_into_file_manager, - ops::report_errors, -}; +use nargo::{insert_all_files_for_workspace_into_file_manager, ops::report_errors}; use nargo_toml::{find_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_artifacts::debug::DebugArtifact; use noirc_driver::{ file_manager_with_stdlib, CompileOptions, DebugFile, NOIR_ARTIFACT_VERSION_STRING, }; diff --git a/noir/noir-repo/tooling/lsp/src/solver.rs b/noir/noir-repo/tooling/lsp/src/solver.rs index 0fcac73b9050..9d1185e3a799 100644 --- a/noir/noir-repo/tooling/lsp/src/solver.rs +++ b/noir/noir-repo/tooling/lsp/src/solver.rs @@ -24,6 +24,14 @@ impl BlackBoxFunctionSolver for WrapperSolver { self.0.pedersen_commitment(inputs, domain_separator) } + fn pedersen_hash( + &self, + inputs: &[acvm::FieldElement], + domain_separator: u32, + ) -> Result { + self.0.pedersen_hash(inputs, domain_separator) + } + fn multi_scalar_mul( &self, points: &[acvm::FieldElement], @@ -36,14 +44,6 @@ impl BlackBoxFunctionSolver for WrapperSolver { self.0.multi_scalar_mul(points, scalars_lo, scalars_hi) } - fn pedersen_hash( - &self, - inputs: &[acvm::FieldElement], - domain_separator: u32, - ) -> Result { - self.0.pedersen_hash(inputs, domain_separator) - } - fn ec_add( &self, input1_x: &acvm::FieldElement, diff --git a/noir/noir-repo/tooling/nargo/Cargo.toml b/noir/noir-repo/tooling/nargo/Cargo.toml index 8abec267d20f..b0cf1cfcbb17 100644 --- a/noir/noir-repo/tooling/nargo/Cargo.toml +++ b/noir/noir-repo/tooling/nargo/Cargo.toml @@ -18,13 +18,12 @@ noirc_errors.workspace = true noirc_frontend.workspace = true noirc_printable_type.workspace = true iter-extended.workspace = true -serde.workspace = true thiserror.workspace = true -codespan-reporting.workspace = true tracing.workspace = true rayon = "1.8.0" jsonrpc.workspace = true rand.workspace = true +serde.workspace = true [dev-dependencies] # TODO: This dependency is used to generate unit tests for `get_all_paths_in_dir` diff --git a/noir/noir-repo/tooling/nargo/src/lib.rs b/noir/noir-repo/tooling/nargo/src/lib.rs index 3deced041f81..c0c7602d14df 100644 --- a/noir/noir-repo/tooling/nargo/src/lib.rs +++ b/noir/noir-repo/tooling/nargo/src/lib.rs @@ -7,7 +7,6 @@ //! This name was used because it sounds like `cargo` and //! Noir Package Manager abbreviated is npm, which is already taken. -pub mod artifacts; pub mod constants; pub mod errors; pub mod ops; diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index ace2e9f0d0cb..18c6f2530b96 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -128,7 +128,7 @@ fn check_expected_failure_message( }; let expected_failure_message_matches = - matches!(&failed_assertion, Some(message) if message == expected_failure_message); + matches!(&failed_assertion, Some(message) if message.contains(expected_failure_message)); if expected_failure_message_matches { return TestStatus::Pass; } diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index 7c7e7b9d5caa..c6cf842a623c 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -32,6 +32,8 @@ noirc_driver.workspace = true noirc_frontend = { workspace = true, features = ["bn254"] } noirc_abi.workspace = true noirc_errors.workspace = true +noir_fuzzer.workspace = true +noirc_artifacts.workspace = true acvm = { workspace = true, features = ["bn254"] } bn254_blackbox_solver.workspace = true toml.workspace = true @@ -41,12 +43,7 @@ prettytable-rs = "0.10" rayon = "1.8.0" thiserror.workspace = true tower.workspace = true -async-lsp = { workspace = true, features = [ - "client-monitor", - "stdio", - "tracing", - "tokio", -] } +async-lsp = { workspace = true, features = ["client-monitor", "stdio", "tracing", "tokio"] } const_format.workspace = true similar-asserts.workspace = true termcolor = "1.1.2" @@ -54,6 +51,7 @@ color-eyre.workspace = true tokio = { version = "1.0", features = ["io-std", "rt"] } dap.workspace = true clap-markdown = { git = "https://github.com/noir-lang/clap-markdown", rev = "450d759532c88f0dba70891ceecdbc9ff8f25d2b", optional = true } +proptest.workspace = true notify = "6.1.1" notify-debouncer-full = "0.3.1" diff --git a/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs b/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs index 9f67bcffd6e7..effab7d7c279 100644 --- a/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs +++ b/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs @@ -28,16 +28,10 @@ macro_rules! criterion_command { }; } criterion_command!(execution, "execute"); -criterion_command!(prove, "prove"); criterion_group! { name = execution_benches; config = Criterion::default().sample_size(20).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); targets = criterion_selected_tests_execution } -criterion_group! { - name = prove_benches; - config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); - targets = criterion_selected_tests_prove -} -criterion_main!(execution_benches, prove_benches); +criterion_main!(execution_benches); diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index fcc09653c7d9..a6873910524d 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -42,392 +42,318 @@ fn main() { /// These should be fixed and removed from this list. const IGNORED_BRILLIG_TESTS: [&str; 11] = [ // Takes a very long time to execute as large loops do not get simplified. - &"regression_4709", + "regression_4709", // bit sizes for bigint operation doesn't match up. - &"bigint", + "bigint", // ICE due to looking for function which doesn't exist. - &"fold_after_inlined_calls", - &"fold_basic", - &"fold_basic_nested_call", - &"fold_call_witness_condition", - &"fold_complex_outputs", - &"fold_distinct_return", - &"fold_fibonacci", - &"fold_numeric_generic_poseidon", + "fold_after_inlined_calls", + "fold_basic", + "fold_basic_nested_call", + "fold_call_witness_condition", + "fold_complex_outputs", + "fold_distinct_return", + "fold_fibonacci", + "fold_numeric_generic_poseidon", // Expected to fail as test asserts on which runtime it is in. - &"is_unconstrained", + "is_unconstrained", ]; -fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "execution_success"; - let test_data_dir = test_data_dir.join(test_sub_dir); +/// Certain features are only available in the elaborator. +/// We skip these tests for non-elaborator code since they are not +/// expected to work there. This can be removed once the old code is removed. +const IGNORED_NEW_FEATURE_TESTS: [&str; 5] = [ + "macros", + "wildcard_type", + "type_definition_annotation", + "numeric_generics_explicit", + "derive_impl", +]; +fn read_test_cases( + test_data_dir: &Path, + test_sub_dir: &str, +) -> impl Iterator { + let test_data_dir = test_data_dir.join(test_sub_dir); let test_case_dirs = fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - for test_dir in test_case_dirs { + test_case_dirs.into_iter().map(|dir| { let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); + dir.file_name().into_string().expect("Directory can't be converted to string"); if test_name.contains('-') { panic!( "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" ); - }; - let test_dir = &test_dir.path(); - - let brillig_ignored = - if IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()) { "\n#[ignore]" } else { "" }; - - write!( - test_file, - r#" -#[test] -fn execution_success_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force"); - - cmd.assert().success(); -}} + } + (test_name, dir.path()) + }) +} +fn generate_test_case( + test_file: &mut File, + test_type: &str, + test_name: &str, + test_dir: &std::path::Display, + test_content: &str, +) { + write!( + test_file, + r#" #[test] -fn execution_success_elaborator_{test_name}() {{ +fn {test_type}_{test_name}() {{ let test_program_dir = PathBuf::from("{test_dir}"); - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force").arg("--use-elaborator"); - - cmd.assert().success(); + let mut nargo = Command::cargo_bin("nargo").unwrap(); + nargo.arg("--program-dir").arg(test_program_dir); + {test_content} }} +"# + ) + .expect("Could not write templated test file."); +} -#[test]{brillig_ignored} -fn execution_success_{test_name}_brillig() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force").arg("--force-brillig"); +fn generate_execution_success_tests(test_file: &mut File, test_data_dir: &Path) { + let test_type = "execution_success"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); - cmd.assert().success(); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + generate_test_case( + test_file, + test_type, + &test_name, + &test_dir, + r#" + nargo.arg("execute").arg("--force"); + + nargo.assert().success();"#, + ); + + if !IGNORED_NEW_FEATURE_TESTS.contains(&test_name.as_str()) { + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("execute").arg("--force").arg("--use-legacy"); + + nargo.assert().success();"#, + ); + } + + if !IGNORED_BRILLIG_TESTS.contains(&test_name.as_str()) { + generate_test_case( + test_file, + test_type, + &format!("{test_name}_brillig"), + &test_dir, + r#" + nargo.arg("execute").arg("--force").arg("--force-brillig"); + + nargo.assert().success();"#, + ); + } } } fn generate_execution_failure_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "execution_failure"; - let test_data_dir = test_data_dir.join(test_sub_dir); + let test_type = "execution_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); - - write!( + generate_test_case( test_file, + test_type, + &test_name, + &test_dir, r#" -#[test] -fn execution_failure_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force"); - - cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); -}} + nargo.arg("execute").arg("--force"); + + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, + ); -#[test] -fn execution_failure_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("execute").arg("--force").arg("--use-elaborator"); - - cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("execute").arg("--force").arg("--use-legacy"); + + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, + ); } } fn generate_noir_test_success_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "noir_test_success"; - let test_data_dir = test_data_dir.join(test_sub_dir); - - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); + let test_type = "noir_test_success"; + let test_cases = read_test_cases(test_data_dir, "noir_test_success"); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); - write!( + generate_test_case( test_file, + test_type, + &test_name, + &test_dir, r#" -#[test] -fn noir_test_success_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("test"); + nargo.arg("test"); + + nargo.assert().success();"#, + ); - cmd.assert().success(); -}} - -#[test] -fn noir_test_success_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("test").arg("--use-elaborator"); - - cmd.assert().success(); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("test").arg("--use-legacy"); + + nargo.assert().success();"#, + ); } } fn generate_noir_test_failure_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "noir_test_failure"; - let test_data_dir = test_data_dir.join(test_sub_dir); - - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); - - write!( + let test_type = "noir_test_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + generate_test_case( test_file, + test_type, + &test_name, + &test_dir, r#" -#[test] -fn noir_test_failure_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("test"); - - cmd.assert().failure(); -}} - -#[test] -fn noir_test_failure_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("test").arg("--use-elaborator"); + nargo.arg("test"); + + nargo.assert().failure();"#, + ); - cmd.assert().failure(); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("test").arg("--use-legacy"); + + nargo.assert().failure();"#, + ); } } fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "compile_success_empty"; - let test_data_dir = test_data_dir.join(test_sub_dir); - - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); - - write!( + let test_type = "compile_success_empty"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); + + let assert_zero_opcodes = r#" + let output = nargo.output().expect("Failed to execute command"); + + if !output.status.success() {{ + panic!("`nargo info` failed with: {}", String::from_utf8(output.stderr).unwrap_or_default()); + }} + + // `compile_success_empty` tests should be able to compile down to an empty circuit. + let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ + panic!("JSON was not well-formatted {:?}\n\n{:?}", e, std::str::from_utf8(&output.stdout)) + }}); + let num_opcodes = &json["programs"][0]["functions"][0]["acir_opcodes"]; + assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); + "#; + + generate_test_case( test_file, - r#" -#[test] -fn compile_success_empty_{test_name}() {{ - - let test_program_dir = PathBuf::from("{test_dir}"); - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("info"); - cmd.arg("--json"); - cmd.arg("--force"); - - let output = cmd.output().expect("Failed to execute command"); - - if !output.status.success() {{ - panic!("`nargo info` failed with: {{}}", String::from_utf8(output.stderr).unwrap_or_default()); - }} - - // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ - panic!("JSON was not well-formatted {{:?}}\n\n{{:?}}", e, std::str::from_utf8(&output.stdout)) - }}); - let num_opcodes = &json["programs"][0]["functions"][0]["acir_opcodes"]; - assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); -}} - -#[test] -fn compile_success_empty_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("info"); - cmd.arg("--json"); - cmd.arg("--force"); - cmd.arg("--use-elaborator"); - - let output = cmd.output().expect("Failed to execute command"); - - if !output.status.success() {{ - panic!("`nargo info` failed with: {{}}", String::from_utf8(output.stderr).unwrap_or_default()); - }} - - // `compile_success_empty` tests should be able to compile down to an empty circuit. - let json: serde_json::Value = serde_json::from_slice(&output.stdout).unwrap_or_else(|e| {{ - panic!("JSON was not well-formatted {{:?}}\n\n{{:?}}", e, std::str::from_utf8(&output.stdout)) - }}); - let num_opcodes = &json["programs"][0]["functions"][0]["acir_opcodes"]; - assert_eq!(num_opcodes.as_u64().expect("number of opcodes should fit in a u64"), 0); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + test_type, + &test_name, + &test_dir, + &format!( + r#" + nargo.arg("info").arg("--json").arg("--force"); + + {assert_zero_opcodes}"#, + ), + ); + + if !IGNORED_NEW_FEATURE_TESTS.contains(&test_name.as_str()) { + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + &format!( + r#" + nargo.arg("info").arg("--json").arg("--force").arg("--use-legacy"); + + {assert_zero_opcodes}"#, + ), + ); + } } } fn generate_compile_success_contract_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "compile_success_contract"; - let test_data_dir = test_data_dir.join(test_sub_dir); + let test_type = "compile_success_contract"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); - - write!( + generate_test_case( test_file, + test_type, + &test_name, + &test_dir, r#" -#[test] -fn compile_success_contract_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("compile").arg("--force"); + nargo.arg("compile").arg("--force"); + + nargo.assert().success();"#, + ); - cmd.assert().success(); -}} -#[test] -fn compile_success_contract_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("compile").arg("--force").arg("--use-elaborator"); - - cmd.assert().success(); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("compile").arg("--force").arg("--use-legacy"); + + nargo.assert().success();"#, + ); } } fn generate_compile_failure_tests(test_file: &mut File, test_data_dir: &Path) { - let test_sub_dir = "compile_failure"; - let test_data_dir = test_data_dir.join(test_sub_dir); - - let test_case_dirs = - fs::read_dir(test_data_dir).unwrap().flatten().filter(|c| c.path().is_dir()); - - for test_dir in test_case_dirs { - let test_name = - test_dir.file_name().into_string().expect("Directory can't be converted to string"); - if test_name.contains('-') { - panic!( - "Invalid test directory: {test_name}. Cannot include `-`, please convert to `_`" - ); - }; - let test_dir = &test_dir.path(); + let test_type = "compile_failure"; + let test_cases = read_test_cases(test_data_dir, test_type); + for (test_name, test_dir) in test_cases { + let test_dir = test_dir.display(); - write!( + generate_test_case( test_file, - r#" -#[test] -fn compile_failure_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("compile").arg("--force"); - - cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); -}} -#[test] -fn compile_failure_elaborator_{test_name}() {{ - let test_program_dir = PathBuf::from("{test_dir}"); - - let mut cmd = Command::cargo_bin("nargo").unwrap(); - cmd.arg("--program-dir").arg(test_program_dir); - cmd.arg("compile").arg("--force").arg("--use-elaborator"); - - cmd.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not()); -}} - "#, - test_dir = test_dir.display(), - ) - .expect("Could not write templated test file."); + test_type, + &test_name, + &test_dir, + r#"nargo.arg("compile").arg("--force"); + + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, + ); + + if !IGNORED_NEW_FEATURE_TESTS.contains(&test_name.as_str()) { + generate_test_case( + test_file, + test_type, + &format!("legacy_{test_name}"), + &test_dir, + r#" + nargo.arg("compile").arg("--force").arg("--use-legacy"); + + nargo.assert().failure().stderr(predicate::str::contains("The application panicked (crashed).").not());"#, + ); + } } } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs index e2e1f147b902..2db3b10429a0 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/check_cmd.rs @@ -87,7 +87,7 @@ fn check_package( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, - compile_options.use_elaborator, + compile_options.use_legacy, )?; if package.is_library() || package.is_contract() { @@ -160,9 +160,9 @@ pub(crate) fn check_crate_and_report_errors( deny_warnings: bool, disable_macros: bool, silence_warnings: bool, - use_elaborator: bool, + use_legacy: bool, ) -> Result<(), CompileError> { - let result = check_crate(context, crate_id, deny_warnings, disable_macros, use_elaborator); + let result = check_crate(context, crate_id, deny_warnings, disable_macros, use_legacy); report_errors(result, &context.file_manager, deny_warnings, silence_warnings) } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs index bd76cf248055..e83b1728c932 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/compile_cmd.rs @@ -3,7 +3,6 @@ use std::path::Path; use std::time::Duration; use fm::FileManager; -use nargo::artifacts::program::ProgramArtifact; use nargo::ops::{collect_errors, compile_contract, compile_program, report_errors}; use nargo::package::Package; use nargo::workspace::Workspace; @@ -11,7 +10,7 @@ use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::file_manager_with_stdlib; use noirc_driver::NOIR_ARTIFACT_VERSION_STRING; -use noirc_driver::{CompilationResult, CompileOptions, CompiledContract, CompiledProgram}; +use noirc_driver::{CompilationResult, CompileOptions, CompiledContract}; use noirc_frontend::graph::CrateName; @@ -121,39 +120,22 @@ pub(super) fn compile_workspace_full( let compiled_workspace = compile_workspace(&workspace_file_manager, &parsed_files, workspace, compile_options); - let (compiled_programs, compiled_contracts) = report_errors( + report_errors( compiled_workspace, &workspace_file_manager, compile_options.deny_warnings, compile_options.silence_warnings, )?; - let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace - .into_iter() - .filter(|package| !package.is_library()) - .cloned() - .partition(|package| package.is_binary()); - - // Save build artifacts to disk. - for (package, program) in binary_packages.into_iter().zip(compiled_programs) { - let program = nargo::ops::transform_program(program, compile_options.expression_width); - save_program(program.clone(), &package, &workspace.target_directory_path()); - } - let circuit_dir = workspace.target_directory_path(); - for (package, contract) in contract_packages.into_iter().zip(compiled_contracts) { - let contract = nargo::ops::transform_contract(contract, compile_options.expression_width); - save_contract(contract, &package, &circuit_dir, compile_options.show_artifact_paths); - } - Ok(()) } -pub(super) fn compile_workspace( +fn compile_workspace( file_manager: &FileManager, parsed_files: &ParsedFiles, workspace: &Workspace, compile_options: &CompileOptions, -) -> CompilationResult<(Vec, Vec)> { +) -> CompilationResult<()> { let (binary_packages, contract_packages): (Vec<_>, Vec<_>) = workspace .into_iter() .filter(|package| !package.is_library()) @@ -161,32 +143,20 @@ pub(super) fn compile_workspace( .partition(|package| package.is_binary()); // Compile all of the packages in parallel. - let program_results: Vec> = binary_packages - .par_iter() - .map(|package| { - let program_artifact_path = workspace.package_build_path(package); - let cached_program: Option = - read_program_from_file(program_artifact_path) - .ok() - .filter(|p| p.noir_version == NOIR_ARTIFACT_VERSION_STRING) - .map(|p| p.into()); - - compile_program(file_manager, parsed_files, package, compile_options, cached_program) - }) - .collect(); - let contract_results: Vec> = contract_packages - .par_iter() - .map(|package| compile_contract(file_manager, parsed_files, package, compile_options)) - .collect(); - - // Collate any warnings/errors which were encountered during compilation. - let compiled_programs = collect_errors(program_results); - let compiled_contracts = collect_errors(contract_results); + let program_warnings_or_errors: CompilationResult<()> = + compile_programs(file_manager, parsed_files, workspace, &binary_packages, compile_options); + let contract_warnings_or_errors: CompilationResult<()> = compiled_contracts( + file_manager, + parsed_files, + &contract_packages, + compile_options, + &workspace.target_directory_path(), + ); - match (compiled_programs, compiled_contracts) { - (Ok((programs, program_warnings)), Ok((contracts, contract_warnings))) => { + match (program_warnings_or_errors, contract_warnings_or_errors) { + (Ok((_, program_warnings)), Ok((_, contract_warnings))) => { let warnings = [program_warnings, contract_warnings].concat(); - Ok(((programs, contracts), warnings)) + Ok(((), warnings)) } (Err(program_errors), Err(contract_errors)) => { Err([program_errors, contract_errors].concat()) @@ -195,22 +165,79 @@ pub(super) fn compile_workspace( } } -pub(super) fn save_program(program: CompiledProgram, package: &Package, circuit_dir: &Path) { - let program_artifact = ProgramArtifact::from(program.clone()); - save_program_to_file(&program_artifact, &package.name, circuit_dir); +fn compile_programs( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + workspace: &Workspace, + binary_packages: &[Package], + compile_options: &CompileOptions, +) -> CompilationResult<()> { + let load_cached_program = |package| { + let program_artifact_path = workspace.package_build_path(package); + read_program_from_file(program_artifact_path) + .ok() + .filter(|p| p.noir_version == NOIR_ARTIFACT_VERSION_STRING) + .map(|p| p.into()) + }; + + let program_results: Vec> = binary_packages + .par_iter() + .map(|package| { + let (program, warnings) = compile_program( + file_manager, + parsed_files, + package, + compile_options, + load_cached_program(package), + )?; + let program = nargo::ops::transform_program(program, compile_options.expression_width); + save_program_to_file( + &program.clone().into(), + &package.name, + workspace.target_directory_path(), + ); + Ok(((), warnings)) + }) + .collect(); + + // Collate any warnings/errors which were encountered during compilation. + collect_errors(program_results).map(|(_, warnings)| ((), warnings)) +} + +fn compiled_contracts( + file_manager: &FileManager, + parsed_files: &ParsedFiles, + contract_packages: &[Package], + compile_options: &CompileOptions, + target_dir: &Path, +) -> CompilationResult<()> { + let contract_results: Vec> = contract_packages + .par_iter() + .map(|package| { + let (contract, warnings) = + compile_contract(file_manager, parsed_files, package, compile_options)?; + let contract = + nargo::ops::transform_contract(contract, compile_options.expression_width); + save_contract(contract, package, target_dir, compile_options.show_artifact_paths); + Ok(((), warnings)) + }) + .collect(); + + // Collate any warnings/errors which were encountered during compilation. + collect_errors(contract_results).map(|(_, warnings)| ((), warnings)) } fn save_contract( contract: CompiledContract, package: &Package, - circuit_dir: &Path, + target_dir: &Path, show_artifact_paths: bool, ) { let contract_name = contract.name.clone(); let artifact_path = save_contract_to_file( &contract.into(), &format!("{}-{}", package.name, contract_name), - circuit_dir, + target_dir, ); if show_artifact_paths { println!("Saved contract artifact to: {}", artifact_path.display()); 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 086dddc27e5f..778009bf7914 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 @@ -6,7 +6,6 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use fm::FileManager; -use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::CompileError; use nargo::ops::{compile_program, compile_program_with_debug_instrumenter, report_errors}; @@ -16,6 +15,7 @@ use nargo::{insert_all_files_for_workspace_into_file_manager, parse_all}; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; +use noirc_artifacts::debug::DebugArtifact; use noirc_driver::{ file_manager_with_stdlib, CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING, }; 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 b548336275bd..cf9dc1141a1a 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 @@ -3,7 +3,6 @@ use acvm::FieldElement; use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; -use nargo::artifacts::debug::DebugArtifact; use nargo::constants::PROVER_INPUT_FILE; use nargo::errors::try_to_diagnose_runtime_error; use nargo::ops::DefaultForeignCallExecutor; @@ -11,6 +10,7 @@ use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_abi::input_parser::{Format, InputValue}; use noirc_abi::InputMap; +use noirc_artifacts::debug::DebugArtifact; use noirc_driver::{CompileOptions, CompiledProgram, NOIR_ARTIFACT_VERSION_STRING}; use noirc_frontend::graph::CrateName; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs index 324eed340ad4..ee30b29b0f0e 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/export_cmd.rs @@ -89,7 +89,7 @@ fn compile_exported_functions( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, - compile_options.use_elaborator, + compile_options.use_legacy, )?; let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs index ba017651667f..caeaafd4ab3a 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/fs/program.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use nargo::artifacts::{contract::ContractArtifact, program::ProgramArtifact}; +use noirc_artifacts::{contract::ContractArtifact, program::ProgramArtifact}; use noirc_frontend::graph::CrateName; use crate::errors::FilesystemError; 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 7c50e907dc97..3759fb31c763 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -3,11 +3,9 @@ use std::collections::HashMap; use acvm::acir::circuit::ExpressionWidth; use clap::Args; use iter_extended::vecmap; -use nargo::{ - artifacts::{debug::DebugArtifact, program::ProgramArtifact}, - package::Package, -}; +use nargo::package::Package; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; +use noirc_artifacts::{debug::DebugArtifact, program::ProgramArtifact}; use noirc_driver::{CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; use noirc_errors::{debug_info::OpCodesCount, Location}; use noirc_frontend::graph::CrateName; diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index 99c284e5019b..de9e8dc5d7c4 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -10,7 +10,8 @@ use nargo::{ }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml, PackageSelection}; use noirc_driver::{ - check_crate, file_manager_with_stdlib, CompileOptions, NOIR_ARTIFACT_VERSION_STRING, + check_crate, compile_no_check, file_manager_with_stdlib, CompileOptions, + NOIR_ARTIFACT_VERSION_STRING, }; use noirc_frontend::{ graph::CrateName, @@ -175,7 +176,7 @@ fn run_test + Default>( crate_id, compile_options.deny_warnings, compile_options.disable_macros, - compile_options.use_elaborator, + compile_options.use_legacy, ) .expect("Any errors should have occurred when collecting test functions"); @@ -185,14 +186,47 @@ fn run_test + Default>( let blackbox_solver = S::default(); - nargo::ops::run_test( - &blackbox_solver, - &mut context, - test_function, - show_output, - foreign_call_resolver_url, - compile_options, - ) + let test_function_has_no_arguments = context + .def_interner + .function_meta(&test_function.get_id()) + .function_signature() + .0 + .is_empty(); + + if test_function_has_no_arguments { + nargo::ops::run_test( + &blackbox_solver, + &mut context, + test_function, + show_output, + foreign_call_resolver_url, + compile_options, + ) + } else { + use noir_fuzzer::FuzzedExecutor; + use proptest::test_runner::TestRunner; + + let compiled_program = + compile_no_check(&mut context, compile_options, test_function.get_id(), None, false); + match compiled_program { + Ok(compiled_program) => { + let runner = TestRunner::default(); + + let fuzzer = FuzzedExecutor::new(compiled_program.into(), runner); + + let result = fuzzer.fuzz(); + if result.success { + TestStatus::Pass + } else { + TestStatus::Fail { + message: result.reason.unwrap_or_default(), + error_diagnostic: None, + } + } + } + Err(err) => TestStatus::CompileError(err.into()), + } + } } fn get_tests_in_package( @@ -209,7 +243,7 @@ fn get_tests_in_package( compile_options.deny_warnings, compile_options.disable_macros, compile_options.silence_warnings, - compile_options.use_elaborator, + compile_options.use_legacy, )?; Ok(context diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs index 0bb967e75029..bf6614860e2d 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs @@ -1,7 +1,8 @@ +use std::io::Write; use std::{collections::BTreeMap, path::PathBuf}; -use acvm::blackbox_solver::StubbedBlackBoxSolver; -use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; +use fm::FileManager; +use noirc_driver::{check_crate, compile_no_check, file_manager_with_stdlib, CompileOptions}; use noirc_frontend::hir::FunctionNameMatch; use nargo::{ @@ -9,6 +10,7 @@ use nargo::{ package::{Package, PackageType}, parse_all, prepare_package, }; +use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; #[test] fn run_stdlib_tests() { @@ -23,14 +25,14 @@ fn run_stdlib_tests() { root_dir: PathBuf::from("."), package_type: PackageType::Binary, entry_path: PathBuf::from("main.nr"), - name: "dummy".parse().unwrap(), + name: "stdlib".parse().unwrap(), dependencies: BTreeMap::new(), }; let (mut context, dummy_crate_id) = prepare_package(&file_manager, &parsed_files, &dummy_package); - let result = check_crate(&mut context, dummy_crate_id, true, false, false); + let result = check_crate(&mut context, dummy_crate_id, false, false, false); report_errors(result, &context.file_manager, true, false) .expect("Error encountered while compiling standard library"); @@ -44,19 +46,136 @@ fn run_stdlib_tests() { let test_report: Vec<(String, TestStatus)> = test_functions .into_iter() .map(|(test_name, test_function)| { - let status = run_test( - &StubbedBlackBoxSolver, - &mut context, - &test_function, - false, - None, - &CompileOptions::default(), - ); + let test_function_has_no_arguments = context + .def_interner + .function_meta(&test_function.get_id()) + .function_signature() + .0 + .is_empty(); + let status = if test_function_has_no_arguments { + run_test( + &bn254_blackbox_solver::Bn254BlackBoxSolver, + &mut context, + &test_function, + false, + None, + &CompileOptions::default(), + ) + } else { + use noir_fuzzer::FuzzedExecutor; + use proptest::test_runner::TestRunner; + + let compiled_program = compile_no_check( + &mut context, + &CompileOptions::default(), + test_function.get_id(), + None, + false, + ); + match compiled_program { + Ok(compiled_program) => { + let runner = TestRunner::default(); + + let fuzzer = FuzzedExecutor::new(compiled_program.into(), runner); + + let result = fuzzer.fuzz(); + if result.success { + TestStatus::Pass + } else { + TestStatus::Fail { + message: result.reason.unwrap_or_default(), + error_diagnostic: None, + } + } + } + Err(err) => TestStatus::CompileError(err.into()), + } + }; (test_name, status) }) .collect(); assert!(!test_report.is_empty(), "Could not find any tests within the stdlib"); + display_test_report(&file_manager, &dummy_package, &CompileOptions::default(), &test_report); assert!(test_report.iter().all(|(_, status)| !status.failed())); } + +// This code is copied from `src/cli/test_cmd.rs`. +// This should be abstracted into a proper test runner at some point. +fn display_test_report( + file_manager: &FileManager, + package: &Package, + compile_options: &CompileOptions, + test_report: &[(String, TestStatus)], +) { + let writer = StandardStream::stderr(ColorChoice::Always); + let mut writer = writer.lock(); + + for (test_name, test_status) in test_report { + write!(writer, "[{}] Testing {test_name}... ", package.name) + .expect("Failed to write to stderr"); + writer.flush().expect("Failed to flush writer"); + + match &test_status { + TestStatus::Pass { .. } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + writeln!(writer, "ok").expect("Failed to write to stderr"); + } + TestStatus::Fail { message, error_diagnostic } => { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Red))) + .expect("Failed to set color"); + writeln!(writer, "FAIL\n{message}\n").expect("Failed to write to stderr"); + if let Some(diag) = error_diagnostic { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[diag.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + TestStatus::CompileError(err) => { + noirc_errors::reporter::report_all( + file_manager.as_file_map(), + &[err.clone()], + compile_options.deny_warnings, + compile_options.silence_warnings, + ); + } + } + writer.reset().expect("Failed to reset writer"); + } + + write!(writer, "[{}] ", package.name).expect("Failed to write to stderr"); + + let count_all = test_report.len(); + let count_failed = test_report.iter().filter(|(_, status)| status.failed()).count(); + let plural = if count_all == 1 { "" } else { "s" }; + if count_failed == 0 { + writer.set_color(ColorSpec::new().set_fg(Some(Color::Green))).expect("Failed to set color"); + write!(writer, "{count_all} test{plural} passed").expect("Failed to write to stderr"); + writer.reset().expect("Failed to reset writer"); + writeln!(writer).expect("Failed to write to stderr"); + } else { + let count_passed = count_all - count_failed; + let plural_failed = if count_failed == 1 { "" } else { "s" }; + let plural_passed = if count_passed == 1 { "" } else { "s" }; + + if count_passed != 0 { + writer + .set_color(ColorSpec::new().set_fg(Some(Color::Green))) + .expect("Failed to set color"); + write!(writer, "{count_passed} test{plural_passed} passed, ",) + .expect("Failed to write to stderr"); + } + + writer.set_color(ColorSpec::new().set_fg(Some(Color::Red))).expect("Failed to set color"); + writeln!(writer, "{count_failed} test{plural_failed} failed") + .expect("Failed to write to stderr"); + writer.reset().expect("Failed to reset writer"); + } +} diff --git a/noir/noir-repo/tooling/nargo_fmt/src/items.rs b/noir/noir-repo/tooling/nargo_fmt/src/items.rs index 7f998f45b591..80b641fd830f 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/items.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/items.rs @@ -74,7 +74,8 @@ impl<'me, T> Items<'me, T> { let mut different_line = false; let leading = self.visitor.slice(start..end); - let leading_trimmed = leading.trim(); + // Trim any possible whitespace before and after a comma separator + let leading_trimmed = leading.trim().trim_start_matches(',').trim(); let starts_with_block_comment = leading_trimmed.starts_with("/*"); let ends_with_block_comment = leading_trimmed.ends_with("*/"); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs index 7ff943aea62e..015644c15cb2 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/expr.rs @@ -63,7 +63,8 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - format!("{callee}{args}") + let bang = if call_expr.is_macro_call { "!" } else { "" }; + format!("{callee}{bang}{args}") } ExpressionKind::MethodCall(method_call_expr) => { let args_span = visitor.span_before( @@ -85,7 +86,8 @@ pub(crate) fn rewrite( NewlineMode::IfContainsNewLineAndWidth, ); - format!("{object}.{method}{turbofish}{args}") + let bang = if method_call_expr.is_macro_call { "!" } else { "" }; + format!("{object}.{method}{turbofish}{bang}{args}") } ExpressionKind::MemberAccess(member_access_expr) => { let lhs_str = rewrite_sub_expr(visitor, shape, member_access_expr.lhs); @@ -166,7 +168,7 @@ pub(crate) fn rewrite( format!("{path_string}{turbofish}") } ExpressionKind::Lambda(_) => visitor.slice(span).to_string(), - ExpressionKind::Quote(block) => format!("quote {}", rewrite_block(visitor, block, span)), + ExpressionKind::Quote(_) => visitor.slice(span).to_string(), ExpressionKind::Comptime(block, block_span) => { format!("comptime {}", rewrite_block(visitor, block, block_span)) } @@ -174,6 +176,13 @@ pub(crate) fn rewrite( ExpressionKind::Resolved(_) => { unreachable!("ExpressionKind::Resolved should only emitted by the comptime interpreter") } + ExpressionKind::Unquote(expr) => { + if matches!(&expr.kind, ExpressionKind::Variable(..)) { + format!("${expr}") + } else { + format!("$({})", rewrite_sub_expr(visitor, shape, *expr)) + } + } } } 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 278457f82d16..3298ed8ae731 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs @@ -55,6 +55,10 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) format!("fn{env}({args}) -> {return_type}") } + UnresolvedTypeData::Resolved(_) => { + unreachable!("Unexpected macro expansion of a type in nargo fmt input") + } + UnresolvedTypeData::Unspecified => todo!(), UnresolvedTypeData::FieldElement | UnresolvedTypeData::Integer(_, _) @@ -64,7 +68,7 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) | UnresolvedTypeData::Expression(_) | UnresolvedTypeData::String(_) | UnresolvedTypeData::FormatString(_, _) - | UnresolvedTypeData::Code + | UnresolvedTypeData::Quoted(_) | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), UnresolvedTypeData::Error => unreachable!(), } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/utils.rs b/noir/noir-repo/tooling/nargo_fmt/src/utils.rs index 2c5c3085e668..020f411ae2fe 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/utils.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/utils.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use crate::items::HasItem; use crate::rewrite; use crate::visitor::{FmtVisitor, Shape}; -use noirc_frontend::ast::{Expression, Ident, Param, Visibility}; +use noirc_frontend::ast::{Expression, Ident, Param, UnresolvedGeneric, Visibility}; use noirc_frontend::hir::resolution::errors::Span; use noirc_frontend::lexer::Lexer; use noirc_frontend::token::Token; @@ -80,6 +80,7 @@ pub(crate) fn find_comment_end(slice: &str, is_last: bool) -> usize { std::cmp::max(find_comment_end(slice) + block, separator_index + 1) } (_, Some(newline)) if newline > separator_index => newline + 1, + (None, None) => 0, _ => slice.len(), } } else if let Some(newline_index) = newline_index { @@ -170,6 +171,26 @@ impl HasItem for Ident { } } +impl HasItem for UnresolvedGeneric { + fn span(&self) -> Span { + self.span() + } + + fn format(self, visitor: &FmtVisitor, _shape: Shape) -> String { + match self { + UnresolvedGeneric::Variable(_) => visitor.slice(self.span()).into(), + UnresolvedGeneric::Numeric { ident, typ } => { + let mut result = "".to_owned(); + result.push_str(&ident.0.contents); + result.push_str(": "); + let typ = rewrite::typ(visitor, _shape, typ); + result.push_str(&typ); + result + } + } + } +} + pub(crate) fn first_line_width(exprs: &str) -> usize { exprs.lines().next().map_or(0, |line: &str| line.chars().count()) } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs b/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs index a5d042dc71e6..5aaaf20ff479 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/visitor/item.rs @@ -44,7 +44,7 @@ impl super::FmtVisitor<'_> { if !func.def.generics.is_empty() { let full_span = name_span.end()..params_open; - let start = name_span.end(); + let start = self.span_before(full_span.clone(), Token::Less).start(); let end = self.span_after(full_span, Token::Greater).start(); let generics = func.def.generics; @@ -188,8 +188,8 @@ impl super::FmtVisitor<'_> { continue; } - let slice = - self.slice(self.last_position..impl_.object_type.span.unwrap().end()); + let before_brace = self.span_before(span, Token::LeftBrace).start(); + let slice = self.slice(self.last_position..before_brace).trim(); let after_brace = self.span_after(span, Token::LeftBrace).start(); self.last_position = after_brace; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr index 97a6ebd6b773..e3a5877725af 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/contract.nr @@ -3,11 +3,11 @@ // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. // Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. contract Benchmarking { - use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; + use aztec::protocol_types::abis::function_selector::FunctionSelector; - use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; + use value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; - use dep::aztec::{ + use aztec::{ context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/fn.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/fn.nr index 3d231cd3f7fb..4dde9a1b3ece 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/fn.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/fn.nr @@ -61,3 +61,11 @@ fn main( ) {} pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} + +fn id(x: [Field; I]) -> [Field; I] {} + +fn id_two(x: [Field; I]) -> [Field; I] {} + +fn whitespace_before_generics(foo: T) {} + +fn more_whitespace_before_generics(foo: T) {} diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/impl.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/impl.nr index 1c0d4564b5ea..3c2fa42837a7 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/impl.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/impl.nr @@ -1,10 +1,10 @@ -impl Type {} +impl MyType {} -impl Type {} +impl MyType {} -impl Type {} +impl MyType {} -impl Type { +impl MyType { fn method(self) {} fn method(mut self) {} @@ -12,10 +12,16 @@ impl Type { fn method(&mut self) {} } -impl Type { +impl MyType { fn method(self) {} } -impl Type { +impl MyType { fn method(self) {} } + +impl MyStruct where T: MyEq { + fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr index 49c9d09001ef..9c74c477f5fa 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/import_braces.nr @@ -1 +1 @@ -use dep::std::hash::sha256; +use std::hash::sha256; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr index c57801155a00..0edc0eaf922e 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/let.nr @@ -44,17 +44,17 @@ fn let_() { } }; - let expr = Expr { + let expr = MyExpr { // A boolean literal (true, false). kind: ExprKind::Bool(true) }; - let expr = Expr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; + let expr = MyExpr { /*A boolean literal (true, false).*/ kind: ExprKind::Bool(true) }; - let mut V = dep::crate2::MyStruct { Q: x }; - let mut V = dep::crate2::MyStruct {}; - let mut V = dep::crate2::MyStruct {/*test*/}; - let mut V = dep::crate2::MyStruct { + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct {/*test*/}; + let mut V = crate2::MyStruct { // sad }; } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/print.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/print.nr index 3bce0941da26..d8404f674b07 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/print.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/print.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { std::print("Hello world"); std::println("Hello world"); diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/print2.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/print2.nr index 3bce0941da26..d8404f674b07 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/expected/print2.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/print2.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { std::print("Hello world"); std::println("Hello world"); diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/expected/singleton_import.nr b/noir/noir-repo/tooling/nargo_fmt/tests/expected/singleton_import.nr new file mode 100644 index 000000000000..bb1bad500d9a --- /dev/null +++ b/noir/noir-repo/tooling/nargo_fmt/tests/expected/singleton_import.nr @@ -0,0 +1,2 @@ +use dep::std; +use some_crate; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr index 97a6ebd6b773..e3a5877725af 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/contract.nr @@ -3,11 +3,11 @@ // Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. // Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. contract Benchmarking { - use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; + use aztec::protocol_types::abis::function_selector::FunctionSelector; - use dep::value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; + use value_note::{utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote, ValueNoteMethods}}; - use dep::aztec::{ + use aztec::{ context::Context, note::{note_getter_options::NoteGetterOptions, note_header::NoteHeader}, log::emit_unencrypted_log, state_vars::{Map, PublicMutable, PrivateSet}, types::type_serialization::field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/fn.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/fn.nr index 1c6d201fa391..16ed95a540d6 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/fn.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/fn.nr @@ -44,3 +44,13 @@ fn main( ) {} pub fn from_baz(x: [Field; crate::foo::MAGIC_NUMBER]) {} + +fn id< T , let I : Field > ( x : [ Field ; I ] ) -> [Field; I ] { } + +fn id_two(x: [Field ; I]) -> [ Field; I] {} + +fn whitespace_before_generics < T > (foo: T) {} + +fn more_whitespace_before_generics < +T > (foo: T) {} diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/impl.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/impl.nr index 1f111371a439..21ce6a2e1757 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/impl.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/impl.nr @@ -1,10 +1,10 @@ -impl Type {} +impl MyType {} -impl Type {} +impl MyType {} -impl Type {} +impl MyType {} -impl Type { +impl MyType { fn method(self) {} fn method(mut self) {} @@ -12,10 +12,16 @@ impl Type { fn method(&mut self) {} } -impl Type { +impl MyType { fn method(self) {} } -impl Type { +impl MyType { fn method(self) {} -} \ No newline at end of file +} + +impl MyStruct where T: MyEq { + fn my_eq(self, other: Self) -> bool { + (self.a == other.a) & self.b.my_eq(other.b) + } +} diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr index 88c7e9562a89..0647bbaa5808 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/import_braces.nr @@ -1 +1 @@ -use dep::std::hash::{sha256}; \ No newline at end of file +use std::hash::{sha256}; diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr index 67c4ab8bd52a..16ce0a9d7f15 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/let.nr @@ -20,16 +20,16 @@ fn let_() { let person = Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345", master: Person { first_name: "John", last_name: "Doe", home_address: Address { street: "123 Main St", city: "Exampleville", zip_code: "12345" } } } }; - let expr = Expr {// A boolean literal (true, false). + let expr = MyExpr {// A boolean literal (true, false). kind: ExprKind::Bool(true), }; - let expr = Expr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; + let expr = MyExpr {/*A boolean literal (true, false).*/kind: ExprKind::Bool(true),}; - let mut V = dep::crate2::MyStruct { Q: x }; - let mut V = dep::crate2::MyStruct {}; - let mut V = dep::crate2::MyStruct {/*test*/}; - let mut V = dep::crate2::MyStruct { + let mut V = crate2::MyStruct { Q: x }; + let mut V = crate2::MyStruct {}; + let mut V = crate2::MyStruct {/*test*/}; + let mut V = crate2::MyStruct { // sad }; } diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/print.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/print.nr index 3bce0941da26..d8404f674b07 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/print.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/print.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { std::print("Hello world"); std::println("Hello world"); diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/print2.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/print2.nr index 3bce0941da26..d8404f674b07 100644 --- a/noir/noir-repo/tooling/nargo_fmt/tests/input/print2.nr +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/print2.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main() { std::print("Hello world"); std::println("Hello world"); diff --git a/noir/noir-repo/tooling/nargo_fmt/tests/input/singleton_import.nr b/noir/noir-repo/tooling/nargo_fmt/tests/input/singleton_import.nr new file mode 100644 index 000000000000..bb1bad500d9a --- /dev/null +++ b/noir/noir-repo/tooling/nargo_fmt/tests/input/singleton_import.nr @@ -0,0 +1,2 @@ +use dep::std; +use some_crate; diff --git a/noir/noir-repo/tooling/noir_codegen/package.json b/noir/noir-repo/tooling/noir_codegen/package.json index 5d3a7d6315e5..eb9694a3b0c5 100644 --- a/noir/noir-repo/tooling/noir_codegen/package.json +++ b/noir/noir-repo/tooling/noir_codegen/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.30.0", + "version": "0.31.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js/package.json b/noir/noir-repo/tooling/noir_js/package.json index eca3f29957fa..3bb2ab5826f8 100644 --- a/noir/noir-repo/tooling/noir_js/package.json +++ b/noir/noir-repo/tooling/noir_js/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.30.0", + "version": "0.31.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr index a9aaae5f2f70..5a20a92048fc 100644 --- a/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr +++ b/noir/noir-repo/tooling/noir_js/test/noir_compiled_examples/assert_lt/src/main.nr @@ -1,5 +1,3 @@ -use dep::std; - fn main(x: u64, y: pub u64) -> pub u64 { // We include a println statement to show that noirJS will ignore this and continue execution std::println("foo"); diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json index 35fbd6f438bf..3ce97f89ec2c 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.30.0", + "version": "0.31.0", "packageManager": "yarn@3.5.1", "license": "(MIT OR Apache-2.0)", "type": "module", diff --git a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts index ce2c27124912..96c4d13aa613 100644 --- a/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts +++ b/noir/noir-repo/tooling/noir_js_backend_barretenberg/src/backend.ts @@ -45,9 +45,10 @@ export class BarretenbergVerifierBackend implements VerifierBackend { const { Barretenberg, RawBuffer, Crs } = await import('@aztec/bb.js'); const api = await Barretenberg.new(this.options); + const honkRecursion = false; const [_exact, _total, subgroupSize] = await api.acirGetCircuitSizes( this.acirUncompressedBytecode, - /*honkRecursion=*/ false, // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): Remove this flag + honkRecursion, ); const crs = await Crs.new(subgroupSize + 1); await api.commonInitSlabAllocator(subgroupSize); diff --git a/noir/noir-repo/tooling/noir_js_types/package.json b/noir/noir-repo/tooling/noir_js_types/package.json index b2b84b640a57..0de1a1fd4be8 100644 --- a/noir/noir-repo/tooling/noir_js_types/package.json +++ b/noir/noir-repo/tooling/noir_js_types/package.json @@ -4,7 +4,7 @@ "The Noir Team " ], "packageManager": "yarn@3.5.1", - "version": "0.30.0", + "version": "0.31.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/tooling/noirc_abi/Cargo.toml b/noir/noir-repo/tooling/noirc_abi/Cargo.toml index baae2dfa35e6..4c0c1f75e420 100644 --- a/noir/noir-repo/tooling/noirc_abi/Cargo.toml +++ b/noir/noir-repo/tooling/noirc_abi/Cargo.toml @@ -11,7 +11,6 @@ license.workspace = true [dependencies] acvm.workspace = true iter-extended.workspace = true -noirc_frontend.workspace = true noirc_printable_type.workspace = true toml.workspace = true serde_json = "1.0" @@ -23,13 +22,9 @@ num-traits = "0.2" [dev-dependencies] strum = "0.24" strum_macros = "0.24" +proptest.workspace = true +proptest-derive.workspace = true [features] -bn254 = [ - "acvm/bn254", - "noirc_frontend/bn254", -] -bls12_381 = [ - "acvm/bls12_381", - "noirc_frontend/bls12_381", -] \ No newline at end of file +bn254 = ["acvm/bn254"] +bls12_381 = ["acvm/bls12_381"] diff --git a/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs b/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs new file mode 100644 index 000000000000..aecb620b79d0 --- /dev/null +++ b/noir/noir-repo/tooling/noirc_abi/src/arbitrary.rs @@ -0,0 +1,154 @@ +use iter_extended::{btree_map, vecmap}; +use prop::collection::vec; +use proptest::prelude::*; + +use acvm::{AcirField, FieldElement}; + +use crate::{ + input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, InputMap, + Sign, +}; +use std::collections::{BTreeMap, HashSet}; + +pub(super) use proptest_derive::Arbitrary; + +/// Mutates an iterator of mutable references to [`String`]s to ensure that all values are unique. +fn ensure_unique_strings<'a>(iter: impl Iterator) { + let mut seen_values: HashSet = HashSet::default(); + for value in iter { + while seen_values.contains(value.as_str()) { + value.push('1'); + } + seen_values.insert(value.clone()); + } +} + +proptest::prop_compose! { + pub(super) fn arb_field_from_integer(bit_size: u32)(value: u128)-> FieldElement { + let width = (bit_size % 128).clamp(1, 127); + let max_value = 2u128.pow(width) - 1; + FieldElement::from(value.clamp(0, max_value)) + } +} + +fn arb_value_from_abi_type(abi_type: &AbiType) -> SBoxedStrategy { + match abi_type { + AbiType::Field => vec(any::(), 32) + .prop_map(|bytes| InputValue::Field(FieldElement::from_be_bytes_reduce(&bytes))) + .sboxed(), + AbiType::Integer { width, .. } => { + arb_field_from_integer(*width).prop_map(InputValue::Field).sboxed() + } + + AbiType::Boolean => { + any::().prop_map(|val| InputValue::Field(FieldElement::from(val))).sboxed() + } + + AbiType::String { length } => { + // Strings only allow ASCII characters as each character must be able to be represented by a single byte. + let string_regex = format!("[[:ascii:]]{{{length}}}"); + proptest::string::string_regex(&string_regex) + .expect("parsing of regex should always succeed") + .prop_map(InputValue::String) + .sboxed() + } + AbiType::Array { length, typ } => { + let length = *length as usize; + let elements = vec(arb_value_from_abi_type(typ), length..=length); + + elements.prop_map(InputValue::Vec).sboxed() + } + + AbiType::Struct { fields, .. } => { + let fields: Vec> = fields + .iter() + .map(|(name, typ)| (Just(name.clone()), arb_value_from_abi_type(typ)).sboxed()) + .collect(); + + fields + .prop_map(|fields| { + let fields: BTreeMap<_, _> = fields.into_iter().collect(); + InputValue::Struct(fields) + }) + .sboxed() + } + + AbiType::Tuple { fields } => { + let fields: Vec<_> = fields.iter().map(arb_value_from_abi_type).collect(); + fields.prop_map(InputValue::Vec).sboxed() + } + } +} + +fn arb_primitive_abi_type() -> SBoxedStrategy { + const MAX_STRING_LEN: u32 = 1000; + proptest::prop_oneof![ + Just(AbiType::Field), + Just(AbiType::Boolean), + any::<(Sign, u32)>().prop_map(|(sign, width)| { + let width = (width % 128).clamp(1, 127); + AbiType::Integer { sign, width } + }), + // restrict length of strings to avoid running out of memory + (1..MAX_STRING_LEN).prop_map(|length| AbiType::String { length }), + ] + .sboxed() +} + +pub(super) fn arb_abi_type() -> BoxedStrategy { + let leaf = arb_primitive_abi_type(); + + leaf.prop_recursive( + 8, // up to 8 levels deep + 256, // Shoot for maximum size of 256 nodes + 10, // We put up to 10 items per collection + |inner| { + prop_oneof![ + (1..10u32, inner.clone()) + .prop_map(|(length, typ)| { AbiType::Array { length, typ: Box::new(typ) } }) + .boxed(), + prop::collection::vec(inner.clone(), 1..10) + .prop_map(|fields| { AbiType::Tuple { fields } }) + .boxed(), + (".*", prop::collection::vec((".+", inner), 1..10)) + .prop_map(|(path, mut fields)| { + // Require that all field names are unique. + ensure_unique_strings(fields.iter_mut().map(|(field_name, _)| field_name)); + AbiType::Struct { path, fields } + }) + .boxed(), + ] + }, + ) + .boxed() +} + +fn arb_abi_param_and_value() -> BoxedStrategy<(AbiParameter, InputValue)> { + arb_abi_type() + .prop_flat_map(|typ| { + let value = arb_value_from_abi_type(&typ); + let param = arb_abi_param(typ); + (param, value) + }) + .boxed() +} + +fn arb_abi_param(typ: AbiType) -> SBoxedStrategy { + (".+", any::()) + .prop_map(move |(name, visibility)| AbiParameter { name, typ: typ.clone(), visibility }) + .sboxed() +} + +prop_compose! { + pub(super) fn arb_abi_and_input_map() + (mut parameters_with_values in proptest::collection::vec(arb_abi_param_and_value(), 0..100), return_type: Option) + -> (Abi, InputMap) { + // Require that all parameter names are unique. + ensure_unique_strings(parameters_with_values.iter_mut().map(|(param_name,_)| &mut param_name.name)); + + let parameters = vecmap(¶meters_with_values, |(param, _)| param.clone()); + let input_map = btree_map(parameters_with_values, |(param, value)| (param.name, value)); + + (Abi { parameters, return_type, error_types: BTreeMap::default() }, input_map) + } +} diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index 86c982b5b0d2..c3e1ade04fad 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -13,8 +13,6 @@ use acvm::{ use errors::AbiError; use input_parser::InputValue; use iter_extended::{try_btree_map, try_vecmap, vecmap}; -use noirc_frontend::ast::{Signedness, Visibility}; -use noirc_frontend::{hir::Context, Type, TypeBinding, TypeVariableKind}; use noirc_printable_type::{ decode_value as printable_type_decode_value, PrintableType, PrintableValue, PrintableValueDisplay, @@ -27,6 +25,9 @@ use std::{collections::BTreeMap, str}; // // This ABI has nothing to do with ACVM or ACIR. Although they implicitly have a relationship +#[cfg(test)] +mod arbitrary; + pub mod errors; pub mod input_parser; mod serialization; @@ -77,6 +78,7 @@ pub enum AbiType { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] #[serde(rename_all = "lowercase")] /// Represents whether the parameter is public or known only to the prover. pub enum AbiVisibility { @@ -87,27 +89,8 @@ pub enum AbiVisibility { DataBus, } -impl From for AbiVisibility { - fn from(value: Visibility) -> Self { - match value { - Visibility::Public => AbiVisibility::Public, - Visibility::Private => AbiVisibility::Private, - Visibility::DataBus => AbiVisibility::DataBus, - } - } -} - -impl From<&Visibility> for AbiVisibility { - fn from(value: &Visibility) -> Self { - match value { - Visibility::Public => AbiVisibility::Public, - Visibility::Private => AbiVisibility::Private, - Visibility::DataBus => AbiVisibility::DataBus, - } - } -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] #[serde(rename_all = "lowercase")] pub enum Sign { Unsigned, @@ -115,70 +98,6 @@ pub enum Sign { } impl AbiType { - pub fn from_type(context: &Context, typ: &Type) -> Self { - // Note; use strict_eq instead of partial_eq when comparing field types - // in this method, you most likely want to distinguish between public and private - match typ { - Type::FieldElement => Self::Field, - Type::Array(size, typ) => { - let length = size - .evaluate_to_u32() - .expect("Cannot have variable sized arrays as a parameter to main"); - let typ = typ.as_ref(); - Self::Array { length, typ: Box::new(Self::from_type(context, typ)) } - } - Type::Integer(sign, bit_width) => { - let sign = match sign { - Signedness::Unsigned => Sign::Unsigned, - Signedness::Signed => Sign::Signed, - }; - - Self::Integer { sign, width: (*bit_width).into() } - } - Type::TypeVariable(binding, TypeVariableKind::IntegerOrField) - | Type::TypeVariable(binding, TypeVariableKind::Integer) => match &*binding.borrow() { - TypeBinding::Bound(typ) => Self::from_type(context, typ), - TypeBinding::Unbound(_) => { - Self::from_type(context, &Type::default_int_or_field_type()) - } - }, - Type::Bool => Self::Boolean, - Type::String(size) => { - let size = size - .evaluate_to_u32() - .expect("Cannot have variable sized strings as a parameter to main"); - Self::String { length: size } - } - - Type::Struct(def, args) => { - let struct_type = def.borrow(); - let fields = struct_type.get_fields(args); - let fields = vecmap(fields, |(name, typ)| (name, Self::from_type(context, &typ))); - // For the ABI, we always want to resolve the struct paths from the root crate - let path = - context.fully_qualified_struct_path(context.root_crate_id(), struct_type.id); - Self::Struct { fields, path } - } - Type::Alias(def, args) => Self::from_type(context, &def.borrow().get_type(args)), - Type::Tuple(fields) => { - let fields = vecmap(fields, |typ| Self::from_type(context, typ)); - Self::Tuple { fields } - } - Type::Error - | Type::Unit - | Type::Constant(_) - | Type::TraitAsType(..) - | Type::TypeVariable(_, _) - | Type::NamedGeneric(..) - | Type::Forall(..) - | Type::Code - | Type::Slice(_) - | Type::Function(_, _, _) => unreachable!("{typ} cannot be used in the abi"), - Type::FmtString(_, _) => unreachable!("format strings cannot be used in the abi"), - Type::MutableReference(_) => unreachable!("&mut cannot be used in the abi"), - } - } - /// Returns the number of field elements required to represent the type once encoded. pub fn field_count(&self) -> u32 { match self { @@ -228,10 +147,12 @@ impl From<&AbiType> for PrintableType { } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] /// An argument or return value of the circuit's `main` function. pub struct AbiParameter { pub name: String, #[serde(rename = "type")] + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] pub typ: AbiType, pub visibility: AbiVisibility, } @@ -243,16 +164,20 @@ impl AbiParameter { } #[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] pub struct AbiReturnType { + #[cfg_attr(test, proptest(strategy = "arbitrary::arb_abi_type()"))] pub abi_type: AbiType, pub visibility: AbiVisibility, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] +#[cfg_attr(test, derive(arbitrary::Arbitrary))] pub struct Abi { /// An ordered list of the arguments to the program's `main` function, specifying their types and visibility. pub parameters: Vec, pub return_type: Option, + #[cfg_attr(test, proptest(strategy = "proptest::prelude::Just(BTreeMap::from([]))"))] pub error_types: BTreeMap, } @@ -543,22 +468,6 @@ pub enum AbiErrorType { FmtString { length: u32, item_types: Vec }, Custom(AbiType), } -impl AbiErrorType { - pub fn from_type(context: &Context, typ: &Type) -> Self { - match typ { - Type::FmtString(len, item_types) => { - let length = len.evaluate_to_u32().expect("Cannot evaluate fmt length"); - let Type::Tuple(item_types) = item_types.as_ref() else { - unreachable!("FmtString items must be a tuple") - }; - let item_types = - item_types.iter().map(|typ| AbiType::from_type(context, typ)).collect(); - Self::FmtString { length, item_types } - } - _ => Self::Custom(AbiType::from_type(context, typ)), - } - } -} pub fn display_abi_error( fields: &[F], @@ -590,56 +499,18 @@ pub fn display_abi_error( #[cfg(test)] mod test { - use std::collections::BTreeMap; + use proptest::prelude::*; - use acvm::{AcirField, FieldElement}; + use crate::arbitrary::arb_abi_and_input_map; - use crate::{ - input_parser::InputValue, Abi, AbiParameter, AbiReturnType, AbiType, AbiVisibility, - InputMap, - }; + proptest! { + #[test] + fn encoding_and_decoding_returns_original_witness_map((abi, input_map) in arb_abi_and_input_map()) { + let witness_map = abi.encode(&input_map, None).unwrap(); + let (decoded_inputs, return_value) = abi.decode(&witness_map).unwrap(); - #[test] - fn witness_encoding_roundtrip() { - let abi = Abi { - parameters: vec![ - AbiParameter { - name: "thing1".to_string(), - typ: AbiType::Array { length: 2, typ: Box::new(AbiType::Field) }, - visibility: AbiVisibility::Public, - }, - AbiParameter { - name: "thing2".to_string(), - typ: AbiType::Field, - visibility: AbiVisibility::Public, - }, - ], - return_type: Some(AbiReturnType { - abi_type: AbiType::Field, - visibility: AbiVisibility::Public, - }), - error_types: BTreeMap::default(), - }; - - // Note we omit return value from inputs - let inputs: InputMap = BTreeMap::from([ - ( - "thing1".to_string(), - InputValue::Vec(vec![ - InputValue::Field(FieldElement::one()), - InputValue::Field(FieldElement::one()), - ]), - ), - ("thing2".to_string(), InputValue::Field(FieldElement::zero())), - ]); - - let witness_map = abi.encode(&inputs, None).unwrap(); - let (reconstructed_inputs, return_value) = abi.decode(&witness_map).unwrap(); - - for (key, expected_value) in inputs { - assert_eq!(reconstructed_inputs[&key], expected_value); + prop_assert_eq!(decoded_inputs, input_map); + prop_assert_eq!(return_value, None); } - - assert!(return_value.is_none()); } } diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/package.json b/noir/noir-repo/tooling/noirc_abi_wasm/package.json index 399a333f157c..b33bb159fcd9 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/package.json +++ b/noir/noir-repo/tooling/noirc_abi_wasm/package.json @@ -3,7 +3,7 @@ "contributors": [ "The Noir Team " ], - "version": "0.30.0", + "version": "0.31.0", "license": "(MIT OR Apache-2.0)", "homepage": "https://noir-lang.org/", "repository": { diff --git a/noir/noir-repo/tooling/noirc_artifacts/Cargo.toml b/noir/noir-repo/tooling/noirc_artifacts/Cargo.toml new file mode 100644 index 000000000000..4249604f9492 --- /dev/null +++ b/noir/noir-repo/tooling/noirc_artifacts/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "noirc_artifacts" +description = "Definitions of Nargo's build artifacts" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +acvm.workspace = true +fm.workspace = true +noirc_abi.workspace = true +noirc_driver.workspace = true +noirc_errors.workspace = true +noirc_printable_type.workspace = true +serde.workspace = true +codespan-reporting.workspace = true + + +[dev-dependencies] +tempfile.workspace = true diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/noirc_artifacts/src/contract.rs similarity index 100% rename from noir/noir-repo/tooling/nargo/src/artifacts/contract.rs rename to noir/noir-repo/tooling/noirc_artifacts/src/contract.rs diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs b/noir/noir-repo/tooling/noirc_artifacts/src/debug.rs similarity index 99% rename from noir/noir-repo/tooling/nargo/src/artifacts/debug.rs rename to noir/noir-repo/tooling/noirc_artifacts/src/debug.rs index 21102c40fcf8..11a3e1c4dd71 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs +++ b/noir/noir-repo/tooling/noirc_artifacts/src/debug.rs @@ -186,7 +186,7 @@ impl<'a> Files<'a> for DebugArtifact { #[cfg(test)] mod tests { - use crate::artifacts::debug::DebugArtifact; + use crate::debug::DebugArtifact; use acvm::acir::circuit::OpcodeLocation; use fm::FileManager; use noirc_errors::{debug_info::DebugInfo, Location, Span}; diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs b/noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs similarity index 100% rename from noir/noir-repo/tooling/nargo/src/artifacts/debug_vars.rs rename to noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/mod.rs b/noir/noir-repo/tooling/noirc_artifacts/src/lib.rs similarity index 73% rename from noir/noir-repo/tooling/nargo/src/artifacts/mod.rs rename to noir/noir-repo/tooling/noirc_artifacts/src/lib.rs index c7b3736f90bb..77873ed94098 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/mod.rs +++ b/noir/noir-repo/tooling/noirc_artifacts/src/lib.rs @@ -1,8 +1,14 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + //! This module defines the structure of Nargo's different compilation artifacts. //! //! These artifacts are intended to remain independent of any applications being built on top of Noir. //! Should any projects require/desire a different artifact format, it's expected that they will write a transformer //! to generate them using these artifacts as a starting point. + pub mod contract; pub mod debug; mod debug_vars; diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/noirc_artifacts/src/program.rs similarity index 100% rename from noir/noir-repo/tooling/nargo/src/artifacts/program.rs rename to noir/noir-repo/tooling/noirc_artifacts/src/program.rs diff --git a/noir/noir-repo/tooling/profiler/Cargo.toml b/noir/noir-repo/tooling/profiler/Cargo.toml index baebe9292e63..0ccd56b791f4 100644 --- a/noir/noir-repo/tooling/profiler/Cargo.toml +++ b/noir/noir-repo/tooling/profiler/Cargo.toml @@ -17,12 +17,11 @@ path = "src/main.rs" [dependencies] color-eyre.workspace = true clap.workspace = true -nargo.workspace = true +noirc_artifacts.workspace = true const_format.workspace = true serde.workspace = true serde_json.workspace = true fm.workspace = true -codespan-reporting.workspace = true inferno = "0.11.19" im.workspace = true acir.workspace = true diff --git a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs index 4f51eed4ba33..154ac38f4bba 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/gates_flamegraph_cmd.rs @@ -1,19 +1,13 @@ -use std::collections::BTreeMap; -use std::io::BufWriter; use std::path::{Path, PathBuf}; -use std::process::Command; use clap::Args; -use codespan_reporting::files::Files; use color_eyre::eyre::{self, Context}; -use inferno::flamegraph::{from_lines, Options}; -use nargo::artifacts::debug::DebugArtifact; -use serde::{Deserialize, Serialize}; -use acir::circuit::OpcodeLocation; -use nargo::artifacts::program::ProgramArtifact; -use nargo::errors::Location; -use noirc_errors::reporter::line_and_column_from_span; +use noirc_artifacts::debug::DebugArtifact; + +use crate::flamegraph::{FlamegraphGenerator, InfernoFlamegraphGenerator}; +use crate::fs::read_program_from_file; +use crate::gates_provider::{BackendGatesProvider, GatesProvider}; #[derive(Debug, Clone, Args)] pub(crate) struct GatesFlamegraphCommand { @@ -30,85 +24,11 @@ pub(crate) struct GatesFlamegraphCommand { output: String, } -trait GatesProvider { - fn get_gates(&self, artifact_path: &Path) -> eyre::Result; -} - -struct BackendGatesProvider { - backend_path: PathBuf, -} - -impl GatesProvider for BackendGatesProvider { - fn get_gates(&self, artifact_path: &Path) -> eyre::Result { - let backend_gates_response = - Command::new(&self.backend_path).arg("gates").arg("-b").arg(artifact_path).output()?; - - // Parse the backend gates command stdout as json - let backend_gates_response: BackendGatesResponse = - serde_json::from_slice(&backend_gates_response.stdout)?; - Ok(backend_gates_response) - } -} - -trait FlamegraphGenerator { - fn generate_flamegraph<'lines, I: IntoIterator>( - &self, - folded_lines: I, - artifact_name: &str, - function_name: &str, - output_path: &Path, - ) -> eyre::Result<()>; -} - -struct InfernoFlamegraphGenerator {} - -impl FlamegraphGenerator for InfernoFlamegraphGenerator { - fn generate_flamegraph<'lines, I: IntoIterator>( - &self, - folded_lines: I, - artifact_name: &str, - function_name: &str, - output_path: &Path, - ) -> eyre::Result<()> { - let flamegraph_file = std::fs::File::create(output_path)?; - let flamegraph_writer = BufWriter::new(flamegraph_file); - - let mut options = Options::default(); - options.hash = true; - options.deterministic = true; - options.title = format!("{}-{}", artifact_name, function_name); - options.subtitle = Some("Sample = Gate".to_string()); - options.frame_height = 24; - options.color_diffusion = true; - - from_lines(&mut options, folded_lines, flamegraph_writer)?; - - Ok(()) - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -struct BackendGatesReport { - acir_opcodes: usize, - circuit_size: usize, - gates_per_opcode: Vec, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -struct BackendGatesResponse { - functions: Vec, -} - -struct FoldedStackItem { - total_gates: usize, - nested_items: BTreeMap, -} - pub(crate) fn run(args: GatesFlamegraphCommand) -> eyre::Result<()> { run_with_provider( &PathBuf::from(args.artifact_path), &BackendGatesProvider { backend_path: PathBuf::from(args.backend_path) }, - &InfernoFlamegraphGenerator {}, + &InfernoFlamegraphGenerator { count_name: "gates".to_string() }, &PathBuf::from(args.output), ) } @@ -119,7 +39,7 @@ fn run_with_provider( flamegraph_generator: &Generator, output_path: &Path, ) -> eyre::Result<()> { - let program = + let mut program = read_program_from_file(artifact_path).context("Error reading program from file")?; let backend_gates_response = @@ -127,10 +47,16 @@ fn run_with_provider( let function_names = program.names.clone(); + let bytecode = std::mem::take(&mut program.bytecode); + let debug_artifact: DebugArtifact = program.into(); - for (func_idx, (func_gates, func_name)) in - backend_gates_response.functions.into_iter().zip(function_names).enumerate() + for (func_idx, ((func_gates, func_name), bytecode)) in backend_gates_response + .functions + .into_iter() + .zip(function_names) + .zip(bytecode.functions) + .enumerate() { println!( "Opcode count: {}, Total gates by opcodes: {}, Circuit size: {}", @@ -139,143 +65,33 @@ fn run_with_provider( func_gates.circuit_size ); - // Create a nested hashmap with the stack items, folding the gates for all the callsites that are equal - let mut folded_stack_items = BTreeMap::new(); - - func_gates.gates_per_opcode.into_iter().enumerate().for_each(|(opcode_index, gates)| { - let call_stack = &debug_artifact.debug_symbols[func_idx] - .locations - .get(&OpcodeLocation::Acir(opcode_index)); - let location_names = if let Some(call_stack) = call_stack { - call_stack - .iter() - .map(|location| location_to_callsite_label(*location, &debug_artifact)) - .collect::>() - } else { - vec!["unknown".to_string()] - }; - - add_locations_to_folded_stack_items(&mut folded_stack_items, location_names, gates); - }); - let folded_lines = to_folded_sorted_lines(&folded_stack_items, Default::default()); - flamegraph_generator.generate_flamegraph( - folded_lines.iter().map(|as_string| as_string.as_str()), + func_gates.gates_per_opcode, + bytecode.opcodes, + &debug_artifact.debug_symbols[func_idx], + &debug_artifact, artifact_path.to_str().unwrap(), &func_name, - &Path::new(&output_path).join(Path::new(&format!("{}.svg", &func_name))), + &Path::new(&output_path).join(Path::new(&format!("{}_gates.svg", &func_name))), )?; } Ok(()) } -pub(crate) fn read_program_from_file>( - circuit_path: P, -) -> eyre::Result { - let file_path = circuit_path.as_ref().with_extension("json"); - - let input_string = std::fs::read(file_path)?; - let program = serde_json::from_slice(&input_string)?; - - Ok(program) -} - -fn location_to_callsite_label<'files>( - location: Location, - files: &'files impl Files<'files, FileId = fm::FileId>, -) -> String { - let filename = - Path::new(&files.name(location.file).expect("should have a file path").to_string()) - .file_name() - .map(|os_str| os_str.to_string_lossy().to_string()) - .unwrap_or("invalid_path".to_string()); - let source = files.source(location.file).expect("should have a file source"); - - let code_slice = source - .as_ref() - .chars() - .skip(location.span.start() as usize) - .take(location.span.end() as usize - location.span.start() as usize) - .collect::(); - - // ";" is used for frame separation, and is not allowed by inferno - // Check code slice for ";" and replace it with 'GREEK QUESTION MARK' (U+037E) - let code_slice = code_slice.replace(';', "\u{037E}"); - - let (line, column) = line_and_column_from_span(source.as_ref(), &location.span); - - format!("{}:{}:{}::{}", filename, line, column, code_slice) -} - -fn add_locations_to_folded_stack_items( - stack_items: &mut BTreeMap, - locations: Vec, - gates: usize, -) { - let mut child_map = stack_items; - for (index, location) in locations.iter().enumerate() { - let current_item = child_map - .entry(location.clone()) - .or_insert(FoldedStackItem { total_gates: 0, nested_items: BTreeMap::new() }); - - child_map = &mut current_item.nested_items; - - if index == locations.len() - 1 { - current_item.total_gates += gates; - } - } -} - -/// Creates a vector of lines in the format that inferno expects from a nested hashmap of stack items -/// The lines have to be sorted in the following way, exploring the graph in a depth-first manner: -/// main 100 -/// main::foo 0 -/// main::foo::bar 200 -/// main::baz 27 -/// main::baz::qux 800 -fn to_folded_sorted_lines( - folded_stack_items: &BTreeMap, - parent_stacks: im::Vector, -) -> Vec { - folded_stack_items - .iter() - .flat_map(move |(location, folded_stack_item)| { - let frame_list: Vec = - parent_stacks.iter().cloned().chain(std::iter::once(location.clone())).collect(); - let line: String = - format!("{} {}", frame_list.join(";"), folded_stack_item.total_gates); - - let mut new_parent_stacks = parent_stacks.clone(); - new_parent_stacks.push_back(location.clone()); - - let child_lines: Vec = - to_folded_sorted_lines(&folded_stack_item.nested_items, new_parent_stacks); - - std::iter::once(line).chain(child_lines) - }) - .collect() -} - #[cfg(test)] mod tests { - use acir::circuit::{OpcodeLocation, Program}; + use acir::circuit::{Circuit, Opcode, Program}; use color_eyre::eyre::{self}; - use fm::{FileId, FileManager}; - use nargo::artifacts::program::ProgramArtifact; - use noirc_driver::DebugFile; - use noirc_errors::{ - debug_info::{DebugInfo, ProgramDebugInfo}, - Location, Span, - }; + use fm::codespan_files::Files; + use noirc_artifacts::program::ProgramArtifact; + use noirc_errors::debug_info::{DebugInfo, ProgramDebugInfo}; use std::{ - cell::RefCell, collections::{BTreeMap, HashMap}, path::{Path, PathBuf}, }; - use tempfile::TempDir; - use super::{BackendGatesReport, BackendGatesResponse, GatesProvider}; + use crate::gates_provider::{BackendGatesReport, BackendGatesResponse, GatesProvider}; struct TestGateProvider { mock_responses: HashMap, @@ -293,194 +109,63 @@ mod tests { } #[derive(Default)] - struct TestFlamegraphGenerator { - lines_received: RefCell>>, - } + struct TestFlamegraphGenerator {} impl super::FlamegraphGenerator for TestFlamegraphGenerator { - fn generate_flamegraph<'lines, I: IntoIterator>( + fn generate_flamegraph<'files, F>( &self, - folded_lines: I, + _samples_per_opcode: Vec, + _opcodes: Vec>, + _debug_symbols: &DebugInfo, + _files: &'files impl Files<'files, FileId = fm::FileId>, _artifact_name: &str, _function_name: &str, - _output_path: &std::path::Path, + output_path: &Path, ) -> eyre::Result<()> { - let lines = folded_lines.into_iter().map(|line| line.to_string()).collect(); - self.lines_received.borrow_mut().push(lines); - Ok(()) - } - } + let output_file = std::fs::File::create(output_path).unwrap(); + std::io::Write::write_all(&mut std::io::BufWriter::new(output_file), b"success") + .unwrap(); - fn find_spans_for(source: &str, needle: &str) -> Vec { - let mut spans = Vec::new(); - let mut start = 0; - while let Some(start_idx) = source[start..].find(needle) { - let start_idx = start + start_idx; - let end_idx = start_idx + needle.len(); - spans.push(Span::inclusive(start_idx as u32, end_idx as u32 - 1)); - start = end_idx; + Ok(()) } - spans } - struct TestCase { - expected_folded_sorted_lines: Vec>, - debug_symbols: ProgramDebugInfo, - file_map: BTreeMap, - gates_report: BackendGatesResponse, - } + #[test] + fn smoke_test() { + let temp_dir = tempfile::tempdir().unwrap(); - fn simple_test_case(temp_dir: &TempDir) -> TestCase { - let source_code = r##" - fn main() { - foo(); - bar(); - whatever(); - } - fn foo() { - baz(); - } - fn bar () { - whatever() - } - fn baz () { - whatever() - } - "##; + let artifact_path = temp_dir.path().join("test.json"); - let source_file_name = Path::new("main.nr"); - let mut fm = FileManager::new(temp_dir.path()); - let file_id = fm.add_file_with_source(source_file_name, source_code.to_string()).unwrap(); + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, + file_map: BTreeMap::default(), + names: vec!["main".to_string()], + }; - let main_declaration_location = - Location::new(find_spans_for(source_code, "fn main()")[0], file_id); - let main_foo_call_location = - Location::new(find_spans_for(source_code, "foo()")[0], file_id); - let main_bar_call_location = - Location::new(find_spans_for(source_code, "bar()")[0], file_id); - let main_whatever_call_location = - Location::new(find_spans_for(source_code, "whatever()")[0], file_id); - let foo_baz_call_location = Location::new(find_spans_for(source_code, "baz()")[0], file_id); - let bar_whatever_call_location = - Location::new(find_spans_for(source_code, "whatever()")[1], file_id); - let baz_whatever_call_location = - Location::new(find_spans_for(source_code, "whatever()")[2], file_id); + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); - let mut opcode_locations = BTreeMap::>::new(); - // main::foo::baz::whatever - opcode_locations.insert( - OpcodeLocation::Acir(0), - vec![ - main_declaration_location, - main_foo_call_location, - foo_baz_call_location, - baz_whatever_call_location, + let mock_gates_response = BackendGatesResponse { + functions: vec![ + (BackendGatesReport { acir_opcodes: 0, gates_per_opcode: vec![], circuit_size: 0 }), ], - ); - - // main::bar::whatever - opcode_locations.insert( - OpcodeLocation::Acir(1), - vec![main_declaration_location, main_bar_call_location, bar_whatever_call_location], - ); - // main::whatever - opcode_locations.insert( - OpcodeLocation::Acir(2), - vec![main_declaration_location, main_whatever_call_location], - ); - - let file_map = BTreeMap::from_iter(vec![( - file_id, - DebugFile { source: source_code.to_string(), path: source_file_name.to_path_buf() }, - )]); - - let debug_symbols = ProgramDebugInfo { - debug_infos: vec![DebugInfo::new( - opcode_locations, - BTreeMap::default(), - BTreeMap::default(), - BTreeMap::default(), - )], }; - let backend_gates_response = BackendGatesResponse { - functions: vec![BackendGatesReport { - acir_opcodes: 3, - circuit_size: 100, - gates_per_opcode: vec![10, 20, 30], - }], + let provider = TestGateProvider { + mock_responses: HashMap::from([(artifact_path.clone(), mock_gates_response)]), }; + let flamegraph_generator = TestFlamegraphGenerator::default(); - let expected_folded_sorted_lines = vec![ - "main.nr:2:9::fn main() 0".to_string(), - "main.nr:2:9::fn main();main.nr:3:13::foo() 0".to_string(), - "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz() 0".to_string(), - "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz();main.nr:14:13::whatever() 10".to_string(), - "main.nr:2:9::fn main();main.nr:4:13::bar() 0".to_string(), - "main.nr:2:9::fn main();main.nr:4:13::bar();main.nr:11:13::whatever() 20".to_string(), - "main.nr:2:9::fn main();main.nr:5:13::whatever() 30".to_string(), - ]; - - TestCase { - expected_folded_sorted_lines: vec![expected_folded_sorted_lines], - debug_symbols, - file_map, - gates_report: backend_gates_response, - } - } - - #[test] - fn test_flamegraph() { - let temp_dir = tempfile::tempdir().unwrap(); - - let test_cases = vec![simple_test_case(&temp_dir)]; - let artifact_names: Vec<_> = - test_cases.iter().enumerate().map(|(idx, _)| format!("test{}.json", idx)).collect(); - - let test_cases_with_names: Vec<_> = test_cases.into_iter().zip(artifact_names).collect(); - - let mut mock_responses: HashMap = HashMap::new(); - // Collect mock responses - for (test_case, artifact_name) in test_cases_with_names.iter() { - mock_responses.insert( - temp_dir.path().join(artifact_name.clone()), - test_case.gates_report.clone(), - ); - } - - let provider = TestGateProvider { mock_responses }; - - for (test_case, artifact_name) in test_cases_with_names.iter() { - let artifact_path = temp_dir.path().join(artifact_name.clone()); - - let artifact = ProgramArtifact { - noir_version: "0.0.0".to_string(), - hash: 27, - abi: noirc_abi::Abi::default(), - bytecode: Program::default(), - debug_symbols: test_case.debug_symbols.clone(), - file_map: test_case.file_map.clone(), - names: vec!["main".to_string()], - }; - - // Write the artifact to a file - let artifact_file = std::fs::File::create(&artifact_path).unwrap(); - serde_json::to_writer(artifact_file, &artifact).unwrap(); - - let flamegraph_generator = TestFlamegraphGenerator::default(); - - super::run_with_provider( - &artifact_path, - &provider, - &flamegraph_generator, - temp_dir.path(), - ) + super::run_with_provider(&artifact_path, &provider, &flamegraph_generator, temp_dir.path()) .expect("should run without errors"); - // Check that the flamegraph generator was called with the correct folded sorted lines - let calls_received = flamegraph_generator.lines_received.borrow().clone(); - - assert_eq!(calls_received, test_case.expected_folded_sorted_lines); - } + // Check that the output file was written to + let output_file = temp_dir.path().join("main_gates.svg"); + assert!(output_file.exists()); } } diff --git a/noir/noir-repo/tooling/profiler/src/cli/mod.rs b/noir/noir-repo/tooling/profiler/src/cli/mod.rs index d54a3f6167c8..4c2503fbe4fb 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/mod.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/mod.rs @@ -3,6 +3,7 @@ use color_eyre::eyre; use const_format::formatcp; mod gates_flamegraph_cmd; +mod opcodes_flamegraph_cmd; const PROFILER_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -12,20 +13,22 @@ static VERSION_STRING: &str = formatcp!("version = {}\n", PROFILER_VERSION,); #[command(name="Noir profiler", author, version=VERSION_STRING, about, long_about = None)] struct ProfilerCli { #[command(subcommand)] - command: GatesFlamegraphCommand, + command: ProfilerCommand, } #[non_exhaustive] #[derive(Subcommand, Clone, Debug)] -enum GatesFlamegraphCommand { +enum ProfilerCommand { GatesFlamegraph(gates_flamegraph_cmd::GatesFlamegraphCommand), + OpcodesFlamegraph(opcodes_flamegraph_cmd::OpcodesFlamegraphCommand), } pub(crate) fn start_cli() -> eyre::Result<()> { let ProfilerCli { command } = ProfilerCli::parse(); match command { - GatesFlamegraphCommand::GatesFlamegraph(args) => gates_flamegraph_cmd::run(args), + ProfilerCommand::GatesFlamegraph(args) => gates_flamegraph_cmd::run(args), + ProfilerCommand::OpcodesFlamegraph(args) => opcodes_flamegraph_cmd::run(args), } .map_err(|err| eyre::eyre!("{}", err))?; diff --git a/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs new file mode 100644 index 000000000000..e1dc1464f6fd --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/cli/opcodes_flamegraph_cmd.rs @@ -0,0 +1,123 @@ +use std::path::{Path, PathBuf}; + +use clap::Args; +use color_eyre::eyre::{self, Context}; + +use noirc_artifacts::debug::DebugArtifact; + +use crate::flamegraph::{FlamegraphGenerator, InfernoFlamegraphGenerator}; +use crate::fs::read_program_from_file; + +#[derive(Debug, Clone, Args)] +pub(crate) struct OpcodesFlamegraphCommand { + /// The path to the artifact JSON file + #[clap(long, short)] + artifact_path: String, + + /// The output folder for the flamegraph svg files + #[clap(long, short)] + output: String, +} + +pub(crate) fn run(args: OpcodesFlamegraphCommand) -> eyre::Result<()> { + run_with_generator( + &PathBuf::from(args.artifact_path), + &InfernoFlamegraphGenerator { count_name: "opcodes".to_string() }, + &PathBuf::from(args.output), + ) +} + +fn run_with_generator( + artifact_path: &Path, + flamegraph_generator: &Generator, + output_path: &Path, +) -> eyre::Result<()> { + let mut program = + read_program_from_file(artifact_path).context("Error reading program from file")?; + + let function_names = program.names.clone(); + + let bytecode = std::mem::take(&mut program.bytecode); + + let debug_artifact: DebugArtifact = program.into(); + + for (func_idx, (func_name, bytecode)) in + function_names.into_iter().zip(bytecode.functions).enumerate() + { + println!("Opcode count: {}", bytecode.opcodes.len()); + + flamegraph_generator.generate_flamegraph( + bytecode.opcodes.iter().map(|_op| 1).collect(), + bytecode.opcodes, + &debug_artifact.debug_symbols[func_idx], + &debug_artifact, + artifact_path.to_str().unwrap(), + &func_name, + &Path::new(&output_path).join(Path::new(&format!("{}_opcodes.svg", &func_name))), + )?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use acir::circuit::{Circuit, Opcode, Program}; + use color_eyre::eyre::{self}; + use fm::codespan_files::Files; + use noirc_artifacts::program::ProgramArtifact; + use noirc_errors::debug_info::{DebugInfo, ProgramDebugInfo}; + use std::{collections::BTreeMap, path::Path}; + + #[derive(Default)] + struct TestFlamegraphGenerator {} + + impl super::FlamegraphGenerator for TestFlamegraphGenerator { + fn generate_flamegraph<'files, F>( + &self, + _samples_per_opcode: Vec, + _opcodes: Vec>, + _debug_symbols: &DebugInfo, + _files: &'files impl Files<'files, FileId = fm::FileId>, + _artifact_name: &str, + _function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let output_file = std::fs::File::create(output_path).unwrap(); + std::io::Write::write_all(&mut std::io::BufWriter::new(output_file), b"success") + .unwrap(); + + Ok(()) + } + } + + #[test] + fn smoke_test() { + let temp_dir = tempfile::tempdir().unwrap(); + + let artifact_path = temp_dir.path().join("test.json"); + + let artifact = ProgramArtifact { + noir_version: "0.0.0".to_string(), + hash: 27, + abi: noirc_abi::Abi::default(), + bytecode: Program { functions: vec![Circuit::default()], ..Program::default() }, + debug_symbols: ProgramDebugInfo { debug_infos: vec![DebugInfo::default()] }, + file_map: BTreeMap::default(), + names: vec!["main".to_string()], + }; + + // Write the artifact to a file + let artifact_file = std::fs::File::create(&artifact_path).unwrap(); + serde_json::to_writer(artifact_file, &artifact).unwrap(); + + let flamegraph_generator = TestFlamegraphGenerator::default(); + + super::run_with_generator(&artifact_path, &flamegraph_generator, temp_dir.path()) + .expect("should run without errors"); + + // Check that the output file was written to + let output_file = temp_dir.path().join("main_opcodes.svg"); + assert!(output_file.exists()); + } +} diff --git a/noir/noir-repo/tooling/profiler/src/flamegraph.rs b/noir/noir-repo/tooling/profiler/src/flamegraph.rs new file mode 100644 index 000000000000..70de6e743b28 --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/flamegraph.rs @@ -0,0 +1,300 @@ +use std::path::Path; +use std::{collections::BTreeMap, io::BufWriter}; + +use acir::circuit::{Opcode, OpcodeLocation}; +use color_eyre::eyre::{self}; +use fm::codespan_files::Files; +use inferno::flamegraph::{from_lines, Options}; +use noirc_errors::debug_info::DebugInfo; +use noirc_errors::reporter::line_and_column_from_span; +use noirc_errors::Location; + +use super::opcode_formatter::format_opcode; + +#[derive(Debug, Default)] +pub(crate) struct FoldedStackItem { + pub(crate) total_samples: usize, + pub(crate) nested_items: BTreeMap, +} + +pub(crate) trait FlamegraphGenerator { + #[allow(clippy::too_many_arguments)] + fn generate_flamegraph<'files, F>( + &self, + samples_per_opcode: Vec, + opcodes: Vec>, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()>; +} + +pub(crate) struct InfernoFlamegraphGenerator { + pub(crate) count_name: String, +} + +impl FlamegraphGenerator for InfernoFlamegraphGenerator { + fn generate_flamegraph<'files, F>( + &self, + samples_per_opcode: Vec, + opcodes: Vec>, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, + artifact_name: &str, + function_name: &str, + output_path: &Path, + ) -> eyre::Result<()> { + let folded_lines = + generate_folded_sorted_lines(samples_per_opcode, opcodes, debug_symbols, files); + + let flamegraph_file = std::fs::File::create(output_path)?; + let flamegraph_writer = BufWriter::new(flamegraph_file); + + let mut options = Options::default(); + options.hash = true; + options.deterministic = true; + options.title = format!("{}-{}", artifact_name, function_name); + options.frame_height = 24; + options.color_diffusion = true; + options.min_width = 0.0; + options.count_name = self.count_name.clone(); + + from_lines( + &mut options, + folded_lines.iter().map(|as_string| as_string.as_str()), + flamegraph_writer, + )?; + + Ok(()) + } +} + +fn generate_folded_sorted_lines<'files, F>( + samples_per_opcode: Vec, + opcodes: Vec>, + debug_symbols: &DebugInfo, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> Vec { + // Create a nested hashmap with the stack items, folding the gates for all the callsites that are equal + let mut folded_stack_items = BTreeMap::new(); + + samples_per_opcode.into_iter().enumerate().for_each(|(opcode_index, gates)| { + let call_stack = debug_symbols.locations.get(&OpcodeLocation::Acir(opcode_index)); + let location_names = if let Some(call_stack) = call_stack { + call_stack + .iter() + .map(|location| location_to_callsite_label(*location, files)) + .chain(std::iter::once(format_opcode(&opcodes[opcode_index]))) + .collect::>() + } else { + vec!["unknown".to_string()] + }; + + add_locations_to_folded_stack_items(&mut folded_stack_items, location_names, gates); + }); + + to_folded_sorted_lines(&folded_stack_items, Default::default()) +} + +fn location_to_callsite_label<'files>( + location: Location, + files: &'files impl Files<'files, FileId = fm::FileId>, +) -> String { + let filename = + Path::new(&files.name(location.file).expect("should have a file path").to_string()) + .file_name() + .map(|os_str| os_str.to_string_lossy().to_string()) + .unwrap_or("invalid_path".to_string()); + let source = files.source(location.file).expect("should have a file source"); + + let code_slice = source + .as_ref() + .chars() + .skip(location.span.start() as usize) + .take(location.span.end() as usize - location.span.start() as usize) + .collect::(); + + // ";" is used for frame separation, and is not allowed by inferno + // Check code slice for ";" and replace it with 'GREEK QUESTION MARK' (U+037E) + let code_slice = code_slice.replace(';', "\u{037E}"); + + let (line, column) = line_and_column_from_span(source.as_ref(), &location.span); + + format!("{}:{}:{}::{}", filename, line, column, code_slice) +} + +fn add_locations_to_folded_stack_items( + stack_items: &mut BTreeMap, + locations: Vec, + gates: usize, +) { + let mut child_map = stack_items; + for (index, location) in locations.iter().enumerate() { + let current_item = child_map.entry(location.clone()).or_default(); + + child_map = &mut current_item.nested_items; + + if index == locations.len() - 1 { + current_item.total_samples += gates; + } + } +} + +/// Creates a vector of lines in the format that inferno expects from a nested hashmap of stack items +/// The lines have to be sorted in the following way, exploring the graph in a depth-first manner: +/// main 100 +/// main::foo 0 +/// main::foo::bar 200 +/// main::baz 27 +/// main::baz::qux 800 +fn to_folded_sorted_lines( + folded_stack_items: &BTreeMap, + parent_stacks: im::Vector, +) -> Vec { + let mut result_vector = Vec::with_capacity(folded_stack_items.len()); + + for (location, folded_stack_item) in folded_stack_items.iter() { + if folded_stack_item.total_samples > 0 { + let frame_list: Vec = + parent_stacks.iter().cloned().chain(std::iter::once(location.clone())).collect(); + let line: String = + format!("{} {}", frame_list.join(";"), folded_stack_item.total_samples); + + result_vector.push(line); + }; + + let mut new_parent_stacks = parent_stacks.clone(); + new_parent_stacks.push_back(location.clone()); + let child_lines = + to_folded_sorted_lines(&folded_stack_item.nested_items, new_parent_stacks); + + result_vector.extend(child_lines); + } + + result_vector +} + +#[cfg(test)] +mod tests { + use acir::{ + circuit::{opcodes::BlockId, Opcode, OpcodeLocation}, + native_types::Expression, + FieldElement, + }; + use fm::FileManager; + use noirc_errors::{debug_info::DebugInfo, Location, Span}; + use std::{collections::BTreeMap, path::Path}; + + use super::generate_folded_sorted_lines; + + fn find_spans_for(source: &str, needle: &str) -> Vec { + let mut spans = Vec::new(); + let mut start = 0; + while let Some(start_idx) = source[start..].find(needle) { + let start_idx = start + start_idx; + let end_idx = start_idx + needle.len(); + spans.push(Span::inclusive(start_idx as u32, end_idx as u32 - 1)); + start = end_idx; + } + spans + } + + #[test] + fn simple_test_case() { + let source_code = r##" + fn main() { + foo(); + bar(); + whatever(); + } + fn foo() { + baz(); + } + fn bar () { + whatever() + } + fn baz () { + whatever() + } + "##; + + let source_file_name = Path::new("main.nr"); + let temp_dir = tempfile::tempdir().unwrap(); + + let mut fm = FileManager::new(temp_dir.path()); + let file_id = fm.add_file_with_source(source_file_name, source_code.to_string()).unwrap(); + + let main_declaration_location = + Location::new(find_spans_for(source_code, "fn main()")[0], file_id); + let main_foo_call_location = + Location::new(find_spans_for(source_code, "foo()")[0], file_id); + let main_bar_call_location = + Location::new(find_spans_for(source_code, "bar()")[0], file_id); + let main_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[0], file_id); + let foo_baz_call_location = Location::new(find_spans_for(source_code, "baz()")[0], file_id); + let bar_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[1], file_id); + let baz_whatever_call_location = + Location::new(find_spans_for(source_code, "whatever()")[2], file_id); + + let mut opcode_locations = BTreeMap::>::new(); + // main::foo::baz::whatever + opcode_locations.insert( + OpcodeLocation::Acir(0), + vec![ + main_declaration_location, + main_foo_call_location, + foo_baz_call_location, + baz_whatever_call_location, + ], + ); + + // main::bar::whatever + opcode_locations.insert( + OpcodeLocation::Acir(1), + vec![main_declaration_location, main_bar_call_location, bar_whatever_call_location], + ); + // main::whatever + opcode_locations.insert( + OpcodeLocation::Acir(2), + vec![main_declaration_location, main_whatever_call_location], + ); + + let debug_info = DebugInfo::new( + opcode_locations, + BTreeMap::default(), + BTreeMap::default(), + BTreeMap::default(), + ); + + let samples_per_opcode = vec![10, 20, 30]; + + let expected_folded_sorted_lines = vec![ + "main.nr:2:9::fn main();main.nr:3:13::foo();main.nr:8:13::baz();main.nr:14:13::whatever();opcode::arithmetic 10".to_string(), + "main.nr:2:9::fn main();main.nr:4:13::bar();main.nr:11:13::whatever();opcode::arithmetic 20".to_string(), + "main.nr:2:9::fn main();main.nr:5:13::whatever();opcode::memory::init 30".to_string(), + ]; + + let opcodes: Vec> = vec![ + Opcode::AssertZero(Expression::default()), + Opcode::AssertZero(Expression::default()), + Opcode::MemoryInit { + block_id: BlockId(0), + init: vec![], + block_type: acir::circuit::opcodes::BlockType::Memory, + }, + ]; + + let actual_folded_sorted_lines = generate_folded_sorted_lines( + samples_per_opcode, + opcodes, + &debug_info, + fm.as_file_map(), + ); + + assert_eq!(expected_folded_sorted_lines, actual_folded_sorted_lines); + } +} diff --git a/noir/noir-repo/tooling/profiler/src/fs.rs b/noir/noir-repo/tooling/profiler/src/fs.rs new file mode 100644 index 000000000000..e8eec2cbb145 --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/fs.rs @@ -0,0 +1,15 @@ +use std::path::Path; + +use color_eyre::eyre; +use noirc_artifacts::program::ProgramArtifact; + +pub(crate) fn read_program_from_file>( + circuit_path: P, +) -> eyre::Result { + let file_path = circuit_path.as_ref().with_extension("json"); + + let input_string = std::fs::read(file_path)?; + let program = serde_json::from_slice(&input_string)?; + + Ok(program) +} diff --git a/noir/noir-repo/tooling/profiler/src/gates_provider.rs b/noir/noir-repo/tooling/profiler/src/gates_provider.rs new file mode 100644 index 000000000000..caed26664261 --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/gates_provider.rs @@ -0,0 +1,37 @@ +use std::path::{Path, PathBuf}; +use std::process::Command; + +use color_eyre::eyre::{self}; +use serde::{Deserialize, Serialize}; + +pub(crate) trait GatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result; +} + +pub(crate) struct BackendGatesProvider { + pub(crate) backend_path: PathBuf, +} + +impl GatesProvider for BackendGatesProvider { + fn get_gates(&self, artifact_path: &Path) -> eyre::Result { + let backend_gates_response = + Command::new(&self.backend_path).arg("gates").arg("-b").arg(artifact_path).output()?; + + // Parse the backend gates command stdout as json + let backend_gates_response: BackendGatesResponse = + serde_json::from_slice(&backend_gates_response.stdout)?; + Ok(backend_gates_response) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct BackendGatesReport { + pub(crate) acir_opcodes: usize, + pub(crate) circuit_size: usize, + pub(crate) gates_per_opcode: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct BackendGatesResponse { + pub(crate) functions: Vec, +} diff --git a/noir/noir-repo/tooling/profiler/src/main.rs b/noir/noir-repo/tooling/profiler/src/main.rs index 8e08644de23d..215feb0a4e70 100644 --- a/noir/noir-repo/tooling/profiler/src/main.rs +++ b/noir/noir-repo/tooling/profiler/src/main.rs @@ -4,6 +4,10 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))] mod cli; +mod flamegraph; +mod fs; +mod gates_provider; +mod opcode_formatter; use std::env; diff --git a/noir/noir-repo/tooling/profiler/src/opcode_formatter.rs b/noir/noir-repo/tooling/profiler/src/opcode_formatter.rs new file mode 100644 index 000000000000..aba92c95d85f --- /dev/null +++ b/noir/noir-repo/tooling/profiler/src/opcode_formatter.rs @@ -0,0 +1,53 @@ +use acir::circuit::{directives::Directive, opcodes::BlackBoxFuncCall, Opcode}; + +fn format_blackbox_function(call: &BlackBoxFuncCall) -> String { + match call { + BlackBoxFuncCall::AES128Encrypt { .. } => "aes128_encrypt".to_string(), + BlackBoxFuncCall::AND { .. } => "and".to_string(), + BlackBoxFuncCall::XOR { .. } => "xor".to_string(), + BlackBoxFuncCall::RANGE { .. } => "range".to_string(), + BlackBoxFuncCall::SHA256 { .. } => "sha256".to_string(), + BlackBoxFuncCall::Blake2s { .. } => "blake2s".to_string(), + BlackBoxFuncCall::Blake3 { .. } => "blake3".to_string(), + BlackBoxFuncCall::SchnorrVerify { .. } => "schnorr_verify".to_string(), + BlackBoxFuncCall::PedersenCommitment { .. } => "pedersen_commitment".to_string(), + BlackBoxFuncCall::PedersenHash { .. } => "pedersen_hash".to_string(), + BlackBoxFuncCall::EcdsaSecp256k1 { .. } => "ecdsa_secp256k1".to_string(), + BlackBoxFuncCall::EcdsaSecp256r1 { .. } => "ecdsa_secp256r1".to_string(), + BlackBoxFuncCall::MultiScalarMul { .. } => "multi_scalar_mul".to_string(), + BlackBoxFuncCall::EmbeddedCurveAdd { .. } => "embedded_curve_add".to_string(), + BlackBoxFuncCall::Keccak256 { .. } => "keccak256".to_string(), + BlackBoxFuncCall::Keccakf1600 { .. } => "keccakf1600".to_string(), + BlackBoxFuncCall::RecursiveAggregation { .. } => "recursive_aggregation".to_string(), + BlackBoxFuncCall::BigIntAdd { .. } => "big_int_add".to_string(), + BlackBoxFuncCall::BigIntSub { .. } => "big_int_sub".to_string(), + BlackBoxFuncCall::BigIntMul { .. } => "big_int_mul".to_string(), + BlackBoxFuncCall::BigIntDiv { .. } => "big_int_div".to_string(), + BlackBoxFuncCall::BigIntFromLeBytes { .. } => "big_int_from_le_bytes".to_string(), + BlackBoxFuncCall::BigIntToLeBytes { .. } => "big_int_to_le_bytes".to_string(), + BlackBoxFuncCall::Poseidon2Permutation { .. } => "poseidon2_permutation".to_string(), + BlackBoxFuncCall::Sha256Compression { .. } => "sha256_compression".to_string(), + } +} + +fn format_directive_kind(directive: &Directive) -> String { + match directive { + Directive::ToLeRadix { .. } => "to_le_radix".to_string(), + } +} + +fn format_opcode_kind(opcode: &Opcode) -> String { + match opcode { + Opcode::AssertZero(_) => "arithmetic".to_string(), + Opcode::BlackBoxFuncCall(call) => format!("blackbox::{}", format_blackbox_function(call)), + Opcode::MemoryOp { .. } => "memory::op".to_string(), + Opcode::MemoryInit { .. } => "memory::init".to_string(), + Opcode::Directive(directive) => format!("directive::{}", format_directive_kind(directive)), + Opcode::BrilligCall { .. } => "brillig_call".to_string(), + Opcode::Call { .. } => "acir_call".to_string(), + } +} + +pub(crate) fn format_opcode(opcode: &Opcode) -> String { + format!("opcode::{}", format_opcode_kind(opcode)) +} diff --git a/noir/scripts/sync-in-fixup.sh b/noir/scripts/sync-in-fixup.sh index ba3c591eac40..fce52060fa7e 100755 --- a/noir/scripts/sync-in-fixup.sh +++ b/noir/scripts/sync-in-fixup.sh @@ -16,3 +16,6 @@ YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install # Remove requirement for `wasm-opt` to be installed sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./tooling/noirc_abi_wasm/build.sh sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./acvm-repo/acvm_js/build.sh + +# Replace `verify_honk_proof` test +cp -r ../verify_honk_proof ./test_programs/execution_success/verify_honk_proof diff --git a/noir/scripts/sync-out-fixup.sh b/noir/scripts/sync-out-fixup.sh index 79976883d0b0..072cefa4afee 100755 --- a/noir/scripts/sync-out-fixup.sh +++ b/noir/scripts/sync-out-fixup.sh @@ -16,3 +16,6 @@ YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install # Add requirement for `wasm-opt` to be installed sed -i "s/^#require_command wasm-opt/require_command wasm-opt/" ./tooling/noirc_abi_wasm/build.sh sed -i "s/^#require_command wasm-opt/require_command wasm-opt/" ./acvm-repo/acvm_js/build.sh + +# Remove `verify_honk_proof` test +rm -rf ./test_programs/execution_success/verify_honk_proof diff --git a/noir/verify_honk_proof/Nargo.toml b/noir/verify_honk_proof/Nargo.toml new file mode 100644 index 000000000000..8fce1bf44b6e --- /dev/null +++ b/noir/verify_honk_proof/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "verify_honk_proof" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/verify_honk_proof/Prover.toml b/noir/verify_honk_proof/Prover.toml new file mode 100644 index 000000000000..af4e99197a5b --- /dev/null +++ b/noir/verify_honk_proof/Prover.toml @@ -0,0 +1,4 @@ +key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" +proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] +public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"]" diff --git a/noir/verify_honk_proof/src/main.nr b/noir/verify_honk_proof/src/main.nr new file mode 100644 index 000000000000..ecfd18f38374 --- /dev/null +++ b/noir/verify_honk_proof/src/main.nr @@ -0,0 +1,21 @@ + +// This circuit aggregates a single Honk proof from `assert_statement_recursive`. +global SIZE_OF_PROOF_IF_LOGN_IS_28 : u32 = 409; +fn main( + verification_key: [Field; 103], + // This is the proof without public inputs attached. + // + // This means: the size of this does not change with the number of public inputs. + proof: [Field; SIZE_OF_PROOF_IF_LOGN_IS_28], + public_inputs: pub [Field; 1], + // This is currently not public. It is fine given that the vk is a part of the circuit definition. + // I believe we want to eventually make it public too though. + key_hash: Field +) { + std::verify_proof( + verification_key.as_slice(), + proof.as_slice(), + public_inputs.as_slice(), + key_hash + ); +} diff --git a/yarn-project/.earthlyignore b/yarn-project/.earthlyignore index 90a25913737c..bd9d331e9a60 100644 --- a/yarn-project/.earthlyignore +++ b/yarn-project/.earthlyignore @@ -39,10 +39,9 @@ cmake-build-debug **/tsconfig.tsbuildinfo **/.eslintcache **/target -accounts/src/artifacts +accounts/artifacts aztec-faucet/data* aztec-node/data* -aztec-js/src/account_contract/artifacts aztec/log circuits.js/fixtures/*.json docs/dist @@ -51,8 +50,8 @@ end-to-end/log end-to-end/data end-to-end/src/web/main.js end-to-end/src/web/main.js.LICENSE.txt -entry-points/src/artifacts l1-contracts/generated +noir-protocol-circuits-types/artifacts builder/target/ builder/proofs/ builder/Prover.toml @@ -64,7 +63,7 @@ builder/Verifier.toml builder/src/target builder/src/crs builder/src/types -protocol-contracts/src/artifacts +protocol-contracts/artifacts scripts/tmp noir-contracts.js/src noir-contracts.js/artifacts/ diff --git a/yarn-project/.gitignore b/yarn-project/.gitignore index e92d481c2524..e044af6d3bdd 100644 --- a/yarn-project/.gitignore +++ b/yarn-project/.gitignore @@ -12,10 +12,9 @@ **/.debounce-* **/.tsc.pid **/*.result -accounts/src/artifacts +accounts/artifacts aztec-faucet/data* aztec-node/data* -aztec-js/src/account_contract/artifacts aztec/log circuits.js/fixtures/*.json circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs_variants.ts @@ -25,9 +24,9 @@ end-to-end/log end-to-end/data end-to-end/src/web/main.js end-to-end/src/web/main.js.LICENSE.txt -entry-points/src/artifacts l1-artifacts/generated l1-contracts/generated +noir-protocol-circuits-types/artifacts builder/target/ builder/proofs/ builder/Prover.toml @@ -40,7 +39,7 @@ builder/src/target builder/src/crs builder/src/types noir-protocol-circuits-types/src/types/ -protocol-contracts/src/artifacts +protocol-contracts/artifacts scripts/tmp noir-contracts.js/src noir-contracts.js/artifacts/ diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 0631918b4113..220f8292c8e6 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -73,8 +73,7 @@ bb-cli: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src # yarn symlinks the binary to node_modules/.bin ENTRYPOINT ["/usr/src/yarn-project/node_modules/.bin/bb-cli"] @@ -124,8 +123,7 @@ txe: ../l1-contracts \ ../barretenberg/ts/src \ ../barretenberg/ts/dest/node-cjs \ - ../barretenberg/ts/dest/browser \ - **/artifacts + ../barretenberg/ts/dest/browser SAVE ARTIFACT /usr/src /usr/src aztec-prod: @@ -140,8 +138,7 @@ aztec-prod: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src COPY --dir +rollup-verifier-contract/usr/src/bb /usr/src SAVE ARTIFACT /usr/src /usr/src @@ -172,8 +169,7 @@ aztec-faucet-build: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ - **/artifacts + **/src SAVE ARTIFACT /usr/src /usr/src aztec-faucet: @@ -230,8 +226,7 @@ end-to-end-prod: ../l1-contracts \ ../barretenberg/ts/src \ ../barretenberg/ts/dest/node-cjs \ - ../barretenberg/ts/dest/browser \ - **/artifacts + ../barretenberg/ts/dest/browser COPY --dir +rollup-verifier-contract/usr/src/bb /usr/src SAVE ARTIFACT /usr/src /usr/src diff --git a/yarn-project/accounts/.prettierignore b/yarn-project/accounts/.prettierignore index 2ade63ee6f97..eb6b23ceb906 100644 --- a/yarn-project/accounts/.prettierignore +++ b/yarn-project/accounts/.prettierignore @@ -1 +1 @@ -src/artifacts/*.json \ No newline at end of file +artifacts/*.json \ No newline at end of file diff --git a/yarn-project/accounts/package.json b/yarn-project/accounts/package.json index 90d2d36ab832..b1209964ae45 100644 --- a/yarn-project/accounts/package.json +++ b/yarn-project/accounts/package.json @@ -28,7 +28,7 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests" @@ -91,7 +91,8 @@ "files": [ "dest", "src", - "!*.test.*" + "!*.test.*", + "artifacts" ], "engines": { "node": ">=18" diff --git a/yarn-project/accounts/package.local.json b/yarn-project/accounts/package.local.json index c5987104cfcc..6e3a34a9358f 100644 --- a/yarn-project/accounts/package.local.json +++ b/yarn-project/accounts/package.local.json @@ -5,6 +5,12 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts" - } -} + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/accounts/scripts/copy-contracts.sh b/yarn-project/accounts/scripts/copy-contracts.sh index 8b945155a9d9..5984357006a6 100755 --- a/yarn-project/accounts/scripts/copy-contracts.sh +++ b/yarn-project/accounts/scripts/copy-contracts.sh @@ -1,9 +1,17 @@ #! /bin/bash set -euo pipefail -mkdir -p ./src/artifacts +mkdir -p ./artifacts contracts=(schnorr_account_contract-SchnorrAccount ecdsa_account_contract-EcdsaAccount schnorr_single_key_account_contract-SchnorrSingleKeyAccount) +decl=$(cat < ./artifacts/${contract#*-}.d.json.ts done \ No newline at end of file diff --git a/yarn-project/accounts/src/artifacts/EcdsaAccount.json b/yarn-project/accounts/src/artifacts/EcdsaAccount.json new file mode 100644 index 000000000000..a1a1f0d2a1a6 --- /dev/null +++ b/yarn-project/accounts/src/artifacts/EcdsaAccount.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"EcdsaAccount","functions":[{"name":"constructor","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(initializer)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"signing_pub_key_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"signing_pub_key_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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CxAmm0BuswCh0AlBJ+x0QqUTGp3Q6QRumwUIg07gtlngEAS3zQKEQicEncBtswCh0gmNTuh0wkEnDDqB/uaE3WYxj4Q2ixNi3GYBe98btmHve8M27H1v2IZ9tbb3vWEb9r43bMPe94Zt2PvesA173zaL0964zQL21rPWuM0C9taz1rjNAvbWs9a4zQL21rPWuM0C9lJtFqeQVpsFhHxv2Ia97w3bsPe9YRv21dre94Zt2PvesA173xu2Ye97wzbsfW/YPu2N2yxgbz1rjdssYG89a43bLGBvPWuN2yxgbz1rjdssYG89a7XaLCAk1WYBIak2CwhJtVlASGVuXUJSbRYQkmqzgJBUmwWEpNosICTVZnEKabVZQCh52X933T+UxNosoCR2gR6Oa4m1WUBJrM0CSmJtFlASa7OAklibBZTE2iygJNZmcSqptVlASazNAkpibRZQEmuzgFLVUxJrs4CSWJsFlMTaLKAk1mYBJbE2i1NJrc0CSmJtFlASa7OAklibBZSqnpJYmwWUxNosoCTWZgElsTYLKIm1Wawok1ibxXISa7NYTmJtFstJ7Lb45STWZrGcxNoslpPeyzi5NovlJNZmsZzE2iyWUxV00tqfjq3y88GA+OaDl71tZmnZ22aWlr1tZmnZV2t728zSsrfNLC1728zSsrfNLC1723ww7H3zwcveetb65oOXvfWs9c0HL3vrWeubD1721rPWNx+87JXywRCSygcvIdvM0rK3zSwte9vM0rKv1va2maVlb5tZWva2maVlb5tZWva2mSXY++aDl731rPXNBy9761nrmw9e9taz1jcfvOytZ61vPnjZW89aqXzwElLKBy8hpXzwElLKBy8hlbl1CSnlg5eQUj54CSnlg5eQUj54CSnlgyEklQ9eQsnL/psA5VLSygcvJa0jieu4llY+eClp5YOXklY+eClp5YOXklY+eClp5YOXklY+GEpi+eClpJUPXkpa+eClpJUPXkpVT0krH7yUtPLBS0krH7yUtPLBS0krHwwlsXzwUtLKBy8lrXzwUtLKBy+lqqeklQ9eSlr54KWklQ9eSlr54KWklQ/+ijJp5YO/nLTywV9OWvngLye9/J1aPvjLSSsf/OWk9zJOLR/85aSVD/5y0soHfzlVQSex/anEf97tca7bQ6fGNzbj2sDnVn99abzw6fgpPlzFp6t42WzN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KHQCt80ChE4ncO9kPAnkNgsQ6N8lcpsFCINOmGwCuc0ChEInBJ2w0wmVTmh0QqcTuG0WIAw6gdtmgY+zuG0WIBQ6IegEbpsFCJVOaHRCpxMOOoHbZgHCZBPIbRYgFDoh6ISdTqh0QqMTOp3AbbMAYdAJ3DYLHILgtlmAUOiEoBO4bRYgVDqh0QmdTjjohEEn0N+csNss9khoszghxm0WsPe9YRv2vjdsw973hm3YV2t73xu2Ye97wzbsfW/Yhr3vDduw922zOO2N2yxgbz1rjdssYG89a43bLGBvPWuN2yxgbz1rjdssYC/VZnEKabVZQMj3hm3Y+96wDXvfG7ZhX63tfW/Yhr3vDduw971hG/a+N2zD3veG7dPeuM0C9taz1rjNAvbWs9a4zQL21rPWuM0C9taz1rjNAvbWs1arzQJCUm0WEJJqs4CQVJsFhFTm1iUk1WYBIak2CwhJtVlASKrNAkJSbRankFabBYSSl/131/1DSazNAkpiF+jhuJZYmwWUxNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFqeSWpsFlMTaLKAk1mYBJbE2CyhVPSWxNgsoibVZQEmszQJKYm0WUBJrsziV1NosoCTWZgElsTYLKIm1WUCp6imJtVlASazNAkpibRZQEmuzgJJYm8WKMom1WSwnsTaL5STWZrGcxG6LX05ibRbLSazNYjnpvYyTa7NYTmJtFstJrM1iOVVBJ7X9aWbkg6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pniq5YOnWj54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6daPniq5YOnWj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnXD64Pz3af5QH5Dh+fTZdov167njxufHi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EzqdMOiEk07gtlmAsNgEcpsFCIVOCDqh0gmNTuh0wqATuG0WIEw6gdtmgUMQ3DYLEAqdEHQCt80ChEYndDph0AknnTDpBPqbE3abxSgJbRYPiHGbBex9b9iGve8N27D3vWEb9s3a3veGbdj73rANe98btmHve8M27H3bLB72xm0WsLeetcZtFrC3nrXGbRawt561xm0WsLeetcZtFrCXarN4CGm1WUDI94Zt2PvesA173xu2Yd+s7X1v2Ia97w3bsPe9YRv2vjdsw973hu2HvXGbBeytZ61xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXsrWetVpsFhKTaLCAk1WYBIak2CwipzK1LSKrNAkJSbRYQkmqzgJBUmwWEpNosHkJabRYQSl72X133DyWxNgsoiV2gh+NaYm0WUBJrs4CSWJsFlMTaLKAk1mYBJbE2CyiJtVk8lNTaLKAk1mYBJbE2CyiJtVlAqekpibVZQEmszQJKYm0WUBJrs4CSWJvFQ0mtzQJKYm0WUBJrs4CSWJsFlJqeklibBZTE2iygJNZmASWxNgsoibVZ7CiTWJvFdhJrs9hOYm0W20nstvjtJNZmsZ3E2iy2k97LOLk2i+0k1maxncTaLLZTE3RS259mRj54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp1o+eKrlg6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pniq5YOnWj54quWDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dgPngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eOrlg8/xn3d7nNvx1Gnxhc28NvB1tJ9fGt/4dPwhPl3Fl6t4OWzNi6152JpXW/Nma95tzYetue0ELbYjtNjO0LCdoWE7Q8N2hobtDA3bGRq2MzRoM/QinHTC2zOpP0/qtN5uCYtNqAedUOiEoBPe3tvmc/G0WW8JjU7odMKgE95d0/04//nSfsxbwqQTFpvQDjqh0Anv/rb2eH5pj3vCoBPe/UmP+jzqNnrcEfpBJ9C/S/3tNd2u36V+3hImnbDYhHHQCYVOCDqh0gmNTuh0wqATPrimx7glTDrh/TV97XznLeF8e01fu/crQqETgk54d02PKw8xjnVLaHRCpxMGnXDSCW+v6fW8/HmU45aw2IR50AmFTgg6odIJjU7odMKgE84PEm7X9Jx0wvtr+nmiZcQtYb29pq/Xoa8IhU4IOuHtOf3V/0VXoxM6nTDohJNOmHQC/c3Ji6PTH0PMkdBmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzOHcZjGHc5vFHM5tFnM4t1nM4dxmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzCHWZjGHWJvFHM5tFnM4t1nM4dxmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzOHcZgF761lr3GYBe+tZa9xmMYdzmwXsrWetcZvFHM5tFnOItVlASKrNAkJSbRYQkmqzgJDK3LqEpNos5hBrs5hDrM1iDrE2iznE2izmEGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos55Nos5pBrs5hDrs1iDrk2iznk2izmkGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos55Nos5pBrs5hDrs1iDrk2iznk2izmkGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos59NostpNYm8V2Emuz2E5it8VvJ7E2i+0k1maxnfRexsm1WWwnsTaL7STWZrGdmqCT2P60qmmbxUPc8yruh7jnTdwPcdM2C5h73sQNc8+buGHueRM3zJutuedN3DD3bLOAue0ENW2zgLntDDVts4C57Qw1bbOAue0MNW2zgLntDCW3WYBw0gncNgsQFptAbrMAodAJQSdw2yxAaHRCpxMGncBtswBh0gmLTSC3WYBQ6ARumwUIg07g3sn4IJDbLECgf5fIbRYgTDphsQnkNgsQCp0QdEKlExqd0OmEQSdw2yxAmHQCt80CH2dx2yxAKHRC0AncNgsQGp3Q6YRBJ5x0ArfNAoTFJpDbLEAodELQCZVOaHRCpxMGncBtswBh0gncNgscguC2WYBQ6ISgE7htFiA0OqHTCYNOOOmESSfQ35yQ2yzmEfw2C0B82yy2ve0N29ve9obtbW97w/a2b9b2tjdsb3vbG7a3ve0N29ve9obtbW/bZgF73zaLbW89a33bLLa99az1bbPY9taz1rfNYttbz1rfNottr9RmASGpNostZHvD9ra3vWF729vesL3tm7W97Q3b2972hu1tb3vD9ra3vWF729vesA173zaLbW89a33bLLa99az1bbPY9taz1rfNYttbz1rfNottbz1rpdostpBSm8UWUmqz2EJKbRZbSGVuXUJKbRZbSKnNYgsptVlsIaU2iy2k1GYBIak2iy2UvOy/uO5/K2m1WWwlrQv09nEtrTaLraTVZrGVtNostpJWm8VW0mqz2EpabRZbSavNAkpibRZbSavNYitptVlsJa02i63U9JS02iy2klabxVbSarPYSlptFltJq80CSmJtFltJq81iK2m1WWwlrTaLrdT0lLTaLLaSVpvFVtJqs9hKWm0WW0mrzeJHlEmrzeKHk1abxQ8nrTaLH05at8X/cNJqs/jhpNVm8cNJ72WcWpvFDyetNosfTlptFj+cmqCT2v60MvLByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvNTywUstH7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88FLLR+81PLBSy0fvNTywUstH7zU8sFLLR+81PLBSy0fvNTywUstH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7wE88FLMB+8BPPBSzAfvATzwUswH7wE88FLMB+8BPPBSzAfvATzwUstHzzKy6P9Z3lCzvPnZ9Ml+s/nzm8+N7/53Prec/fnvf/gufLN5+Kbz90uoXn9vTLjxXPtm8/1bz43vvnc+c3n5jefW9977v6A45zP9/9zxf1z5ZvPxTefq998rn3zuf7N58Y3n7v9ffnlg89y3D83v/nc+t5z94d0/uC58s3n4pvP1W8+d/v7suK5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G/bN2t73hm3Y+96wDXvfG7Zh73vDNux9b9h+2Bu3WcDeetYat1nA3nrWGrdZwN561hq3WcDeetYat1nA3nrWarVZQEiqzQJCUm0WEJJqs4CQyty6hKTaLCAk1WYBIak2CwhJtVlASKrN4iGk1WYBoeRl/9V1/1ASa7OAktgFejiuJdZmASWxNgsoibVZQEmszQJKYm0WUBJrs4CSWJvFQ0mtzQJKYm0WUBJrs4CSWJsFlJqeklibBZTE2iygJNZmASWxNgsoibVZPJTU2iygJNZmASWxNgsoibVZQKnpKYm1WUBJrM0CSmJtFlASa7OAklibxY4yibVZbCexNovtJNZmsZ3EbovfTmJtFttJrM1iO+m9jJNrs9hOYm0W20mszWI7NUEntf1pZuSDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eKrlg6daPnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OnWj54quWDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6daPnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eArmg6dePriN/7zb49yOp06LL2zmtYGvo/380vjGp+MP8ekqvlzFy2FrXmzNw9a82po3W/Nuaz5szW0naLEdocV2hobtDA3bGRq2MzRsZ2jYztCwnaFBm6EX4aQT3p5J/XlSp/V2S1hsQj3ohEInBJ3w9t42n4unzXpLaHRCpxMGnfDumu7H+c+X9mPeEiadsNiEdtAJhU5497e1x/NLe9wTBp3w7k961OdRt9HjjtAPOoH+Xepvr+l2/S7185Yw6YTFJoyDTih0QtAJlU5odEKnEwad8ME1PcYtYdIJ76/pa+c7bwnn22v62r1fEQqdEHTCu2t6XHmIcaxbQqMTOp0w6ISTTnh7Ta/n5c+jHLeExSbMg04odELQCZVOaHRCpxMGnXB+kHC7puekE95f088TLSNuCevtNX29Dn1FKHRC0Alvz+mv/i+6Gp3Q6YRBJ5x0wqQT6G9OXhyd/hiij4Q2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog/nNos+nNss+nBus+jDuc2iD+c2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog+xNos+xNos+nBus+jDuc2iD+c2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog/nNgvYW89a4zYL2FvPWuM2iz6c2yxgbz1rjdss+nBus+hDrM0CQlJtFhCSarOAkFSbBYRU5tYlJNVm0YdYm0UfYm0WfYi1WfQh1mbRh1ibRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0Iddm0Ydcm0Ufcm0Wfci1WfQh12bRh1ybRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0Iddm0Ydcm0Ufcm0Wfci1WfQh12bRh1ybRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0oddmsZ3E2iy2k1ibxXYSuy1+O4m1WWwnsTaL7aT3Mk6uzWI7ibVZbCexNovt1ASdxPanUU3bLB7inldxP8Q9b+J+iJu2WcDc8yZumHvexA1zz5u4Yd5szT1v4oa5Z5sFzG0nqGmbBcxtZ6hpmwXMbWeoaZsFzG1nqGmbBcxtZyi5zQKEk07gtlmAsNgEcpsFCIVOCDqB22YBQqMTOp0w6ARumwUIk05YbAK5zQKEQidw2yxAGHQC907GB4HcZgEC/btEbrMAYdIJi00gt1mAUOiEoBMqndDohE4nDDqB22YBwqQTuG0W+DiL22YBQqETgk7gtlmA0OiETicMOuGkE7htFiAsNoHcZgFCoROCTqh0QqMTOp0w6ARumwUIk07gtlngEAS3zQKEQicEncBtswCh0QmdThh0wkknTDqB/uaE3WZxRkKbxQNi3GYBe98btmHve8M27H1v2IZ9s7b3vWEb9r43bMPe94Zt2PvesA173zaLh71xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXsrWetcZsF7KXaLB5CWm0WEPK9YRv2vjdsw973hm3YN2t73xu2Ye97wzbsfW/Yhr3vDduw971h+2Fv3GYBe+tZa9xmAXvrWWvcZgF761lr3GYBe+tZa9xmAXvrWavVZgEhqTYLCEm1WUBIqs0CQipz6xKSarOAkFSbBYSk2iwgJNVmASGpNouHkFabBYSSl/1X1/1DSazNAkpiF+jhuJZYmwWUxNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFg8ltTYLKIm1WUBJrM0CSmJtFlBqekpibRZQEmuzgJJYmwWUxNosoCTWZvFQUmuzgJJYmwWUxNosoCTWZgGlpqck1mYBJbE2CyiJtVlASazNAkpibRY7yiTWZrGdxNostpNYm8V2ErstfjuJtVlsJ7E2i+2k9zJOrs1iO4m1WWwnsTaL7dQEndT2p5WRD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eCllg9eavngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXmr54KWWD15q+eCllg9eavngpZYPXmr54KWWD15q+eCllg9eavngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngJZgPXoL54CWYD16C+eAlmA9egvngJZgPXoL54CWYD16C+eAlmA9ecvng/vJo/1mekPP8+dl0if7zufObz81vPre+99z9ee8/eK5887n45nO3S2hef6/MePFc++Zz/ZvPjW8+d37zufnN59b3nrs/4Djn8/3/XHH/XPnmc/HN5+o3n2vffK5/87nxzeduf19++eCzHPfPzW8+t7733P0hnT94rnzzufjmc/Wbz93+vqx4rqNV79fR/TmPP3hufPO585vPzW8+t7733P1RgT94rnzxXLv/+Y345nP1m8/d/77053pf43693x8P+IPnxjefO7/53Pzmc+t7z53HN5+7/32Zx/WquM//efD//ZsvviiRQqkplJZC6SmUkUI5UygzhbIyKPef7H+ckrL2Z8ranylrf6as/Zmy9mfK2p8pa3+mrP2ZsvZXytpfKWt/paz9lbL2V8raXylrf6Ws/ZWy9lfK2l8pa//Fp4qfx5QcTORgag6m5WB6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1WaxlbTaLLaSVpvFVmp6SlptFltJq81iK2m1WWwlrTaLraTVZgElsTaLraTVZrGVtNostpJWm8VWanpKWm0WW0mrzWIrabVZbCWtNoutpNVm8SPKpNVm8cNJq83ih5NWm8UPJ63b4n84abVZ/HDSarP44aT3Mk6tzeKHk1abxQ8nrTaLH05N0Eltf5oZ+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+eavngqZYPntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54KmWD55q+eCplg+eavngqZYPnmr54KmWD55q+eCplg+eavngqZYPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnoL54CmYD56C+eApmA+egvngKZgPnoL54CmYD56C+eApmA+egvngqZcPLuM/7/Y4t+Op0+ILm3lt4OtoP780vvHp+EN8uoovV/Fy2JoXW/OwNa+25s3WvNuaD1tz2wlabEdosZ2hYTtDw3aGhu0MDdsZGrYzNGxnaNBm6EU46YS3Z1J/ntRpvd0SFptQDzqh0AlBJ7y9t83n4mmz3hIandDphEEnvLum+3H+86X9mLeESScsNqEddEKhE979be3x/NIe94RBJ7z7kx71edRt9Lgj9INOoH+X+ttrul2/S/28JUw6YbEJ46ATCp0QdEKlExqd0OmEQSd8cE2PcUuYdML7a/ra+c5bwvn2mr5271eEQicEnfDumh5XHmIc65bQ6IROJww64aQT3l7T63n58yjHLWGxCfOgEwqdEHRCpRMandDphEEnnB8k3K7pOemE99f080TLiFvCentNX69DXxEKnRB0wttz+qv/i65GJ3Q6YdAJJ50w6QT6m5MXR6c/hoiR0GYRw7nNIoZzm0UM5zaLGM5tFjGc2yxiOLdZxHBus4jh3GYRw7nNIoZzm0UM5zaLGM5tFjGc2yxiOLdZxHBus4jh3GYRw7nNIoZzm0UM5zaLGGJtFjHE2ixiOLdZxHBus4jh3GYRw7nNIoZzm0UM5zaLGM5tFjGc2yxiOLdZxHBus4jh3GYBe+tZa9xmAXvrWWvcZhHDuc0C9taz1rjNIoZzm0UMsTYLCEm1WUBIqs0CQlJtFhBSmVuXkFSbRQyxNosYYm0WMcTaLGKItVnEEGuziCHXZhFDrs0ihlybRQy5NosYcm0WMeTaLGLItVnEkGuziCHXZhFDrs0ihlybRQy5NosYcm0WMeTaLGLItVnEkGuziCHXZhFDrs0ihlybRQy5NosYcm0WMeTaLGLItVnEkGuziCHXZhFDrs0ihlybRQy5NosYcm0WMeTaLGLotVlsJ7E2i+0k1maxncRui99OYm0W20mszWI76b2Mk2uz2E5ibRbbSazNYjs1QSex/alW0zaLh7jnVdwPcc+buB/ipm0WMPe8iRvmnjdxw9zzJm6YN1tzz5u4Ye7ZZgFz2wlq2mYBc9sZatpmAXPbGWraZgFz2xlq2mYBc9sZSm6zAOGkE7htFiAsNoHcZgFCoROCTuC2WYDQ6IROJww6gdtmAcKkExabQG6zAKHQCdw2CxAGncC9k/FBILdZgED/LpHbLECYdMJiE8htFiAUOiHohEonNDqh0wmDTuC2WYAw6QRumwU+zuK2WYBQ6ISgE7htFiA0OqHTCYNOOOkEbpsFCItNILdZgFDohKATKp3Q6IROJww6gdtmAcKkE7htFjgEwW2zAKHQCUEncNssQGh0QqcTBp1w0gmTTqC/OWG3WbRIaLN4QIzbLGDve8M27H1v2Ia97w3bsG/W9r43bMPe94Zt2PvesA173xu2Ye/bZvGwN26zgL31rDVus4C99aw1brOAvfWsNW6zgL31rDVus4C9VJvFQ0irzQJCvjdsw973hm3Y+96wDftmbe97wzbsfW/Yhr3vDduw971hG/a+N2w/7I3bLGBvPWuN2yxgbz1rjdssYG89a43bLGBvPWuN2yxgbz1rtdosICTVZgEhqTYLCEm1WUBIZW5dQlJtFhCSarOAkFSbBYSk2iwgJNVm8RDSarOAUPKy/+q6fyiJtVlASewCPRzXEmuzgJJYmwWUxNosoCTWZgElsTYLKIm1WUBJrM3ioaTWZgElsTYLKIm1WUBJrM0CSk1PSazNAkpibRZQEmuzgJJYmwWUxNosHkpqbRZQEmuzgJJYmwWUxNosoNT0lMTaLKAk1mYBJbE2CyiJtVlASazNYkeZxNostpNYm8V2Emuz2E5it8VvJ7E2i+0k1maxnfRexsm1WWwnsTaL7STWZrGdmqCT2v60MvLByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvNTywUstH7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88FLLR+81PLBSy0fvNTywUstH7zU8sFLLR+81PLBSy0fvNTywUstH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7wE88FLMB+8BPPBSzAfvATzwUswH7wE88FLMB+8BPPBSzAfvATzwUstH3xGay+O9p/lCTnPn59Nl+g/nzu/+dz85nPre8/dn/f+g+fKN5+Lbz53u4Tm9ffKjBfPtW8+17/53Pjmc+c3n5vffG5977n7A45zPt//zxX3z5VvPhfffK5+87n2zef6N58b33zu9vfllw8+y3H/3Pzmc+t7z90f0vmD58o3n4tvPle/+dzt78uK5zpa9X4d3Z/z+IPnxjefO7/53Pzmc+t7z90fFfiD58oXz7X7n9+Ibz5Xv/nc/e9Lf673Ne7X+/3xgD94bnzzufObz81vPre+99x5fPO5+9+XeVyvivv8nwf/37/54osSKZSaQmkplJ5CGSmUM4UyUygrg3L/yf7HKSlrf6as/Zmy9mfK2p8pa3+mrP2ZsvZnytqfKWt/paz9lbL2V8raXylrf6Ws/ZWy9lfK2l8pa3+lrP2VsvZffKr4eUzJwUQOpuZgWg6m52BGDubMwcwcTM4uUHJ2gZKzC5ScXaDk7AIlZxcoObtAydkFSs4uUHJ2gZKzC0TOLhA5u0Dk7AKRswtEzi4QObtA5OwCkbMLRM4uEDm7QM3ZBWrOLlBzdoGaswvUnF2g5uwCNWcXqDm7QM3ZBWrOLtBydoGWswu0nF2g5ewCLWcXaDm7QMvZBVrOLtBydoGWswv0nF2g5+wCPWcX6Dm7QM/ZBXrOLtBzdoGeswv0nF2g5+wCI2cXGDm7wMjZBUbOLjBydoGRswuMnF1g5OwCI2cXGDm7wJmzC+ScDyw5BwRLzgnBknNEsOScESw5hwRLzinBknNMsOScEyw5BwVLzknBknNUsOScFSw5hwVLzmnBknNcsOScFyw5BwZLzonBknNksOScGSw5hwZLzqnBknNssOScGyw5BwdLzsnBknN0sOScHYycs4ORc3Ywcs4ORs7ZwThaDqbnYEYO5szBzBxMzi6Qc3Ywcs4ORs7Zwcg5Oxg5Zwcj5+xg5JwdjJyzg5FzdjByzg5GztnByDk7GDlnByPn7GDknB2MnLODkXN2MHLODkbO2cHIOTsYOWcHI+fsYOScHYycs4ORc3Ywcs4ORs7Zwcg5Oxg5Zwcj5+xg5JwdjJyzg5FzdjByzg5GztnB+MBpu96f3Q/9/OWGwF+vCPzAYbs/oHzgdFqfzyti+683xP4PJVIoNYXSUig9hfJvB83PJ8/vPvmBUwN/8Hv9gUMDf0LpKZSRQknZ1T5wYKCv/s8Xj6O/oKwMygeOC/wJpaRQIoXygbW/ykUZLygthdJTKCOFcqZQZgplZUzODxwS+BNKyl9nK+Wvs5Xy19kHDgj8CSXlr7MPHA/4E8qZQpkplIy1X48jhVJSKJFCqSmUlkLpKZSRQjlTKDOFkrL2S8raLylrv6Ss/ZKy9kvK2i8pa7+krP2SsvZLytovKWs/UtZ+pKz9SFn7kbL2I2XtR8raj5S1H/S134//3Ned9XY+IX38T2/q/2XM/mTMWX7/paXMn6VLv7TMRFw+U8xnifnc/2nzN4WKmlCoCVU1oaYm1NWEhpqQ2j5d1DbqorZTh9pOHWo7dajt1KG2U4faTh1qO3UQd+qLcSYw3t9Pf2msq8f739glJlQPNaGiJhRqQlVNqKkJdTWhoSZ0qgmp7dRVbaduajt1U9upm9pO3dR26qa2Uze1nbqp7dSNuFNfjJnAWHxGPxIYJYERCYyawGgJjJ7AGAmMhHU+3v/dLcfxbIIuR4lbSqRQ3v+5l2g/d99x+wJhrIx/y3mkUFJ++mf7AGWsizLHLaWnUEYK5UyhzBTKJ9bLKD8p5x1lHimUkkKJFEpNobQUSk+hjBTKmUKZKZQPrP1S2vOLS7v9G2YdKZSSQokUSk2htBRKT6GMFMqZQvnA2i9nXJRfT7z9QlkZlBet1p/H1Iz/W7zogf48pudgRg5mpWA+cCLwjzAlBxM5mIR1E/eHa8/rsfP84qVrO+Y/X9qi//5L57VXrKP995e3s994lRv3p3AdxJer+P0qtjAvtuZha15tzZutebc1H7bmthO02I7QYjtDw3aGhu0MDdsZGrYzNGxnaNjO0KDN0Itw0glvz6T+/Ey19XZLWGxCPeiEQicEnfD23nYFh9ust4RGJ3Q6YdAJ767pfjxfSPVj3hImnbDYhHbQCYVOePe3tcfzS3vcEwad8O5PetTnqYvR447QDzqB/l3qb6/p6yVz7+ctYdIJi00YB51Q6ISgEyqd0OiETicMOuGDa3qMW8KkE95f09fOd94SzrfXdF1fEAqdEHTCu2t6XCdXx7FuCY1O6HTCoBNOOuHtNf3zMu5y3BIWmzAPOqHQCUEnVDqh0QmdThh0wvlBwu2anpNOeH9NP0/SjbglrLfX9PU69BWh0AlBJ7w9p7/6v+hqdEKnEwadcNIJk06gvzl5caD0Y4jx4rRaGfU6tzv6Fx+5lHY8N7/SSrmDvDit+O8obV6U86tPgT5329B4ddbJxj6s7au1fbO279b2w9r+tLaf1vbL2T6sZ21Yz9qwnrVhPWvDetaG9awN61kb1rM2rGdtqMzap1BVGZ+XUPJE/OD1YOPVqTcb+2pt36ztu7X9sLY/re2ntf1ytm+Htb31rG3Ws7ZZz9pmPWub9axt1rO2Wc/aZj1rm/Ws7Sqz9hJSGZ+XkMpEvIRUhtwlpDK3LiGVUXQJqUyXS0hlYFxCKjPgElLZ1p9CQ22nHsnL/quLmcerRMnfVUr+xf7qcrHxKivxV79LZ+gpVT2lka30+8uwx6usxN9VmnpKS05pHnpK6fvS7+97Hq8CIn9XqeopNT2lrqc09JROPaWpp7TklNahp5S9e39xL/h4FQX6u0pVT6npKXU9paGndOopTT2lJaf06o5/otPvCwG2UxF0CkGnLvdC51Uvwd91OgWd9F7Glexk4B85haBTFXRqgk5q+9MybbN4iHtexf0Q97yJ+yFu2mYBc8+buGHueRM3zD1v4oZ5szX3vIkb5p5tFjC3naCmbRYwt52hpm0WMLedoaZtFjC3naGmbRYwt52h5DYLEE46gdtmAcJiE8htFiAUOiHoBG6bBQiNTuh0wqATuG0WIEw6YbEJ5DYLEAqdwG2zAGHQCdw7GR8EcpsFCPTvErnNAoRJJyw2gdxmAUKhE4JOqHRCoxM6nTDoBG6bBQiTTuC2WeDjLG6bBQiFTgg6gdtmAUKjEzqdMOiEk07gtlmAsNgEcpsFCIVOCDqh0gmNTuh0wqATuG0WIEw6gdtmgUMQ3DYLEAqdEHQCt80ChEYndDph0AknnTDpBPqbE3abxTkT2iweEOM2C9j73rANe98btmHve8M27Ju1ve8N27D3vWEb9r43bMPe94Zt2Pu2WTzsjdssYG89a43bLGBvPWuN2yxgbz1rjdssYG89a43bLGAv1WbxENJqs4CQ7w3bsPe9YRv2vjdsw75Z2/vesA173xu2Ye97wzbsfW/Yhr3vDdsPe+M2C9hbz1rjNgvYW89a4zYL2FvPWuM2C9hbz1rjNgvYW89arTYLCEm1WUBIqs0CQlJtFhBSmVuXkFSbBYSk2iwgJNVmASGpNgsISbVZPIS02iwglLzsv7ruH0pibRZQErtAD8e1xNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFlASa7N4KKm1WUBJrM0CSmJtFlASa7OAUtNTEmuzgJJYmwWUxNosoCTWZgElsTaLh5JamwWUxNosoCTWZgElsTYLKDU9JbE2CyiJtVlASazNAkpibRZQEmuz2FEmsTaL7STWZrGdxNostpPYbfHbSazNYjuJtVlsJ72XcXJtFttJrM1iO4m1WWynJugktj/NnpAPfkCM88Gw980swd43swR738wS7Ju1vW9mCfa+mSXY+2aWYO+bWYK9bz74YW+cD4a99aw1zgfD3nrWGueDYW89a43zwbC3nrXG+WDYS+WDH0Ja+WAI+WaWYO+bWYK9b2YJ9s3a3jezBHvfzBLsfTNLsPfNLMHeN7P0sDfOB8PeetYa54Nhbz1rjfPBsLeetcb5YNhbz1rjfDDsrWetVj4YQlL5YAhJ5YMhJJUPhpDK3LqEpPLBEJLKB0NIKh8MIal8MISk8sEPIa18MISSl/1XAUooieWDoSR2JBHHtcTywVASywdDSSwfDCWxfDCUxPLBUBLLB0NJLB/8UFLLB0NJLB8MJbF8MJTE8sFQanpKYvlgKInlg6Eklg+Gklg+GEpi+eCHklo+GEpi+WAoieWDoSSWD4ZS01MSywdDSSwfDCWxfDCUxPLBUBLLB+8ok1g+eDuJ5YO3k1g+eDvp5e/k8sHbSSwfvJ30XsbJ5YO3k1g+eDuJ5YO3UxN0EtufVv3Puz3O7XjqtPjCZl4b+Drazy+Nb3w6/hCfruLLVbwctubF1jxszautebM177bmw9bcdoIW2xFabGdo2M7QsJ2hYTtDw3aGhu0MDdsZGrQZehFOOuHtmdSfJ3Vab7eExSbUg04odELQCW/vbfO5eNqst4RGJ3Q6YdAJ767pfpz/fGk/5i1h0gmLTWgHnVDohHd/W3s8v7THPWHQCe/+pEd9HnUbPe4I/aAT6N+l/vaabtfvUj9vCZNOWGzCOOiEQicEnVDphEYndDph0AkfXNNj3BImnfD+mr52vvOWcL69pq/d+xWh0AlBJ7y7pseVhxjHuiU0OqHTCYNOOOmEt9f0el7+PMpxS1hswjzohEInBJ1Q6YRGJ3Q6YdAJ5wcJt2t6Tjrh/TX9PNEy4paw3l7T1+vQV4RCJwSd8Pac/ur/oqvRCZ1OGHTCSSdMOoH+5uTF0elPIepR+W0WgPi2WWx72xu2t73tDdvb3vaG7W3frO1tb9je9rY3bG972xu2t73tDdvb3rbNAva+bRbb3nrW+rZZbHvrWevbZrHtrWetb5vFtreetb5tFtteqc0CQlJtFlvI9obtbW97w/a2t71he9s3a3vbG7a3ve0N29ve9obtbW97w/a2t71hG/a+bRbb3nrW+rZZbHvrWevbZrHtrWetb5vFtreetb5tFtveetZKtVlsIaU2iy2k1GaxhZTaLLaQyty6hJTaLLaQUpvFFlJqs9hCSm0WW0ipzQJCUm0WWyh52X9x3f9W0mqz2EpaF+jt41pabRZbSavNYitptVlsJa02i62k1WaxlbTaLLaSVpsFlMTaLLaSVpvFVtJqs9hKWm0WW6npKWm1WWwlrTaLraTVZrGVtNostpJWmwWUxNostpJWm8VW0mqz2EpabRZbqekpabVZbCWtNoutpNVmsZW02iy2klabxY8ok1abxQ8nrTaLH05abRY/nLRui//hpNVm8cNJq83ih5Peyzi1NosfTlptFj+ctNosfjg1QSex/akcnm0WELe8ihviljdxQ9yzzWKbW97Evc0tb+Le5pY3cW/zZmtueRP3Nrdss9jmthPUs81im9vOUM82i21uO0M92yy2ue0M9Wyz2Oa2M5TbZrEJJ51AbbPYhMUmcNssNqHQCUEnUNssNqHRCZ1OGHQCtc1iEyadsNgEbpvFJhQ6gdpmsQmDTqDeyQgCt81iE+jfJW6bxSZMOmGxCdw2i00odELQCZVOaHRCpxMGnUBts9iESSdQ2yz2x1nUNotNKHRC0AnUNotNaHRCpxMGnXDSCdQ2i01YbAK3zWITCp0QdEKlExqd0OmEQSdQ2yw2YdIJ1DaLfQiC2maxCYVOCDqB2maxCY1O6HTCoBNOOmHSCfQ3J+w2i7IS2iweEOM2C9j73rANe98btmHve8M27Ju1ve8N27D3vWEb9r43bMPe94Zt2Pu2WTzsjdssYG89a43bLGBvPWuN2yxgbz1rjdssYG89a43bLGAv1WbxENJqs4CQ7w3bsPe9YRv2vjdsw75Z2/vesA173xu2Ye97wzbsfW/Yhr3vDdsPe+M2C9hbz1rjNgvYW89a4zYL2FvPWuM2C9hbz1rjNgvYW89arTYLCEm1WUBIqs0CQlJtFhBSmVuXkFSbBYSk2iwgJNVmASGpNgsISbVZPIS02iwglLzsv7ruH0pibRZQErtAD8e1xNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFlASa7N4KKm1WUBJrM0CSmJtFlASa7OAUtNTEmuzgJJYmwWUxNosoCTWZgElsTaLh5JamwWUxNosoCTWZgElsTYLKDU9JbE2CyiJtVlASazNAkpibRZQEmuz2FEmsTaL7STWZrGdxNostpPabfFLr81iO4m1WWwnvZdxcm0W20mszWI7ibVZbKcm6CS2P8VIyAc/IMb5YNj7ZpZg75tZgr1vZgn2zdreN7MEe9/MEux9M0uw980swd43H/ywN84Hw9561hrng2FvPWuN88Gwt561xvlg2FvPWuN8MOyl8sEPIa18MIR8M0uw980swd43swT7Zm3vm1mCvW9mCfa+mSXY+2aWYO+bWXrYG+eDYW89a43zwbC3nrXG+WDYW89a43ww7K1nrXE+GPbWs1YrHwwhqXwwhKTywRCSygdDSGVuXUJS+WAISeWDISSVD4aQVD4YQlL54IeQVj4YQsnL/qsAJZTE8sFQEjuSiONaYvlgKInlg6Eklg+Gklg+GEpi+WAoieWDoSSWD34oqeWDoSSWD4aSWD4YSmL5YCg1PSWxfDCUxPLBUBLLB0NJLB8MJbF88ENJLR8MJbF8MJTE8sFQEssHQ6npKYnlg6Eklg+Gklg+GEpi+WAoieWDd5RJLB+8ncTywdtJLB+8nfTyd3L54O0klg/eTnov4+TywdtJLB+8ncTywdupCTqJ7U91vsgH93Y+n+vj/D3kgwfGHz5TzGeJ+byIWv9FoaImFGpCVU2oqQl1NaGhJqS2Txe1jbqo7dShtlOH2k4dajt1qO3UobZTh9pOHcSd+mKcCYz399MPnj6F0BITqoeaUFETCjWhqibU1IS6mtBQEzrVhNR26qq2Uze1nbqp7dRNbaduajt1U9upm9pO3dR26kbcqS/GTGAsPqMfCYySwIgERk1gtARGT2CMBEbCOh/v/+5+dWgflEihvP9z/4MP8sbK+LecRwol5ad/tg9Qfn9yHpSeQhkplDOFMlMon1gvvz95i4+zjxRKSaFECqWmUFoKpadQRgrlTKHMFMoH1v4XR0lxdORIoZQUSqRQagqlpVB6CmWkUM4UygfW/heHhEFZGZRXx8g/jqkZ/7coR8vB9BzMyMGsFMwHTgT+EabkYCIHw1837bg/XHtej53nFy9d2/E869vii6O+89or1tH++8vb2X//KvchPl3Fl6v4/Sq2MC+25mFrXm3Nm615tzUftua2E7TYjtBiO0PDdoaG7QwN2xkatjM0bGdo2M7QoM3Qi3DSCW/PpP78TLX1dktYbEI96IRCJwSd8PbeNp+Lp816S2h0QqcTBp3w7prux/OFVD/mLWHSCYtNaAedUOiEd39bezy/tMc9YdAJ7/6kR32euhg97gj9oBPo36X+9pq+XjL3ft4SJp2w2IRx0AmFTgg6odIJjU7odMKgEz64pse4JUw64f01fe185y3hfHtNX7v3K0KhE4JOeHdNj+vk6jjWLaHRCZ1OGHTCSSe8vaZXfxLKcUtYbMI86IRCJwSdUOmERid0OmHQCecHCbdrek464f01/TxJN+KWsN5e09fr0FeEQicEnfD2nP7q/6Kr0QmdThh0wkknTDqB/ubkxYHSjyH6i9Nq//JyyuO5+ZVWyh2kJF+v/MHbhvqrs0429mFtX63tm7V9t7Yf1vantf20tl/O9mE9a8N61ob1rA3rWRvWszasZ21Yz9qwnrVhPWtDZdY+harK+LyEkifiB68H669OvdnYV2v7Zm3fre2Htf1pbT+t7ZezfTus7a1nbbOetc161jbrWdusZ22znrXNetY261nbrGdtV5m1l5DK+LyEVCbiJaQy5C4hlbl1CamMoktIZbpcQioD4xJSmQGXkMq2/hQaajv1SF72X13M3F8lSv6uklg7dX+Vlfir36Uz9JSqnlJ2I/wXl2H3V1mJv6s09ZSWnNI89JTS96Xf3/fcXwVE/q5S1VNqekpdT2noKZ16SlNPackprUNPKXv3/uJe8P4qCvR3laqeUtNT6npKQ0/p1FOaekpLTunVHf9Ep98XAmynIugUgk5d7oXOq16Cv+t0CjrpvYwr2cnAP3IKQacq6NQEndT2p9O0zeIh7nkV90Pc8ybuh7hpmwXMPW/ihrnnTdww97yJG+bN1tzzJm6Ye7ZZwNx2gpq2WcDcdoaatlnA3HaGmrZZwNx2hpq2WcDcdoaS2yxAOOkEbpsFCItNILdZgFDohKATuG0WIDQ6odMJg07gtlmAMOmExSaQ2yxAKHQCt80ChEEncO9kfBDIbRYg0L9L5DYLECadsNgEcpsFCIVOCDqh0gmNTuh0wqATuG0WIEw6gdtmgY+zuG0WIBQ6IegEbpsFCI1O6HTCoBNOOoHbZgHCYhPIbRYgFDoh6IRKJzQ6odMJg07gtlmAMOkEbpsFDkFw2yxAKHRC0AncNgsQGp3Q6YRBJ5x0wqQT6G9O2G0WYyS0WTwgxm0WsPe9YRv2vjdsw973hm3YN2t73xu2Ye97wzbsfW/Yhr3vDduw922zeNgbt1nA3nrWGrdZwN561hq3WcDeetYat1nA3nrWGrdZwF6qzeIhpNVmASHfG7Zh73vDNux9b9iGfbO2971hG/a+N2zD3veGbdj73rANe98bth/2xm0WsLeetcZtFrC3nrXGbRawt561xm0WsLeetcZtFrC3nrVabRYQkmqzgJBUmwWEpNosIKQyty4hqTYLCEm1WUBIqs0CQlJtFhCSarN4CGm1WUAoedl/dd0/lMTaLKAkdoEejmuJtVlASazNAkpibRZQEmuzgJJYmwWUxNosoCTWZvFQUmuzgJJYmwWUxNosoCTWZgGlpqck1mYBJbE2CyiJtVlASazNAkpibRYPJbU2CyiJtVlASazNAkpibRZQanpKYm0WUBJrs4CSWJsFlMTaLKAk1maxo0xibRbbSazNYjuJtVlsJ7Hb4reTWJvFdhJrs9hOei/j5NostpNYm8V2Emuz2E5N0ElsfzprQj74ATHOB8PeN7MEe9/MEux9M0uwb9b2vpkl2PtmlmDvm1mCvW9mCfa++eCHvXE+GPbWs9Y4Hwx761lrnA+GvfWsNc4Hw9561hrng2EvlQ9+CGnlgyHkm1mCvW9mCfa+mSXYN2t738wS7H0zS7D3zSzB3jezBHvfzNLD3jgfDHvrWWucD4a99aw1zgfD3nrWGueDYW89a43zwbC3nrVa+WAISeWDISSVD4aQVD4YQipz6xKSygdDSCofDCGpfDCEpPLBEJLKBz+EtPLBEEpe9l8FKKEklg+GktiRRBzXEssHQ0ksHwwlsXwwlMTywVASywdDSSwfDCWxfPBDSS0fDCWxfDCUxPLBUBLLB0Op6SmJ5YOhJJYPhpJYPhhKYvlgKInlgx9KavlgKInlg6Eklg+Gklg+GEpNT0ksHwwlsXwwlMTywVASywdDSSwfvKNMYvng7SSWD95OYvng7aSXv5PLB28nsXzwdtJ7GSeXD95OYvng7SSWD95OTdBJbH+a5T/v9ji346nT4gubeW3g62g/vzS+8en4Q3y6ii9X8XLYmhdb87A1r7bmzda825oPW3PbCVpsR2ixnaFhO0PDdoaG7QwN2xkatjM0bGdo0GboRTjphLdnUn+e1Gm93RIWm1APOqHQCUEnvL23zefiabPeEhqd0OmEQSe8u6b7cf7zpf2Yt4RJJyw2oR10QqET3v1t7fH80h73hEEnvPuTHvV51G30uCP0g06gf5f622u6Xb9L/bwlTDphsQnjoBMKnRB0QqUTGp3Q6YRBJ3xwTY9xS5h0wvtr+tr5zlvC+faavnbvV4RCJwSd8O6aHlceYhzrltDohE4nDDrhpBPeXtPrefnzKMctYbEJ86ATCp0QdEKlExqd0OmEQSecHyTcruk56YT31/TzRMuIW8J6e01fr0NfEQqdEHTC23P6q/+LrkYndDph0AknnTDpBPqbkxdHpz+GWCWhzWIV5zaLVZzbLFZxbrNYxbnNYhXnNotVnNssVnFus1jFuc1iFec2i1Wc2yxWcW6zWMW5zWIV5zaLVZzbLFZxbrNYxbnNYhXnNotVnNssVnFus1hFrM1iFbE2i1Wc2yxWcW6zWMW5zWIV5zaLVZzbLFZxbrNYxbnNYhXnNotVnNssVnFus1jFuc0C9taz1rjNAvbWs9a4zWIV5zYL2FvPWuM2i1Wc2yxWEWuzgJBUmwWEpNosICTVZgEhlbl1CUm1Wawi1maxilibxSpibRariLVZrCLWZrGKXJvFKnJtFqvItVmsItdmsYpcm8Uqcm0Wq8i1Wawi12axilybxSpybRaryLVZrCLXZrGKXJvFKnJtFqvItVmsItdmsYpcm8Uqcm0Wq8i1Wawi12axilybxSpybRaryLVZrCLXZrGKXJvFKnJtFqvItVmsItdmsYpcm8Uqcm0Wq+i1WWwnsTaL7STWZrGdxG6L305ibRbbSazNYjvpvYyTa7PYTmJtFttJrM1iOzVBJ7X9aZq2WTzEPa/ifoh73sT9EDdts4C5503cMPe8iRvmnjdxw7zZmnvexA1zzzYLmNtOUNM2C5jbzlDTNguY285Q0zYLmNvOUNM2C5jbzlBymwUIJ53AbbMAYbEJ5DYLEAqdEHQCt80ChEYndDph0AncNgsQJp2w2ARymwUIhU7gtlmAMOgE7p2MDwK5zQIE+neJ3GYBwqQTFptAbrMAodAJQSdUOqHRCZ1OGHQCt80ChEkncNss8HEWt80ChEInBJ3AbbMAodEJnU4YdMJJJ3DbLEBYbAK5zQKEQicEnVDphEYndDph0AncNgsQJp3AbbPAIQhumwUIhU4IOoHbZgFCoxM6nTDohJNOmHQC/c0Juc2iHSe/zQIQ3zaLbW97w/a2t71he9vb3rC97Zu1ve0N29ve9obtbW97w/a2t71he9vbtlnA3rfNYttbz1rfNottbz1rfdsstr31rPVts9j21rPWt81i2yu1WUBIqs1iC9nesL3tbW/Y3va2N2xv+2Ztb3vD9ra3vWF729vesL3tbW/Y3va2N2zD3rfNYttbz1rfNottbz1rfdsstr31rPVts9j21rPWt81i21vPWqk2iy2k1GaxhZTaLLaQUpvFFlKZW5eQUpvFFlJqs9hCSm0WW0ipzWILKbVZQEiqzWILJS/7L67730pabRZbSesCvX1cS6vNYitptVlsJa02i62k1WaxlbTaLLaSVpvFVtJqs4CSWJvFVtJqs9hKWm0WW0mrzWIrNT0lrTaLraTVZrGVtNostpJWm8VW0mqzgJJYm8VW0mqz2EpabRZbSavNYis1PSWtNoutpNVmsZW02iy2klabxVbSarP4EWXSarP44aTVZvHDSavN4oeT1m3xP5y02ix+OGm1Wfxw0nsZp9Zm8cNJq83ih5NWm8UPpyboJLY/lZaQD35AjPPBsPfNLMHeN7MEe9/MEuybtb1vZgn2vpkl2PtmlmDvm1mCvW8++GFvnA+GvfWsNc4Hw9561hrng2FvPWuN88Gwt561xvlg2Evlgx9CWvlgCPlmlmDvm1mCvW9mCfbN2t43swR738wS7H0zS7D3zSzB3jez9LA3zgfD3nrWGueDYW89a43zwbC3nrXG+WDYW89a43ww7K1nrVY+GEJS+WAISeWDISSVD4aQyty6hKTywRCSygdDSCofDCGpfDCEpPLBDyGtfDCEkpf9VwFKKInlg6EkdiQRx7XE8sFQEssHQ0ksHwwlsXwwlMTywVASywdDSSwf/FBSywdDSSwfDCWxfDCUxPLBUGp6SmL5YCiJ5YOhJJYPhpJYPhhKYvngh5JaPhhKYvlgKInlg6Eklg+GUtNTEssHQ0ksHwwlsXwwlMTywVASywfvKJNYPng7ieWDt5NYPng76eXv5PLB20ksH7yd9F7GyeWDt5NYPng7ieWDt1MTdNLan86XR/vP8oSc58/Ppkv0n8+d33xufvO59b3n7s97/8Fz5ZvPxTefu11C8/p7ZcaL59o3n+vffG5887nzm8/Nbz63vvfc/QHHOZ/v/+eK++fKN5+Lbz5Xv/lc++Zz/ZvPjW8+d/v78ssHn+W4f25+87n1vefuD+n8wXPlm8/FN5+r33zu9vdlxXMdrXq/ju7PefzBc+Obz53ffG5+87n1vefujwr8wXPli+fa/c9vxDefq9987v73pT/X+xr36/3+eMAfPDe++dz5zefmN59b33vuPL753P3vyzyuV8V9/s+D/+/ffPFFiRRKTaG0FEpPoYwUyplCmSmUlUG5/2T/45SUtT9T1v5MWfszZe3PlLU/U9b+TFn7M2Xtz5S1v1LW/kpZ+ytl7a+Utb9S1v5KWfsrZe2vlLW/Utb+Sln7Lz5V/Dym5GAiB1NzMC0H03MwIwdz5mBmDiZnFyg5u0DJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u0DJ2QUiZxeInF0gcnaByNkFImcXiJxdIHJ2gcjZBSJnF4icXaDm7AI1ZxeoObtAzdkFas4uUHN2gZqzC9ScXaDm7AI1ZxdoObtAy9kFWs4u0HJ2gZazC7ScXaDl7AItZxdoObtAy9kFes4u0HN2gZ6zC/ScXaDn7AI9ZxfoObtAz9kFes4u0HN2gZGzC4ycXWDk7AIjZxcYObvAyNkFRs4uMHJ2gZGzC4ycXeDM2QVyzgeWnAOCJeeEYMk5IlhyzgiWnEOCJeeUYMk5JlhyzgmWnIOCJeekYMk5KlhyzgqWnMOCJee0YMk5LlhyzguWnAODJefEYMk5MlhyzgyWnEODJefUYMk5Nlhyzg2WnIODJefkYMk5Olhyzg5GztnByDk7GDlnByPn7GAcLQfTczAjB3PmYGYOJmcXyDk7GDlnByPn7GDknB2MnLODkXN2MHLODkbO2cHIOTsYOWcHI+fsYOScHYycs4ORc3Ywcs4ORs7Zwcg5Oxg5Zwcj5+xg5JwdjJyzg5FzdjByzg5GztnByDk7GDlnByPn7GDknB2MnLODkXN2MHLODkbO2cHIOTsYOWcHI+fsYHzgtF3vz+6Hfv5yQ+CvVwR+4LDdH1A+cDqtz+cVsf3XG2L/hxIplJpCaSmUnkL5t4Pm55Pnd5/8wKmBP/i9/sChgT+h9BTKSKGk7GofODDQV//ni8fRX1BWBuUDxwX+hFJSKJFC+cDaX+WijBeUlkLpKZSRQjlTKDOFsjIm5wcOCfwJJeWvs5Xy19lK+evsAwcE/oSS8tfZB44H/AnlTKHMFErG2q/HkUIpKZRIodQUSkuh9BTKSKGcKZSZQklZ+yVl7ZeUtV9S1n5JWfslZe2XlLVfUtZ+SVn7JWXtl5S1HylrP1LWfqSs/UhZ+5Gy9iNl7UfK2g/62o/jP/d1Z72dT0gf/9Ob+n8Zsz8Zc5bff2kp82fp0i8tMxGXzxTzWWI+93/a/E2hoiYUakJVTaipCXU1oaEmpLZPF7WNuqjt1KG2U4faTh1qO3Wo7dShtlOH2k4dxJ36YpwJjPf3018a6+rx/jd2iQnVQ02oqAmFmlBVE2pqQl1NaKgJnWpCajt1Vdupm9pO3dR26qa2Uze1nbqp7dRNbaduajt1I+7UF2MmMBaf0Y8ERklgRAKjJjBaAqMnMEYCI2Gdj/d/d8txPJugy1HilhIplPd/7iXaz9133L5AGCvj33IeKZSUn/7ZPkAZ66LMcUvpKZSRQjlTKDOF8on1MspPynlHmUcKpaRQIoVSUygthdJTKCOFcqZQZgrlA2u/lPb84tJu/4ZZRwqlpFAihVJTKC2F0lMoI4VyplA+sPbLGRfl1xNvv1BWBuVFq/XnMTXj/xYveqA/j+k5mJGDWSmYD5wI/CNMycFEDiZh3cT94drzeuw8v3jp2o75z5e26L//0nntFeto//3l7ew3XuXG/SlcB/HlKn6/ii3Mi6152JpXW/Nma95tzYetue0ELbYjtNjO0LCdoWE7Q8N2hobtDA3bGRq2MzRoM/QinHTC2zOpPz9Tbb3dEhabUA86odAJQSe8vbddweE26y2h0QmdThh0wrtruh/PF1L9mLeESScsNqEddEKhE979be3x/NIe94RBJ7z7kx71eepi9Lgj9INOoH+X+ttr+nrJ3Pt5S5h0wmITxkEnFDoh6IRKJzQ6odMJg0744Joe45Yw6YT31/S18523hPPtNV3XF4RCJwSd8O6aHtfJ1XGsW0KjEzqdMOiEk054e03/vIy7HLeExSbMg04odELQCZVOaHRCpxMGnXB+kHC7puekE95f08+TdCNuCevtNX29Dn1FKHRC0Alvz+mv/i+6Gp3Q6YRBJ5x0wqQT6G9OXhwo/RiivjitVka9zu2O/sVHLqUdz82vtFLuIC9OK/47SpsX5fzqU6DP3TZUX511srEPa/tqbd+s7bu1/bC2P63tp7X9crYP61kb1rM2rGdtWM/asJ61YT1rw3rWhvWsDetZGyqz9ilUVcbnJZQ8ET94PVh9derNxr5a2zdr+25tP6ztT2v7aW2/nO3bYW1vPWub9axt1rO2Wc/aZj1rm/WsbdaztlnP2mY9a7vKrL2EVMbnJaQyES8hlSF3CanMrUtIZRRdQirT5RJSGRiXkMoMuIRUtvWn0FDbqUfysv/qYub6KlHyd5WSf7G/ulysvspK/NXv0hl6SlVPaWQr/f4y7PoqK/F3laae0pJTmoeeUvq+9Pv7nuurgMjfVap6Sk1PqespDT2lU09p6iktOaV16Cll795f3AteX0WB/q5S1VNqekpdT2noKZ16SlNPackpvbrjn+j0+0KA7VQEnULQqcu90HnVS/B3nU5BJ72XcSU7GfhHTiHoVAWdmqCT2v60TNssHuKeV3E/xD1v4n6Im7ZZwNzzJm6Ye97EDXPPm7hh3mzNPW/ihrlnmwXMbSeoaZsFzG1nqGmbBcxtZ6hpmwXMbWeoaZsFzG1nKLnNAoSTTuC2WYCw2ARymwUIhU4IOoHbZgFCoxM6nTDoBG6bBQiTTlhsArnNAoRCJ3DbLEAYdAL3TsYHgdxmAQL9u0RuswBh0gmLTSC3WYBQ6ISgEyqd0OiETicMOoHbZgHCpBO4bRb4OIvbZgFCoROCTuC2WYDQ6IROJww64aQTuG0WICw2gdxmAUKhE4JOqHRCoxM6nTDoBG6bBQiTTuC2WeAQBLfNAoRCJwSdwG2zAKHRCZ1OGHTCSSdMOoH+5oTdZtFmQpvFA2LcZgF73xu2Ye97wzbsfW/Yhn2ztve9YRv2vjdsw973hm3Y+96wDXvfNouHvXGbBeytZ61xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXspdosHkJabRYQ8r1hG/a+N2zD3veGbdg3a3vfG7Zh73vDNux9b9iGve8N27D3vWH7YW/cZgF761lr3GYBe+tZa9xmAXvrWWvcZgF761lr3GYBe+tZq9VmASGpNgsISbVZQEiqzQJCKnPrEpJqs4CQVJsFhKTaLCAk1WYBIak2i4eQVpsFhJKX/VfX/UNJrM0CSmIX6OG4llibBZTE2iygJNZmASWxNgsoibVZQEmszQJKYm0WDyW1NgsoibVZQEmszQJKYm0WUGp6SmJtFlASa7OAklibBZTE2iygJNZm8VBSa7OAklibBZTE2iygJNZmAaWmpyTWZgElsTYLKIm1WUBJrM0CSmJtFjvKJNZmsZ3E2iy2k1ibxXYSuy1+O4m1WWwnsTaL7aT3Mk6uzWI7ibVZbCexNovt1ASdxPan3hPywQ+IcT4Y9r6ZJdj7ZpZg75tZgn2ztvfNLMHeN7MEe9/MEux9M0uw980HP+yN88Gwt561xvlg2FvPWuN8MOytZ61xPhj21rPWOB8Me6l88ENIKx8MId/MEux9M0uw980swb5Z2/tmlmDvm1mCvW9mCfa+mSXY+2aWHvbG+WDYW89a43ww7K1nrXE+GPbWs9Y4Hwx761lrnA+GvfWs1coHQ0gqHwwhqXwwhKTywRBSmVuXkFQ+GEJS+WAISeWDISSVD4aQVD74IaSVD4ZQ8rL/KkAJJbF8MJTEjiTiuJZYPhhKYvlgKInlg6Eklg+Gklg+GEpi+WAoieWDH0pq+WAoieWDoSSWD4aSWD4YSk1PSSwfDCWxfDCUxPLBUBLLB0NJLB/8UFLLB0NJLB8MJbF8MJTE8sFQanpKYvlgKInlg6Eklg+Gklg+GEpi+eAdZRLLB28nsXzwdhLLB28nvfydXD54O4nlg7eT3ss4uXzwdhLLB28nsXzwdmqCTmL706j/ebfHuR1PnRZf2MxrA19H+/ml8Y1Pxx/i01V8uYqXw9a82JqHrXm1NW+25t3WfNia207QYjtCi+0MDdsZGrYzNGxnaNjO0LCdoWE7Q4M2Qy/CSSe8PZP686RO6+2WsNiEetAJhU4IOuHtvW0+F0+b9ZbQ6IROJww64d013Y/zny/tx7wlTDphsQntoBMKnfDub2uP55f2uCcMOuHdn/Soz6Nuo8cdoR90Av271N9e0+36XernLWHSCYtNGAedUOiEoBMqndDohE4nDDrhg2t6jFvCpBPeX9PXznfeEs631/S1e78iFDoh6IR31/S48hDjWLeERid0OmHQCSed8PaaXs/Ln0c5bgmLTZgHnVDohKATKp3Q6IROJww64fwg4XZNz0knvL+mnydaRtwS1ttr+nod+opQ6ISgE96e01/9X3Q1OqHTCYNOOOmESSfQ35y8ODr9McRZE9oszurcZnFW5zaLszq3WZzVuc3irM5tFmd1brM4q3ObxVmd2yzO6txmcVbnNouzOrdZnNW5zeKszm0WZ3Vuszirc5vFWZ3bLM7q3GZxVuc2i7M6t1mcVazN4qxibRZndW6zOKtzm8VZndsszurcZnFW5zaLszq3WZzVuc3irM5tFmd1brM4q3ObxVmd2yxgbz1rjdssYG89a43bLM7q3GYBe+tZa9xmcVbnNouzirVZQEiqzQJCUm0WEJJqs4CQyty6hKTaLM4q1mZxVrE2i7OKtVmcVazN4qxibRZnlWuzOKtcm8VZ5doszirXZnFWuTaLs8q1WZxVrs3irHJtFmeVa7M4q1ybxVnl2izOKtdmcVa5NouzyrVZnFWuzeKscm0WZ5VrszirXJvFWeXaLM4q12ZxVrk2i7PKtVmcVa7N4qxybRZnlWuzOKtcm8VZ5doszirXZnFWuTaLs8q1WZxVr81iO4m1WWwnsTaL7SR2W/x2Emuz2E5ibRbbSe9lnFybxXYSa7PYTmJtFtupCTqJ7U/zMG2zeIh7XsX9EPe8ifshbtpmAXPPm7hh7nkTN8w9b+KGebM197yJG+aebRYwt52gpm0WMLedoaZtFjC3naGmbRYwt52hpm0WMLedoeQ2CxBOOoHbZgHCYhPIbRYgFDoh6ARumwUIjU7odMKgE7htFiBMOmGxCeQ2CxAKncBtswBh0AncOxkfBHKbBQj07xK5zQKESScsNoHcZgFCoROCTqh0QqMTOp0w6ARumwUIk07gtlng4yxumwUIhU4IOoHbZgFCoxM6nTDohJNO4LZZgLDYBHKbBQiFTgg6odIJjU7odMKgE7htFiBMOoHbZoFDENw2CxAKnRB0ArfNAoRGJ3Q6YdAJJ50w6QT6mxN2m8VcCW0WD4hxmwXsfW/Yhr3vDduw971hG/bN2t73hm3Y+96wDXvfG7Zh73vDNux92ywe9sZtFrC3nrXGbRawt561xm0WsLeetcZtFrC3nrXGbRawl2qzeAhptVlAyPeGbdj73rANe98btmHfrO19b9iGve8N27D3vWEb9r43bMPe94bth71xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXsrWetcZsF7K1nrVabBYSk2iwgJNVmASGpNgsIqcytS0iqzQJCUm0WEJJqs4CQVJsFhKTaLB5CWm0WEEpe9l9d9w8lsTYLKIldoIfjWmJtFlASa7OAklibBZTE2iygJNZmASWxNgsoibVZPJTU2iygJNZmASWxNgsoibVZQKnpKYm1WUBJrM0CSmJtFlASa7OAklibxUNJrc0CSmJtFlASa7OAklibBZSanpJYmwWUxNosoCTWZgElsTYLKIm1Wewok1ibxXYSa7PYTmJtFttJ7bb4pddmsZ3E2iy2k97LOLk2i+0k1maxncTaLLZTE3QS25/WSMgHPyDG+WDY+2aWYO+bWYK9b2YJ9s3a3jezBHvfzBLsfTNLsPfNLMHeNx/8sDfOB8PeetYa54Nhbz1rjfPBsLeetcb5YNhbz1rjfDDspfLBDyGtfDCEfDNLsPfNLMHeN7ME+2Zt75tZgr1vZgn2vpkl2PtmlmDvm1l62Bvng2FvPWuN88Gwt561xvlg2FvPWuN8MOytZ61xPhj21rNWKx8MIal8MISk8sEQksoHQ0hlbl1CUvlgCEnlgyEklQ+GkFQ+GEJS+eCHkFY+GELJy/6rACWUxPLBUBI7kojjWmL5YCiJ5YOhJJYPhpJYPhhKYvlgKInlg6Eklg9+KKnlg6Eklg+Gklg+GEpi+WAoNT0lsXwwlMTywVASywdDSSwfDCWxfPBDSS0fDCWxfDCUxPLBUBLLB0Op6SmJ5YOhJJYPhpJYPhhKYvlgKInlg3eUSSwfvJ3E8sHbSSwfvJ308ndy+eDtJJYP3k56L+Pk8sHbSSwfvJ3E8sHbqQk6ae1P85gv8sG9nc/n+jh/D/ncgXH4TDGfJebzImr9F4WKmlCoCVU1oaYm1NWEhpqQ2j5d1DbqorZTh9pOHWo7dajt1KG2U4faTh1qO3UQd+qLcSYw3t9PP3f6dAstMaF6qAkVNaFQE6pqQk1NqKsJDTWhU01Ibaeuajt1U9upm9pO3dR26qa2Uze1nbqp7dRNbaduxJ36YswExuIz+pHAKAmMSGDUBEZLYPQExkhgJKzz8f7v7heH9jclUijv/9z/4IO8sTL+LeeRQkn56Z/tA5TfnpzflJ5CGSmUM4UyUyifWC+/PXm7P84+UiglhRIplJpCaSmUnkIZKZQzhTJTKB9Y+78/SrqPjhwplJJCiRRKTaG0FEpPoYwUyplC+cDa//0h4U1ZGZRXx8g/jqkZ/7coR8vB9BzMyMGsFMwHTgT+EabkYCIHw1835bg/XHtej53nFy9d2/E869vii6O+89or1tH++8vb2X//KvchPl3Fl6v4/Sq2MC+25mFrXm3Nm615tzUftua2E7TYjtBiO0PDdoaG7QwN2xkatjM0bGdo2M7QoM3Qi3DSCW/PpP78TLX1dktYbEI96IRCJwSd8PbeNp+Lp816S2h0QqcTBp3w7prux/OFVD/mLWHSCYtNaAedUOiEd39bezy/tMc9YdAJ7/6kR32euhg97gj9oBPo36X+9pq+XjL3ft4SJp2w2IRx0AmFTgg6odIJjU7odMKgEz64pse4JUw64f01fe185y3hfHtNX7v3K0KhE4JOeHdNj+vk6jjWLaHRCZ1OGHTCSSe8vaZXfxLKcUtYbMI86IRCJwSdUOmERid0OmHQCecHCbdrek464f01/TxJN+KWsN5e09fr0FeEQicEnfD2nP7q/6Kr0QmdThh0wkknTDqB/ubkxYHSjyHixWm1f3k55fHc/Eor5Q5Skq9X/uBtQ/HqrJONfVjbV2v7Zm3fre2Htf1pbT+t7ZezfVjP2rCetWE9a8N61ob1rA3rWRvWszasZ21Yz9pQmbVPoaoyPi+h5In4wevB4tWpNxv7am3frO27tf2wtj+t7ae1/XK2b4e1vfWsbdaztlnP2mY9a5v1rG3Ws7ZZz9pmPWub9aztKrP2ElIZn5eQykS8hFSG3CWkMrcuIZVRdAmpTJdLSGVgXEIqM+ASUtnWn0JDbaceycv+q4uZ41Wi5O8qabVT7+NaRe67dIaeUtVTym6E/+Iy7HiVlfi7SlNPackpzUNPKX1f+v19z/EqIPJ3laqeUtNT6npKQ0/p1FOaekpLTmkdekrZu/cX94LHqyjQ31WqekpNT6nrKQ09pVNPaeopLTmlV3f8E51+XwiwnYqgUwg6dbkXOq96Cf6u0ynopPcyrmQnA//IKQSdqqBTE3RS259O0zaLh7jnVdwPcc+buB/ipm0WMPe8iRvmnjdxw9zzJm6YN1tzz5u4Ye7ZZgFz2wlq2mYBc9sZatpmAXPbGWraZgFz2xlq2mYBc9sZSm6zAOGkE7htFiAsNoHcZgFCoROCTuC2WYDQ6IROJww6gdtmAcKkExabQG6zAKHQCdw2CxAGncC9k/FBILdZgED/LpHbLECYdMJiE8htFiAUOiHohEonNDqh0wmDTuC2WYAw6QRumwU+zuK2WYBQ6ISgE7htFiA0OqHTCYNOOOkEbpsFCItNILdZgFDohKATKp3Q6IROJww6gdtmAcKkE7htFjgEwW2zAKHQCUEncNssQGh0QqcTBp1w0gmTTqC/OWG3WdSR0GbxgBi3WcDe94Zt2PvesA173xu2Yd+s7X1v2Ia97w3bsPe9YRv2vjdsw963zeJhb9xmAXvrWWvcZgF761lr3GYBe+tZa9xmAXvrWWvcZgF7qTaLh5BWmwWEfG/Yhr3vDduw971hG/bN2t73hm3Y+96wDXvfG7Zh73vDNux9b9h+2Bu3WcDeetYat1nA3nrWGrdZwN561hq3WcDeetYat1nA3nrWarVZQEiqzQJCUm0WEJJqs4CQyty6hKTaLCAk1WYBIak2CwhJtVlASKrN4iGk1WYBoeRl/9V1/1ASa7OAktgFejiuJdZmASWxNgsoibVZQEmszQJKYm0WUBJrs4CSWJvFQ0mtzQJKYm0WUBJrs4CSWJsFlJqeklibBZTE2iygJNZmASWxNgsoibVZPJTU2iygJNZmASWxNgsoibVZQKnpKYm1WUBJrM0CSmJtFlASa7OAklibxY4yibVZbCexNovtJNZmsZ3EbovfTmJtFttJrM1iO+m9jJNrs9hOYm0W20mszWI7NUEnsf2p1YR88ANinA+GvW9mCfa+mSXY+2aWYN+s7X0zS7D3zSzB3jezBHvfzBLsffPBD3vjfDDsrWetcT4Y9taz1jgfDHvrWWucD4a99aw1zgfDXiof/BDSygdDyDezBHvfzBLsfTNLsG/W9r6ZJdj7ZpZg75tZgr1vZgn2vpmlh71xPhj21rPWOB8Me+tZa5wPhr31rDXOB8PeetYa54Nhbz1rtfLBEJLKB0NIKh8MIal8MIRU5tYlJJUPhpBUPhhCUvlgCEnlgyEklQ9+CGnlgyGUvOy/ClBCSSwfDCWxI4k4riWWD4aSWD4YSmL5YCiJ5YOhJJYPhpJYPhhKYvngh5JaPhhKYvlgKInlg6Eklg+GUtNTEssHQ0ksHwwlsXwwlMTywVASywc/lNTywVASywdDSSwfDCWxfDCUmp6SWD4YSmL5YCiJ5YOhJJYPhpJYPnhHmcTywdtJLB+8ncTywdtJL38nlw/eTmL54O2k9zJOLh+8ncTywdtJLB+8nZqgk9j+1Mt/3u1xbsdTp8UXNvPawNfRfn5pfOPT8Yf4dBVfruLlsDUvtuZha15tzZutebc1H7bmthO02I7QYjtDw3aGhu0MDdsZGrYzNGxnaNjO0KDN0Itw0glvz6T+PKnTerslLDahHnRCoROCTnh7b5vPxdNmvSU0OqHTCYNOeHdN9+P850v7MW8Jk05YbEI76IRCJ7z729rj+aU97gmDTnj3Jz3q86jb6HFH6AedQP8u9bfXdLt+l/p5S5h0wmITxkEnFDoh6IRKJzQ6odMJg0744Joe45Yw6YT31/S18523hPPtNX3t3q8IhU4IOuHdNT2uPMQ41i2h0QmdThh0wkknvL2m1/Py51GOW8JiE+ZBJxQ6IeiESic0OqHTCYNOOD9IuF3Tc9IJ76/p54mWEbeE9faavl6HviIUOiHohLfn9Ff/F12NTuh0wqATTjph0gn0Nycvjk5/DDFKQpvFKM5tFqM4t1mM4txmMYpzm8Uozm0Wozi3WYzi3GYxinObxSjObRajOLdZjOLcZjGKc5vFKM5tFqM4t1mM4txmMYpzm8Uozm0Wozi3WYzi3GYxilibxShibRajOLdZjOLcZjGKc5vFKM5tFqM4t1mM4txmMYpzm8Uozm0Wozi3WYzi3GYxinObBeytZ61xmwXsrWetcZvFKM5tFrC3nrXGbRajOLdZjCLWZgEhqTYLCEm1WUBIqs0CQipz6xKSarMYRazNYhSxNotRxNosRhFrsxhFrM1iFLk2i1Hk2ixGkWuzGEWuzWIUuTaLUeTaLEaRa7MYRa7NYhS5NotR5NosRpFrsxhFrs1iFLk2i1Hk2ixGkWuzGEWuzWIUuTaLUeTaLEaRa7MYRa7NYhS5NotR5NosRpFrsxhFrs1iFLk2i1Hk2ixGkWuzGEWuzWIUuTaLUeTaLEbRa7PYTmJtFttJrM1iO4ndFr+dxNostpNYm8V20nsZJ9dmsZ3E2iy2k1ibxXZqgk5q+9M0bbN4iHtexf0Q97yJ+yFu2mYBc8+buGHueRM3zD1v4oZ5szX3vIkb5p5tFjC3naCmbRYwt52hpm0WMLedoaZtFjC3naGmbRYwt52h5DYLEE46gdtmAcJiE8htFiAUOiHoBG6bBQiNTuh0wqATuG0WIEw6YbEJ5DYLEAqdwG2zAGHQCdw7GR8EcpsFCPTvErnNAoRJJyw2gdxmAUKhE4JOqHRCoxM6nTDoBG6bBQiTTuC2WeDjLG6bBQiFTgg6gdtmAUKjEzqdMOiEk07gtlmAsNgEcpsFCIVOCDqh0gmNTuh0wqATuG0WIEw6gdtmgUMQ3DYLEAqdEHQCt80ChEYndDph0AknnTDpBPqbE3abxXkmtFk8IMZtFrD3vWEb9r43bMPe94Zt2Ddre98btmHve8M27H1v2Ia97w3bsPdts3jYG7dZwN561hq3WcDeetYat1nA3nrWGrdZwN561hq3WcBeqs3iIaTVZgEh3xu2Ye97wzbsfW/Yhn2ztve9YRv2vjdsw973hm3Y+96wDXvfG7Yf9sZtFrC3nrXGbRawt561xm0WsLeetcZtFrC3nrXGbRawt561Wm0WEJJqs4CQVJsFhKTaLCCkMrcuIak2CwhJtVlASKrNAkJSbRYQkmqzeAhptVlAKHnZf3XdP5TE2iygJHaBHo5ribVZQEmszQJKYm0WUBJrs4CSWJsFlMTaLKAk1mbxUFJrs4CSWJsFlMTaLKAk1mYBpaanJNZmASWxNgsoibVZQEmszQJKYm0WDyW1NgsoibVZQEmszQJKYm0WUGp6SmJtFlASa7OAklibBZTE2iygJNZmsaNMYm0W20mszWI7ibVZbCex2+K3k1ibxXYSa7PYTnov4+TaLLaTWJvFdhJrs9hOTdBJbH+aLSEf/IAY54Nh75tZgr1vZgn2vpkl2Ddre9/MEux9M0uw980swd43swR733zww944Hwx761lrnA+GvfWsNc4Hw9561hrng2FvPWuN88Gwl8oHP4S08sEQ8s0swd43swR738wS7Ju1vW9mCfa+mSXY+2aWYO+bWYK9b2bpYW+cD4a99aw1zgfD3nrWGueDYW89a43zwbC3nrXG+WDYW89arXwwhKTywRCSygdDSCofDCGVuXUJSeWDISSVD4aQVD4YQlL5YAhJ5YMfQlr5YAglL/uvApRQEssHQ0nsSCKOa4nlg6Eklg+Gklg+GEpi+WAoieWDoSSWD4aSWD74oaSWD4aSWD4YSmL5YCiJ5YOh1PSUxPLBUBLLB0NJLB8MJbF8MJTE8sEPJbV8MJTE8sFQEssHQ0ksHwylpqcklg+Gklg+GEpi+WAoieWDoSSWD95RJrF88HYSywdvJ7F88HbSy9/J5YO3k1g+eDvpvYyTywdvJ7F88HYSywdvpyboJLU/zfLyaP9ZnpDz/PnZdIn+87nzm8/Nbz63vvfc/XnvP3iufPO5+OZzt0toXn+vzHjxXPvmc/2bz41vPnd+87n5zefW9567P+A45/P9/1xx/1z55nPxzefqN59r33yuf/O58c3nbn9ffvngsxz3z81vPre+99z9IZ0/eK5887n45nP1m8/d/r6seK6jVe/X0f05jz94bnzzufObz81vPre+99z9UYE/eK588Vy7//mN+OZz9ZvP3f++9Od6X+N+vd8fD/iD58Y3nzu/+dz85nPre8+dxzefu/99mcf1qrjP/3nw//2bL74okUKpKZSWQukplJFCOVMoM4WyMij3n+x/nJKy9mfK2p8pa3+mrP2ZsvZnytqfKWt/pqz9mbL2V8raXylrf6Ws/ZWy9lfK2l8pa3+lrP2VsvZXytpfKWv/xaeKn8eUHEzkYGoOpuVgeg5m5GDOHMzMweTsAiVnFyg5u0DJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u0Dk7AKRswtEzi4QObtA5OwCkbMLRM4uEDm7QOTsApGzC9ScXaDm7AI1ZxeoObtAzdkFas4uUHN2gZqzC9ScXaDm7AItZxdoObtAy9kFWs4u0HJ2gZazC7ScXaDl7AItZxdoObtAz9kFes4u0HN2gZ6zC/ScXaDn7AI9ZxfoObtAz9kFes4uMHJ2gZGzC4ycXWDk7AIjZxcYObvAyNkFRs4uMHJ2gZGzC5w5u0DO+cCSc0Cw5JwQLDlHBEvOGcGSc0iw5JwSLDnHBEvOOcGSc1Cw5JwULDlHBUvOWcGSc1iw5JwWLDnHBUvOecGSc2Cw5JwYLDlHBkvOmcGSc2iw5JwaLDnHBkvOucGSc3Cw5JwcLDlHB0vO2cHIOTsYOWcHI+fsYOScHYyj5WB6DmbkYM4czMzB5OwCOWcHI+fsYOScHYycs4ORc3Ywcs4ORs7Zwcg5Oxg5Zwcj5+xg5JwdjJyzg5FzdjByzg5GztnByDk7GDlnByPn7GDknB2MnLODkXN2MHLODkbO2cHIOTsYOWcHI+fsYOScHYycs4ORc3Ywcs4ORs7Zwcg5Oxg5Zwcj5+xg5JwdjA+ctuv92f3Qz19uCPz1isAPHLb7A8oHTqf1+bwitv96Q+z/UCKFUlMoLYXSUyj/dtD8fPL87pMfODXwB7/XHzg08CeUnkIZKZSUXe0DBwb66v988Tj6C8rKoHzguMCfUEoKJVIoH1j7q1yU8YLSUig9hTJSKGcKZaZQVsbk/MAhgT+hpPx1tlL+Olspf5194IDAn1BS/jr7wPGAP6GcKZSZQslY+/U4UiglhRIplJpCaSmUnkIZKZQzhTJTKClrv6Ss/ZKy9kvK2i8pa7+krP2SsvZLytovKWu/pKz9krL2I2XtR8raj5S1HylrP1LWfqSs/UhZ+0Ff++v4z33dWW/nE9LH//Sm/l/G7E/GnOX3X1rK/Fm69EvLTMTlM8V8lpjP/Z82f1OoqAmFmlBVE2pqQl1NaKgJqe3TRW2jLmo7dajt1KG2U4faTh1qO3Wo7dShtlMHcae+GGcC4/399JfGunq8/41dYkL1UBMqakKhJlTVhJqaUFcTGmpCp5qQ2k5d1XbqprZTN7Wduqnt1E1tp25qO3VT26mb2k7diDv1xZgJjMVn9COBURIYkcCoCYyWwOgJjJHASFjn4/3f3XIczybocpS4pUQK5f2fe4n2c/cdty8Qxsr4t5xHCiXlp3+2D1DGuihz3FJ6CmWkUM4UykyhfGK9jPKTct5R5pFCKSmUSKHUFEpLofQUykihnCmUmUL5wNovpT2/uLTbv2HWkUIpKZRIodQUSkuh9BTKSKGcKZQPrP1yxkX59cTbL5SVQXnRav15TM34v8WLHujPY3oOZuRgVgrmAycC/whTcjCRg0lYN3F/uPa8HjvPL166tmP+86Ut+u+/dF57xTraf395O/uNV7lxfwrXQXy5it+vYgvzYmsetubV1rzZmndb82FrbjtBi+0ILbYzNGxnaNjO0LCdoWE7Q8N2hobtDA3aDL0IJ53w9kzqz89UW2+3hMUm1INOKHRC0Alv721XcLjNektodEKnEwad8O6a7sfzhVQ/5i1h0gmLTWgHnVDohHd/W3s8v7THPWHQCe/+pEd9nroYPe4I/aAT6N+l/vaavl4y937eEiadsNiEcdAJhU4IOqHSCY1O6HTCoBM+uKbHuCVMOuH9NX3tfOct4Xx7Tdf1BaHQCUEnvLumx3VydRzrltDohE4nDDrhpBPeXtM/L+Muxy1hsQnzoBMKnRB0QqUTGp3Q6YRBJ5wfJNyu6TnphPfX9PMk3Yhbwnp7TV+vQ18RCp0QdMLbc/qr/4uuRid0OmHQCSedMOkE+puTFwdKP4WI48VptTLqdW539C8+cinteG5+pZVyB3lxWvHfUdq8KOdXnwJ97LahbV+s7cPavlrbN2v7bm0/rO1Pa/tpbb+c7cN61ob1rA3rWRvWszasZ21Yz9qwnrVhPWvDetaGyqx9ClWV8XkJJU/Ez10Ptu3D2r5a2zdr+25tP6ztT2v7aW2/nO3bYW1vPWub9axt1rO2Wc/aZj1rm/WsbdaztlnP2mY9a7vKrL2EVMbnJaQyES8hlSF3CanMrUtIZRRdQirT5RJSGRiXkMoMuIRUtvWn0FDbqUfysv/iYuat1PWUkn+xv7hcbB/XKnLfpTP0lKqe0shW+u1l2Fvp1FOaekpLTmkeekrp+9Jv73veSqGnVPWUmp5S11MaekqnntLUU1pySuvQU8revX9/L/hWCj2lqqfU9JS6ntLQUzr1lKae0pJTenXHP9Hpt4UAP5yKoFMIOnW5Fzqvegn+rtMp6KT3Mq5kJwP/yCkEnaqgUxN0UtuflmebBcQtr+KGuOVN3BD3bLPY5pY3cW9zy5u4t7nlTdzbvNmaW97Evc0t2yy2ue0E9Wyz2Oa2M9SzzWKb285QzzaLbW47Qz3bLLa57QzltllswkknUNssNmGxCdw2i00odELQCdQ2i01odEKnEwadQG2z2IRJJyw2gdtmsQmFTqC2WWzCoBOodzKC0A86gf5d4rZZbMKkExabwG2z2IRCJwSdUOmERid0OmHQCdQ2i02YdAK1zWJ/nEVts9iEQicEnUBts9iERid0OmHQCSedQG2z2ITFJnDbLDah0AlBJ1Q6odEJnU4YdAK1zWITJp1AbbPYhyCobRabUOiEoBOobRab0OiETicMOuGkEyadQH9zwm6zKDOhzeIBMW6zgL3vDduw971hG/a+N2zDvlnb+96wDXvfG7Zh73vDNux9b9iGvW+bxcPeuM0C9taz1rjNAvbWs9a4zQL21rPWuM0C9taz1rjNAvZSbRYPIa02Cwj53rANe98btmHve8M27Ju1ve8N27D3vWEb9r43bMPe94Zt2PvesP2wN26zgL31rDVus4C99aw1brOAvfWsNW6zgL31rDVus4C99azVarOAkFSbBYSk2iwgJNVmASGVuXUJSbVZQEiqzQJCUm0WEJJqs4CQVJvFQ0irzQJCycv+q+v+oSTWZgElsQv0cFxLrM0CSmJtFlASa7OAklibBZTE2iygJNZmASWxNouHklqbBZTE2iygJNZmASWxNgsoNT0lsTYLKIm1WUBJrM0CSmJtFlASa7N4KKm1WUBJrM0CSmJtFlASa7OAUtNTEmuzgJJYmwWUxNosoCTWZgElsTaLHWUSa7PYTmJtFttJrM1iO4ndFr+dxNostpNYm8V20nsZJ9dmsZ3E2iy2k1ibxXZqgk5i+1P0hHzwA2KcD4a9b2YJ9r6ZJdj7ZpZg36ztfTNLsPfNLMHeN7MEe9/MEux988EPe+N8MOytZ61xPhj21rPWOB8Me+tZa5wPhr31rDXOB8NeKh/8ENLKB0PIN7MEe9/MEux9M0uwb9b2vpkl2PtmlmDvm1mCvW9mCfa+maWHvXE+GPbWs9Y4Hwx761lrnA+GvfWsNc4Hw9561hrng2FvPWu18sEQksoHQ0gqHwwhqXwwhFTm1iUklQ+GkFQ+GEJS+WAISeWDISSVD34IaeWDIZS87L8KUEJJLB8MJbEjiTiuJZYPhpJYPhhKYvlgKInlg6Eklg+Gklg+GEpi+eCHklo+GEpi+WAoieWDoSSWD4ZS01MSywdDSSwfDCWxfDCUxPLBUBLLBz+U1PLBUBLLB0NJLB8MJbF8MJSanpJYPhhKYvlgKInlg6Eklg+Gklg+eEeZxPLB20ksH7ydxPLB20kvfyeXD95OYvng7aT3Mk4uH7ydxPLB20ksH7ydmqCT2P5U63/e7XFux1OnxRc289rA19F+fml849Pxh/h0FV+u4uWwNS+25mFrXm3Nm615tzUftua2E7TYjtBiO0PDdoaG7QwN2xkatjM0bGdo2M7QoM3Qi3DSCW/PpP48qdN6uyUsNqEedEKhE4JOeHtvm8/F02a9JTQ6odMJg054d0334/znS/sxbwmTTlhsQjvohEInvPvb2uP5pT3uCYNOePcnPerzqNvocUfoB51A/y71t9d0u36X+nlLmHTCYhPGQScUOiHohEonNDqh0wmDTvjgmh7jljDphPfX9LXznbeE8+01fe3erwiFTgg64d01Pa48xDjWLaHRCZ1OGHTCSSe8vabX8/LnUY5bwmIT5kEnFDoh6IRKJzQ6odMJg044P0i4XdNz0gnvr+nniZYRt4T19pq+Xoe+IhQ6IeiEt+f0V/8XXY1O6HTCoBNOOmHSCfQ3Jy+OTn8M0WpCm0Wrzm0WrTq3WbTq3GbRqnObRavObRatOrdZtOrcZtGqc5tFq85tFq06t1m06txm0apzm0Wrzm0WrTq3WbTq3GbRqnObRavObRatOrdZtOrcZtGqWJtFq2JtFq06t1m06txm0apzm0Wrzm0WrTq3WbTq3GbRqnObRavObRatOrdZtOrcZtGqc5sF7K1nrXGbBeytZ61xm0Wrzm0WsLeetcZtFq06t1m0KtZmASGpNgsISbVZQEiqzQJCKnPrEpJqs2hVrM2iVbE2i1bF2ixaFWuzaFWszaJVuTaLVuXaLFqVa7NoVa7NolW5NotW5dosWpVrs2hVrs2iVbk2i1bl2ixalWuzaFWuzaJVuTaLVuXaLFqVa7NoVa7NolW5NotW5dosWpVrs2hVrs2iVbk2i1bl2ixalWuzaFWuzaJVuTaLVuXaLFqVa7NoVa7NolW5NotW5dosWtVrs9hOYm0W20mszWI7id0Wv53E2iy2k1ibxXbSexkn12axncTaLLaTWJvFdmqCTmL7Uz9M2ywe4p5XcT/EPW/ifoibtlnA3PMmbph73sQNc8+buGHebM09b+KGuWebBcxtJ6hpmwXMbWeoaZsFzG1nqGmbBcxtZ6hpmwXMbWcouc0ChJNO4LZZgLDYBHKbBQiFTgg6gdtmAUKjEzqdMOgEbpsFCJNOWGwCuc0ChEIncNssQBh0AvdOxgeB3GYBAv27RG6zAGHSCYtNILdZgFDohKATKp3Q6IROJww6gdtmAcKkE7htFvg4i9tmAUKhE4JO4LZZgNDohE4nDDrhpBO4bRYgLDaB3GYBQqETgk6odEKjEzqdMOgEbpsFCJNO4LZZ4BAEt80ChEInBJ3AbbMAodEJnU4YdMJJJ0w6gf7mhN1m0VdCm8UDYtxmAXvfG7Zh73vDNux9b9iGfbO2971hG/a+N2zD3veGbdj73rANe982i4e9cZsF7K1nrXGbBeytZ61xmwXsrWetcZsF7K1nrXGbBeyl2iweQlptFhDyvWEb9r43bMPe94Zt2Ddre98btmHve8M27H1v2Ia97w3bsPe9Yfthb9xmAXvrWWvcZgF761lr3GYBe+tZa9xmAXvrWWvcZgF761mr1WYBIak2CwhJtVlASKrNAkIqc+sSkmqzgJBUmwWEpNosICTVZgEhqTaLh5BWmwWEkpf9V9f9Q0mszQJKYhfo4biWWJsFlMTaLKAk1mYBJbE2CyiJtVlASazNAkpibRYPJbU2CyiJtVlASazNAkpibRZQanpKYm0WUBJrs4CSWJsFlMTaLKAk1mbxUFJrs4CSWJsFlMTaLKAk1mYBpaanJNZmASWxNgsoibVZQEmszQJKYm0WO8ok1maxncTaLLaTWJvFdlK7LX7ptVlsJ7E2i+2k9zJOrs1iO4m1WWwnsTaL7dQEncT2pzES8sEPiHE+GPa+mSXY+2aWYO+bWYJ9s7b3zSzB3jezBHvfzBLsfTNLsPfNBz/sjfPBsLeetcb5YNhbz1rjfDDsrWetcT4Y9taz1jgfDHupfPBDSCsfDCHfzBLsfTNLsPfNLMG+Wdv7ZpZg75tZgr1vZgn2vpkl2Ptmlh72xvlg2FvPWuN8MOytZ61xPhj21rPWOB8Me+tZa5wPhr31rNXKB0NIKh8MIal8MISk8sEQUplbl5BUPhhCUvlgCEnlgyEklQ+GkFQ++CGklQ+GUPKy/ypACSWxfDCUxI4k4riWWD4YSmL5YCiJ5YOhJJYPhpJYPhhKYvlgKInlgx9KavlgKInlg6Eklg+Gklg+GEpNT0ksHwwlsXwwlMTywVASywdDSSwf/FBSywdDSSwfDCWxfDCUxPLBUGp6SmL5YCiJ5YOhJJYPhpJYPhhKYvngHWUSywdvJ7F88HYSywdvJ738nVw+eDuJ5YO3k97LOLl88HYSywdvJ7F88HZqgk5i+9M5X+SDezufz/Vx/h7ywQPjD58p5rPEfF5Erf+iUFETCjWhqibU1IS6mtBQE1Lbp4vaRl3UdupQ26lDbacOtZ061HbqUNupQ22nDuJOfTHOBMb7++kHT59CaIkJ1UNNqKgJhZpQVRNqakJdTWioCZ1qQmo7dVXbqZvaTt3UduqmtlM3tZ26qe3UTW2nbmo7dSPu1BdjJjAWn9GPBEZJYEQCoyYwWgKjJzBGAiNhnY/3f3e/OrQPSqRQ3v+5/8EHeWNl/FvOI4WS8tM/2wcovz85D0pPoYwUyplCmSmUT6yX35+8xcfZRwqlpFAihVJTKC2F0lMoI4VyplBmCuUDa/+Lo6Q4OnKkUEoKJVIoNYXSUig9hTJSKGcK5QNr/4tDwqCsDMqrY+Qfx9SM/1uUo+Vgeg5m5GBWCuYDJwL/CFNyMJGD4a+bedwfrj2vx87zi5eu7Xie9W3xxVHfee0V62j//eXt7L9/lfsQn67iy1X8fhVbmBdb87A1r7bmzda825oPW3PbCVpsR2ixnaFhO0PDdoaG7QwN2xkatjM0bGdo0GboRTjphLdnUn9+ptp6uyUsNqEedEKhE4JOeHtvm8/F02a9JTQ6odMJg054d0334/lCqh/zljDphMUmtINOKHTCu7+tPZ5f2uOeMOiEd3/Soz5PXYwed4R+0An071J/e01fL5l7P28Jk05YbMI46IRCJwSdUOmERid0OmHQCR9c02PcEiad8P6avna+85Zwvr2mr937FaHQCUEnvLumx3VydRzrltDohE4nDDrhpBPeXtOrPwnluCUsNmEedEKhE4JOqHRCoxM6nTDohPODhNs1PSed8P6afp6kG3FLWG+v6et16CtCoROCTnh7Tn/1f9HV6IROJww64aQTJp1Af3Py4kDpxxDrxWm1f3k55fHc/Eor5Q5Skq9X/uBtQ+vVWScb+7C2r9b2zdq+W9sPa/vT2n5a2y9n+7CetWE9a8N61ob1rA3rWRvWszasZ21Yz9qwnrWhMmufQlVlfF5CyRPxg9eDrVen3mzsq7V9s7bv1vbD2v60tp/W9svZvh3W9taztlnP2mY9a5v1rG3Ws7ZZz9pmPWub9axt1rO2q8zaS0hlfF5CKhPxElIZcpeQyty6hFRG0SWkMl0uIZWBcQmpzIBLSGVbfwoNtZ16JC/7ry5mXq8SJX9XSayder3KSvzV79IZekpVTym7Ef6Ly7DXq6zE31WaekpLTmkeekrp+9Lv73terwIif1ep6ik1PaWupzT0lE49pamntOSU1qGnlL17f3Ev+HoVBfq7SlVPqekpdT2load06ilNPaUlp/Tqjn+i0+8LAbZTEXQKQacu90LnVS/B33U6BZ30XsaV7GTgHzmFoFMVdGqCTmr702naZvEQ97yK+yHueRP3Q9y0zQLmnjdxw9zzJm6Ye97EDfNma+55EzfMPdssYG47QU3bLGBuO0NN2yxgbjtDTdssYG47Q03bLGBuO0PJbRYgnHQCt80ChMUmkNssQCh0QtAJ3DYLEBqd0OmEQSdw2yxAmHTCYhPIbRYgFDqB22YBwqATuHcyPgjkNgsQ6N8lcpsFCJNOWGwCuc0ChEInBJ1Q6YRGJ3Q6YdAJ3DYLECadwG2zwMdZ3DYLEAqdEHQCt80ChEYndDph0AknncBtswBhsQnkNgsQCp0QdEKlExqd0OmEQSdw2yxAmHQCt80ChyC4bRYgFDoh6ARumwUIjU7odMKgE046YdIJ9Dcn5DaLegx+mwUgvm0W2972hu1tb3vD9ra3vWF72zdre9sbtre97Q3b2972hu1tb3vD9ra3bbOAvW+bxba3nrW+bRbb3nrW+rZZbHvrWevbZrHtrWetb5vFtldqs4CQVJvFFrK9YXvb296wve1tb9je9s3a3vaG7W1ve8P2tre9YXvb296wve1tb9iGvW+bxba3nrW+bRbb3nrW+rZZbHvrWevbZrHtrWetb5vFtreetVJtFltIqc1iCym1WWwhpTaLLaQyty4hpTaLLaTUZrGFlNostpBSm8UWUmqzgJBUm8UWSl72X1z3v5W02iy2ktYFevu4llabxVbSarPYSlptFltJq81iK2m1WWwlrTaLraTVZgElsTaLraTVZrGVtNostpJWm8VWanpKWm0WW0mrzWIrabVZbCWtNoutpNVmASWxNoutpNVmsZW02iy2klabxVZqekpabRZbSavNYitptVlsJa02i62k1WbxI8qk1Wbxw0mrzeKHk1abxQ8nrdvifzhptVn8cNJqs/jhpPcyTq3N4oeTVpvFDyetNosfTk3QSWx/KjUhH/yAGOeDYe+bWYK9b2YJ9r6ZJdg3a3vfzBLsfTNLsPfNLMHeN7MEe9988MPeOB8Me+tZa5wPhr31rDXOB8PeetYa54Nhbz1rjfPBsJfKBz+EtPLBEPLNLMHeN7MEe9/MEuybtb1vZgn2vpkl2PtmlmDvm1mCvW9m6WFvnA+GvfWsNc4Hw9561hrng2FvPWuN88Gwt561xvlg2FvPWq18MISk8sEQksoHQ0gqHwwhlbl1CUnlgyEklQ+GkFQ+GEJS+WAISeWDH0Ja+WAIJS/7rwKUUBLLB0NJ7EgijmuJ5YOhJJYPhpJYPhhKYvlgKInlg6Eklg+Gklg++KGklg+Gklg+GEpi+WAoieWDodT0lMTywVASywdDSSwfDCWxfDCUxPLBDyW1fDCUxPLBUBLLB0Op6ik1PSWxfDCUxPLBUBLLB0NJLB8MJbF88I4yieWDt5NYPng7ieWDt5Ne/k4uH7ydxPLB20nvZZxcPng7ieWDt5NYPng7NUEnsf0pyn/e7XFux1OnxRc289rA19F+fml849Pxh/h0FV+u4uWwNS+25mFrXm3Nm615tzUftua2E7TYjtBiO0PDdoaG7QwN2xkatjM0bGdo2M7QoM3Qi3DSCW/PpP48qfP/qTu7JDeOpNlu6DNZReT/4mbvtzwpAJTdgtACEEH3ee6ac9TsiiDR6em11UvCiiaUI5xg4QQPJ3w82+bt5amzXBJqOKGFE3o44dN3uh3j7y9tx7wkzHDCiibUI5xg4YRPf1qb3760+TWhhxM+/ZPu5XbUrTe/IrQjnBD+XWofv9P1/rPUxiVhhhNWNKEf4QQLJ3g4oYQTajihhRN6OOGL73Tvl4QZTvj8nb5PvnFJGB+/0/fp/Yxg4QQPJ3z6Tvd7HqIf65JQwwktnNDDCSOc8PE7vW6XP3c7LgkrmjCPcIKFEzycUMIJNZzQwgk9nDC+SLh8p+cMJ3z+Tt9OtHS/JKyP3+n7x6HPCBZO8HDCx3v61b9FVw0ntHBCDyeMcMIMJ4R/cvLk6PTXEMUS2iyKKbdZFFNusyim3GZRTLnNophym0Ux5TaLYsptFsWU2yyKKbdZFFNusyim3GZRTLnNophym0Ux5TaLYsptFsWU2yyKKbdZFFNusyim3GZRjKzNohhZm0Ux5TaLYsptFsWU2yyKKbdZFFNusyim3GZRTLnNophym0Ux5TaLYsptFsWU2yxgL71rhdssYC+9a4XbLIopt1nAXnrXCrdZFFNusyhG1mYBIao2CwhRtVlAiKrNAkIse+suRNVmUYyszaIYWZtFMbI2i2JkbRbFyNositG1WRSja7MoRtdmUYyuzaIYXZtFMbo2i2J0bRbF6NositG1WRSja7MoRtdmUYyuzaIYXZtFMbo2i2J0bRbF6NositG1WRSja7MoRtdmUYyuzaIYXZtFMbo2i2J0bRbF6NositG1WRSja7MoRtdmUYyuzaIYXZtFMbo2i2J8bRbbiazNYjuRtVlsJ7Lb4rcTWZvFdiJrs9hOfB/G0bVZbCeyNovtRNZmsZ0qoRPbfJqibRanuOZV3Ke45k3cp7homwXMNW/ihrnmTdww17yJG+ZV1lzzJm6Ya7ZZwFx2g4q2WcBcdoeKtlnAXHaHirZZwFx2h4q2WcBcdocGt1mAMMIJsW0WIKxoQnCbBQgWTvBwQmybBQg1nNDCCT2cENtmAcIMJ6xoQnCbBQgWTohtswChhxNi72Q8CcFtFiCEf5eC2yxAmOGEFU0IbrMAwcIJHk4o4YQaTmjhhB5OiG2zAGGGE2LbLPDrrNg2CxAsnODhhNg2CxBqOKGFE3o4YYQTYtssQFjRhOA2CxAsnODhhBJOqOGEFk7o4YTYNgsQZjghts0ChyBi2yxAsHCChxNi2yxAqOGEFk7o4YQRTpjhhPBPTqLbLOpIaLM4IcJtFrDXvWEb9ro3bMNe94Zt2Fdpe90btmGve8M27HVv2Ia97g3bsNdtszjthdssYC+9a4XbLGAvvWuF2yxgL71rhdssYC+9a4XbLGBP1WZxCnG1WUBI94Zt2OvesA173Ru2YV+l7XVv2Ia97g3bsNe9YRv2ujdsw173hu3TXrjNAvbSu1a4zQL20rtWuM0C9tK7VrjNAvbSu1a4zQL20ruWq80CQlRtFhCiarOAEFWbBYRY9tZdiKrNAkJUbRYQomqzgBBVmwWEqNosTiGuNgsIJb/2r677hxJZmwWUyC7Qw3EtsjYLKJG1WUCJrM0CSmRtFlAia7OAElmbBZTI2ixOJbY2CyiRtVlAiazNAkpkbRZQqnxKZG0WUCJrs4ASWZsFlMjaLKBE1mZxKrG1WUCJrM0CSmRtFlAia7OAUuVTImuzgBJZmwWUyNosoETWZgElsjaLHWUia7PYTmRtFtuJrM1iO5HdFr+dyNosthNZm8V24vswjq7NYjuRtVlsJ7I2i+1UCZ3I5lOrCfngEyKcD4a9bmYJ9rqZJdjrZpZgX6XtdTNLsNfNLMFeN7MEe93MEux188GnvXA+GPbSu1Y4Hwx76V0rnA+GvfSuFc4Hw1561wrng2FPlQ8+hbjywRDSzSzBXjezBHvdzBLsq7S9bmYJ9rqZJdjrZpZgr5tZgr1uZum0F84Hw1561wrng2EvvWuF88Gwl961wvlg2EvvWuF8MOyldy1XPhhCVPlgCFHlgyFElQ+GEMveugtR5YMhRJUPhhBVPhhCVPlgCFHlg08hrnwwhJJf+1cBSiiR5YOhRHYkEce1yPLBUCLLB0OJLB8MJbJ8MJTI8sFQIssHQ4ksH3wqseWDoUSWD4YSWT4YSmT5YChVPiWyfDCUyPLBUCLLB0OJLB8MJbJ88KnElg+GElk+GEpk+WAokeWDoVT5lMjywVAiywdDiSwfDCWyfDCUyPLBO8pElg/eTmT54O1Elg/eTnz5O7p88HYiywdvJ74P4+jywduJLB+8ncjywdupEjpxzaf+9Gj/sBtkjMfvps3b47nx5nPzzefWe89dn/f+wXP25nP+5nOXr9C8/31l+pPn6pvPtTef628+N958br753HrvuesDjnPePv+fy6+fszef8zefK28+V998rr35XH/zucufl99+8WnH9XPzzefWe89dH9L5wXP25nP+5nPlzecuf16W396jVa7fo+tzHj94rr/53Hjzufnmc+u9566PCvzgOXvxXL3+8+v+5nPlzeeuf17a7X1f/fp9vz4e8IPn+pvPjTefm28+t957bhxvPnf98zKP+0fFbf7jwf/7L198p3gKpaRQagqlpVB6CmWkUGYKZWVQrn+z/3VKyrs/U979mfLuz5R3f6a8+zPl3Z8p7/5Mefdnyru/Ut79lfLur5R3f6W8+yvl3V8p7/5KefdXyru/Ut79lfLuP/mt4vcxloPxHEzJwdQcTMvB9BzMyMHMHEzOFLCcKWA5U8BypoDlTAHLmQKWMwUsZwpYzhSwnClgOVPAc6aA50wBz5kCnjMFPGcKeM4U8Jwp4DlTwHOmgOdMgZIzBUrOFCg5U6DkTIGSMwVKzhQoOVOg5EyBkjMFSs4UqDlToOZMgZozBWrOFKg5U6DmTIGaMwVqzhSoOVOg5kyBljMFWs4UaDlToOVMgZYzBVrOFGg5U6DlTIGWMwVazhToOVOg50yBnjMFes4U6DlToOdMgZ4zBXrOFOg5U6DnTIGRMwVyzgdazgFByzkhaDlHBC3njKDlHBK0nFOClnNM0HLOCVrOQUHLOSloOUcFLeesoOUcFrSc04KWc1zQcs4LWs6BQcs5MWg5RwYt58yg5RwatJxTg5ZzbNByzg1azsFByzk5aDlHBy3n7KDnnB30nLODnnN20HPODvpRczAtB9NzMCMHM3MwOVMg5+yg55wd9Jyzg55zdtBzzg56ztlBzzk76DlnBz3n7KDnnB30nLODnnN20HPODnrO2UHPOTvoOWcHPefsoOecHfScs4Oec3bQc84Oes7ZQc85O+g5Zwc95+yg55wd9Jyzg55zdtBzzg56ztlBzzk76DlnBz3n7KDnnB30nLOD/oXTdq3duh/a+O2GwN+vCPzCYbsfUL5wOq3N2xWx7fcbYv9B8RRKSaHUFEpLofzXRfN4crz75BdODfzg5/oLhwZ+QmkplJ5CSZlqXzgw0Fb7+4v70Z5QVgblC8cFfkKxFIqnUL7w7i+7U/oTSk2htBRKT6GMFMpMoayMzfmFQwI/oaT87Wyl/O1spfzt7AsHBH5CSfnb2ReOB/yEMlIoM4WS8e6X40ihWArFUyglhVJTKC2F0lMoI4UyUygp776lvPuW8u5byrtvKe++pbz7lvLuW8q7bynvvqW8+5by7nvKu+8p776nvPue8u57yrvvKe++p7z7Hv7u9+Ov67qzVscN0vo/elP/f8ZsN8ac9u9fajYfpUu/tcy4330mmc8i87n+q82fFDI2IWcTKmxClU2osQl1NiG2OW1sg9rYJrWzTWpnm9TONqmdbVI726R2tkntgZP6zhgJjM/n6W+NdeX4/Bu7yITKwSZkbELOJlTYhCqbUGMT6mxCg02IbVIXtkld2SZ1ZZvUlW1SV7ZJXdkmdWWb1JVtUtfASX1nzATGime0I4FhCQxPYJQERk1gtARGT2AkvOf9859dO45bE7Qd5pcUT6F8/uduXh/Tt19+gNBXxn/LOFIoKX/6o36B0tedMvslpaVQegplpFBmCuUb70u3B2VcUeaRQrEUiqdQSgqlplBaCqWnUEYKZaZQvvDum9XbF1u9/DvMOlIolkLxFEpJodQUSkuh9BTKSKF84d234XfK7yfefqOsDMqTVuvvY0rGvy2e9EB/H9NyMD0Hs1IwXzgR+COM5WA8B5Pw3vj14dpxf2yMFx+61mP+/aXV279/6bzPinXU//326ewbH+X69SlcBfGlKn79FkuYm6y5y5oXWfMqa95kzbusuewGNdkVarI71GV3qMvuUJfdoS67Q112h7rsDvWwHXonjHDCxzup3X6nWlu9JKxoQjnCCRZO8HDCx7PtHhyus1wSajihhRN6OOHTd7odtw+k2jEvCTOcsKIJ9QgnWDjh05/W5rcvbX5N6OGET/+ke7mduujNrwjtCCeEf5fax+/0/UPm1sYlYYYTVjShH+EECyd4OKGEE2o4oYUTejjhi+9075eEGU74/J2+T75xSRgfv9NlvSBYOMHDCZ++0/1+crUf65JQwwktnNDDCSOc8PE7/biM245LwoomzCOcYOEEDyeUcEINJ7RwQg8njC8SLt/pOcMJn7/Tt5N03S8J6+N3+v5x6DOChRM8nPDxnn71b9FVwwktnNDDCSOcMMMJ4Z+cPDlQ+jXEeHJazXq5n9vt7cWvXKwet+Fn1ewK8uS04n+j1HmnjFe/BfrebUPj2VknGXuXti/S9lXavknbd2n7IW0/pe2Xsr1L71qX3rUuvWtdete69K516V3r0rvWpXetS+9aZ9m1N6HCsj7vQskb8YvXg41np95k7Iu0fZW2b9L2Xdp+SNtPafulbF8PaXvpXVuld22V3rVVetdW6V1bpXdtld61VXrXVuld21h27V2IZX3ehVg24l2IZcndhVj21l2IZRXdhVi2y12IZWHchVh2wF2IZazfhDrbpO7Jr/2ri5nHs0TJn1VK/sF+dbnYeJaV+KPfpeF8SoVPqWcr/ftl2ONZVuLPKk0+pUWnNA8+pfS59O/3PY9nAZE/q1T4lCqfUuNT6nxKg09p8iktOqV18CllT+8X94KPZ1GgP6tU+JQqn1LjU+p8SoNPafIpLTqlZ3f8Bzr9eyHAdjJCJyd0anQf6DzrJfizToPQie/DOMtOBv7IyQmdCqFTJXRim09LtM3iFNe8ivsU17yJ+xQXbbOAueZN3DDXvIkb5po3ccO8yppr3sQNc802C5jLblDRNguYy+5Q0TYLmMvuUNE2C5jL7lDRNguYy+7Q4DYLEEY4IbbNAoQVTQhuswDBwgkeTohtswChhhNaOKGHE2LbLECY4YQVTQhuswDBwgmxbRYg9HBC7J2MJyG4zQKE8O9ScJsFCDOcsKIJwW0WIFg4wcMJJZxQwwktnNDDCbFtFiDMcEJsmwV+nRXbZgGChRM8nBDbZgFCDSe0cEIPJ4xwQmybBQgrmhDcZgGChRM8nFDCCTWc0MIJPZwQ22YBwgwnxLZZ4BBEbJsFCBZO8HBCbJsFCDWc0MIJPZwwwgkznBD+yUl0m8WcCW0WJ0S4zQL2ujdsw173hm3Y696wDfsqba97wzbsdW/Yhr3uDduw171hG/a6bRanvXCbBeyld61wmwXspXetcJsF7KV3rXCbBeyld61wmwXsqdosTiGuNgsI6d6wDXvdG7Zhr3vDNuyrtL3uDduw171hG/a6N2zDXveGbdjr3rB92gu3WcBeetcKt1nAXnrXCrdZwF561wq3WcBeetcKt1nAXnrXcrVZQIiqzQJCVG0WEKJqs4AQy966C1G1WUCIqs0CQlRtFhCiarOAEFWbxSnE1WYBoeTX/tV1/1Aia7OAEtkFejiuRdZmASWyNgsokbVZQImszQJKZG0WUCJrs4ASWZvFqcTWZgElsjYLKJG1WUCJrM0CSpVPiazNAkpkbRZQImuzgBJZmwWUyNosTiW2NgsokbVZQImszQJKZG0WUKp8SmRtFlAia7OAElmbBZTI2iygRNZmsaNMZG0W24mszWI7kbVZbCey2+K3E1mbxXYia7PYTnwfxtG1WWwnsjaL7UTWZrGdKqET2XxaLSEffEKE88Gw180swV43swR73cwS7Ku0vW5mCfa6mSXY62aWYK+bWYK9bj74tBfOB8NeetcK54NhL71rhfPBsJfetcL5YNhL71rhfDDsqfLBpxBXPhhCupkl2OtmlmCvm1mCfZW2180swV43swR73cwS7HUzS7DXzSyd9sL5YNhL71rhfDDspXetcD4Y9tK7VjgfDHvpXSucD4a99K7lygdDiCofDCGqfDCEqPLBEGLZW3chqnwwhKjywRCiygdDiCofDCGqfPApxJUPhlDya/8qQAklsnwwlMiOJOK4Flk+GEpk+WAokeWDoUSWD4YSWT4YSmT5YCiR5YNPJbZ8MJTI8sFQIssHQ4ksHwylyqdElg+GElk+GEpk+WAokeWDoUSWDz6V2PLBUCLLB0OJLB8MJbJ8MJQqnxJZPhhKZPlgKJHlg6FElg+GElk+eEeZyPLB24ksH7ydyPLB24kvf0eXD95OZPng7cT3YRxdPng7keWDtxNZPng7VUInrvk0jvLXpz3O9bjpVH9hM+8DfB318aX+3387DvGpKr5Uxe2QNTdZc5c1L7LmVda8yZp3WXPZDWqyK9Rkd6jL7lCX3aEuu0Nddoe67A512R3qYTv0ThjhhI93Urud1KmtXhJWNKEc4QQLJ3g44ePZNm8vT53lklDDCS2c0MMJn77T7Rh/f2k75iVhhhNWNKEe4QQLJ3z609r89qXNrwk9nPDpn3Qvt6NuvfkVoR3hhPDvUvv4na73n6U2LgkznLCiCf0IJ1g4wcMJJZxQwwktnNDDCV98p3u/JMxwwufv9H3yjUvC+Pidvk/vZwQLJ3g44dN3ut/zEP1Yl4QaTmjhhB5OGOGEj9/pdbv8udtxSVjRhHmEEyyc4OGEEk6o4YQWTujhhPFFwuU7PWc44fN3+naipfslYX38Tt8/Dn1GsHCChxM+3tOv/i26ajihhRN6OGGEE2Y4IfyTkydHp7+GsBLfZgGIbpvFtpe9YXvby96wve1lb9je9lXaXvaG7W0ve8P2tpe9YXvby96wve1l2yxgr9tmse2ld61um8W2l961um0W21561+q2WWx76V2r22ax7ZnaLCBE1WaxhWRv2N72sjdsb3vZG7a3fZW2l71he9vL3rC97WVv2N72sjdsb3vZG7Zhr9tmse2ld61um8W2l961um0W21561+q2WWx76V2r22ax7aV3LVWbxRZiarPYQkxtFluIqc1iC7HsrbsQU5vFFmJqs9hCTG0WW4ipzWILMbVZQIiqzWILJb/2L67730pcbRZbiesCvX1ci6vNYitxtVlsJa42i63E1WaxlbjaLLYSV5vFVuJqs4ASWZvFVuJqs9hKXG0WW4mrzWIrVT4lrjaLrcTVZrGVuNosthJXm8VW4mqzgBJZm8VW4mqz2EpcbRZbiavNYitVPiWuNoutxNVmsZW42iy2ElebxVbiarP4FWXiarP45cTVZvHLiavN4pcT2W3x24mrzeKXE1ebxS8nvg/j2NosfjlxtVn8cuJqs/jlVAmdyOaTH6JtFqe45lXcp7jmTdynuGibBcw1b+KGueZN3DDXvIkb5lXWXPMmbphrtlnAXHaDirZZwFx2h4q2WcBcdoeKtlnAXHaHirZZwFx2hwa3WYAwwgmxbRYgrGhCcJsFCBZO8HBCbJsFCDWc0MIJPZwQ22YBwgwnrGhCcJsFCBZOiG2zAKGHE2LvZDwJwW0WIIR/l4LbLECY4YQVTQhuswDBwgkeTijhhBpOaOGEHk6IbbMAYYYTYtss8Ous2DYLECyc4OGE2DYLEGo4oYUTejhhhBNi2yxAWNGE4DYLECyc4OGEEk6o4YQWTujhhNg2CxBmOCG2zQKHIGLbLECwcIKHE2LbLECo4YQWTujhhBFOmOGE8E9OotssfCW0WZwQ4TYL2OvesA173Ru2Ya97wzbsq7S97g3bsNe9YRv2ujdsw173hm3Y67ZZnPbCbRawl961wm0WsJfetcJtFrCX3rXCbRawl961wm0WsKdqsziFuNosIKR7wzbsdW/Yhr3uDduwr9L2ujdsw173hm3Y696wDXvdG7Zhr3vD9mkv3GYBe+ldK9xmAXvpXSvcZgF76V0r3GYBe+ldK9xmAXvpXcvVZgEhqjYLCFG1WUCIqs0CQix76y5E1WYBIao2CwhRtVlAiKrNAkJUbRanEFebBYSSX/tX1/1DiazNAkpkF+jhuBZZmwWUyNosoETWZgElsjYLKJG1WUCJrM0CSmRtFqcSW5sFlMjaLKBE1mYBJbI2CyhVPiWyNgsokbVZQImszQJKZG0WUCJrsziV2NosoETWZgElsjYLKJG1WUCp8imRtVlAiazNAkpkbRZQImuzgBJZm8WOMpG1WWwnsjaL7UTWZrGd2G6LX3xtFtuJrM1iO/F9GEfXZrGdyNosthNZm8V2qoROZPOp9IR88AkRzgfDXjezBHvdzBLsdTNLsK/S9rqZJdjrZpZgr5tZgr1uZgn2uvng0144Hwx76V0rnA+GvfSuFc4Hw1561wrng2EvvWuF88Gwp8oHn0Jc+WAI6WaWYK+bWYK9bmYJ9lXaXjezBHvdzBLsdTNLsNfNLMFeN7N02gvng2EvvWuF88Gwl961wvlg2EvvWuF8MOyld61wPhj20ruWKx8MIap8MISo8sEQosoHQ4hlb92FqPLBEKLKB0OIKh8MIap8MISo8sGnEFc+GELJr/2rACWUyPLBUCI7kojjWmT5YCiR5YOhRJYPhhJZPhhKZPlgKJHlg6FElg8+ldjywVAiywdDiSwfDCWyfDCUKp8SWT4YSmT5YCiR5YOhRJYPhhJZPvhUYssHQ4ksHwwlsnwwlMjywVCqfEpk+WAokeWDoUSWD4YSWT4YSmT54B1lIssHbyeyfPB2IssHbye+/B1dPng7keWDtxPfh3F0+eDtRJYP3k5k+eDtVAmdyOZTnU/ywa2O23Otj3+HfPHA+OkzyXwWmc+TqPUfFDI2IWcTKmxClU2osQl1NiG2OW1sg9rYJrWzTWpnm9TONqmdbVI726R2tkntgZP6zhgJjM/n6RdPn0JokQmVg03I2IScTaiwCVU2ocYm1NmEBpsQ26QubJO6sk3qyjapK9ukrmyTurJN6so2qSvbpK6Bk/rOmAmMFc9oRwLDEhiewCgJjJrAaAmMnsBIeM/75z+7rw7tg+IplM//3H/wi7y+Mv5bxpFCSfnTH/ULlH8/OQ9KS6H0FMpIocwUyjfel38/eYtfZx8pFEuheAqlpFBqCqWlUHoKZaRQZgrlC+/+i6OkODpypFAsheIplJJCqSmUlkLpKZSRQvnCu//ikDAoK4Py7Bj51zEl498WdtQcTMvB9BzMSsF84UTgjzCWg/EcTPx7047rw7Xj/tgYLz50rcftrG/1F0d9531WrKP+77dPZ//7R7mn+FQVX6ri12+xhLnJmruseZE1r7LmTda8y5rLblCTXaEmu0Nddoe67A512R3qsjvUZXeoy+5QD9uhd8IIJ3y8k9rtd6q11UvCiiaUI5xg4QQPJ3w82+bt5amzXBJqOKGFE3o44dN3uh23D6TaMS8JM5ywogn1CCdYOOHTn9bmty9tfk3o4YRP/6R7uZ266M2vCO0IJ4R/l9rH7/T9Q+bWxiVhhhNWNKEf4QQLJ3g4oYQTajihhRN6OOGL73Tvl4QZTvj8nb5PvnFJGB+/0/fp/Yxg4QQPJ3z6Tvf7ydV+rEtCDSe0cEIPJ4xwwsfv9Go3gh2XhBVNmEc4wcIJHk4o4YQaTmjhhB5OGF8kXL7Tc4YTPn+nbyfpul8S1sfv9P3j0GcECyd4OOHjPf3q36KrhhNaOKGHE0Y4YYYTwj85eXKg9GuI/uS02n+8nPK4DT+rZlcQS75e+Yu3DfVnZ51k7F3avkjbV2n7Jm3fpe2HtP2Utl/K9i69a11617r0rnXpXevSu9ald61L71qX3rUuvWudZdfehArL+rwLJW/EL14P1p+depOxL9L2Vdq+Sdt3afshbT+l7ZeyfT2k7aV3bZXetVV611bpXVuld22V3rVVetdW6V1bpXdtY9m1dyGW9XkXYtmIdyGWJXcXYtlbdyGWVXQXYtkudyGWhXEXYtkBdyGWsX4T6myTuie/9q8uZu7PEiV/Vomsnbo/y0r80e/ScD6lwqeU3Qj/4jLs/iwr8WeVJp/SolOaB59S+lz69/ue+7OAyJ9VKnxKlU+p8Sl1PqXBpzT5lBad0jr4lLKn94t7wfuzKNCfVSp8SpVPqfEpdT6lwac0+ZQWndKzO/4Dnf69EGA7GaGTEzo1ug90nvUS/FmnQejE92GcZScDf+TkhE6F0KkSOrHNpyHaZnGKa17FfYpr3sR9iou2WcBc8yZumGvexA1zzZu4YV5lzTVv4oa5ZpsFzGU3qGibBcxld6homwXMZXeoaJsFzGV3qGibBcxld2hwmwUII5wQ22YBwoomBLdZgGDhBA8nxLZZgFDDCS2c0MMJsW0WIMxwwoomBLdZgGDhhNg2CxB6OCH2TsaTENxmAUL4dym4zQKEGU5Y0YTgNgsQLJzg4YQSTqjhhBZO6OGE2DYLEGY4IbbNAr/Oim2zAMHCCR5OiG2zAKGGE1o4oYcTRjghts0ChBVNCG6zAMHCCR5OKOGEGk5o4YQeTohtswBhhhNi2yxwCCK2zQIECyd4OCG2zQKEGk5o4YQeThjhhBlOCP/kJLrNYvSENosTItxmAXvdG7Zhr3vDNux1b9iGfZW2171hG/a6N2zDXveGbdjr3rANe902i9NeuM0C9tK7VrjNAvbSu1a4zQL20rtWuM0C9tK7VrjNAvZUbRanEFebBYR0b9iGve4N27DXvWEb9lXaXveGbdjr3rANe90btmGve8M27HVv2D7thdssYC+9a4XbLGAvvWuF2yxgL71rhdssYC+9a4XbLGAvvWu52iwgRNVmASGqNgsIUbVZQIhlb92FqNosIETVZgEhqjYLCFG1WUCIqs3iFOJqs4BQ8mv/6rp/KJG1WUCJ7AI9HNcia7OAElmbBZTI2iygRNZmASWyNgsokbVZQImszeJUYmuzgBJZmwWUyNosoETWZgGlyqdE1mYBJbI2CyiRtVlAiazNAkpkbRanElubBZTI2iygRNZmASWyNgsoVT4lsjYLKJG1WUCJrM0CSmRtFlAia7PYUSayNovtRNZmsZ3I2iy2E9lt8duJrM1iO5G1WWwnvg/j6NosthNZm8V2Imuz2E6V0IlsPs2SkA8+IcL5YNjrZpZgr5tZgr1uZgn2VdpeN7MEe93MEux1M0uw180swV43H3zaC+eDYS+9a4XzwbCX3rXC+WDYS+9a4Xww7KV3rXA+GPZU+eBTiCsfDCHdzBLsdTNLsNfNLMG+StvrZpZgr5tZgr1uZgn2upkl2Otmlk574Xww7KV3rXA+GPbSu1Y4Hwx76V0rnA+GvfSuFc4Hw15613LlgyFElQ+GEFU+GEJU+WAIseytuxBVPhhCVPlgCFHlgyFElQ+GEFU++BTiygdDKPm1fxWghBJZPhhKZEcScVyLLB8MJbJ8MJTI8sFQIssHQ4ksHwwlsnwwlMjywacSWz4YSmT5YCiR5YOhRJYPhlLlUyLLB0OJLB8MJbJ8MJTI8sFQIssHn0ps+WAokeWDoUSWD4YSWT4YSpVPiSwfDCWyfDCUyPLBUCLLB0OJLB+8o0xk+eDtRJYP3k5k+eDtxJe/o8sHbyeyfPB24vswji4fvJ3I8sHbiSwfvJ0qoRPZfFr216c9zvW46VR/YTPvA3wd9fGl/sZvx0/xqSq+VMXtkDU3WXOXNS+y5lXWvMmad1lz2Q1qsivUZHeoy+5Ql92hLrtDXXaHuuwOddkd6mE79E4Y4YSPd1K7ndSprV4SVjShHOEECyd4OOHj2TZvL0+d5ZJQwwktnNDDCZ++0+0Yf39pO+YlYYYTVjShHuEECyd8+tPa/Palza8JPZzw6Z90L7ejbr35FaEd4YTw71L7+J2u95+lNi4JM5ywogn9CCdYOMHDCSWcUMMJLZzQwwlffKd7vyTMcMLn7/R98o1Lwvj4nb5P72cECyd4OOHTd7rf8xD9WJeEGk5o4YQeThjhhI/f6XW7/LnbcUlY0YR5hBMsnODhhBJOqOGEFk7o4YTxRcLlOz1nOOHzd/p2oqX7JWF9/E7fPw59RrBwgocTPt7Tr/4tumo4oYUTejhhhBNmOCH8k5MnR6e/hZiHxbdZAKLbZrHtZW/Y3vayN2xve9kbtrd9lbaXvWF728vesL3tZW/Y3vayN2xve9k2C9jrtllse+ldq9tmse2ld61um8W2l961um0W21561+q2WWx7pjYLCFG1WWwh2Ru2t73sDdvbXvaG7W1fpe1lb9je9rI3bG972Ru2t73sDdvbXvaGbdjrtllse+ldq9tmse2ld61um8W2l961um0W21561+q2WWx76V1L1WaxhZjaLLYQU5vFFmJqs9hCLHvrLsTUZrGFmNosthBTm8UWYmqz2EJMbRYQomqz2ELJr/2L6/63ElebxVbiukBvH9fiarPYSlxtFluJq81iK3G1WWwlrjaLrcTVZrGVuNosoETWZrGVuNosthJXm8VW4mqz2EqVT4mrzWIrcbVZbCWuNoutxNVmsZW42iygRNZmsZW42iy2ElebxVbiarPYSpVPiavNYitxtVlsJa42i63E1WaxlbjaLH5FmbjaLH45cbVZ/HLiarP45cR1W/wvJ642i19OXG0Wv5z4Poxja7P45cTVZvHLiavN4pdTJXRim09Ts80C4pJXcUNc8iZuiGu2WWxzyZu4t7nkTdzbXPIm7m1eZc0lb+Le5pJtFttcdoNqtllsc9kdqtlmsc1ld6hmm8U2l92hmm0W21x2h8a2WWzCCCeEtllswoomxLZZbIKFEzycENpmsQk1nNDCCT2cENpmsQkznLCiCbFtFptg4YTQNotN6OGE0DsZQWhHOCH8uxTbZrEJM5ywogmxbRabYOEEDyeUcEINJ7RwQg8nhLZZbMIMJ4S2WexfZ4W2WWyChRM8nBDaZrEJNZzQwgk9nDDCCaFtFpuwogmxbRabYOEEDyeUcEINJ7RwQg8nhLZZbMIMJ4S2WexDEKFtFptg4QQPJ4S2WWxCDSe0cEIPJ4xwwgwnhH9yEt1mYSOhzeKECLdZwF73hm3Y696wDXvdG7ZhX6XtdW/Yhr3uDduw171hG/a6N2zDXrfN4rQXbrOAvfSuFW6zgL30rhVus4C99K4VbrOAvfSuFW6zgD1Vm8UpxNVmASHdG7Zhr3vDNux1b9iGfZW2171hG/a6N2zDXveGbdjr3rANe90btk974TYL2EvvWuE2C9hL71rhNgvYS+9a4TYL2EvvWuE2C9hL71quNgsIUbVZQIiqzQJCVG0WEGLZW3chqjYLCFG1WUCIqs0CQlRtFhCiarM4hbjaLCCU/Nq/uu4fSmRtFlAiu0APx7XI2iygRNZmASWyNgsokbVZQImszQJKZG0WUCJrsziV2NosoETWZgElsjYLKJG1WUCp8imRtVlAiazNAkpkbRZQImuzgBJZm8WpxNZmASWyNgsokbVZQImszQJKlU+JrM0CSmRtFlAia7OAElmbBZTI2ix2lImszWI7kbVZbCeyNovtRHZb/HYia7PYTmRtFtuJ78M4ujaL7UTWZrGdyNostlMldCKbT14T8sEnRDgfDHvdzBLsdTNLsNfNLMG+StvrZpZgr5tZgr1uZgn2upkl2Ovmg0974Xww7KV3rXA+GPbSu1Y4Hwx76V0rnA+GvfSuFc4Hw54qH3wKceWDIaSbWYK9bmYJ9rqZJdhXaXvdzBLsdTNLsNfNLMFeN7MEe93M0mkvnA+GvfSuFc4Hw1561wrng2EvvWuF88Gwl961wvlg2EvvWq58MISo8sEQosoHQ4gqHwwhlr11F6LKB0OIKh8MIap8MISo8sEQosoHn0Jc+WAIJb/2rwKUUCLLB0OJ7EgijmuR5YOhRJYPhhJZPhhKZPlgKJHlg6FElg+GElk++FRiywdDiSwfDCWyfDCUyPLBUKp8SmT5YCiR5YOhRJYPhhJZPhhKZPngU4ktHwwlsnwwlMjywVAiywdDqfIpkeWDoUSWD4YSWT4YSmT5YCiR5YN3lIksH7ydyPLB24ksH7yd+PJ3dPng7USWD95OfB/G0eWDtxNZPng7keWDt1MldKKaT6v4ehKGKvNmVMuDYaXcn7uOIf3gOXvzOX/zufKfnzvX7fAnmYdht+/+GI9f2pu33x4c7z44331wvfng9WH4nzxo7z7o7z54+ec473+fm/7swfrug+3dB/u7D453H5zvPrjefPD6HOict1+TzOVPHrR3H/R3HyzvPljffbC9+2B/98HLn5zffk1sx5MH57sPrjcfvD7V9JMH7d0H/d0Hy7sPXv7kLL+9Vqs8ea2uT8f85MH+7oPj3Qfnuw+uNx+8PmXxkwftxYP1yZ9j93cfLO8+eP2T024TYPUnE+D6eMVPHuzvPjjefXC+++B688FxvPvg9U/OPO4fuLf5jyf/77988QPjOZiSg6k5mJaD6TmYkYOZOZiVgrk+KPF9TM4UmDlTYOZMgZkzBWbOFJg5U2DmTIGZMwVmzhRYOVNg5UyBlTMFVs4UWDlTYOVMgZUzBVbOFFg5U2DlTIEnv7gN4FgSx5M4JYlTkzgtidOTOCOJM5M4SfPAkuaBJc0DS5oHljQPLGkeWNI8sKR5YEnzwJLmgSXNA0+aB540DzxpHnjSPPCkeeBJ88CT5oEnzQNPmgeeNA9K0jwoSfOgJM2DkjQPStI8KEnzoCTNg5I0D0rSPChJ86AmzYOaNA9q0jyoSfOgJs2DmjQPatI8qEnzoCbNg5o0D1rSPGhJ86AlzYOWNA9a0jxoSfOgJc2DljQPWtI8aEnzoCfNg540D3rSPOhJ86AnzYOeNA960jzoSfOgJ82DnjQPRtI8SDqDaEmHEC3pFKIlHUO0pHOIlnQQ0ZJOIlrSUURLOotoSYcRLek0oiUdR7Sk84iWdCDRkk4kWtKRREs6k2hJhxIt6VSiJR1LtKRziZZ0MNGSTiZa0tFESzqbaEmHEy3pdKIlHU+0pPOJnnQ+0ZPOJ3rS+URPOp/oR03itCROT+KMJM5M4iTNg6TziZ50PtGTzid60vlETzqf6EnnEz3pfKInnU/0pPOJnnQ+0ZPOJ3rS+URPOp/oSecTPel8oiedT/Sk84medD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtGTzid60vlETzqf6EnnEz3pfKInnU/0pPOJnnQ+0ZPOJ/oXzvO1duv7aOO3WyF/XQt5w8wUzBdOv7V5uxi4/X4v8D8xnoMpOZiag2k5mP+6eH57dLz96BeOIfzk5/sLpxB+hGk5mJ6DyRlxXziB0Fb7+4v70Z5hVgrmC+cPfoSxHIznYL4wBZbdMf0ZpuZgWg6m52BGDmbmYFbKMv3CqYMfYXL+2rZy/tq2cv7a9oUTBz/C5Py17QvnDX6EGTmYmYNJmQLlOHIwloPxHEzJwdQcTMvB9BzMyMHMHEzOFLCcKWA5U8BypoDlTAHLmQKWMwUsZwpYzhSwnClgOVPAc6aA50wBz5kCnjMFPGcKeM4U8Jwp4AlTYP51XZHX6rhRWv9H1+7/D5ntBpnT/v1LzeajqOu3zh33h9BkE1psQtd/3/mjRkZn5HRGhc6o0hk1OqNOZ0Q3sY1uZBvdzHa6me10M9vpZrbTzWynm9lON7M9cGY/ICMD8vlk/a3Grxxf+N4uNqNy0BkZnZHTGRU6o0pn1OiMOp3RoDOim9mFbmZXupld6WZ2pZvZlW5mV7qZXelmdqWb2TVwZj8gMwOyEiDtyIBYBsQzICUDUjMgLQPSMyAZb3z//EfYjuPWlX3+f/o1xnMwn//hm9fHLO7XnzD0lfJfM44cTM6PwKhfwPR1x8x+jWk5mJ6DGTmYmYP5xnvT7YEZl5h55GAsB+M5mJKDqTmYloPpOZiRg5k5mC9MAbN6+2Kr13+zWUcOxnIwnoMpOZiag2k5mJ6DGTmYL0wBG37H/H6G7nfMSsE8af4O4JSUf3o8acoO4LQkTk/irBzOF84Z/oxjSRxP4iS8P/O4Prk77s+N8eKj2nrMv7+0evv3L533qbGO+r/fPtN94wPg03zKmi9Z8+uXWUPddNVdV73oqldd9aar3nXVdXep6S5T092mrrtNXXebuu42dd1t6rrb1HW3qYdt0wdixCM+3k7t9tvY2uo1YoUjyhGPsHiExyM+nnL3wHKd5RpR4xEtHtHjEZ++3e24fV7VjnmNmPGIFY6oRzzC4hGf/tA2v31p8yeIHo/49I+7l9vRjd78EtGOeET8N6p9/HbfP41ubVwjZjxihSP6EY+weITHI0o8osYjWjyixyO++Hb3fo2Y8YjP3+77GBzXiPHx213WK4TFIzwe8enb3e/HYvuxrhE1HtHiET0eMeIRH7/dj0vF7bhGrHDEPOIRFo/weESJR9R4RItH9HjE+CLi+u2eMx7x+dt9O57X/RqxPn6775+iPkVYPMLjER/v7pf/Yl01HtHiET0eMeIRMx4R/zHLk9Oq32OsJyfgrJf7weDeXvzSxupxm4RWzS4pT45B/jdMnXfMePWLpC/ehrSenZ7S0Xdt/aKtX7X1m7Z+19Yf2vpTW39J67v21nXtrevaW9e1t65rb13X3rquvXVde+u69tZ1lq17Nyosi/RhlLwbv3l92Xp2jk5Hv2jrV239pq3ftfWHtv7U1l/S+vXQ1tfeulV761btrVu1t27V3rpVe+tW7a1btbdu1d66jWXrPoxYFunDiGU3PoxY1t3DiGWDPYxYltLDiGXPPIxYVsfDiGUbPIxYBvzdqNPN7J789r+8RXo9i6r8Yafkn+6X95ytZwGMP/t9Gk7oVAiderbTi6u717P4xR92moROi89pHoRO6fPpxcXU61nm5A87FUKnSujUCJ06odMgdJqETovPaR2ETtlz/NUN5utZuugPOxVCp0ro1AidOqHTIHSahE6Lz+lZJ0Gg1IsCgy1ljFLOKNX4Pu951qPwh6UGoxThx3WWHTj8mZQzShVGqcooRTenhmr/xmkuemX4aS56Y/hprtq/AXXRG8OhLnpjONRFbwyHetVVF70xHOqi/RtQ192lqv0bUNfdpqr9G1DX3aaq/RtQ192mqv0bUNfdptH9G0CMeERw/wYQKxwR3b8BhMUjPB4R3L8BRI1HtHhEj0cE928AMeMRKxwR3b8BhMUjgvs3gOjxiOCLIU9EdP8GEPHfqOj+DSBmPGKFI6L7N4CweITHI0o8osYjWjyixyOC+zeAmPGI4P4N/A4suH8DCItHeDwiuH8DiBqPaPGIHo8Y8Yjg/g0gVjgiun8DCItHeDyixCNqPKLFI3o8Irh/A4gZjwju38BZiuD+DSAsHuHxiOD+DSBqPKLFI3o8YsQjZjwi/mOW6P4NP3pC/wYowv0bW1/3JvCtr3sT+NbXvQl861dtfd2bwLe+7k3gW1/3JvCtr3sT+NbX7d+AvnD/xtbX3rrC/RtbX3vrCvdvbH3trSvcv7H1tbeucP/G1qfq34ARV//GNtK9CXzr694EvvV1bwLf+lVbX/cm8K2vexP41te9CXzr694EvvV1bwKHvnD/xtbX3rrC/RtbX3vrCvdvbH3trSvcv7H1tbeucP/G1tfeulz9G9uIqn9jG1H1b2wjqv6NbcSywR5GVP0b24iqf2MbUfVvbCOq/o1tRNW/ASOu/o1tlPz2v+om2E5k/RvbiexCv33Ki6x/YzuR9W9sJ7L+je1E1r+xncj6N7YTWf/GdiLr34ATW//GdiLr39hOZP0b24msf2M7VUInsv6N7UTWv7GdyPo3thNZ/8Z2IuvfgBNb/8Z2Iuvf2E5k/Rvbiax/YztVQiey/o3tRNa/sZ3I+je2E1n/xnYi69/4lY0i69/4JUXWv/FLiqx/45cU2b32v6TI+jd+SZH1b/ySIvy4jq5/45cUWf/GLymy/o1fUpVRim1OWclIH58U5fQx9IVzUNAXzkFBXzgHBf2qrS+cg4K+cA4K+sI5KOgL56CgL5w+PvWV08fQ1966yulj6GtvXeX0MfS1t65y+hj62ltXOX0Mfa708WlElj6GkXAOCvrCOSjoC+egoF+19YVzUNAXzkFBXzgHBX3hHBT0hXNQp75y+hj62ltXOX0Mfe2tq5w+hr721lVOH0Nfe+sqp4+hr711ydLHMOJKH8OIK30MI670MYxYNtjDiCt9DCOu9DGMuNLHMOJKH8OIK318GpGlj2GU/Pa/TGbCiS19DCe244w45cWWPoYTW/oYTmzpYzixpY/hxJY+hhNb+hhObOnj04kufQwntvQxnNjSx3BiSx/DqRI6saWP4cSWPoYTW/oYTmzpYzixpY9PJ7r0MZzY0sdwYksfw4ktfQynSujElj6GE1v6GE5s6WM4saWP4cSWPt7ZKLb08ZZiSx9vKbb08ZYiTPXxpY+3FFv6eEsRflzHlz7eUmzp4y3Flj7eUpVRim1Ouf31aQ91PW4+1V/ozPsoX0d9fKm/8zv103zKmi9Zczt01U1X3XXVi6561VVvuupdV113l5ruMjXdbeq629R1t6nrblPX3aauu01dd5t62DZ9IEY84uPt1G5nfGqr14gVjihHPMLiER6P+HjKzdtLVGe5RtR4RItH9HjEp293O8bfX9qOeY2Y8YgVjqhHPMLiEZ/+0Da/fWnzJ4gej/j0j7uX23m53vwS0Y54RPw3qn38dtf7T1Qb14gZj1jhiH7EIywe4fGIEo+o8YgWj+jxiC++3b1fI2Y84vO3+z4GxzVifPx234f5U4TFIzwe8enb3e9hi36sa0SNR7R4RI9HjHjEx2/3ut1L3e24RqxwxDziERaP8HhEiUfUeESLR/R4xPgi4vrtnjMe8fnbfTsa0/0asT5+u++foj5FWDzC4xEf7+6X/2JdNR7R4hE9HjHiETMeEf8xy5OT2d9jFMvo3ygm3b9RTLp/o5h0/0Yx6f6NYtL9G8Wk+zeKSfdvFJPu3ygm3b9RTLp/o5h0/0Yx6f6NYtL9G8Wk+zeKSfdvFJPu3ygm3b9RTLp/o5h0/0Yxtv6NYmz9G8Wk+zeKSfdvFJPu3ygm3b9RTLp/o5h0/0Yx6f6NYtL9G8Wk+zeKSfdvFJPu34C+9tZV7t+AvvbWVe7fKCbdvwF97a2r3L9RTLp/oxhb/waMuPo3YMTVvwEjrv4NGLFssIcRV/9GMbb+jWJs/RvF2Po3irH1bxRj698oxte/UYyvf6MYX/9GMb7+jWJ8/RvF+Po3ivH1bxTj698oxte/UYyvf6MYX/9GMb7+jWJ8/RvF+Po3ivH1bxTj698oxte/UYyvf6MYX/9GMb7+jWJ8/RvF+Po3ivH1bxTj698oxte/UYyvf6MYX/9GMb7+jWJ8/RvF+Po3ihH2b2wptv6NLcXWv7Gl2O6131Js/Rtbiq1/Y0sRflzH17+xpdj6N7YUW//GlqqMUnRzaqr2b5zmoleGn+aiN4af5qr9G1AXvTEc6qI3hkNd9MZwqFddddEbw6Eu2r8Bdd1dqtq/AXXdbaravwF13W2q2r8Bdd1tqtq/AXXdbRrdvwHEiEcE928AscIR0f0bQFg8wuMRwf0bQNR4RItH9HhEcP8GEDMescIR0f0bQFg8Irh/A4gejwi+GPJERPdvABH/jYru3wBixiNWOCK6fwMIi0d4PKLEI2o8osUjejwiuH8DiBmPCO7fwO/Agvs3gLB4hMcjgvs3gKjxiBaP6PGIEY8I7t8AYoUjovs3gLB4hMcjSjyixiNaPKLHI4L7N4CY8Yjg/g2cpQju3wDC4hEejwju3wCixiNaPKLHI0Y8YsYj4j9mCe/fqCOjf+OkKPdvQF/4JnDoC98EDn3hm8ChX7X1hW8Ch77wTeDQF74JHPrCN4FDX7h/49RX7t+AvvbWVe7fgL721lXu34C+9tZV7t+AvvbWVe7fgD5X/8ZpRNa/ASPhm8ChL3wTOPSFbwKHftXWF74JHPrCN4FDX/gmcOgL3wQOfeGbwE995f4N6GtvXeX+Dehrb13l/g3oa29d5f4N6GtvXeX+Dehrb12y/g0YcfVvwIirfwNGXP0bMGLZYA8jrv4NGHH1b8CIq38DRlz9GzDi6t84jcj6N2CU/Pa/7CaAE1v/BpzYLvTDKS+2/g04sfVvwImtfwNObP0bcGLr34ATW/8GnNj6N04nuv4NOLH1b8CJrX8DTmz9G3CqhE5s/RtwYuvfgBNb/wac2Po34MTWv3E60fVvwImtfwNObP0bcGLr34BTJXRi69+AE1v/BpzY+jfgxNa/ASe2/o2djWLr39hSbP0bW4qtf2NLsd1rv6XY+je2FFv/xpYi/LiOr39jS7H1b2wptv6NLVUZpdjmVKsZ6eOTopw+hr5wDgr6wjko6AvnoKBftfWFc1DQF85BQV84BwV94RwU9IXTx6e+cvoY+tpbVzl9DH3traucPoa+9tZVTh9DX3vrKqePoc+VPj6NyNLHMBLOQUFfOAcFfeEcFPSrtr5wDgr6wjko6AvnoKAvnIOCvnAO6tRXTh9DX3vrKqePoa+9dZXTx9DX3rrK6WPoa29d5fQx9LW3Lln6GEZc6WMYcaWPYcSVPoYRywZ7GHGlj2HElT6GEVf6GEZc6WMYcaWPTyOy9DGMkt/+l8lMOLGlj+HEdpwRp7zY0sdwYksfw4ktfQwntvQxnNjSx3BiSx/DiS19fDrRpY/hxJY+hhNb+hhObOljOFVCJ7b0MZzY0sdwYksfw4ktfQwntvTx6USXPoYTW/oYTmzpYzixpY/hVAmd2NLHcGJLH8OJLX0MJ7b0MZzY0sc7G8WWPt5SbOnjLcWWPt5ShKk+vvTxlmJLH28pwo/r+NLHW4otfbyl2NLHW6oySrHNqd6fpI9bHbcHWx//Tvnm2fNTaLIJLTahJ1HuP2lkdEZOZ1TojCqdUaMz6nRGdBPb6Ea20c1sp5vZTjeznW5mO93MdrqZ7XQz2wNn9gMyMiCfT9ZvHmSF0WIzKgedkdEZOZ1RoTOqdEaNzqjTGQ06I7qZXehmdqWb2ZVuZle6mV3pZnalm9mVbmZXupldA2f2AzIzICsB0o4MiGVAPANSMiA1A9IyID0DkvHG989/hF+GAYDxHMznf/g/+fVfXyn/NePIweT8CIz6BcyLI/nAtBxMz8GMHMzMwXzjvXlxmhe/DD9yMJaD8RxMycHUHEzLwfQczMjBzBzMF6bAq/OpOIFy5GAsB+M5mJKDqTmYloPpOZiRg/nCFHh1/hiYlYJ5dkr9+5yS8k8PO2oSpyVxehJn5XC+cM7wZxxL4ngSJ+P9mdcnd8f9uTFefFRbj9tJ4uovDhLP+9RYR/3fb5/pvvMB8Lw+4ithvmTNr19mDXXTVXdd9aKrXnXVm65611XX3aWmu0xNd5u67jZ13W3qutvUdbep625T192mHrZNH4gRj/h4O7Xbb2Nrq9eIFY4oRzzC4hEej/h4ys3bS1RnuUbUeESLR/R4xKdvdztun1e1Y14jZjxihSPqEY+weMSnP7TNb1/a/AmixyM+/ePu5XZ0oze/RLQjHhH/jWofv933T6NbG9eIGY9Y4Yh+xCMsHuHxiBKPqPGIFo/o8Ygvvt29XyNmPOLzt/s+Bsc1Ynz8dt+H+VOExSM8HvHp293vx2L7sa4RNR7R4hE9HjHiER+/3avdEHZcI1Y4Yh7xCItHeDyixCNqPKLFI3o8YnwRcf12zxmP+Pztvh3P636NWB+/3fdPUZ8iLB7h8YiPd/fLf7GuGo9o8YgejxjxiBmPiP+Y5clp1e8xxpMTcP/xOs3jNgmtml1SLPly6G/ehjSenZ7S0Xdt/aKtX7X1m7Z+19Yf2vpTW39J67v21nXtrevaW9e1t65rb13X3rquvXVde+u69tZ1lq17Nyosi/RhlLwbv3l92Xh2jk5Hv2jrV239pq3ftfWHtv7U1l/S+vXQ1tfeulV761btrVu1t27V3rpVe+tW7a1btbdu1d66jWXrPoxYFunDiGU3PoxY1t3DiGWDPYxYltLDiGXPPIxYVsfDiGUbPIxYBvzdqNPN7J789r+8RXo8i6r8YSe2Ku7xLIDxZ79PwwmdCqFTz3Z6cXX3eBa/+MNOk9Bp8TnNg9ApfT69uJh6PMuc/GGnQuhUCZ0aoVMndBqETpPQafE5rYPQKXuOv7rBfDxLF/1hp0LoVAmdGqFTJ3QahE6T0GnxOT3rJAiUelFgsKWMUcoZpRrf5z3PehT+sNRglCL8uM6yA4c/k3JGqcIoVRml2ObUbKr9G6e56JXhp7nojeGnuWr/BtRFbwyHuuiN4VAXvTEc6lVXXfTGcKiL9m9AXXeXqvZvQF13m6r2b0Bdd5uq9m9AXXebqvZvQF13m0b3bwAx4hHB/RtArHBEdP8GEBaP8HhEcP8GEDUe0eIRPR4R3L8BxIxHrHBEdP8GEBaPCO7fAKLHI4IvhjwR0f0bQMR/o6L7N4CY8YgVjoju3wDC4hEejyjxiBqPaPGIHo8I7t8AYsYjgvs38Duw4P4NICwe4fGI4P4NIGo8osUjejxixCOC+zeAWOGI6P4NICwe4fGIEo+o8YgWj+jxiOD+DSBmPCK4fwNnKYL7N4CweITHI4L7N4Co8YgWj+jxiBGPmPGI+I9Zwvs3Vs3o3zgpyv0b0Be+CRz6wjeBQ1/4JnDoV2194ZvAoS98Ezj0hW8Ch77wTeDQF+7fOPWV+zegr711lfs3oK+9dZX7N6CvvXWV+zegr711lfs3oM/Vv3EakfVvwEj4JnDoC98EDn3hm8ChX7X1hW8Ch77wTeDQF74JHPrCN4FDX/gm8FNfuX8D+tpbV7l/A/raW1e5fwP62ltXuX8D+tpbV7l/A/raW5esfwNGXP0bMOLq34ARV/8GjFg22MOIq38DRlz9GzDi6t+AEVf/Boy4+jdOI7L+DRglv/0vuwngxNa/ASe2C/1wyoutfwNObP0bcGLr34ATW/8GnNj6N+DE1r8BJ7b+jdOJrn8DTmz9G3Bi69+AE1v/BpwqoRNb/wac2Po34MTWvwEntv4NOLH1b5xOdP0bcGLr34ATW/8GnNj6N+BUCZ3Y+jfgxNa/ASe2/g04sfVvwImtf2Nno9j6N7YUW//GlmLr39hSbPfabym2/o0txda/saUIP67j69/YUmz9G1uKrX9jS1VGKbI5VQ5LSB+DIpw+3vq6Oaitr5uD2vq6OaitX7X1dXNQW183B7X1dXNQW183B7X1ddPH0BdOH2997a0rnD7e+tpbVzh9vPW1t65w+njra29d4fTx1qdKH8OIK328jXRzUFtfNwe19XVzUFu/auvr5qC2vm4Oauvr5qC2vm4Oauvr5qCgL5w+3vraW1c4fbz1tbeucPp462tvXeH08dbX3rrC6eOtr711udLH24gqfbyNqNLH24gqfbyNWDbYw4gqfbyNqNLH24gqfbyNqNLH24gqfQwjrvTxNkp++18lM7cTWfp4O5EdZ9ynvMjSx9uJLH28ncjSx9uJLH28ncjSx9uJLH28ncjSx3BiSx9vJ7L08XYiSx9vJ7L08XaqhE5k6ePtRJY+3k5k6ePtRJY+3k5k6WM4saWPtxNZ+ng7kaWPtxNZ+ng7VUInsvTxdiJLH28nsvTxdiJLH28nsvTxr2wUWfr4lxRZ+viXFFn6+JcUYaqPLn38S4osffxLivDjOrr08S8psvTxLymy9PEvqcooRTen1l+f9lDX4+ZT/YXOvI/yddTHl/pbv1Nff01Z8yVrboeuuumqu6560VWvuupNV73rquvuUtNdpqa7TV13m7ruNnXdbeq629R1t6nrblMP26YPxIhHfLyd2u2MT231GrHCEeWIR1g8wuMRH0+5eXuJ6izXiBqPaPGIHo/49O1ux/j7S9sxrxEzHrHCEfWIR1g84tMf2ua3L23+BNHjEZ/+cfdyOy/Xm18i2hGPiP9GtY/f7nr/iWrjGjHjESsc0Y94hMUjPB5R4hE1HtHiET0e8cW3u/drxIxHfP5238fguEaMj9/u+zB/irB4hMcjPn27+z1s0Y91jajxiBaP6PGIEY/4+O1et3upux3XiBWOmEc8wuIRHo8o8Ygaj2jxiB6PGF9EXL/dc8YjPn+7b0djul8j1sdv9/1T1KcIi0d4POLj3f3yX6yrxiNaPKLHI0Y8YsYj4j9meXIy+3sMWxn9G7ak+zdsSfdv2JLu37Al3b9hS7p/w5Z0/4Yt6f4NW9L9G7ak+zdsSfdv2JLu37Al3b9hS7p/w5Z0/4Yt6f4NW9L9G7ak+zdsSfdv2JLu37DF1r9hi61/w5Z0/4Yt6f4NW9L9G7ak+zdsSfdv2JLu37Al3b9hS7p/w5Z0/4Yt6f4NW9L9G9DX3rrK/RvQ1966yv0btqT7N6CvvXWV+zdsSfdv2GLr34ARV/8GjLj6N2DE1b8BI5YN9jDi6t+wxda/YYutf8MWW/+GLbb+DVts/Ru2+Po3bPH1b9ji69+wxde/YYuvf8MWX/+GLb7+DVt8/Ru2+Po3bPH1b9ji69+wxde/YYuvf8MWX/+GLb7+DVt8/Ru2+Po3bPH1b9ji69+wxde/YYuvf8MWX/+GLb7+DVt8/Ru2+Po3bPH1b9ji69+wxde/YYuvf8MWX/+GLcL+jS3F1r+xpdj6N7YU2732W4qtf2NLsfVvbCnCj+v4+je2FFv/xpZi69/YUpVRim1OeVft3zjNRa8MP81Fbww/zVX7N6AuemM41EVvDIe66I3hUK+66qI3hkNdtH8D6rq7VLV/A+q621S1fwPquttUtX8D6rrbVLV/A+q62zS6fwOIEY8I7t8AYoUjovs3gLB4hMcjgvs3gKjxiBaP6PGI4P4NIGY8YoUjovs3gLB4RHD/BhA9HhF8MeSJiO7fACL+GxXdvwHEjEescER0/wYQFo/weESJR9R4RItH9HhEcP8GEDMeEdy/gd+BBfdvAGHxCI9HBPdvAFHjES0e0eMRIx4R3L8BxApHRPdvAGHxCI9HlHhEjUe0eESPRwT3bwAx4xHB/Rs4SxHcvwGExSM8HhHcvwFEjUe0eESPR4x4xIxHxH/MEt6/UVpG/8ZJUe7fgL7wTeDQF74JHPrCN4FDv2rrC98EDn3hm8ChL3wTOPSFbwKHvnD/xqmv3L8Bfe2tq9y/AX3travcvwF97a2r3L8Bfe2tq9y/AX2u/o3TiKx/A0bCN4FDX/gmcOgL3wQO/aqtL3wTOPSFbwKHvvBN4NAXvgkc+sI3gZ/6yv0b0Nfeusr9G9DX3rrK/RvQ1966yv0b0Nfeusr9G9DX3rpk/Rsw4urfgBFX/waMuPo3YMSywR5GXP0bMOLq34ARV/8GjLj6N2DE1b9xGpH1b8Ao+e1/2U0AJ7b+DTixXeiHU15s/RtwYuvfgBNb/wac2Po34MTWvwEntv4NOLH1b5xOdP0bcGLr34ATW/8GnNj6N+BUCZ3Y+jfgxNa/ASe2/g04sfVvwImtf+N0ouvfgBNb/wac2Po34MTWvwGnSujE1r8BJ7b+DTix9W/Aia1/A05s/Rs7G8XWv7Gl2Po3thRb/8aWYrvXfkux9W9sKbb+jS1F+HEdX//GlmLr39hSbP0bW6oySrHNqeoZ6eOTopw+hr5wDgr6wjko6AvnoKBftfWFc1DQF85BQV84BwV94RwU9IXTx6e+cvoY+tpbVzl9DH3traucPoa+9tZVTh9DX3vrKqePoc+VPj6NyNLHMBLOQUFfOAcFfeEcFPSrtr5wDgr6wjko6AvnoKAvnIOCvnAO6tRXTh9DX3vrKqePoa+9dZXTx9DX3rrK6WPoa29d5fQx9LW3Lln6GEZc6WMYcaWPYcSVPoYRywZ7GHGlj2HElT6GEVf6GEZc6WMYcaWPTyOy9DGMkt/+l8lMOLGlj+HEdpwRp7zY0sdwYksfw4ktfQwntvQxnNjSx3BiSx/DiS19fDrRpY/hxJY+hhNb+hhObOljOFVCJ7b0MZzY0sdwYksfw4ktfQwntvTx6USXPoYTW/oYTmzpYzixpY/hVAmd2NLHcGJLH8OJLX0MJ7b0MZzY0sc7G8WWPt5SbOnjLcWWPt5ShKk+vvTxlmJLH28pwo/r+NLHW4otfbyl2NLHW6oySpHNqf40JzDsRhnj8Rtt8/bbg+PdB+e7D643H7w+PP6TB+3dB/3dBy9fpnn/O8z0Zw/Wdx9s7z7Y331wvPvgfPfB9eaD16cl57z9ymAuf/Kgvfugv/tgeffB+u6D7d0H+7sPXv7k/PaLUzuePDjffXC9+eD1iZ+fPGjvPujvPljeffDyJ2f57bVa5clrdX1o5CcP9ncfHO8+ON99cL354PW5g588aC8erE/+HLu/+2B598Hrn5x2mwCrP5kA18cNfvJgf/fB8e6D890H15sPjuPdB69/cuZx/7S5zX88+X//5YsfGM/BlBxMzcG0HEzPwYwczMzBrBTM9XmB72NypsDMmQIzZwrMnCkwc6bAzJkCM2cKzJwpMHOmwMqZAitnCqycKbBypsDKmQIrZwqsnCmwcqbAypkCK2cKPPldZQDHkjiexClJnJrEaUmcnsQZSZyZxEmaB5Y0DyxpHljSPLCkeWBJ88CS5oElzQNLmgeWNA8saR540jzwpHngSfPAk+aBJ80DT5oHnjQPPGkeeNI88KR5UJLmQUmaByVpHpSkeVCS5kFJmgclaR6UpHlQkuZBSZoHNWke1KR5UJPmQU2aBzVpHtSkeVCT5kFNmgc1aR7UpHnQkuZBS5oHLWketKR50JLmQUuaBy1pHrSkedCS5kFLmgc9aR70pHnQk+ZBT5oHPWke9KR50JPmQU+aBz1pHvSkeTCS5kHSGURLOoRoSacQLekYoiWdQ7Skg4iWdBLRko4iWtJZREs6jGhJpxEt6TiiJZ1HtKQDiZZ0ItGSjiRa0plESzqUaEmnEi3pWKIlnUu0pIOJlnQy0ZKOJlrS2URLOpxoSacTLel4oiWdT/Sk84medD7Rk84netL5RD9qEqclcXoSZyRxZhInaR4knU/0pPOJnnQ+0ZPOJ3rS+URPOp/oSecTPel8oiedT/Sk84medD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtGTzid60vlETzqf6EnnEz3pfKInnU/0pPOJnnQ+0ZPOJ3rS+URPOp/oSecTPel8oiedT/Sk84medD7Rv3Cer7Vb7UUbv91++I/rD79wnO8nmC+cfmvzdhNu+/0i3H9iPAdTcjA1B9NyMP918fz26Hj70S8cQ/jJz/cXTiH8CNNyMD0HkzPivnACoa329xf3oz3DrBTMF84f/AhjORjPwXxhCiy7Y/ozTM3BtBxMz8GMHMzMwayUZfqFUwc/wuT8tW3l/LVt5fy17QsnDn6Eyflr2xfOG/wIM3IwMweTMgXKceRgLAfjOZiSg6k5mJaD6TmYkYOZOZicKWA5U8BypoDlTAHLmQKWMwUsZwpYzhSwnClgOVPAcqaA50wBz5kCnjMFPGcKeM4U8Jwp4DlTwBOmwPzruhCu1XGjtP6Potn/HzLbDTKn/fuXms1HIdVvnTvuD6HJJrTYhK7/vvNHjYzOyOmMCp1RpTNqdEadzohuYhvdyDa6me10M9vpZrbTzWynm9lON7OdbmZ74Mx+QEYG5PPJ+luNXzm+8L1dbEbloDMyOiOnMyp0RpXOqNEZdTqjQWdEN7ML3cyudDO70s3sSjezK93MrnQzu9LN7Eo3s2vgzH5AZgZkJUDakQGxDIhnQEoGpGZAWgakZ0Ay3vj++Y+wHcetK9sO82uM52A+/8M3r49Z3K8/Yegr5b9mHDmYnB+BUb+A6euOmf0a03IwPQczcjAzB/ON96bbAzMuMfPIwVgOxnMwJQdTczAtB9NzMCMHM3MwX5gCZvX2xVav/2azjhyM5WA8B1NyMDUH03IwPQczcjBfmAI2/I75/Qzd75iVgnnS/B3AKSn/9HjSlB3AaUmcnsRZOZwvnDP8GceSOJ7ESXh/2nF9cnfcnxvjxUe19Zh/f2n19u9fOu9TYx31f799pvvGB8Cn+ZQ1X7Lm1y+zhrrpqruuetFVr7rqTVe966rr7lLTXaamu01dd5u67jZ13W3qutvUdbep625TD9umD8SIR3y8ndrtt7G11WvECkeUIx5h8QiPR3w85e6B5TrLNaLGI1o8oscjPn2723H7vKod8xox4xErHFGPeITFIz79oW1++9LmTxA9HvHpH3cvt6Mbvfkloh3xiPhvVPv47b5/Gt3auEbMeMQKR/QjHmHxCI9HlHhEjUe0eESPR3zx7e79GjHjEZ+/3fcxOK4R4+O3u6xXCItHeDzi07e734/F9mNdI2o8osUjejxixCM+frsfl4rbcY1Y4Yh5xCMsHuHxiBKPqPGIFo/o8YjxRcT12z1nPOLzt/t2PK/7NWJ9/HbfP0V9irB4hMcjPt7dL//Fumo8osUjejxixCNmPCL+Y5Ynp1W/x+hPTsBZL/eDwb29+KWN1eM2Ca2aXVKeHIP8b5g675jx6hdJX7wNqT87PaWj79r6RVu/aus3bf2urT+09ae2/pLWd+2t69pb17W3rmtvXdfeuq69dV1767r21nXtressW/duVFgW6cMoeTd+8/qy/uwcnY5+0dav2vpNW79r6w9t/amtv6T166Gtr711q/bWrdpbt2pv3aq9dav21q3aW7dqb92qvXUby9Z9GLEs0ocRy258GLGsu4cRywZ7GLEspYcRy555GLGsjocRyzZ4GLEM+LtRp5vZPfntf3mLdH8WVfnDTsk/3S/vOevPAhh/9vs0nNCpEDr1bKcXV3f3Z/GLP+w0CZ0Wn9M8CJ3S59OLi6n7s8zJH3YqhE6V0KkROnVCp0HoNAmdFp/TOgidsuf4qxvM+7N00R92KoROldCpETp1QqdB6DQJnRaf07NOgkCpFwUGW8oYpZxRqvF93mNHZ5QajFKEH9dZduDwZ1LOKFUYpSqjFN2cGqr9G6e56JXhp7nojeGnuWr/BtRFbwyHuuiN4VAXvTEc6lVXXfTGcKiL9m9AXXeXqvZvQF13m6r2b0Bdd5uq9m9AXXebqvZvQF13m0b3bwAx4hHB/RtArHBEdP8GEBaP8HhEcP8GEDUe0eIRPR4R3L8BxIxHrHBEdP8GEBaPCO7fAKLHI4IvhjwR0f0bQMR/o6L7N4CY8YgVjoju3wDC4hEejyjxiBqPaPGIHo8I7t8AYsYjgvs38Duw4P4NICwe4fGI4P4NIGo8osUjejxixCOC+zeAWOGI6P4NICwe4fGIEo+o8YgWj+jxiOD+DSBmPCK4fwNnKYL7N4CweITHI4L7N4Co8YgWj+jxiBGPmPGI+I9Zwvs3Rs/o3zgpyv0b0Be+CRz6wjeBQ1/4JnDoV2194ZvAoS98Ezj0hW8Ch77wTeDQF+7fOPWV+zegr711lfs3oK+9dZX7N6CvvXWV+zegr711lfs3oM/Vv3EakfVvwEj4JnDoC98EDn3hm8ChX7X1hW8Ch77wTeDQF74JHPrCN4FDX/gm8FNfuX8D+tpbV7l/A/raW1e5fwP62ltXuX8D+tpbV7l/A/raW5esfwNGXP0bMOLq34ARV/8GjFg22MOIq38DRlz9GzDi6t+AEVf/Boy4+jdOI7L+DRglv/0vuwngxNa/ASe2C/1wyoutfwNObP0bcGLr34ATW/8GnNj6N+DE1r8BJ7b+jdOJrn8DTmz9G3Bi69+AE1v/BpwqoRNb/wac2Po34MTWvwEntv4NOLH1b5xOdP0bcGLr34ATW/8GnNj6N+BUCZ3Y+jfgxNa/ASe2/g04sfVvwImtf2Nno9j6N7YUW//GlmLr39hSbPfabym2/o0txda/saUIP67j69/YUmz9G1uKrX9jS1VGKbY5NUtG+vikKKePoS+cg4K+cA4K+sI5KOhXbX3hHBT0hXNQ0BfOQUFfOAcFfeH08amvnD6GvvbWVU4fQ1976yqnj6GvvXWV08fQ1966yulj6HOlj08jsvQxjIRzUNAXzkFBXzgHBf2qrS+cg4K+cA4K+sI5KOgL56CgL5yDOvWV08fQ1966yulj6GtvXeX0MfS1t65y+hj62ltXOX0Mfe2tS5Y+hhFX+hhGXOljGHGlj2HEssEeRlzpYxhxpY9hxJU+hhFX+hhGXOnj04gsfQyj5Lf/ZTITTmzpYzixHWfEKS+29DGc2NLHcGJLH8OJLX0MJ7b0MZzY0sdwYksfn0506WM4saWP4cSWPoYTW/oYTpXQiS19DCe29DGc2NLHcGJLH8OJLX18OtGlj+HElj6GE1v6GE5s6WM4VUIntvQxnNjSx3BiSx/DiS19DCe29PHORrGlj7cUW/p4S7Glj7cUYaqPL328pdjSx1uK8OM6vvTxlmJLH28ptvTxlqqMUmxzatlfn/ZQ1+PmU/2FzryP8nXUx5f6O79TP82nrPmSNbdDV9101V1XveiqV131pqveddV1d6npLlPT3aauu01dd5u67jZ13W3qutvUdbeph23TB2LEIz7eTu12xqe2eo1Y4YhyxCMsHuHxiI+n3Ly9RHWWa0SNR7R4RI9HfPp2t2P8/aXtmNeIGY9Y4Yh6xCMsHvHpD23z25c2f4Lo8YhP/7h7uZ2X680vEe2IR8R/o9rHb3e9/0S1cY2Y8YgVjuhHPMLiER6PKPGIGo9o8Ygej/ji2937NWLGIz5/u+9jcFwjxsdv932YP0VYPMLjEZ++3f0etujHukbUeESLR/R4xIhHfPx2r9u91N2Oa8QKR8wjHmHxCI9HlHhEjUe0eESPR4wvIq7f7jnjEZ+/3bejMd2vEevjt/v+KepThMUjPB7x8e5++S/WVeMRLR7R4xEjHjHjEfEfszw5mf01xjgsoX8DFOH+ja2vexP41te9CXzr694EvvWrtr7uTeBbX/cm8K2vexP41te9CXzr6/ZvQF+4f2Pra29d4f6Nra+9dYX7N7a+9tYV7t/Y+tpbV7h/Y+tT9W/AiKt/Yxvp3gS+9XVvAt/6ujeBb/2qra97E/jW170JfOvr3gS+9XVvAt/6ujeBQ1+4f2Pra29d4f6Nra+9dYX7N7a+9tYV7t/Y+tpbV7h/Y+trb12u/o1tRNW/sY2o+je2EVX/xjZi2WAPI6r+jW1E1b+xjaj6N7YRVf/GNqLq34ARV//GNkp++191E2wnsv6N7UR2od8+5UXWv7GdyPo3thNZ/8Z2Iuvf2E5k/Rvbiax/YzuR9W/Aia1/YzuR9W9sJ7L+je1E1r+xnSqhE1n/xnYi69/YTmT9G9uJrH9jO5H1b8CJrX9jO5H1b2wnsv6N7UTWv7GdKqETWf/GdiLr39hOZP0b24msf2M7kfVv/MpGkfVv/JIi69/4JUXWv/FLiuxe+19SZP0bv6TI+jd+SRF+XEfXv/FLiqx/45cUWf/GL6nKKEU3p6Zo/wbMNa8Mh7nmjeEwF+3f2OqaN4Zvdc0bw7e65o3hW73qqmveGL7VNfs3trruLhXt39jquttUtH9jq+tuU9H+ja2uu01F+ze2uu42De7f2IgRj4jt39iIFY4I7t/YCItHeDwitn9jI2o8osUjejwitn9jI2Y8YoUjgvs3NsLiEbH9GxvR4xGxF0MC0Y54RPw3Krh/YyNmPGKFI4L7NzbC4hEejyjxiBqPaPGIHo+I7d/YiBmPiO3f2L8Di+3f2AiLR3g8IrZ/YyNqPKLFI3o8YsQjYvs3NmKFI4L7NzbC4hEejyjxiBqPaPGIHo+I7d/YiBmPiO3f2GcpYvs3NsLiER6PiO3f2Igaj2jxiB6PGPGIGY+I/5glvH/DRkb/xklR7t+AvvBN4NAXvgkc+sI3gUO/ausL3wQOfeGbwKEvfBM49IVvAoe+cP/Gqa/cvwF97a2r3L8Bfe2tq9y/AX3travcvwF97a2r3L8Bfa7+jdOIrH8DRsI3gUNf+CZw6AvfBA79qq0vfBM49IVvAoe+8E3g0Be+CRz6wjeBn/rK/RvQ1966yv0b0Nfeusr9G9DX3rrK/RvQ1966yv0b0NfeumT9GzDi6t+AEVf/Boy4+jdgxLLBHkZc/Rsw4urfgBFX/waMuPo3YMTVv3EakfVvwCj57X/ZTQAntv4NOLFd6IdTXmz9G3Bi69+AE1v/BpzY+jfgxNa/ASe2/g04sfVvnE50/RtwYuvfgBNb/wac2Po34FQJndj6N+DE1r8BJ7b+DTix9W/Aia1/43Si69+AE1v/BpzY+jfgxNa/AadK6MTWvwEntv4NOLH1b8CJrX8DTmz9Gzsbxda/saXY+je2FFv/xpZiu9d+S7H1b2wptv6NLUX4cR1f/8aWYuvf2FJs/RtbqjJKsc0prxnp45OinD6GvnAOCvrCOSjoC+egoF+19YVzUNAXzkFBXzgHBX3hHBT0hdPHp75y+hj62ltXOX0Mfe2tq5w+hr721lVOH0Nfe+sqp4+hz5U+Po3I0scwEs5BQV84BwV94RwU9Ku2vnAOCvrCOSjoC+egoC+cg4K+cA7q1FdOH0Nfe+sqp4+hr711ldPH0NfeusrpY+hrb13l9DH0tbcuWfoYRlzpYxhxpY9hxJU+hhHLBnsYcaWPYcSVPoYRV/oYRlzpYxhxpY9PI7L0MYyS3/6XyUw4saWP4cR2nBGnvNjSx3BiSx/DiS19DCe29DGc2NLHcGJLH8OJLX18OtGlj+HElj6GE1v6GE5s6WM4VUIntvQxnNjSx3BiSx/DiS19DCe29PHpRJc+hhNb+hhObOljOLGlj+FUCZ3Y0sdwYksfw4ktfQwntvQxnNjSxzsbxZY+3lJs6eMtxZY+3lKEqT6+9PGWYksfbynCj+v40sdbii19vKXY0sdbqjJKsc2p0p+kj1sdtwdbH/9O+ebZ81NosgktNqEnUe4/aWR0Rk5nVOiMKp1RozPqdEZ0E9voRrbRzWynm9lON7OdbmY73cx2upntdDPbA2f2AzIyIJ9P1m8eZIXRYjMqB52R0Rk5nVGhM6p0Ro3OqNMZDTojupld6GZ2pZvZlW5mV7qZXelmdqWb2ZVuZle6mV0DZ/YDMjMgKwHSjgyIZUA8A1IyIDUD0jIgPQOS8cb3z3+EX4YBgPEczOd/+D/59V9fKf8148jB5PwIjPoFzIsj+cC0HEzPwYwczMzBfOO9eXGa98TMIwdjORjPwZQcTM3BtBxMz8GMHMzMwXxhCrw6n3pi1pGDsRyM52BKDqbmYFoOpudgRg7mC1Pg1fljYFYK5tkp9e9zSso/PeyoSZyWxOlJnJXD+cI5w59xLInjSZyM92den9wd9+fGePFRbT1uJ4mrvzhIPO9TYx31f799pvvOB8Dz+oivhPmSNb9+mTXUTVfdddWLrnrVVW+66l1XXXeXmu4yNd1t6rrb1HW3qetuU9fdpq67TV13m3rYNn0gRjzi4+3Ubr+Nra1eI1Y4ohzxCItHeDzi4yk3by9RneUaUeMRLR7R4xGfvt3tuH1e1Y55jZjxiBWOqEc8wuIRn/7QNr99afMniB6P+PSPu5fb0Y3e/BLRjnhE/Deqffx23z+Nbm1cI2Y8YoUj+hGPsHiExyNKPKLGI1o8oscjvvh2936NmPGIz9/u+xgc14jx8dt9H+ZPERaP8HjEp293vx+L7ce6RtR4RItH9HjEiEd8/HavdkPYcY1Y4Yh5xCMsHuHxiBKPqPGIFo/o8YjxRcT12z1nPOLzt/t2PK/7NWJ9/HbfP0V9irB4hMcjPt7dL//Fumo8osUjejxixCNmPCL+Y5Ynp1W/x6hPTsD9x+s0j9sktGp2SbHky6G/eRtSfXZ6SkfftfWLtn7V1m/a+l1bf2jrT239Ja3v2lvXtbeua29d1966rr11XXvruvbWde2t69pb11m27t2osCzSh1Hybvzm9WX12Tk6Hf2irV+19Zu2ftfWH9r6U1t/SevXQ1tfe+tW7a1btbdu1d66VXvrVu2tW7W3btXeulV76zaWrfswYlmkDyOW3fgwYll3DyOWDfYwYllKDyOWPfMwYlkdDyOWbfAwYhnwd6NON7N78tv/8hbp+iyq8oed2Kq467MAxp/9Pg0ndCqETj3b6cXV3fVZ/OIPO01Cp8XnNA9Cp/T59OJi6vosc/KHnQqhUyV0aoROndBpEDpNQqfF57QOQqfsOf7qBvP6LF30h50KoVMldGqETp3QaRA6TUKnxef0rJMgUOpFgcGWMkYpZ5RqfJ/3POtR+MNSg1GK8OM6yw4c/kzKGaUKo1RllGKbU62p9m+c5qJXhp/mojeGn+aq/RtQF70xHOqiN4ZDXfTGcKhXXXXRG8OhLtq/AXXdXaravwF13W2q2r8Bdd1tqtq/AXXdbaravwF13W0a3b8BxIhHBPdvALHCEdH9G0BYPMLjEcH9G0DUeESLR/R4RHD/BhAzHrHCEdH9G0BYPCK4fwOIHo8IvhjyRET3bwAR/42K7t8AYsYjVjgiun8DCItHeDyixCNqPKLFI3o8Irh/A4gZjwju38DvwIL7N4CweITHI4L7N4Co8YgWj+jxiBGPCO7fAGKFI6L7N4CweITHI0o8osYjWjyixyOC+zeAmPGI4P4NnKUI7t8AwuIRHo8I7t8AosYjWjyixyNGPGLGI+I/Zgnv3+g1o3/jpCj3b0Bf+CZw6AvfBA594ZvAoV+19YVvAoe+8E3g0Be+CRz6wjeBQ1+4f+PUV+7fgL721lXu34C+9tZV7t+AvvbWVe7fgL721lXu34A+V//GaUTWvwEj4ZvAoS98Ezj0hW8Ch37V1he+CRz6wjeBQ1/4JnDoC98EDn3hm8BPfeX+Dehrb13l/g3oa29d5f4N6GtvXeX+Dehrb13l/g3oa29dsv4NGHH1b8CIq38DRlz9GzBi2WAPI67+DRhx9W/AiKt/A0Zc/Rsw4urfOI3I+jdglPz2v+wmgBNb/wac2C70wykvtv4NOLH1b8CJrX8DTmz9G3Bi69+AE1v/BpzY+jdOJ7r+DTix9W/Aia1/A05s/RtwqoRObP0bcGLr34ATW/8GnNj6N+DE1r9xOtH1b8CJrX8DTmz9G3Bi69+AUyV0YuvfgBNb/wac2Po34MTWvwEntv6NnY1i69/YUmz9G1uKrX9jS7Hda7+l2Po3thRb/8aWIvy4jq9/Y0ux9W9sKbb+jS1VGaXY5tSwjPTxSVFOH0NfOAcFfeEcFPSFc1DQr9r6wjko6AvnoKAvnIOCvnAOCvrC6eNTXzl9DH3traucPoa+9tZVTh9DX3vrKqePoa+9dZXTx9DnSh+fRmTpYxgJ56CgL5yDgr5wDgr6VVtfOAcFfeEcFPSFc1DQF85BQV84B3XqK6ePoa+9dZXTx9DX3rrK6WPoa29d5fQx9LW3rnL6GPraW5csfQwjrvQxjLjSxzDiSh/DiGWDPYy40scw4kofw4grfQwjrvQxjLjSx6cRWfoYRslv/8tkJpzY0sdwYjvOiFNebOljOLGlj+HElj6GE1v6GE5s6WM4saWP4cSWPj6d6NLHcGJLH8OJLX0MJ7b0MZwqoRNb+hhObOljOLGlj+HElj6GE1v6+HSiSx/DiS19DCe29DGc2NLHcKqETmzpYzixpY/hxJY+hhNb+hhObOnjnY1iSx9vKbb08ZZiSx9vKcJUH1/6eEuxpY+3FOHHdXzp4y3Flj7eUmzp4y1VGaXo5tT669Me6nrcfKq/0Jn3Ub6O+vhSf+t36uuvKWu+ZM3t0FU3XXXXVS+66lVXvemqd1113V1qusvUdLep625T192mrrtNXXebuu42dd1t6mHb9IEY8YiPt1O7nfGprV4jVjiiHPEIi0d4POLjKTdvL1Gd5RpR4xEtHtHjEZ++3e0Yf39pO+Y1YsYjVjiiHvEIi0d8+kPb/PalzZ8gejzi0z/uXm7n5XrzS0Q74hHx36j28dtd7z9RbVwjZjxihSP6EY+weITHI0o8osYjWjyixyO++Hb3fo2Y8YjP3+77GBzXiPHx230f5k8RFo/weMSnb3e/hy36sa4RNR7R4hE9HjHiER+/3et2L3W34xqxwhHziEdYPMLjESUeUeMRLR7R4xHji4jrt3vOeMTnb/ftaEz3a8T6+O2+f4r6FGHxCI9HfLy7X/6LddV4RItH9HjEiEfMeET8xyxPTmZ/jzFXRv/GXNL9G3NJ92/MJd2/MZd0/8Zc0v0bc0n3b8wl3b8xl3T/xlzS/RtzSfdvzCXdvzGXdP/GXNL9G3NJ92/MJd2/MZd0/8Zc0v0bc0n3b8wl3b8xF1v/xlxs/RtzSfdvzCXdvzGXdP/GXNL9G3NJ92/MJd2/MZd0/8Zc0v0bc0n3b8wl3b8xl3T/BvS1t65y/wb0tbeucv/GXNL9G9DX3rrK/RtzSfdvzMXWvwEjrv4NGHH1b8CIq38DRiwb7GHE1b8xF1v/xlxs/RtzsfVvzMXWvzEXW//GXHz9G3Px9W/Mxde/MRdf/8ZcfP0bc/H1b8zF178xF1//xlx8/Rtz8fVvzMXXvzEXX//GXHz9G3Px9W/Mxde/MRdf/8ZcfP0bc/H1b8zF178xF1//xlx8/Rtz8fVvzMXXvzEXX//GXHz9G3Px9W/Mxde/MRdf/8ZcfP0bc/H1b8xF2L+xpdj6N7YUW//GlmK7135LsfVvbCm2/o0tRfhxHV//xpZi69/YUmz9G1uqMkqxzanVVfs3TnPRK8NPc9Ebw09z1f4NqIveGA510RvDoS56YzjUq6666I3hUBft34C67i5V7d+Auu42Ve3fgLruNlXt34C67jZV7d+Auu42je7fAGLEI4L7N4BY4Yjo/g0gLB7h8Yjg/g0gajyixSN6PCK4fwOIGY9Y4Yjo/g0gLB4R3L8BRI9HBF8MeSKi+zeAiP9GRfdvADHjESscEd2/AYTFIzweUeIRNR7R4hE9HhHcvwHEjEcE92/gd2DB/RtAWDzC4xHB/RtA1HhEi0f0eMSIRwT3bwCxwhHR/RtAWDzC4xElHlHjES0e0eMRwf0bQMx4RHD/Bs5SBPdvAGHxCI9HBPdvAFHjES0e0eMRIx4x4xHxH7NE92/MoyX0b4Ai3L+x9XVvAt/6ujeBb33dm8C3ftXW170JfOvr3gS+9XVvAt/6ujeBb33d/g3oC/dvbH3trSvcv7H1tbeucP/G1tfeusL9G1tfe+sK929sfar+DRhx9W9sI92bwLe+7k3gW1/3JvCtX7X1dW8C3/q6N4Fvfd2bwLe+7k3gW1/3JnDoC/dvbH3trSvcv7H1tbeucP/G1tfeusL9G1tfe+sK929sfe2ty9W/sY2o+je2EVX/xjai6t/YRiwb7GFE1b+xjaj6N7YRVf/GNqLq39hGVP0bMOLq39hGyW//q26C7UTWv7GdyC7026e8yPo3thNZ/8Z2Iuvf2E5k/Rvbiax/YzuR9W9sJ7L+DTix9W9sJ7L+je1E1r+xncj6N7ZTJXQi69/YTmT9G9uJrH9jO5H1b2wnsv4NOLH1b2wnsv6N7UTWv7GdyPo3tlMldCLr39hOZP0b24msf2M7kfVvbCey/o1f2Siy/o1fUmT9G7+kyPo3fkmR3Wv/S4qsf+OXFFn/xi8pwo/r6Po3fkmR9W/8kiLr3/glVRml2OaUeUb6+KQop4+hL5yDgr5wDgr6wjko6FdtfeEcFPSFc1DQF85BQV84BwV94fTxqa+cPoa+9tZVTh9DX3vrKqePoa+9dZXTx9DX3rrK6WPoc6WPTyOy9DGMhHNQ0BfOQUFfOAcF/aqtL5yDgr5wDgr6wjko6AvnoKAvnIM69ZXTx9DX3rrK6WPoa29d5fQx9LW3rnL6GPraW1c5fQx97a1Llj6GEVf6GEZc6WMYcaWPYcSywR5GXOljGHGlj2HElT6GEVf6GEZc6ePTiCx9DKPkt/9lMhNObOljOLEdZ8QpL7b0MZzY0sdwYksfw4ktfQwntvQxnNjSx3BiSx+fTnTpYzixpY/hxJY+hhNb+hhOldCJLX0MJ7b0MZzY0sdwYksfw4ktfXw60aWP4cSWPoYTW/oYTmzpYzhVQie29DGc2NLHcGJLH8OJLX0MJ7b08c5GsaWPtxRb+nhLsaWPtxRhqo8vfbyl2NLHW4rw4zq+9PGWYksfbym29PGWqoxSXHPq/N+znMCwG2WMx2+0zdtvD453H5zvPrjefPD68PhPHrR3H/R3H7x8meb97zDTnz1Y332wvftgf/fB8e6D890H15sPXp+WnPP2K4O5/MmD9u6D/u6D5d0H67sPtncf7O8+ePmT89svTu148uB898H15oPXJ35+8qC9+6C/+2B598HLn5zlt9dqlSev1fWhkZ882N99cLz74Hz3wfXmg9fnDn7yoL14sD75c+z+7oPl3Qevf3LabQKs/mQCXB83+MmD/d0Hx7sPzncfXG8+OI53H7z+yZnH/dPmNv/x5P/9ly9+YDwHU3IwNQfTcjA9BzNyMDMHs1Iw1+cFvo/JmQIzZwrMnCkwc6bAzJkCM2cKzJwpMHOmwMyZAitnCqycKbBypsDKmQIrZwqsnCmwcqbAypkCK2cKrJwp8OR3lQEcS+J4EqckcWoSpyVxehJnJHFmEidpHljSPLCkeWBJ88CS5oElzQNLmgeWNA8saR5Y0jywpHngSfPAk+aBJ80DT5oHnjQPPGkeeNI88KR54EnzwJPmQUmaByVpHpSkeVCS5kFJmgclaR6UpHlQkuZBSZoHJWke1KR5UJPmQU2aBzVpHtSkeVCT5kFNmgc1aR7UpHlQk+ZBS5oHLWketKR50JLmQUuaBy1pHrSkedCS5kFLmgctaR70pHnQk+ZBT5oHPWke9KR50JPmQU+aBz1pHvSkedCT5sFImgdJZxAt6RCiJZ1CtKRjiJZ0DtGSDiJa0klESzqKaElnES3pMKIlnUa0pOOIlnQe0ZIOJFrSiURLOpJoSWcSLelQoiWdSrSkY4mWdC7Rkg4mWtLJREs6mmhJZxMt6XCiJZ1OtKTjiZZ0PtGTzid60vlETzqf6EnnE/2oSZyWxOlJnJHEmUmcpHmQdD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtGTzid60vlETzqf6EnnEz3pfKInnU/0pPOJnnQ+0ZPOJ3rS+URPOp/oSecTPel8oiedT/Sk84medD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtGTzid60vlE/8J5vtZutRdt/Hb74T+uP/zCcb6fYL5w+q3N20247feLcP+J8RxMycHUHEzLwfzXxfPbo+PtR79wDOEnP99fOIXwI0zLwfQcTM6I+8IJhLba31/cj/YMs1IwXzh/8COM5WA8B/OFKbDsjunPMDUH03IwPQczcjAzB7NSlukXTh38CJPz17aV89e2lfPXti+cOPgRJuevbV84b/AjzMjBzBxMyhQox5GDsRyM52BKDqbmYFoOpudgRg5m5mBypoDlTAHLmQKWMwUsZwpYzhSwnClgOVPAcqaA5UwBy5kCnjMFPGcKeM4U8Jwp4DlTwHOmgOdMAU+YAvOv60K4VseN0vo/imb/f8hsN8ic9u9fegIfhVS/de64P4Qmm9BiE7r++84fNTI6I6czKnRGlc6o0Rl1OiO6iW10I9voZrbTzWynm9lON7OdbmY73cx2upntgTP7ARkZkM8n6281fuX4wvd2sRmVg87I6IyczqjQGVU6o0Zn1OmMBp0R3cwudDO70s3sSjezK93MrnQzu9LN7Eo3syvdzK6BM/sBmRmQlQBpRwbEMiCeASkZkJoBaRmQngHJeOP75z/Cdhy3rmw7zK8xnoP5/A/fvD5mcb/+hKGvlP+aceRgcn4ERv0Cpq87ZvZrTMvB9BzMyMHMHMw33ptuD8y4xMwjB2M5GM/BlBxMzcG0HEzPwYwczMzBfGEKmNXbF1u9/pvNOnIwloPxHEzJwdQcTMvB9BzMyMF8YQrY8Dvm9zN0v2NWCuZJ83cAp6T80+NJU3YApyVxehJn5XC+cM7wZxxL4ngSJ+H98eP65O64PzfGi49q6zH//tLq7d+/dN6nxjrq/377TPeND4BP8ylrvmTNr19mDXXTVXdd9aKrXnXVm65611XX3aWmu0xNd5u67jZ13W3qutvUdbep625T192mHrZNH4gRj/h4O7Xbb2Nrq9eIFY4oRzzC4hEej/h4yt0Dy3WWa0SNR7R4RI9HfPp2t+P2eVU75jVixiNWOKIe8QiLR3z6Q9v89qXNnyB6POLTP+5ebkc3evNLRDviEfHfqPbx233/NLq1cY2Y8YgVjuhHPMLiER6PKPGIGo9o8Ygej/ji2937NWLGIz5/u+9jcFwjxsdvd1mvEBaP8HjEp293vx+L7ce6RtR4RItH9HjEiEd8/HY/LhW34xqxwhHziEdYPMLjESUeUeMRLR7R4xHji4jrt3vOeMTnb/fteF73a8T6+O2+f4r6FGHxCI9HfLy7X/6LddV4RItH9HjEiEfMeET8xyxPTqt+j1GenICzXu4Hg3t78Usbq8dtElo1u6Q8OQb53zB13jHj1S+SvngbUnl2ekpH37X1i7Z+1dZv2vpdW39o609t/SWt79pb17W3rmtvXdfeuq69dV1767r21nXtrevaW9dZtu7dqLAs0odR8m785vVl5dk5Oh39oq1ftfWbtn7X1h/a+lNbf0nr10NbX3vrVu2tW7W3btXeulV761btrVu1t27V3rpVe+s2lq37MGJZpA8jlt34MGJZdw8jlg32MGJZSg8jlj3zMGJZHQ8jlm3wMGIZ8HejTjeze/Lb//IW6fIsqvKHnZJ/ul/ec1aeBTD+7PdpOKFTIXTq2U4vru4uz+IXf9hpEjotPqd5EDqlz6cXF1OXZ5mTP+xUCJ0qoVMjdOqEToPQaRI6LT6ndRA6Zc/xVzeYl2fpoj/sVAidKqFTI3TqhE6D0GkSOi0+p2edBIFSLwoMtpQxSjmjVOP7vOdZj8IflhqMUoQf11l24PBnUs4oVRilKqMU3Zwaqv0bp7noleGnueiN4ae5av8G1EVvDIe66I3hUBe9MRzqVVdd9MZwqIv2b0Bdd5eq9m9AXXebqvZvQF13m6r2b0Bdd5uq9m9AXXebRvdvADHiEcH9G0CscER0/wYQFo/weERw/wYQNR7R4hE9HhHcvwHEjEescER0/wYQFo8I7t8Aoscjgi+GPBHR/RtAxH+jovs3gJjxiBWOiO7fAMLiER6PKPGIGo9o8Ygejwju3wBixiOC+zfwO7Dg/g0gLB7h8Yjg/g0gajyixSN6PGLEI4L7N4BY4Yjo/g0gLB7h8YgSj6jxiBaP6PGI4P4NIGY8Irh/A2cpgvs3gLB4hMcjgvs3gKjxiBaP6PGIEY+Y8Yj4j1nC+zdqz+jfOCnK/RvQF74JHPrCN4FDX/gmcOhXbX3hm8ChL3wTOPSFbwKHvvBN4NAX7t849ZX7N6CvvXWV+zegr711lfs3oK+9dZX7N6CvvXWV+zegz9W/cRqR9W/ASPgmcOgL3wQOfeGbwKFftfWFbwKHvvBN4NAXvgkc+sI3gUNf+CbwU1+5fwP62ltXuX8D+tpbV7l/A/raW1e5fwP62ltXuX8D+tpbl6x/A0Zc/Rsw4urfgBFX/waMWDbYw4irfwNGXP0bMOLq34ARV/8GjLj6N04jsv4NGCW//S+7CeDE1r8BJ7YL/XDKi61/A05s/RtwYuvfgBNb/wac2Po34MTWvwEntv6N04mufwNObP0bcGLr34ATW/8GnCqhE1v/BpzY+jfgxNa/ASe2/g04sfVvnE50/RtwYuvfgBNb/wac2Po34FQJndj6N+DE1r8BJ7b+DTix9W/Aia1/Y2ej2Po3thRb/8aWYuvf2FJs99pvKbb+jS3F1r+xpQg/rjO6/o0txda/saXY+je2VGWUYptTrWSkj0+KcvoY+sI5KOgL56CgL5yDgn7V1hfOQUFfOAcFfeEcFPSFc1DQF04fn/rK6WPoa29d5fQx9LW3rnL6GPraW1c5fQx97a2rnD6GPlf6+DQiSx/DSDgHBX3hHBT0hXNQ0K/a+sI5KOgL56CgL5yDgr5wDgr6wjmoU185fQx97a2rnD6GvvbWVU4fQ1976yqnj6GvvXWV08fQ1966ZOljGHGlj2HElT6GEVf6GEYsG+xhxJU+hhFX+hhGXOljGHGlj2HElT4+jcjSxzBKfvtfJjPhxJY+hhPbcUac8mJLH8OJLX0MJ7b0MZzY0sdwYksfw4ktfQwntvTx6USXPoYTW/oYTmzpYzixpY/hVAmd2NLHcGJLH8OJLX0MJ7b0MZzY0senE136GE5s6WM4saWP4cSWPoZTJXRiSx/DiS19DCe29DGc2NLHcGJLH+9sFFv6eEuxpY+3FFv6eEsRpvr40sdbii19vKUIP67jSx9vKbb08ZZiSx9vqcooxTanuv31aQ91PW4+1V/ozPsoX0d9fKm/8zv103zKmi9Zczt01U1X3XXVi6561VVvuupdV113l5ruMjXdbeq629R1t6nrblPX3aauu01dd5t62DZ9IEY84uPt1G5nfGqr14gVjihHPMLiER6P+HjKzdtLVGe5RtR4RItH9HjEp293O8bfX9qOeY2Y8YgVjqhHPMLiEZ/+0Da/fWnzJ4gej/j0j7uX23m53vwS0Y54RPw3qn38dtf7T1Qb14gZj1jhiH7EIywe4fGIEo+o8YgWj+jxiC++3b1fI2Y84vO3+z4GxzVifPx234f5U4TFIzwe8enb3e9hi36sa0SNR7R4RI9HjHjEx2/3ut1L3e24RqxwxDziERaP8HhEiUfUeESLR/R4xPgi4vrtnjMe8fnbfTsa0/0asT5+u++foj5FWDzC4xEf7+6X/2JdNR7R4hE9HjHiETMeEf8xy5OT2d9jDMvo3xgm3b8xTLp/Y5h0/8Yw6f6NYdL9G8Ok+zeGSfdvDJPu3xgm3b8xTLp/Y5h0/8Yw6f6NYdL9G8Ok+zeGSfdvDJPu3xgm3b8xTLp/Y5h0/8Ywtv6NYWz9G8Ok+zeGSfdvDJPu3xgm3b8xTLp/Y5h0/8Yw6f6NYdL9G8Ok+zeGSfdvDJPu34C+9tZV7t+AvvbWVe7fGCbdvwF97a2r3L8xTLp/Yxhb/waMuPo3YMTVvwEjrv4NGLFssIcRV//GMLb+jWFs/RvD2Po3hrH1bwxj698Yxte/MYyvf2MYX//GML7+jWF8/RvD+Po3hvH1bwzj698Yxte/MYyvf2MYX//GML7+jWF8/RvD+Po3hvH1bwzj698Yxte/MYyvf2MYX//GML7+jWF8/RvD+Po3hvH1bwzj698Yxte/MYyvf2MYX//GML7+jWF8/RvD+Po3hhH2b2wptv6NLcXWv7Gl2O6131Js/Rtbiq1/Y0sRflxndP0bW4qtf2NLsfVvbKnKKEU3p6Zq/8ZpLnpl+GkuemP4aa7avwF10RvDoS56YzjURW8Mh3rVVRe9MRzqov0bUNfdpar9G1DX3aaq/RtQ192mqv0bUNfdpqr9G1DX3abR/RtAjHhEcP8GECscEd2/AYTFIzweEdy/AUSNR7R4RI9HBPdvADHjESscEd2/AYTFI4L7N4Do8YjgiyFPRHT/BhDx36jo/g0gZjxihSOi+zeAsHiExyNKPKLGI1o8oscjgvs3gJjxiOD+DfwOLLh/AwiLR3g8Irh/A4gaj2jxiB6PGPGI4P4NIFY4Irp/AwiLR3g8osQjajyixSN6PCK4fwOIGY8I7t/AWYrg/g0gLB7h8Yjg/g0gajyixSN6PGLEI2Y8Iv5jlvD+jTky+jdOinL/BvSFbwKHvvBN4NAXvgkc+lVbX/gmcOgL3wQOfeGbwKEvfBM49IX7N0595f4N6GtvXeX+Dehrb13l/g3oa29d5f4N6GtvXeX+Dehz9W+cRmT9GzASvgkc+sI3gUNf+CZw6FdtfeGbwKEvfBM49IVvAoe+8E3g0Be+CfzUV+7fgL721lXu34C+9tZV7t+AvvbWVe7fgL721lXu34C+9tYl69+AEVf/Boy4+jdgxNW/ASOWDfYw4urfgBFX/waMuPo3YMTVvwEjrv6N04isfwNGyW//y24COLH1b8CJ7UI/nPJi69+AE1v/BpzY+jfgxNa/ASe2/g04sfVvwImtf+N0ouvfgBNb/wac2Po34MTWvwGnSujE1r8BJ7b+DTix9W/Aia1/A05s/RunE13/BpzY+jfgxNa/ASe2/g04VUIntv4NOLH1b8CJrX8DTmz9G3Bi69/Y2Si2/o0txda/saXY+je2FNu99luKrX9jS7H1b2wpwo/rjK5/Y0ux9W9sKbb+jS1VGaXY5tSqGenjk6KcPoa+cA4K+sI5KOgL56CgX7X1hXNQ0BfOQUFfOAcFfeEcFPSF08envnL6GPraW1c5fQx97a2rnD6GvvbWVU4fQ1976yqnj6HPlT4+jcjSxzASzkFBXzgHBX3hHBT0q7a+cA4K+sI5KOgL56CgL5yDgr5wDurUV04fQ1976yqnj6GvvXWV08fQ1966yulj6GtvXeX0MfS1ty5Z+hhGXOljGHGlj2HElT6GEcsGexhxpY9hxJU+hhFX+hhGXOljGHGlj08jsvQxjJLf/pfJTDixpY/hxHacEae82NLHcGJLH8OJLX0MJ7b0MZzY0sdwYksfw4ktfXw60aWP4cSWPoYTW/oYTmzpYzhVQie29DGc2NLHcGJLH8OJLX0MJ7b08elElz6GE1v6GE5s6WM4saWP4VQJndjSx3BiSx/DiS19DCe29DGc2NLHOxvFlj7eUmzp4y3Flj7eUoSpPr708ZZiSx9vKcKP6/jSx1uKLX28pdjSx1uqMkqRzSk/+pP0cavj9mDr498pXzx7DqHJJrTYhJ5Euf+kkdEZOZ1RoTOqdEaNzqjTGdFNbKMb2UY3s51uZjvdzHa6me10M9vpZrbTzWwPnNkPyMiAfD5Zv3iQdRstNqNy0BkZnZHTGRU6o0pn1OiMOp3RoDOim9mFbmZXupld6WZ2pZvZlW5mV7qZXelmdqWb2TVwZj8gMwOyEiDtyIBYBsQzICUDUjMgLQPSMyAZb3z//Ef4VRhgYzwH8/kf/k9+/ddXyn/NOHIwOT8Co34B8+9H8jem5WB6DmbkYGYO5hvvzb+f5t2/DD9yMJaD8RxMycHUHEzLwfQczMjBzBzMF6bAi/Op+wTKkYOxHIznYEoOpuZgWg6m52BGDuYLU+DF+eONWSmYZ6fUv88pKf/0sKMmcVoSpydxVg7nC+cMf8axJI4ncTLen3l9cnfcnxvjxUe19bidJK7+4iDxvE+NddT//faZ7jsfAM/rI74S5kvW/Ppl1lA3XXXXVS+66lVXvemqd1113V1qusvUdLep625T192mrrtNXXebuu42dd1t6mHb9IEY8YiPt1O7/Ta2tnqNWOGIcsQjLB7h8YiPp9y8vUR1lmtEjUe0eESPR3z6drfj9nlVO+Y1YsYjVjiiHvEIi0d8+kPb/PalzZ8gejzi0z/uXm5HN3rzS0Q74hHx36j28dt9/zS6tXGNmPGIFY7oRzzC4hEejyjxiBqPaPGIHo/44tvd+zVixiM+f7vvY3BcI8bHb/d9mD9FWDzC4xGfvt39fiy2H+saUeMRLR7R4xEjHvHx273aDWHHNWKFI+YRj7B4hMcjSjyixiNaPKLHI8YXEddv95zxiM/f7tvxvO7XiPXx233/FPUpwuIRHo/4eHe//BfrqvGIFo/o8YgRj5jxiPiPWZ6cVv0ew56cgPuP12ket0lo1eySYsmXQ3/zNiR7dnpKR9+19Yu2ftXWb9r6XVt/aOtPbf0lre/aW9e1t65rb13X3rquvXVde+u69tZ17a3r2lvXWbbu3aiwLNKHUfJu/Ob1ZfbsHJ2OftHWr9r6TVu/a+sPbf2prb+k9euhra+9dav21q3aW7dqb92qvXWr9tat2lu3am/dqr11G8vWfRixLNKHEctufBixrLuHEcsGexixLKWHEcueeRixrI6HEcs2eBixDPi7Uaeb2T357X95i7Q9i6r8YSeyKu59ysv4vk/DCZ0KoVPPdnpxdbc9i1/8YadJ6LT4nOZB6JQ+n15cTG3PMid/2KkQOlVCp0bo1AmdBqHTJHRafE7rIHTKnuOvbjC3Z+miP+xUCJ0qoVMjdOqEToPQaRI6LT6nZ50EgVIvCgy2lDFKOaNU4/u851mPwh+WGoxShB/XWXbg8GdSzihVGKUqoxTbnPKm2r9xmoteGX6ai94Yfpqr9m9AXfTGcKiL3hgOddEbw6FeddVFbwyHumj/BtR1d6lq/wbUdbepav8G1HW3qWr/BtR1t6lq/wbUdbdpdP8GECMeEdy/AcQKR0T3bwBh8QiPRwT3bwBR4xEtHtHjEcH9G0DMeMQKR0T3bwBh8Yjg/g0gejwi+GLIExHdvwFE/Dcqun8DiBmPWOGI6P4NICwe4fGIEo+o8YgWj+jxiOD+DSBmPCK4fwO/Awvu3wDC4hEejwju3wCixiNaPKLHI0Y8Irh/A4gVjoju3wDC4hEejyjxiBqPaPGIHo8I7t8AYsYjgvs3cJYiuH8DCItHeDwiuH8DiBqPaPGIHo8Y8YgZj4j/mCW8f6PUjP6Nk6LcvwF94ZvAoS98Ezj0hW8Ch37V1he+CRz6wjeBQ1/4JnDoC98EDn3h/o1TX7l/A/raW1e5fwP62ltXuX8D+tpbV7l/A/raW1e5fwP6XP0bpxFZ/waMhG8Ch77wTeDQF74JHPpVW1/4JnDoC98EDn3hm8ChL3wTOPSFbwI/9ZX7N6CvvXWV+zegr711lfs3oK+9dZX7N6CvvXWV+zegr711yfo3YMTVvwEjrv4NGHH1b8CIZYM9jLj6N2DE1b8BI67+DRhx9W/AiKt/4zQi69+AUfLb/7KbAE5s/RtwYrvQD6e82Po34MTWvwEntv4NOLH1b8CJrX8DTmz9G3Bi6984nej6N+DE1r8BJ7b+DTix9W/AqRI6sfVvwImtfwNObP0bcGLr34ATW//G6UTXvwEntv4NOLH1b8CJrX8DTpXQia1/A05s/RtwYuvfgBNb/wac2Po3djaKrX9jS7H1b2wptv6NLcV2r/2WYuvf2FJs/RtbivDjOr7+jS3F1r+xpdj6N7ZUZZRim1PVMtLHJ0U5fQx94RwU9IVzUNAXzkFBv2rrC+egoC+cg4K+cA4K+sI5KOgLp49PfeX0MfS1t65y+hj62ltXOX0Mfe2tq5w+hr721lVOH0OfK318GpGlj2EknIOCvnAOCvrCOSjoV2194RwU9IVzUNAXzkFBXzgHBX3hHNSpr5w+hr721lVOH0Nfe+sqp4+hr711ldPH0NfeusrpY+hrb12y9DGMuNLHMOJKH8OIK30MI5YN9jDiSh/DiCt9DCOu9DGMuNLHMOJKH59GZOljGCW//S+TmXBiSx/Die04I055saWP4cSWPoYTW/oYTmzpYzixpY/hxJY+hhNb+vh0oksfw4ktfQwntvQxnNjSx3CqhE5s6WM4saWP4cSWPoYTW/oYTmzp49OJLn0MJ7b0MZzY0sdwYksfw6kSOrGlj+HElj6GE1v6GE5s6WM4saWPdzaKLX28pdjSx1uKLX28pQhTfXzp4y3Flj7eUoQf1/Glj7cUW/p4S7Glj7dUZZSim1Prr097qOtx86n+QmfeR/k66uNL/a3fqa+/pqz5kjW3Q1fddNVdV73oqldd9aar3nXVdXep6S5T092mrrtNXXebuu42dd1t6rrb1HW3qYdt0wdixCM+3k7tdsantnqNWOGIcsQjLB7h8YiPp9y8vUR1lmtEjUe0eESPR3z6drdj/P2l7ZjXiBmPWOGIesQjLB7x6Q9t89uXNn+C6PGIT/+4e7mdl+vNLxHtiEfEf6Pax293vf9EtXGNmPGIFY7oRzzC4hEejyjxiBqPaPGIHo/44tvd+zVixiM+f7vvY3BcI8bHb/d9mD9FWDzC4xGfvt39Hrbox7pG1HhEi0f0eMSIR3z8dq/bvdTdjmvECkfMIx5h8QiPR5R4RI1HtHhEj0eMLyKu3+454xGfv923ozHdrxHr47f7/inqU4TFIzwe8fHufvkv1lXjES0e0eMRIx4x4xHxH7M8OZn9PUZbGf0bbUn3b7Ql3b/RlnT/RlvS/RttSfdvtCXdv9GWdP9GW9L9G21J92+0Jd2/0ZZ0/0Zb0v0bbUn3b7Ql3b/RlnT/RlvS/RttSfdvtCXdv9GWdP9GW2z9G22x9W+0Jd2/0ZZ0/0Zb0v0bbUn3b7Ql3b/RlnT/RlvS/RttSfdvtCXdv9GWdP9GW9L9G9DX3rrK/RvQ1966yv0bbUn3b0Bfe+sq92+0Jd2/0RZb/waMuPo3YMTVvwEjrv4NGLFssIcRV/9GW2z9G22x9W+0xda/0RZb/0ZbbP0bbfH1b7TF17/RFl//Rlt8/Rtt8fVvtMXXv9EWX/9GW3z9G23x9W+0xde/0RZf/0ZbfP0bbfH1b7TF17/RFl//Rlt8/Rtt8fVvtMXXv9EWX/9GW3z9G23x9W+0xde/0RZf/0ZbfP0bbfH1b7TF17/RFl//Rlt8/Rtt8fVvtMXXv9EWYf/GlmLr39hSbP0bW4rtXvstxda/saXY+je2FOHHdXz9G1uKrX9jS7H1b2ypyijFNqd6V+3fOM1Frww/zUVvDD/NVfs3oC56YzjURW8Mh7rojeFQr7rqojeGQ120fwPqurtUtX8D6rrbVLV/A+q621S1fwPquttUtX8D6rrbNLp/A4gRjwju3wBihSOi+zeAsHiExyOC+zeAqPGIFo/o8Yjg/g0gZjxihSOi+zeAsHhEcP8GED0eEXwx5ImI7t8AIv4bFd2/AcSMR6xwRHT/BhAWj/B4RIlH1HhEi0f0eERw/wYQMx4R3L+B34EF928AYfEIj0cE928AUeMRLR7R4xEjHhHcvwHECkdE928AYfEIj0eUeESNR7R4RI9HBPdvADHjEcH9GzhLEdy/AYTFIzweEdy/AUSNR7R4RI9HjHjEjEfEf8wS3r8xWkb/xklR7t+AvvBN4NAXvgkc+sI3gUO/ausL3wQOfeGbwKEvfBM49IVvAoe+cP/Gqa/cvwF97a2r3L8Bfe2tq9y/AX3travcvwF97a2r3L8Bfa7+jdOIrH8DRsI3gUNf+CZw6AvfBA79qq0vfBM49IVvAoe+8E3g0Be+CRz6wjeBn/rK/RvQ1966yv0b0Nfeusr9G9DX3rrK/RvQ1966yv0b0NfeumT9GzDi6t+AEVf/Boy4+jdgxLLBHkZc/Rsw4urfgBFX/waMuPo3YMTVv3EakfVvwCj57X/ZTQAntv4NOLFd6IdTXmz9G3Bi69+AE1v/BpzY+jfgxNa/ASe2/g04sfVvnE50/RtwYuvfgBNb/wac2Po34FQJndj6N+DE1r8BJ7b+DTix9W/Aia1/43Si69+AE1v/BpzY+jfgxNa/AadK6MTWvwEntv4NOLH1b8CJrX8DTmz9Gzsbxda/saXY+je2FFv/xpZiu9d+S7H1b2wptv6NLUX4cR1f/8aWYuvf2FJs/RtbqjJKsc2p6Rnp45OinD6GvnAOCvrCOSjoC+egoF+19YVzUNAXzkFBXzgHBX3hHBT0hdPHp75y+hj62ltXOX0Mfe2tq5w+hr721lVOH0Nfe+sqp4+hz5U+Po3I0scwEs5BQV84BwV94RwU9Ku2vnAOCvrCOSjoC+egoC+cg4K+cA7q1FdOH0Nfe+sqp4+hr711ldPH0NfeusrpY+hrb13l9DH0tbcuWfoYRlzpYxhxpY9hxJU+hhHLBnsYcaWPYcSVPoYRV/oYRlzpYxhxpY9PI7L0MYyS3/6XyUw4saWP4cR2nBGnvNjSx3BiSx/DiS19DCe29DGc2NLHcGJLH8OJLX18OtGlj+HElj6GE1v6GE5s6WM4VUIntvQxnNjSx3BiSx/DiS19DCe29PHpRJc+hhNb+hhObOljOLGlj+FUCZ3Y0sdwYksfw4ktfQwntvQxnNjSxzsbxZY+3lJs6eMtxZY+3lKEqT6+9PGWYksfbynCj+v40sdbii19vKXY0sdbqjJKkc2p9jQnMOxGGePxG23z9tuD490H57sPrjcfvD48/pMH7d0H/d0HL1+mef87zPRnD9Z3H2zvPtjffXC8++B898H15oPXpyXnvP3KYC5/8qC9+6C/+2B598H67oPt3Qf7uw9e/uT89otTO548ON99cL354PWJn588aO8+6O8+WN598PInZ/nttVrlyWt1fWjkJw/2dx8c7z44331wvfng9bmDnzxoLx6sT/4cu7/7YHn3weufnHabAKs/mQDXxw1+8mB/98Hx7oPz3QfXmw+O490Hr39y5nH/tLnNfzz5f//lix8Yz8GUHEzNwbQcTM/BjBzMzMGsFMz1eYHvY3KmwMyZAjNnCsycKTBzpsDMmQIzZwrMnCkwc6bAypkCK2cKrJwpsHKmwMqZAitnCqycKbBypsDKmQIrZwo8+V1lAMeSOJ7EKUmcmsRpSZyexBlJnJnESZoHljQPLGkeWNI8sKR5YEnzwJLmgSXNA0uaB5Y0DyxpHnjSPPCkeeBJ88CT5oEnzQNPmgeeNA88aR540jzwpHlQkuZBSZoHJWkelKR5UJLmQUmaByVpHpSkeVCS5kFJmgc1aR7UpHlQk+ZBTZoHNWke1KR5UJPmQU2aBzVpHtSkedCS5kFLmgctaR60pHnQkuZBS5oHLWketKR50JLmQUuaBz1pHvSkedCT5kFPmgc9aR70pHnQk+ZBT5oHPWke9KR5MJLmQdIZREs6hGhJpxAt6RiiJZ1DtKSDiJZ0EtGSjiJa0llESzqMaEmnES3pOKIlnUe0pAOJlnQi0ZKOJFrSmURLOpRoSacSLelYoiWdS7Skg4mWdDLRko4mWtLZREs6nGhJpxMt6XiiJZ1P9KTziZ50PtGTzid60vlEP2oSpyVxehJnJHFmEidpHiSdT/Sk84medD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtGTzid60vlETzqf6EnnEz3pfKInnU/0pPOJnnQ+0ZPOJ3rS+URPOp/oSecTPel8oiedT/Sk84medD7Rk84netL5RE86n+hJ5xM96XyiJ51P9KTziZ50PtG/cJ6vtVvtRRu/3X74j+sPv3Cc7yeYL5x+O/9/bpjfL8L9J8ZzMCUHU3MwLQfzXxfPb4+Otx/9wjGEn/x8f+EUwo8wLQfTczA5I+4LJxDaan9/cT/aM8xKwXzh/MGPMJaD8RzMF6bAsjumP8PUHEzLwfQczMjBzBzMSlmmXzh18CNMzl/bVs5f21bOX9u+cOLgR5icv7Z94bzBjzAjBzNzMClToBxHDsZyMJ6DKTmYmoNpOZiegxk5mJmDyZkCljMFLGcKWM4UsJwpYDlTwHKmgOVMAcuZApYzBSxnCnjOFPCcKeA5U8BzpoDnTAHPmQKeMwU8YQrMv64L4VodN0rr/yia/f8hs90gc9q/f6nZfBRS/da54/4QmmxCi03o+u87f9TI6IyczqjQGVU6o0Zn1OmM6Ca20Y1so5vZTjeznW5mO93MdrqZ7XQz2+lmtgfO7AdkZEA+n6y/1fiV4wvf28VmVA46I6MzcjqjQmdU6YwanVGnMxp0RnQzu9DN7Eo3syvdzK50M7vSzexKN7Mr3cyudDO7Bs7sB2RmQFYCpB0ZEMuAeAakZEBqBqRlQHoGJOON75//CNtx3Lqy7TC/xngO5vM/fPP6mMX9+hOGvlL+a8aRg8n5ERj1C5i+7pjZrzEtB9NzMCMHM3Mw33hvuj0w4xIzjxyM5WA8B1NyMDUH03IwPQczcjAzB/OFKWBWb19s9fpvNuvIwVgOxnMwJQdTczAtB9NzMCMH84UpYMPvmN/P0P2OWSmYJ83fAZyS8k+PJ03ZAZyWxOlJnJXD+cI5w59xLInjSZyE92cd1yd3x/25MV58VFuP+feXVm///qXzPjXWUf/322e6b3wAfJpPWfMla379Mmuom66666oXXfWqq9501buuuu4uNd1larrb1HW3qetuU9fdpq67TV13m7ruNvWwbfpAjHjEx9up3X4bW1u9RqxwRDniERaP8HjEx1PuHlius1wjajyixSN6POLTt7sdt8+r2jGvETMescIR9YhHWDzi0x/a5rcvbf4E0eMRn/5x93I7utGbXyLaEY+I/0a1j9/u+6fRrY1rxIxHrHBEP+IRFo/weESJR9R4RItH9HjEF9/u3q8RMx7x+dt9H4PjGjE+frvLeoWweITHIz59u/v9WGw/1jWixiNaPKLHI0Y84uO3+3GpuB3XiBWOmEc8wuIRHo8o8Ygaj2jxiB6PGF9EXL/dc8YjPn+7b8fzul8j1sdv9/1T1KcIi0d4POLj3f3yX6yrxiNaPKLHI0Y8YsYj4j9meXJa9WuMfjw5AWe93A8G9/bilzZWj9sktGp2SXlyDPK/Yeq8Y8arXyR97zakrW/a+q6tX7T1q7Z+09bv2vpDW39q6y9pfdfeuq69dV1767r21nXtrevaW9e1t65rb13X3rrOsnXvRoVlkT6MknfjF68v2/qurV+09au2ftPW79r6Q1t/ausvaf16aOtrb92qvXWr9tat2lu3am/dqr11q/bWrdpbt2pv3caydR9GLIv0YcSyGx9GLOvuYcSywR5GLEvpYcSyZx5GLKvjYcSyDR5GLAP+btTpZnZPfvtf3SK9nRqhU/JP96t7zvYpL+P7Pg0ndCqETj3b6d+v7t5Og9BpEjotPqd5EDqlz6d/v5h6OzmhUyF0qoROjdCpEzoNQqdJ6LT4nNZB6JQ9x1/cYL6dnNCpEDpVQqdG6NQJnQah0yR0WnxOzzoJAqX+vcDgl5QxSjmjVOP7vOdZj8IflhqMUoQf11l24PBnUs4oVRilKqMU3Zwaov0bMNe8MhzmmjeGw1y0f2Ora94YvtU1bwzf6po3hm/1qquueWP4Vtfs39jqurtUtH9jq+tuU9H+ja2uu01F+ze2uu42Fe3f2Oq62zS4f2MjRjwitn9jI1Y4Irh/YyMsHuHxiNj+jY2o8YgWj+jxiNj+jY2Y8YgVjgju39gIi0fE9m9sRI9HxF4MCUQ74hHx36jg/o2NmPGIFY4I7t/YCItHeDyixCNqPKLFI3o8IrZ/YyNmPCK2f2P/Diy2f2MjLB7h8YjY/o2NqPGIFo/o8YgRj4jt39iIFY4I7t/YCItHeDyixCNqPKLFI3o8IrZ/YyNmPCK2f2OfpYjt39gIi0d4PCK2f2MjajyixSN6PGLEI2Y8Iv5jlvD+DesZ/RsnRbl/A/rCN4FDX/gmcOgL3wQO/aqtL3wTOPSFbwKHvvBN4NAXvgkc+sL9G6e+cv8G9LW3rnL/BvS1t65y/wb0tbeucv8G9LW3rnL/BvS5+jdOI7L+DRgJ3wQOfeGbwKEvfBM49Ku2vvBN4NAXvgkc+sI3gUNf+CZw6AvfBH7qK/dvQF976yr3b0Bfe+sq929AX3vrKvdvQF976yr3b0Bfe+uS9W/AiKt/A0Zc/Rsw4urfgBHLBnsYcfVvwIirfwNGXP0bMOLq34ARV//GaUTWvwGj5Lf/ZTcBnNj6N+DEdqEfTnmx9W/Aia1/A05s/RtwYuvfgBNb/wac2Po34MTWv3E60fVvwImtfwNObP0bcGLr34BTJXRi69+AE1v/BpzY+jfgxNa/ASe2/o3Tia5/A05s/RtwYuvfgBNb/wacKqETW/8GnNj6N+DE1r8BJ7b+DTix9W/sbBRb/8aWYuvf2FJs/Rtbiu1e+y3F1r+xpdj6N7YU4cd1fP0bW4qtf2NLsfVvbKnKKMU2p7xkpI9PinL6GPrCOSjoC+egoC+cg4J+1dYXzkFBXzgHBX3hHBT0hXNQ0BdOH5/6yulj6GtvXeX0MfS1t65y+hj62ltXOX0Mfe2tq5w+hj5X+vg0Iksfw0g4BwV94RwU9IVzUNCv2vrCOSjoC+egoC+cg4K+cA4K+sI5qFNfOX0Mfe2tq5w+hr721lVOH0Nfe+sqp4+hr711ldPH0NfeumTpYxhxpY9hxJU+hhFX+hhGLBvsYcSVPoYRV/oYRlzpYxhxpY9hxJU+Po3I0scwSn77XyYz4cSWPoYT23FGnPJiSx/DiS19DCe29DGc2NLHcGJLH8OJLX0MJ7b08elElz6GE1v6GE5s6WM4saWP4VQJndjSx3BiSx/DiS19DCe29DGc2NLHpxNd+hhObOljOLGlj+HElj6GUyV0Yksfw4ktfQwntvQxnNjSx3BiSx/vbBRb+nhLsaWPtxRb+nhLEab6+NLHW4otfbylCD+u40sfbym29PGWYksfb6nKKMU2p4r99WkPdT1uPtVf6Mz7KF9HfXypv/M79dN8ypovWXM7dNVNV9111YuuetVVb7rqXVddd5ea7jI13W3qutvUdbep625T192mrrtNXXebetg2fSBGPOLj7dRuZ3xqq9eIFY4oRzzC4hEej/h4ys3bS1RnuUbUeESLR/R4xKdvdzvG31/ajnmNmPGIFY6oRzzC4hGf/tA2v31p8yeIHo/49I+7l9t5ud78EtGOeET8N6p9/HbX+09UG9eIGY9Y4Yh+xCMsHuHxiBKPqPGIFo/o8Ygvvt29XyNmPOLzt/s+Bsc1Ynz8dt+H+VOExSM8HvHp293vYYt+rGtEjUe0eESPR4x4xMdv97rdS93tuEascMQ84hEWj/B4RIlH1HhEi0f0eMT4IuL67Z4zHvH52307GtP9GrE+frvvn6I+RVg8wuMRH+/ul/9iXTUe0eIRPR4x4hEzHhH/McuTk9nfY1TL6N+oJt2/UU26f6OadP9GNen+jWrS/RvVpPs3qkn3b1ST7t+oJt2/UU26f6OadP9GNen+jWrS/RvVpPs3qkn3b1ST7t+oJt2/UU26f6OadP9GNbb+jWps/RvVpPs3qkn3b1ST7t+oJt2/UU26f6OadP9GNen+jWrS/RvVpPs3qkn3b1ST7t+AvvbWVe7fgL721lXu36gm3b8Bfe2tq9y/UU26f6MaW/8GjLj6N2DE1b8BI67+DRixbLCHEVf/RjW2/o1qbP0b1dj6N6qx9W9UY+vfqMbXv1GNr3+jGl//RjW+/o1qfP0b1fj6N6rx9W9U4+vfqMbXv1GNr3+jGl//RjW+/o1qfP0b1fj6N6rx9W9U4+vfqMbXv1GNr3+jGl//RjW+/o1qfP0b1fj6N6rx9W9U4+vfqMbXv1GNr3+jGl//RjW+/o1qfP0b1fj6N6oR9m9sKbb+jS3F1r+xpdjutd9SbP0bW4qtf2NLEX5cx9e/saXY+je2FFv/xpaqjFJ0c2qq9m+c5qJXhp/mojeGn+aq/RtQF70xHOqiN4ZDXfTGcKhXXXXRG8OhLtq/AXXdXaravwF13W2q2r8Bdd1tqtq/AXXdbaravwF13W0a3b8BxIhHBPdvALHCEdH9G0BYPMLjEcH9G0DUeESLR/R4RHD/BhAzHrHCEdH9G0BYPCK4fwOIHo8IvhjyRET3bwAR/42K7t8AYsYjVjgiun8DCItHeDyixCNqPKLFI3o8Irh/A4gZjwju38DvwIL7N4CweITHI4L7N4Co8YgWj+jxiBGPCO7fAGKFI6L7N4CweITHI0o8osYjWjyixyOC+zeAmPGI4P4NnKUI7t8AwuIRHo8I7t8AosYjWjyixyNGPGLGI+I/Zgnv32gjo3/jpCj3b0Bf+CZw6AvfBA594ZvAoV+19YVvAoe+8E3g0Be+CRz6wjeBQ1+4f+PUV+7fgL721lXu34C+9tZV7t+AvvbWVe7fgL721lXu34A+V//GaUTWvwEj4ZvAoS98Ezj0hW8Ch37V1he+CRz6wjeBQ1/4JnDoC98EDn3hm8BPfeX+Dehrb13l/g3oa29d5f4N6GtvXeX+Dehrb13l/g3oa29dsv4NGHH1b8CIq38DRlz9GzBi2WAPI67+DRhx9W/AiKt/A0Zc/Rsw4urfOI3I+jdglPz2v+wmgBNb/wac2C70wykvtv4NOLH1b8CJrX8DTmz9G3Bi69+AE1v/BpzY+jdOJ7r+DTix9W/Aia1/A05s/RtwqoRObP0bcGLr34ATW/8GnNj6N+DE1r9xOtH1b8CJrX8DTmz9G3Bi69+AUyV0YuvfgBNb/wac2Po34MTWvwEntv6NnY1i69/YUmz9G1uKrX9jS7Hda7+l2Po3thRb/8aWIvy4jq9/Y0ux9W9sKbb+jS1VGaXY5lSvGenjk6KcPoa+cA4K+sI5KOgL56CgX7X1hXNQ0BfOQUFfOAcFfeEcFPSF08envnL6GPraW1c5fQx97a2rnD6GvvbWVU4fQ1976yqnj6HPlT4+jcjSxzASzkFBXzgHBX3hHBT0q7a+cA4K+sI5KOgL56CgL5yDgr5wDurUV04fQ1976yqnj6GvvXWV08fQ1966yulj6GtvXeX0MfS1ty5Z+hhGXOljGHGlj2HElT6GEcsGexhxpY9hxJU+hhFX+hhGXOljGHGlj08jsvQxjJLf/pfJTDixpY/hxHacEae82NLHcGJLH8OJLX0MJ7b0MZzY0sdwYksfw4ktfXw60aWP4cSWPoYTW/oYTmzpYzhVQie29DGc2NLHcGJLH8OJLX0MJ7b08elElz6GE1v6GE5s6WM4saWP4VQJndjSx3BiSx/DiS19DCe29DGc2NLHOxvFlj7eUmzp4y3Flj7eUoSpPr708ZZiSx9vKcKP6/jSx1uKLX28pdjSx1uqMkqxzanRn6SPWx23B1sf/0755tnzU2iyCS02oSdR7j9pZHRGTmdU6IwqnVGjM+p0RnQT2+hGttHNbKeb2U43s51uZjvdzHa6me10M9sDZ/YDMjIgn0/Wbx5khdFiMyoHnZHRGTmdUaEzqnRGjc6o0xkNOiO6mV3oZnalm9mVbmZXupld6WZ2pZvZlW5mV7qZXQNn9gMyMyArAdKODIhlQDwDUjIgNQPSMiA9A5LxxvfPf4RfhgGA8RzM53/4P/n1X18p/zXjyMHk/AiM+gXMiyP5wLQcTM/BjBzMzMF84715cZoXvww/cjCWg/EcTMnB1BxMy8H0HMzIwcwczBemwKvzqTiBcuRgLAfjOZiSg6k5mJaD6TmYkYP5whR4df4YmJWCeXZK/fuckvJPDztqEqclcXoSZ+VwvnDO8GccS+J4Eifj/ZnXJ3fH/bkxXnxUW4/bSeLqLw4Sz/vUWEf932+f6b7zAfC8PuIrYb5kza9fZg1101V3XfWiq1511ZuuetdV192lprtMTXebuu42dd1t6rrb1HW3qetuU9fdph62TR+IEY/4eDu1229ja6vXiBWOKEc8wuIRHo/4eMrN20tUZ7lG1HhEi0f0eMSnb3c7bp9XtWNeI2Y8YoUj6hGPsHjEpz+0zW9f2vwJoscjPv3j7uV2dKM3v0S0Ix4R/41qH7/d90+jWxvXiBmPWOGIfsQjLB7h8YgSj6jxiBaP6PGIL77dvV8jZjzi87f7PgbHNWJ8/Hbfh/lThMUjPB7x6dvd78di+7GuETUe0eIRPR4x4hEfv92r3RB2XCNWOGIe8QiLR3g8osQjajyixSN6PGJ8EXH9ds8Zj/j87b4dz+t+jVgfv933T1GfIiwe4fGIj3f3y3+xrhqPaPGIHo8Y8YgZj4j/mOXJadXvMeaTE3D/8TrN4zYJrZpdUiz5cuhv3oY0n52e0tF3bf2irV+19Zu2ftfWH9r6U1t/Seu79tZ17a3r2lvXtbeua29d1966rr11XXvruvbWdZatezcqLIv0YZS8G795fdl8do5OR79o61dt/aat37X1h7b+1NZf0vr10NbX3rpVe+tW7a1btbdu1d66VXvrVu2tW7W3btXeuo1l6z6MWBbpw4hlNz6MWNbdw4hlgz2MWJbSw4hlzzyMWFbHw4hlGzyMWAb83ajTzeye/Pa/vEV6Pouq/GEntiru+SyA8We/T8MJnQqhU892enF193wWv/jDTpPQafE5zYPQKX0+vbiYej7LnPxhp0LoVAmdGqFTJ3QahE6T0GnxOa2D0Cl7jr+6wXw+Sxf9YadC6FQJnRqhUyd0GoROk9Bp8Tk96yQIlHpRYLCljFHKGaUa3+c9z3oU/rDUYJQi/LjOsgOHP5NyRqnCKFUZpdjm1Gqq/RunueiV4ae56I3hp7lq/wbURW8Mh7rojeFQF70xHOpVV130xnCoi/ZvQF13l6r2b0Bdd5uq9m9AXXebqvZvQF13m6r2b0Bdd5tG928AMeIRwf0bQKxwRHT/BhAWj/B4RHD/BhA1HtHiET0eEdy/AcSMR6xwRHT/BhAWjwju3wCixyOCL4Y8EdH9G0DEf6Oi+zeAmPGIFY6I7t8AwuIRHo8o8Ygaj2jxiB6PCO7fAGLGI4L7N/A7sOD+DSAsHuHxiOD+DSBqPKLFI3o8YsQjgvs3gFjhiOj+DSAsHuHxiBKPqPGIFo/o8Yjg/g0gZjwiuH8DZymC+zeAsHiExyOC+zeAqPGIFo/o8YgRj5jxiPiPWaL7N8ZRE/o3QBHu39j6ujeBb33dm8C3vu5N4Fu/auvr3gS+9XVvAt/6ujeBb33dm8C3vm7/BvSF+ze2vvbWFe7f2PraW1e4f2Pra29d4f6Nra+9dYX7N7Y+Vf8GjLj6N7aR7k3gW1/3JvCtr3sT+Nav2vq6N4Fvfd2bwLe+7k3gW1/3JvCtr3sTOPSF+ze2vvbWFe7f2PraW1e4f2Pra29d4f6Nra+9dYX7N7a+9tbl6t/YRlT9G9uIqn9jG1H1b2wjlg32MKLq39hGVP0b24iqf2MbUfVvbCOq/g0YcfVvbKPkt/9VN8F2Iuvf2E5kF/rtU15k/Rvbiax/YzuR9W9sJ7L+je1E1r+xncj6N7YTWf8GnNj6N7YTWf/GdiLr39hOZP0b26kSOpH1b2wnsv6N7UTWv7GdyPo3thNZ/wac2Po3thNZ/8Z2Iuvf2E5k/RvbqRI6kfVvbCey/o3tRNa/sZ3I+je2E1n/xq9sFFn/xi8psv6NX1Jk/Ru/pMjutf8lRda/8UuKrH/jlxThx3V0/Ru/pMj6N35JkfVv/JKqjFJsc8osI318UpTTx9AXzkFBXzgHBX3hHBT0q7a+cA4K+sI5KOgL56CgL5yDgr5w+vjUV04fQ1976yqnj6GvvXWV08fQ1966yulj6GtvXeX0MfS50senEVn6GEbCOSjoC+egoC+cg4J+1dYXzkFBXzgHBX3hHBT0hXNQ0BfOQZ36yulj6GtvXeX0MfS1t65y+hj62ltXOX0Mfe2tq5w+hr721iVLH8OIK30MI670MYy40scwYtlgDyOu9DGMuNLHMOJKH8OIK30MI6708WlElj6GUfLb/zKZCSe29DGc2I4z4pQXW/oYTmzpYzixpY/hxJY+hhNb+hhObOljOLGlj08nuvQxnNjSx3BiSx/DiS19DKdK6MSWPoYTW/oYTmzpYzixpY/hxJY+Pp3o0sdwYksfw4ktfQwntvQxnCqhE1v6GE5s6WM4saWP4cSWPoYTW/p4Z6PY0sdbii19vKXY0sdbijDVx5c+3lJs6eMtRfhxHV/6eEuxpY+3FFv6eEtVRim6ObX++rSHuh43n+ovdOZ9lK+jPr7U3/qd+vprypovWXM7dNVNV9111YuuetVVb7rqXVddd5ea7jI13W3qutvUdbep625T192mrrtNXXebetg2fSBGPOLj7dRuZ3xqq9eIFY4oRzzC4hEej/h4ys3bS1RnuUbUeESLR/R4xKdvdzvG31/ajnmNmPGIFY6oRzzC4hGf/tA2v31p8yeIHo/49I+7l9t5ud78EtGOeET8N6p9/HbX+09UG9eIGY9Y4Yh+xCMsHuHxiBKPqPGIFo/o8Ygvvt29XyNmPOLzt/s+Bsc1Ynz8dt+H+VOExSM8HvHp293vYYt+rGtEjUe0eESPR4x4xMdv97rdS93tuEascMQ84hEWj/B4RIlH1HhEi0f0eMT4IuL67Z4zHvH52307GtP9GrE+frvvn6I+RVg8wuMRH+/ul/9iXTUe0eIRPR4x4hEzHhH/McuTk9nfY/jK6N/wJd2/4Uu6f8OXdP+GL+n+DV/S/Ru+pPs3fEn3b/iS7t/wJd2/4Uu6f8OXdP+GL+n+DV/S/Ru+pPs3fEn3b/iS7t/wJd2/4Uu6f8OXdP+GL7b+DV9s/Ru+pPs3fEn3b/iS7t/wJd2/4Uu6f8OXdP+GL+n+DV/S/Ru+pPs3fEn3b/iS7t+AvvbWVe7fgL721lXu3/Al3b8Bfe2tq9y/4Uu6f8MXW/8GjLj6N2DE1b8BI67+DRixbLCHEVf/hi+2/g1fbP0bvtj6N3yx9W/4Yuvf8MXXv+GLr3/DF1//hi++/g1ffP0bvvj6N3zx9W/44uvf8MXXv+GLr3/DF1//hi++/g1ffP0bvvj6N3zx9W/44uvf8MXXv+GLr3/DF1//hi++/g1ffP0bvvj6N3zx9W/44uvf8MXXv+GLr3/DF1//hi++/g1ffP0bvvj6N3wR9m9sKbb+jS3F1r+xpdjutd9SbP0bW4qtf2NLEX5cx9e/saXY+je2FFv/xpaqjFJsc6p01f6N01z0yvDTXPTG8NNctX8D6qI3hkNd9MZwqIveGA71qqsuemM41EX7N6Cuu0tV+zegrrtNVfs3oK67TVX7N6Cuu01V+zegrrtNo/s3gBjxiOD+DSBWOCK6fwMIi0d4PCK4fwOIGo9o8Ygejwju3wBixiNWOCK6fwMIi0cE928A0eMRwRdDnojo/g0g4r9R0f0bQMx4xApHRPdvAGHxCI9HlHhEjUe0eESPRwT3bwAx4xHB/Rv4HVhw/wYQFo/weERw/wYQNR7R4hE9HjHiEcH9G0CscER0/wYQFo/weESJR9R4RItH9HhEcP8GEDMeEdy/gbMUwf0bQFg8wuMRwf0bQNR4RItH9HjEiEfMeET8xyzh/Ru1ZfRvnBTl/g3oC98EDn3hm8ChL3wTOPSrtr7wTeDQF74JHPrCN4FDX/gmcOgL92+c+sr9G9DX3rrK/RvQ1966yv0b0Nfeusr9G9DX3rrK/RvQ5+rfOI3I+jdgJHwTOPSFbwKHvvBN4NCv2vrCN4FDX/gmcOgL3wQOfeGbwKEvfBP4qa/cvwF97a2r3L8Bfe2tq9y/AX3travcvwF97a2r3L8Bfe2tS9a/ASOu/g0YcfVvwIirfwNGLBvsYcTVvwEjrv4NGHH1b8CIq38DRlz9G6cRWf8GjJLf/pfdBHBi69+AE9uFfjjlxda/ASe2/g04sfVvwImtfwNObP0bcGLr34ATW//G6UTXvwEntv4NOLH1b8CJrX8DTpXQia1/A05s/RtwYuvfgBNb/wac2Po3Tie6/g04sfVvwImtfwNObP0bcKqETmz9G3Bi69+AE1v/BpzY+jfgxNa/sbNRbP0bW4qtf2NLsfVvbCm2e+23FFv/xpZi69/YUoQf1/H1b2wptv6NLcXWv7GlKqMU25xqnpE+PinK6WPoC+egoC+cg4K+cA4K+lVbXzgHBX3hHBT0hXNQ0BfOQUFfOH186iunj6GvvXWV08fQ1966yulj6GtvXeX0MfS1t65y+hj6XOnj04gsfQwj4RwU9IVzUNAXzkFBv2rrC+egoC+cg4K+cA4K+sI5KOgL56BOfeX0MfS1t65y+hj62ltXOX0Mfe2tq5w+hr721lVOH0Nfe+uSpY9hxJU+hhFX+hhGXOljGLFssIcRV/oYRlzpYxhxpY9hxJU+hhFX+vg0Iksfwyj57X+ZzIQTW/oYTmzHGXHKiy19DCe29DGc2NLHcGJLH8OJLX0MJ7b0MZzY0senE136GE5s6WM4saWP4cSWPoZTJXRiSx/DiS19DCe29DGc2NLHcGJLH59OdOljOLGlj+HElj6GE1v6GE6V0IktfQwntvQxnNjSx3BiSx/DiS19vLNRbOnjLcWWPt5SbOnjLUWY6uNLH28ptvTxliL8uI4vfbyl2NLHW4otfbylKqMU15xyr+NJTmDYjTLG4zfa5u23B8e7D853H1xvPnh9ePwnD9q7D/q7D16+TPP+d5jpzx6s7z7Y3n2wv/vgePfB+e6D680Hr09Lznn7lcFc/uRBe/dBf/fB8u6D9d0H27sP9ncfvPzJ+e0Xp3Y8eXC+++B688HrEz8/edDefdDffbC8++DlT87y22u1ypPX6vrQyE8e7O8+ON59cL774HrzwetzBz950F48WJ/8OXZ/98Hy7oPXPzntNgFWfzIBro8b/OTB/u6D490H57sPrjcfHMe7D17/5Mzj/mlzm/948v/+yxc/MJ6DKTmYmoNpOZiegxk5mJmDWSmY6/MC38fkTIGZMwVmzhSYOVNg5kyBmTMFZs4UmDlTYOZMgZUzBVbOFFg5U2DlTIGVMwVWzhRYOVNg5UyBlTMFVs4UePK7ygCOJXE8iVOSODWJ05I4PYkzkjgziZM0D+z/Vfd2O44sSZDeCy0GGR4ef4+zEnSxgLASpJUAXcy7ix59SPZgk4d1mDRvs8vBVOL7TnWlezcrLCxpHpSkeVCS5kFJmgclaR6UpHlQkuZBSZoHJWkelKR5YEnzwJLmgSXNA0uaB5Y0DyxpHljSPLCkeWBJ88CS5kFNmgc1aR7UpHlQk+ZBTZoHNWke1KR5UJPmQU2aBzVpHnjSPPCkeeBJ88CT5oEnzQNPmgeeNA88aR540jzwpHnQkuZBS5oHLWketKR50JLmQUuaBy1pHrSkedCS5kFLmgc9aR70pHnQk+ZBT5oHPWke9KR50JPmQU+aBz1pHvSkeTCS5kHSGcSSdAixJJ1CLEnHEEvSOcSSdBCxJJ1ELElHEUvSWcSSdBixJJ1GLEnHEUvSecSSdCCxJJ1ILElHEkvSmcSSdCixJJ1KLEnHEkvSucSSdDCxJJ1MLElHE0vS2cSSdDixJJ1OLEnHE0vS+URLOp9oSecTLel8oiWdT7TDkzgtidOTOCOJM5M4SfMg6XyiJZ1PtKTziZZ0PtGSzida0vlESzqfaEnnEy3pfKIlnU+0pPOJlnQ+0ZLOJ1rS+URLOp9oSecTLel8oiWdT7Sk84mWdD7Rks4nWtL5REs6n2hJ5xMt6XyiJZ1PtKTziZZ0PtGSzida0vlESzqfaEnnEy3pfKIlnU+0pPOJ9oXzfK3day/a+O32w/+4/vALx/l+gvnC6bc27zfhtt8vwv1PjOVgag7GczAtB/NPF89vj46PH/3CMYSf/Hx/4RTCjzAtB9NzMDkj7gsnENpqf31xP9orzErBfOH8wY8wJQdjOZgvTIFVHpj+CuM5mJaD6TmYkYOZOZiVsky/cOrgR5icv7atnL+2rZy/tn3hxMGPMDl/bfvCeYMfYUYOZuZgUqZAPY4cTMnBWA6m5mA8B9NyMD0HM3IwMweTMwVKzhQoOVOg5EyBkjMFSs4UKDlToORMgZIzBUrOFCg5U8BypoDlTAHLmQKWMwUsZwpYzhSwnClg+CnQ6r/OC+Gajzul9f8omv2fIbPdIXOWv//SUuazkOq3zh2zp9BkE1psQud/3/mjRoXOyOiMKp2R0xk1OqNOZ0Q3sQvdyC50M9voZrbRzWyjm9lGN7ONbmYb3cw24Mx+QkYG5Ppk/a3Grx5f+N4uNqN60BkVOiOjM6p0Rk5n1OiMOp3RoDOim9mVbmY73cx2upntdDPb6Wa2081sp5vZTjezHTizn5CZAVkJkHZkQEoGxDIgNQPiGZCWAekZkIw3vl//ES7Hce/KLkexc4zlYK7/4Rfz5yzu558w9JXyXzOOHEzOj8DwL2D6emBmP8e0HEzPwYwczMzBfOO96eWJGaeYeeRgSg7GcjA1B+M5mJaD6TmYkYOZOZgvTIFS/P7Fxc//ZrOOHEzJwVgOpuZgPAfTcjA9BzNyMF+YAmXYA/P7GbrfMSsF86L5G8CpKf/0eNGUDeC0JE5P4qwczhfOGf6MU5I4lsTJeH/a+cnd8XhujDcf1fox//pSt/b3XzofU2Md/u/fPtP95APgdn7EV8J8yZqfv8wa6kVX3XTVq66666o3XfWuq667S4vuMi2629R0t6npblPT3aamu01Nd5ua7jY12DZ9IgYecXk7tftvY735OWLBEfXAIwoeYXjE5Sn3CCz7rOcIxyMaHtHxiKtvdzvun1e1Y54jJh6x4Ag/8IiCR1z9oW12/9JmLxAdj7j6x93r/ehGb3aKaAcegf9Gtctv9+PT6NbGOWLiEQuO6AceUfAIwyMqHuF4RMMjOh7xxbe793PExCOuv92PMTjOEePy213XO0TBIwyPuPp298ex2H6sc4TjEQ2P6HjEwCMuv93PS8XLcY5YcMQ88IiCRxgeUfEIxyMaHtHxiPFFxPnbPScecf3tvh/P63aOWJff7senqC8RBY8wPOLy7n77L9bleETDIzoeMfCIiUfgP2Z5cVr1e4z+4gRc6fVxMLi3N7+0KX7cJ2HxUk4pL45B/jOMzwdmvPtF0hdvQ+qvTk/p6Ju2ftXWd239pq3ftfWHtv7U1l/S+qa9dU1765r21jXtrWvaW9e0t65pb13T3rqmvXWNZes+jCrLIn0aJe/Gb15f1l+do9PRr9r6rq3ftPW7tv7Q1p/a+kta3w9tfe2t69pb17W3rmtvXdfeuq69dV1767r21nXtrdtYtu7TiGWRPo1YduPTiGXdPY1YNtjTiGUpPY1Y9szTiGV1PI1YtsHTiGXAP4w63czuyW//21uk+6uoyh92Sv7pfnvPWX8VwPiz36dhhE6V0KlnO725uru/il/8YadJ6LT4nOZB6JQ+n95cTN1fZU7+sFMldHJCp0bo1AmdBqHTJHRafE7rIHTKnuPvbjDvr9JFf9ipEjo5oVMjdOqEToPQaRI6LT6nV50EQKk3BQZbqjBKGaNU4/u851WPwh+WGoxShB/XlezA4c+kjFGqMko5oxTbnBqm2r9xMxe9MvxmLnpj+M1ctX8j1EVvDA910RvDQ130xvBQd1110RvDQ120fyPUdXepav9GqOtuU9X+jVDX3aaq/RuhrrtNVfs3Ql13m6L7NwIx8Ahw/0YgFhyB7t8IRMEjDI8A928EwvGIhkd0PALcvxGIiUcsOALdvxGIgkeA+zcC0fEI8MWQNwS6fyMQ+G8Uun8jEBOPWHAEun8jEAWPMDyi4hGORzQ8ouMR4P6NQEw8Aty/Eb8DA/dvBKLgEYZHgPs3AuF4RMMjOh4x8Ahw/0YgFhyB7t8IRMEjDI+oeITjEQ2P6HgEuH8jEBOPAPdvxFkKcP9GIAoeYXgEuH8jEI5HNDyi4xEDj5h4BP5jFnj/xiwZ/Rs3inL/RugL3wQe+sI3gYe+8E3goe/a+sI3gYe+8E3goS98E3joC98EHvrC/Rs3feX+jdDX3rrK/Ruhr711lfs3Ql976yr3b4S+9tZV7t8Ifa7+jZsRWf9GGAnfBB76wjeBh77wTeCh79r6wjeBh77wTeChL3wTeOgL3wQe+sI3gd/0lfs3Ql976yr3b4S+9tZV7t8Ife2tq9y/EfraW1e5fyP0tbcuWf9GGHH1b4QRV/9GGHH1b4QRywZ7GnH1b4QRV/9GGHH1b4QRV/9GGHH1b9yMyPo3wij57X/bTRBObP0b4cR2oV+c8mLr3wgntv6NcGLr3wgntv6NcGLr3wgntv6NcGLr37g50fVvhBNb/0Y4sfVvhBNb/0Y4OaETW/9GOLH1b4QTW/9GOLH1b4QTW//GzYmufyOc2Po3womtfyOc2Po3wskJndj6N8KJrX8jnNj6N8KJrX8jnNj6N3Y2iq1/Y0ux9W9sKbb+jS3Fdq/9lmLr39hSbP0bW4rw4zq+/o0txda/saXY+je2lDNK0c2pmZI+ntrp46mdPp7a6eOpnT6e2unjqZ0+ntrp46mdPp7a6eOpnT6e2unjqZ0+ntrp46mdPp7a6eOpnT6e2unjqZ0+ntrp40mXPp506eOpnT6e2unjqZ0+ntrp46mdPp7a6eOpnT6e2unjqZ0+ntrp46mdPp7a6eOpnT6e2unjqZ0+ntrp46mdPp7a6eOpnT6edOnjSZc+nnTp40mXPp506eNJlz6edOnjSZc+nnTp40mXPp506eNJmD6ehOnjSZg+noTp40mYPp6E6eNJmD6ehOnjSZg+noTp40mYPp6E6eNJmD6ehOnjSZg+noTp40mYPp6E6eNJmD6ehOnjSZg+noTp40mYPp6E6eNJmD6ehOnjSZg+noTp40mYPp6E6ePJmD6ejOnjyZg+nozp48mYPp6M6ePJmD6ejOnjyZg+nozp48mYPp6E6ePV/3W1h9qPu4/bG535GOXr8OeX2ie/U7+ZT1nzJWteDl31oqtuuupVV9111ZuuetdV192lRXeZFt1tarrb1HS3qeluU9Pdpqa7TU13mxpsmz4RA4+4vJ3a/YyPNz9HLDiiHnhEwSMMj7g85eb9JfJZzxGORzQ8ouMRV9/udoy/vrQd8xwx8YgFR/iBRxQ84uoPbbP7lzZ7geh4xNU/7l7v5+V6s1NEO/AI/DeqXX67/fET1cY5YuIRC47oBx5R8AjDIyoe4XhEwyM6HvHFt7v3c8TEI66/3Y8xOM4R4/Lb/RjmLxEFjzA84urb3R9hi36sc4TjEQ2P6HjEwCMuv93rfi91L8c5YsER88AjCh5heETFIxyPaHhExyPGFxHnb/eceMT1t/t+NKbbOWJdfrsfn6K+RBQ8wvCIy7v77b9Yl+MRDY/oeMTAIyYegf+Y5cXJ7K8x6tET+jeCIty/sfV1bwLf+ro3gW993ZvAt75r6+veBL71dW8C3/q6N4Fvfd2bwLe+bv9G6Av3b2x97a0r3L+x9bW3rnD/xtbX3rrC/RtbX3vrCvdvbH2q/o0w4urf2Ea6N4Fvfd2bwLe+7k3gW9+19XVvAt/6ujeBb33dm8C3vu5N4Ftf9ybw0Bfu39j62ltXuH9j62tvXeH+ja2vvXWF+ze2vvbWFe7f2PraW5erf2MbUfVvbCOq/o1tRNW/sY1YNtjTiKp/YxtR9W9sI6r+jW1E1b+xjaj6N8KIq39jGyW//e+6CbYTWf/GdiK70G+f8iLr39hOZP0b24msf2M7kfVvbCey/o3tRNa/sZ3I+jfCia1/YzuR9W9sJ7L+je1E1r+xnZzQiax/YzuR9W9sJ7L+je1E1r+xncj6N8KJrX9jO5H1b2wnsv6N7UTWv7GdnNCJrH9jO5H1b2wnsv6N7UTWv7GdyPo3fmWjyPo3fkmR9W/8kiLr3/glRXav/S8psv6NX1Jk/Ru/pAg/rqPr3/glRda/8UuKrH/jl5QzSrHNqVJF+zfCXPPK8DDXvDE8zEX7N7a65o3hW13zxvCtrnlj+FZ3XXXNG8O3umb/xlbX3aWi/RtbXXebivZvbHXdbSrav7HVdbepaP/GVtfdpuD+jY0YeAS2f2MjFhwB7t/YiIJHGB6B7d/YCMcjGh7R8Qhs/8ZGTDxiwRHg/o2NKHgEtn9jIzoegb0YMhDg/o2NwH+jwP0bGzHxiAVHgPs3NqLgEYZHVDzC8YiGR3Q8Atu/sRETj8D2b+zfgWH7Nzai4BGGR2D7NzbC8YiGR3Q8YuAR2P6NjVhwBLh/YyMKHmF4RMUjHI9oeETHI7D9Gxsx8Qhs/8Y+S4Ht39iIgkcYHoHt39gIxyMaHtHxiIFHTDwC/zELvH/DLKN/40ZR7t8IfeGbwENf+Cbw0Be+CTz0XVtf+Cbw0Be+CTz0hW8CD33hm8BDX7h/46av3L8R+tpbV7l/I/S1t65y/0boa29d5f6N0Nfeusr9G6HP1b9xMyLr3wgj4ZvAQ1/4JvDQF74JPPRdW1/4JvDQF74JPPSFbwIPfeGbwENf+Cbwm75y/0boa29d5f6N0Nfeusr9G6GvvXWV+zdCX3vrKvdvhL721iXr3wgjrv6NMOLq3wgjrv6NMGLZYE8jrv6NMOLq3wgjrv6NMOLq3wgjrv6NmxFZ/0YYJb/9b7sJwomtfyOc2C70i1NebP0b4cTWvxFObP0b4cTWvxFObP0b4cTWvxFObP0bNye6/o1wYuvfCCe2/o1wYuvfCCcndGLr3wgntv6NcGLr3wgntv6NcGLr37g50fVvhBNb/0Y4sfVvhBNb/0Y4OaETW/9GOLH1b4QTW/9GOLH1b4QTW//Gzkax9W9sKbb+jS3F1r+xpdjutd9SbP0bW4qtf2NLEX5cx9e/saXY+je2FFv/xpZyRim6ObVS0sdLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO3286NLHiy59vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx4sufbzo0seLLn286NLHiy59vOjSx4sufbzo0seLLn286NLHiy59vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vBjTx4sxfbwY08eLMX28GNPHizF9vBjTx4sxfbwY08eLMX28GNPHizB97OVF+rj5uD/Y+vh7yjfPnt+EJpvQYhN6EeX+k0aFzsjojCqdkdMZNTqjTmdEN7EL3cgudDPb6Ga20c1so5vZRjezjW5mG93MNuDMfkJGBuT6ZP3mQdYwWmxG9aAzKnRGRmdU6YyczqjRGXU6o0FnRDezK93MdrqZ7XQz2+lmttPNbKeb2U43s51uZjtwZj8hMwOyEiDtyICUDIhlQGoGxDMgLQPSMyAZb3y//iP8NgwQGMvBXP/D/8mv//pK+a8ZRw4m50dg+Bcwb47kB6blYHoOZuRgZg7mG+/Nm9O88cvwIwdTcjCWg6k5GM/BtBxMz8GMHMzMwXxhCrw7nxonUI4cTMnBWA6m5mA8B9NyMD0HM3IwX5gC784fB2alYF6dUv8+p6b806McnsRpSZyexFk5nC+cM/wZpyRxLImT8f7U85O74/HcGG8+qvXjfpLY7c1B4vmYGuvwf//2me4nHwDX8yO+EuZL1vz8ZdZQL7rqpqteddVdV73pqndddd1dWnSXadHdpqa7TU13m5ruNjXdbWq629R0t6nBtukTMfCIy9up3X8b683PEQuOqAceUfAIwyMuT7l5f4l81nOE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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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WLN9ijXbp1izfYY122dYs32GNdtnWLN9tkBVZcOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtc6zZPsea7XOs2T7Hmu3zBaoqO9Zsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51mxfxZrtq1izfRVrtq9izfbVBaoqV6zZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYc32NazZvoY129ewZvvaAlWVG9ZsX8Oa7WtYs30Na7avYc32NazZvoY129ewZvsa1mxfw5rta1izfQ1rtq9hzfY1rNm+hjXb17Bm+xrWbF/Dmu1rWLN9DWu2r2HN9jWs2b6GNdvXsGb7GtZsX8Oa7WtYs30Na7avYc32NazZvoY129ewZvsa1mxfw5rta1izfQ1rtq9hzfY1rNm+hjXb17Bm+xrWbF/Dmu1rWLN9DWu2r2HN9rXBs33l/sFlEdn54FZvH5yWdP/k/OyTU2k3oUnKl4v/qTMF0ZmD6CxBdEoQnRpEpwXR6UF01iA6WwydFsQPWRA/ZEH8kAXxQ4Mnlz+nM4gfsiB+yIL4IQvihyyIH/IgfsiD+CEP4oc8iB8azAz4nM4gfsiD+CEP4oc8iB/yIH6oBvFDNYgfqkH8UA3ihwbTOj6nM4gfqkH8UA3ih2oQP1SD+KEWxA+1IH6oBfFDLYgfGszJ+ZzOIH6oBfFDLYgfakH8UBvth7ZoSirpywev4aRlMOWoJFtu8WQtT+IZ7C+y3+Npy5N4OviAluQWj+7EkzzfPji5+v3iZ5+bLOntYiv34HNNf4IvzMELc/A6NviatumGpe4En6VIvl0tam27vN2iN+TotaUteitfon/yD1zKTWsR1+3iVPzJ1d78z8V1uX9wqvVPXnzm5Wle6szL07y0mZdneekB8bpkXtLMy9O85JmXp3kpMy9P8yIzL0/zAu1KP5iXC/ld9dvKpFhqe3nxLS+PzzVseRbIUreoU75/ck7LLzJ+ISdNkvELeXSSjF/I/XNkPF9oXUGS8QutWEgyfqG1EEnGL7TKIsm4zIwPzviFVoYkGZ9rzgMZX1+0bRmv+UvG/87iXEf2yOJcG/bI4lzvdchimWu4Hlmc67IeWZxrrR5ZnOunHlmUmcUOWZzrnB5ZnGuXA1lc14i3OPLjRuAti3Pt0iOLc+3SI4tz7dIhizLXLj2yONcuPbI41y49sjjXLj2yKDOLHbI41y49sjjXLkeyaFs68vrG6nsW59qlRxbn2qVHFufapUMWda5demRxrl16ZHGuXXpkca5demRRZhY7ZHGuXXpkEXrtYtK2LFZb3mcxm28kkFX2kh8v/1ss9BKjt1jolUBvsdCGvbNYg/bVPxRb84PYJ+AQg7a/vcVCu9TeYqHNZG+xEkkstDXrLfZKDmpX7JUcVN0YfNnaM7FXclC7Yq/koPbE+qUc1J7YSzmoPbGXclB7Yi/loPbEyoXEtnp7hpN9yfW72Cs5qF2xV3JQu2Iv5KA8adnE5py+i72Qg/Jctsu9PFCAN7EXclC7YuuFHNS+2As5qH2xF3JQ3tK9Grcm38VeyEHti5XriK1L2VpPfSQnbGIv5KD2xV7IQe2LhXZQtW1hSMv2PXpoS7QbPbTHaX5/6d5qfv9Dq+32zr3l+28y2bNX7imXDc6f2+NrdHkmUPN2WoRWvV9d2t9ZbNDm6UdZbOUeRtvJYl30FkdNRR6ymH+VRWhX9qMsers9dv/rnIcvafxb6lhPtv6s72Xg4R/H84Mrqtv2j2OtH9+LRivU0Qt19EodvVFH79TRV+roG3H0aVmoo0/U0TP32rQw99q0MPfatDD32rQw99q0MPfatDD32rRQ99pE3WsTda9N1L02UffawSca9Y6eutcm6l6bqHttou61ibrXZupem6l7babutZm61w4+faJ39NS9NlP32kzdazN1r83UvbZQ99pC3WsLda8t1L12MNW8d/TUvbZQ99pC3WsLda8t1L1WqHutUPdaoe61Qt1rB1N4e0dP3WuFutcKda8V6l4r1L1WqXutUvdape61St1rB1Mje0dP3WuVutcqda9V6l6r1L3WqHutUfdao+61Rt1rB9P6ekdP3WuNutcada816l5r1L3WqXutU/dap+61Tt1rB3PdekdP3Wudutc6da916l7r1L22UvfaSt1rK3WvrdS9djABrHf01L22UvfaSt1rK3WvrdS9tlH32kbda6m5UYmaG5WouVGJmhuVqLlRiZoblai5UYmaG5WpuVGZmhuVqblRmZoblRfmXpupuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZob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Y8vZGVvOzthydsaWszO2nJ2x5eyMLWdnbDk7Y8vZGVvOzthydsaWszO2nJ2x5eyMLWdnbDk7Y8vZGVuVnbFV2RlblZ2xVdkZW3Uh78SVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsdXYGVuNnbHV2BlbjZ2x1RbyTtzYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW2uk5K34r0jpFZA34zVS8m68RkrejtdIyfvxGil5Q14jJe/Ia6TkLXmNlL4ns+O2VgX0PZkduLUqoO/J7MitVQF9T2aHbq0K6HsyO3ZrVUDfk9nBW6sC+p7Mjt5aFdD3ZHb41qqAviez47dWBfQ9mR3AtSqg78nsCK5VAX1PZodwrQroezI7hmtVQN+T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A77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Tv8Trhe7xO+B6vE77H63ygv5NP+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8brge7wu+B6vC77H64Lv8boe6O/kC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wMvsfL4Hu8DL7Hy+B7vOyB/k42+B4vg+/x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nit4V/4KxXSeK3iv/QrFdJ4reAf9CsV0nouuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQN7oe+kbXQ9/oeugbXQ99exidYjbP1eh66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dB3uh76TtdD3+l66DtdD31/GJ1iNs/V6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+Z+ooH+18fXH7+3d+05vobTylN9FzevT++uLRPulN9JSe0pvoGT2lN9ETekpvokw8ozdTY/WU3kzv3xm9md6/M3oTZeEpvUaml8xfZWqpntIL66/eNMB6pjcNsX3Q1b7+Kdl4uCTz4D3SKxTH9kIrFMd2QysUx/ZDKxQbneLYnmiF4tiuaIXi2L5oheLYLmqFYjrPFbxHeoViOs8VvEd6hWI6zxW8R3qFYjrPFbxHeoViOs8VvEd6hWI2zzWC90ivUMzmuUbwHukVitk813gYnWI2zzWC90ivUMzmuUbwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxXpfNcwbvCVyim81yVznNVo1NM57mCt8KvUEznuYI3w69QTOe5grfDr1BM57mCN8SvUEznuYK3xK9QTOe5gjfFr1BM57mCN8uvUEznueh66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH2w99NeDrYf+qZjMcz0Vk3mup2Iyz/VUbHSKyTzXUzGZ53oqJvNcT8VknuupmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGb5zroeugPuh76g66H/qDroX/qoVPM5rkOuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/o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MOsu9rfEHLAPs+6Qf0vMAfuwgH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCf/hnQT/8M6Kd/BvTTPwP66Z9HCRhzvD7sDOinfwb00z8D+umfAf30z4B++mdAP/0zoJ/+GdBP/wzop38G9NM/A/rpnwH99M+AfvpnQD/9M6Cf/mnJT//tqQx1Sm9PZaiXeXuqYvKpDPUDb09l6MR+eypDZ+rbUxk69d6eytC59PVUlhzA357KZG235KL99lQma7slJ+q3pzJZ2y25Ob89lcnabskR+e2pTNZ2S67Cb09lsrZbcuZ9eyqTtd2Su+3bU5ms7ZYcYt+eymRtt+Sy+vZUJmu7JafSt6cyWdstuX2+PZXJ2m7JMfPtqW6u7W/f1LZ9U9/2TWPbN81d33S3Q+DbN6Vt35S3fdO57ZvKtm/aViPathrRttWItq1GtG01om+rEX1bjejbakTfViP6thrRt9WIvq1G9G01om+rEX1bjRjbasTYViPGthoxttWIsa1GjG01YmyrEWNbjRjbasTYViPmthoxt9WIua1GzG01Ym6rEXNbjZjbasTcViPmthoxd9WIIvJGau7l9U1j/vVNv7wlV0TeGr3jubLR5zqNPlcx+lzV6HM1o8/VjT7XMPpc0+ZzJaP1Phmt98lovU9G630yWu+T0XqfjNb7ZLTeJ6P1Phmt99lovc9G6302Wu+z0Xqfjdb7bLTeZ6P1Phut99lovc9G6/1ptN6fRuv9abTen0br/Wm03p9G6/1ptN6fRuv9abTen0brfTFa74vRel+M1vtitN4Xo/W+GK33xWi9L0brfTFa74vRel+N1vtqtN5Xo/W+Gq331Wi9r0brfTVa76vRel+N1vtqtN43o/W+Ga33zWi9b0brfTNa75vRet+M1vtmtN43o/W+Ga333Wi970brfTda77vRet+N1vtutN53o/W+G6333Wi970br/TBa74fRej+M1vthtN4Po/V+GK33w2i9H0br/TBa74fRej+N1vtptN5Po/V+Gq3302i9n0br/TRa76fRej+N1vtps95Xo+/XVqPv11aj79dWo+/X1sNmva9G36+tRt+vrUbfr61G36+tRt+vrUbfr61G36+tRt+vrUbfr61G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vRwGK3o5DFb0clis6MliRU8WK3qyWNGTxYqeLFb0ZLGiJ4sVPVms6MliRU8WK3q2WNGzxYqeLVb0bLGiZ4sVPVus6NliRc8WK3q2WNGzxYp+Wqzop8WKflqs6KfFin5arOinxYp+Wqzop8WKflqs6KfFil4sVvRisaIXixW9WKzoxWJFLxYrerFY0YvFil4sVvRisaJXixW9Wqzo1WJFrxYrerVY0avFil4tVvRqsaJXixW9WqzozWJFbxYrerNY0ZvFit4sVvRmsaI3ixW9WazozWJFt/jOaLH4zmix+M5osfjOaLH4zmjZ/85oTvn88+lcU/rr01+PVW0+VrP5WN3mYw2bjzVNPtb+90fXHivZfKxs87FOm49ls8oPm1V+2Kzyw2aVHzar/LBZ5afNKj9tVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9NVvl6mKzy9TBZ5ethssrXw2SVr4fJKl8Pk1W+HiarfD1MVvl6mKzy9bBZ5ZPNKp9sVvlks8onm1U+2azyyWaVTzarfLJZ5ZPNKp9sVvlss8pnm1U+26zy2WaVzzarfLZZ5bPNKp9tVvlss8pnm1X+tFnlT5tV/rRZ5U+bVf60WeVPm1X+tFnlT5tV/rRZ5U+bVb7YrPLFZpUvNqt8sVnli80qX2xW+WKzyhebVb7YrPLFZpWvNqt8tVnlq80qX21W+WqzylebVb7arPLVZpWvNqt8tVnlm80q32xW+WazyjebVb7ZrPLNZpVvNqt8s1nlm80q32xW+W6zynebVb7brPLdZpW3+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7P57muz+e5rs/nua7P57ms7TFb5ZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd13b3u69fX1R3fZFEJe51vL6o9Ysv6ru+aOz6ornpi0Te81z6orTri7LwF/Vy8UXnri8qu75IojKM/PqicV7lqO36or7ri8auL5qbvkjk3cClL5L472jU9vqicV58Udn1RQK/deXREPz5dGllXHzR2PVFc9MXSbyrtPZFadcXLZxH5a8v+vqn5+//afn9P62//6ft9/+0//6fjt//0/nrf7ryvsXVP02//6e//21qv/9tar//bWq//21qv/9tar//bWq//21qv/9t6r//beq//23qv/9t6r//beq//23qv/9t6r//beq//23qv/9t6r//bRq//20av/9tGr//bRq//20av/9tGr//bRq//20av/9tGr//bRq//22av/9tmr//bZq//22av/9tmr//bZq//22av/9tmr//bZq//22av/5t6sfx+3+afv9P8+//6fn7f1p+/0/r7/9p+/0/7b//p+P3//T3v03p979N6fe/Ten3v03p979N6fe/Ten3v03p979N6fe/Ten3v03p979N+fe/Tfn3v00Lfyer5//7eRSx8iemvvCXL6EvKru+qO76ova/f1Fvz/WjvdfXZ//6lr7lW8aWb5k7vkXEcmnM/pzpznT8+xdAwhaopP78opKPcfFF564vKru+qO76orbri/quLxq7vmhu+iIJm5q1L5IY8Kdavv+ivOuLzl1fVHZ9Ud31RRKVIZ9fX1TPiy/qu75o7PqiuemLJKxN1r4o7foiicqQ5/NP6OVMV1907vqisuuL6q4varu+SKQyzPT1ReXii8auL5qbvmgcu74o7fqivOuLTuEvyhcCeZRdX1R3fZFEZSjjeV2o1OPqi/quLxq7vmhu+iIJC4VSav36ovzXF/33p+t4DovqeJ/nnW8PlSw+VLb4UKfFhyoWH6pafKhm8aG6xYcaFh9q2nuocRis6OMwWNHHYbCij8NgRR+HwYo+DoMVfRwGK/o4DFb0cRis6OOwWNGTxYqeLFb0ZLGiJ4sVPVms6MliRU8WK3qyWNGTxYqeLFb0bLGiZ4sVPVus6NliRc/7S0Kdz4fqXz85P8bBXw81DD7UqfCLnl/pGxcPlS0+1GnxoYrFh6oWH+rm1uXri/quL5KoJ/V8/e2q9vMbzPk4np9+/N+vxzpLe3usafKxJBwI7nisZPOxss3HOm0+VrH5WNXmYzWbj9VtPpbNKl9sVvlqs8pXm1W+2qzy1WaVrzarfLVZ5avNKl9tVvlqs8pXm1W+2azyzWaVbzarfLNZ5ZvNKt9sVvlms8o3m1W+2azyzWaV7zarfLdZ5bvNKt9tVvlus8p3m1W+26zy3WaV7zarfLdZ5YfNKj9sVvlhs8oPm1V+2Kzyw2aVHzar/LBZ5YfNKj9sVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9tVvlps8pPk1V+Hiar/DxMVvl5mKzy8zBZ5edhssrPw2SVn4fJKj8Pk1V+Hiar/DxsVvlks8onm1U+2azyyWaVTzarfLJZ5ZPNKp9sVvlks8onm1U+26zy2WaVzzarfLZZ5bPNKp9tVvlss8pnm1U+26zy2WaVP21W+dNmlT9tVvnTZpU/bVb502aVP21W+dNmlbf57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu69R497Ucr8d6+9l/P1ay+VjZ5mOdNh+r2HysavOxms3H6jYfa9h8rGnysabNKj9tVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9NVvl0HCbL/OO5TNb5x3OZLPSP5zJZ6R/PZbLUP57LZK1/PJfJYv94LpPV/vFcJsv947mM1vtktN4no/U+Ga33yWi9T0brfTJa75PRep+M1vtktN4no/U+G6332Wi9z0brfTZa77PRep+N1vtstN5no/U+G6332Wi9P43W+9NovT+N1vvTaL0/jdb702i9P43W+9NovT+N1vvTaL0vRut9MVrvi9F6X4zW+2K03hej9b4YrffFaL0vRut9MVrvq9F6X43W+2q03lej9b4arffVaL2vRut9NVrvq9F6X43W+2a03jej9b4ZrffNaL1vRut9M1rvm9F634zW+2a03jej9b4brffdaL3vRut9N1rvu9F6343W+2603nej9b4brffdaL23+TLt47mM1nubr9M+nstovbf5Qu3juYzWe5uv1D6ey2i9t/lS7eO5jNZ7m6/VPp7LaL23+WLt47mM1nubr9Y+nstovbf5cu3juYzWe5uv1z6ey2a9T0bfr01G369NRt+vTUbfr02HzXqfjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fmzTer+1fzzXG1XNlo891Gn2uYvS5qtHnakafqxt9rqH5XA/5+tdz/fen53j+6P94nrw+nP/1HOmc7fnhcv714beAZ7CANd4I1g04RQs4Rwv4jBZwiRZwjRZwixZwjxZwtE7rjNZplWidVonWaZVonVaJ1mlp+B3oBhyt0yrROq0SrdMq0TqtEq3TqtE6rRqt06rROq0ardPScBrRDThap1WjdVo1WqdVo3VaNVqn1aJ1Wi1ap9WidVotWqel4fGjG3C0TqtF67RatE6rReu0mqlO6+u5uqmG6O259p9qKbfXc+WrC4YKhkNrz7W/gjx+2V/PVfrVcw2jzzVtPpeCgc7acyWjz7W/3U/z+emcj3n1XKfR5ypGn6safa5m9Lm60ecaRp9rqj5XrrsbTgVnHuWAU7SAc7SAz2gBl2gB12gBt2gB92gBj2gBB+u08hGs08pHsE4rH8E6rXwE67TyUaIFHKzTykewTisfwTqtfATrtPIRrdNK0TqtFK3TStE6rRSt01Jw/FMOOFqnlaJ1Wilap5WidVopWqeVo3VaOVqnlaN1Wjlap6XgtakccLROK0frtHK0TitH67RytE7rVO60Li7M5TMZfa5s9LlOo89VjD5XNfpczehzdaPPNYw+17T5XMVovVcwP0zj6wWPK0f3rOBRuPZcp9HnKkafqxp9rmb0ubrR5xpGn2vafC4Fb7e15zJa76vRel+N1vtqtN5Xo/W+Gq331Wi9r0brfTVa75vRet+M1vtmtN43o/W+Ga33zWi9b0brfTNa75vRet+M1vtutN53o/W+G6333Wi970brfd9f7x8a7DXH7OnquZrR5+pGn2sYfa5p87kUDJrWnisZfa6s+lzjb+OoDX/QV3B+Ug64RAu4Rgu4RQu4Rwt4RAt4Bgt4HtECTtECjtZpzWidloIfmHLA0TqtGa3TmtE6rRmt05rBOq3zCNZpnUewTus8gnVa5xGs0zqPEi3gYJ3WeQTrtM4jWKd1HsE6rfOI1mmlaJ1WitZppWidVorWaSn4gSkHHK3TStE6rRSt00rROq0UrdPK0TqtHK3TytE6rWyq03p7rmL0ufYX+YeifT7XQ/pcPde0+VwKRjXn16bY8zyunus0+lzF6HNVo8/VjD7X/u737OX1XDNfPdcw+lzT5nMpGNWsPVcy+lzZ6HOdRp+raD5XOcbuhlPBAUc54BYt4B4t4BEt4Bks4HpECzhFCzhHC/iMFnCJFnC0TqtG67RqtE6rRuu0arROq0XrtFq0TqtF67RatE5LwZxNOeBonVaL1mm1aJ1Wi9ZptWidVo/WafVonVaP1mn1aJ2Wgi2icsDROq0erdPq0TqtHq3T6tE6rRGt0xrROq0RrdMa0TotBXtP5YB1O610dWFuNKPP1Y0+1zD6XNPmc83D6HMlo8+VjT7XafS5itHnMlrvFbwAH3/eeD7XeeXofipY9q091zD6XNPkcxUFn7q150pGnysbfa7T6HMVo89VjT6XzXpfDpv1vhw26305jNb7ZLTeJ6P1Phmt98lovU9G630yWu+T0XqfjNb7ZLTeJ6P1Phut99lovc9G6302Wu+z0Xqfjdb7bLTeZ6P1Phut99lovT+N1vvTaL0/jdb702i9P43W+9NovT+N1vvTaL0/jdb702i9L0brfTFa74vRel+M1vtitN4Xo/W+GK33xWi9L0brfTFa76vRel+N1vtqtN4r+M+Ulp/PVcZx9VzF6HNVo8/VjD5XN/pcw+hzTZvPdbchyNs3pW3flLd907ntm8q2b6rbvqlt+6a+7ZvGtm+au76pb6sRfVuN6NtqRN9WI/q2GtG31Yi+rUb0bTWib6sRfVuNGNtqxNhWI8a2GjG21YixrUbIvOE2+vObWjq+6XgfjV95fbqMq+dqRp+rG32uYfS5ps3nknnD7YbnSkafKxt9rtPocxWjz2W03k+j9X4arffTaL2fNut9PWzW+3rYrPf1sFnv62Gz3tfDZr2vh816Xw+b9b4eNut9PW6u92/fNHd9Uzq2fVPa9k152zdJVMJWXzOC1qbIb6rIu193PFc1+lzN6HN1o881jD7XtPlcIu9+3fFc6d7nevumvO2bzm3fVLZ9k0jdXPqNaNu+qW/7prHtm+aubxJ5u2jtm9K2b8rbvunc9k1l2zdtqxHnthpxbqsR57YacW6rEWVbjSjbakTZViPKthpRttWIsq1GlG01omyrEWVbjSjbakTdViPqthpRt9WIuq1G1G01om6rEXVbjajbakTdViPqthrRttWItq1GtG01om2rEW1bjWjbakTbViPathrRttWItq1G9G01om+rEX1bjejbakTfViP6thrRt9WIvq1G9G01om+rEWNbjRjbasTYViPGthoxttWIsa1GjG01YmyrEWNbjRjbasTcViPmthoxt9WIua1GzG01Ym6rEXNbjZjbasTcViPmrhrRjmPbN6Vt35S3fdO57ZvKtm+q276pbfumvu2bxrZvmru+KW2rEWlbjUjbakTaViPSthqRttWItK1GpG01Im2rEWlbjcjbakTeViPythqRt9WIvK1GbLtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7ln2bfcs+7Z7ln3bPcu+7Z5lP8q2b6rbvqlt+6a+7ZvGtm/aViO23bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7lmObfcsx7Z7lmPbPcux7Z7lOMq2b6rbvqlt+6a+7ZvGtm/aViO23bMc2+5Zjm33LMe2e5Zj2z3Lse2e5dh2+3Fsu/04tt1+HNtuP45ttx+HyE3Ber42X9d+/vVN//3pfB7zz6fz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ju6x1dE9tjq6x1ZH99jqB/hJ3NE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tge6xNdA9tga6x9ZA99gaB/hJPNA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tie6xNdE9tia6x9ZE99iaB/hJPNE9tia6x9ZE99ia6B5bE91ja6J7bE10j62J7rE10T22JrrH1kT32JroHlsT3WNrontsTXSPrYnusTXRPbYmusfWRPfYmugeWxPdY2uie2xNdI+tie6xNdE9tia6x9ZE99ia6B5bE91ja6J7bE10j62J7rE10T22JrrH1kT32JroHlsT3WNrontsTXSPrYnusTXRPbYmusfWRPfY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C64habb6iaaykCdNZSFPmspCkzTHV7Isj0/JMvolVzCaykKeNJWFPGkqC3nSVBbypKks5EizKAvN0Sz25TeLfUqWue4Nb6epLORJU1nIk6aJpiNNZSFPmspCnjSVhX5Os3zayDHfpV5AU1nIkSbzzeuZ3iLmm9dTfJRX7vkogdzzMfG55aOUcM9Hvv+eTyonP/prvTvGpyaYXJeepxSncsQzinNdTZ5SnMqHTilO5SynFKfyilOKjU5xKj83pTiVQ5tSTOe5cl2ZnVJM57lyXWydUkznuXJdP51STOe5cl0SnVJM57lyXeWcUkznuXJduJxSTOe5cl2LnFJM57lyXV6cUkznuXJdMZxSTOe5cl0EnFJM57lyXdebUszmuc4Hm+c6H2ye63ywea4z1/3FKcVGp5jNc50PNs915rpXOaWYzXOduW4/zijOdaFxSjGd58p17XBKMZ3nynU5cEoxnefKdYVvSjGd58p10W5KMZ3nynUdbkoxnefKdWltSjGd58p1tWxKMZ3nynUBbEoxnefKdUlrSjGd58p1kWpKMZ3nynXZaUoxnefKdSFpSjGd58p1aWhKMZ3nynWxZ0oxnefKdflmSjGd58p1QWZKMZ3nynWJZUoxnefKddFkSjGd58p1GWRKMZ3nynVhY0oxnefKdaliSjGd58p18WFKMZ3nynU5YUoxnefKdYFgSjGd58rV5D+lmM5z5Wrbn1JM57lyNeJPKabzXLla66cU03kuuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peugvuh76i66H/qLrob/oeuivh9EpZvNcF10P/UXXQ3/R9dBfdD30F10P/UXXQ3/l6ih/fu7H15ef45vv3vr4+iTnN19b7Pz1tcWuTyxTvek3s0zlITazTOVONrNM5Xs2s0zlqPayzNVfv5llKhe4mWWqnd5mlqm2hZtZmli6sVTumWPZX9+4jPKJpXKPH0vlHj+Wyj1+LJV75li23yzrB5a5bkhsZqnc48dSucePpXKPH0sTSzeWyj1zLMvr55Clfvo5ZK77IptZKvf4sVTu8WOp3OPGMtcdl80slXv8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+D2XFYrZPFcNftNlhWI2z1WD33VZoZjNc9WH0Slm81w1+N2YFYrZPFcNfuNlhWI6zxX8HssKxXSeK/jtlBWK6TxX8DsnKxTTea7gN0lWKKbzXMHvh6xQTOe5gt/6WKGYznMFv8uxQjGd5wp+Q2OFYjrPFfzexQrFdJ4r+G2KFYrpPFfwOxIrFNN5ruA3H1YopvNcwe8zrFBM57kuOs8V/LLGCsV0nuui81xG57mCXzpZoZjOcwW/SrJCsdEppvNcwe+CrFBM57mC3/BYoZjOcwW/t7FCMZ3nCn4bY4ViOs8V/I7FCsV0niv4zYkViuk8V/D7ECsU03mu4LccViim81zB7y6sUEznuYLfSFihmM5zBb9nsEIxnecKfntghWI6zxX8TsAKxXSeK3in/wrFdJ4reP/+CsV0nit4V/4KxXSeK3iv/QrFdJ4reAf9CsV0nouuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQN7oe+kbXQ9/oeugbXQ99exidYjbP1eh66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dB3uh76TtdD3+l66DtdD31/GJ1iNs/V6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfT/H3tvlB65rivpzqi/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x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerwO+x+uA7/E64Hu8Dvger+OB/k4+4Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x8vge7wMvsfL4Hu8DL7Hyx7o72SD7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvge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9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+l66DtdD32n66HvdD30/WF0itk8V6froe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+p6po3y08+OL2+/f+UVvorfxlN5Ez+nR+8cXj/ZOb6Kn9JTeRM/oKb2JntBTehNl4hm9mRqrp/Rmev/O6M30/p3RmygLT+k1Mr1k/ipTS/WUXlh/9aIB1jO9aIjtg672+U/JxsMlmQfvkV6hOLYXWqE4thtaoTi2H1qh2OgUx/ZEKxTHdkUrFMf2RSsUx3ZRKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isUs3muEbxHeoViNs81gvdIr1DM5rnGw+gUs3muEbxHeoViNs81gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuSqd5wreFb5CMZ3nqnSeqxqdYjrPFbwVfoViOs8VvBl+hWI6zxW8HX6FYjrPFbwhfoViOs8VvCV+hWI6zxW8KX6FYjrPFbxZfoViOs9F10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/1g66G/Hmw99E/FZJ7rqZjMcz0Vk3mup2KjU0zmuZ6KyTzXUzGZ53oqJvNcT8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K2TzXQddDf9D10B90PfQHXQ/9Uw+dYjbPddD10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9QddDf9D10B90PfQHXQ/9kamjfLTz44vb79/5S2+mhvIpvYme06N/fvFo7/QmekpP6U30jJ7Sm+gJPaU3USae0psoEU/pzfT+ndCbqa16Sm+iLDylN1ESntJL5q8ytVRP6YX1Vy8aYD3Ti4bYPqjYR9YedfTvknn5+BjPpdK7f3exfZC/3tg+yF1v8AZpf72xfZC/3tg+yF9vbB/kr9fI9Mb2Qf56Y3smf71k/ip4Y7S/XjJ/Fbwt2l8vmb8K3hTtr5fMXwVvifbXS+avgjdE++sl81fB26H99XL5qzN4M7S/Xi5/dQZvhfbXy+WvzoeR6eXyV2fwNmh/vVz+6gzeBO2vl8xfBW+B9tdL5q+CN0D76yXzV8Hbn/31kvmr4M3P/nrJ/FXw1md/vWT+Knjjs79eMn8VvO3ZXy+Zvwre9Oyvl8xfBW959tdL5q+CNzz76yXzV8Hbnf31kvmr4M3O/nrJ/FXwVmd/vWT+Knijs79eMn8VvM3ZXy+Zvwre5Oyvl8xfBW9x9tdL5q+CNzj76yXzV8Hbm/31kvmr4M3N/nrJ/FXw1mZ/vWT+Knhjs79eMn8VvK3ZXy+Zvwre1Oyvl8xfFTJ/FbyH211v8B5uf71k/qqS+avgPev+eo1ML5m/Ct6z7q+XzF8F71n310vmr4L3rPvrJfNXwXvW/fWS+avgPev+esn8VfBOdn+9ZP6KrL/9JOtvP8n620+y/vaTrL/9JOtvP8n620+y/vaTrL/9JOtvP8n620+y/vaTrL/9JOtvP8n620+y/vaTrL/9JOtvP8n620+y/vaTrL/9JOtvv8j62y+y/vaLrL/9Iutvvx5GppfLX11k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX+7kfW3G1l/u5H1txtZf7s9jEwvl78ysv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj62+3TH3Xo50fX9yud3oTvY9m9GbqQx69f3zxaO/0JnpeTelN9Lya0mtkehPlwSm9ifLglN5M798ZvZnevzN6E+XBGb2Z+pCn9JL5q0x9yFN6Yf3ViwZLoCG2D2rn+NDQz/ZdLn+M+vGpj+PlU9fyqji2E1qhOLYXWqE4thtaoTi2H1qgOHiD8QrFsT3RCsWxXdEKxbF90QrFRqeYznMFbzNeoZjOcwVvNF6hmM5zBW81XqGYznMFbzZeoZjOcwVvN16hmM5zBW84XqGYznMFbzleoZjNc5XgTccrFLN5rhK87XiFYjbPVR5Gp5jNc5XgrccrFLN5rhK8+XiFYjrPFbz9eIViOs8VvAF5hWI6zxW8BXmFYjrPFbwJeYViOs8VvA15hWI6zxW8EXmFYjrPFbwVeYViOs8VvBl5hWI6zxW8HXmFYjrPFbwheYViOs8VvCV5hWI6zxW8KXmFYjrPFbwteYViOs8VvDF5hWI6zxW8NXmFYjrPFbw5eYViOs8VvD15hWI6zxW8QXmFYjrPFbxFeYViOs8VvEl5hWI6zxW8TXmFYjrPFbxReYViOs9VjE4xnecqdJ4reFf4CsV0nqvQea5K57mCd8KvUEznuYL3wq9QbHSK6TxX8Hb4FYrpPFfwhvgViuk8V/CW+BWK6TxX8Kb4FYrpPFfwZvkViuk8F10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroK10PfaXroa90PfSVroe+PoxOMZvnqnQ99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQ10wd5c+v/vji9vt3ftGb6G08ozdTd/Xo/eOLR3unN9FTekpvomf0lN5ET+gpvYky8ZTeRIl4Sm+m9++M3kzv3xm9ibLwjN5MTdVTesn8VaaW6im9sP7qRYMl0BDbB/XSPv8plfpdMrfzM5nbVb6+uo1XxbGd0ArFsb3QCsWx3dAKxbH90ALFwXukVyiO7YlWKI7tilYoju2LVig2OsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxWyeqwXvkV6hmM1zteA90isUs3mu9jA6xWyeqwXvkV6hmM1zteA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5rpPOcwXvCl+hmM5znXSe66LzXME74VcopvNcwXvhVyg2OsV0nit4O/wKxXSeK3hD/ArFdJ4reEv8CsV0nit4U/wKxXSeK3iz/ArFdJ6Lroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99p+uh73Q99J2uh77T9dD3h9EpZvNcna6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6Xroe6aO8tHOjy9uv3/nF72J3sZTehM9p0fvn1/c3ulN9JSe0pvoGT2lN9ETekpvokw8ozdTY/WU3kzv3xm9md6/M3oTZeEpvUaml8xfZWqpntIL669eNMB6phcNsX3Q+PzOx+M4j++iefn86mJv/uEFr5FeIDi2E1ogOLYVWiA4thdaINjYBMd2QwsEx7ZDCwTH9kMLBMc2TwsEszmt4OXRCwSzOa3g1dELBLM5reDF0QsEszmt4LXRCwSzOa3gpdELBJM5rRG8MnqBYDKnNYIXRi8QTOa0xsPYBJM5rRG8LHqBYDKnNYJXRS8QzOa0ghdFLxDM5rSC10QvEMzmtIKXRC8QzOa0gldELxDM5rSCF0QvEMzmtILXQy8QzOa0gpdDLxDM5rSCV0MvEMzmtIIXQy8QzOa0gtdCLxDM5rSCl0IvEMzmtIJXQi8QzOa0ghdCLxDM5rSC10EvEMzmtIKXQS8QzOa0gldBLxDM5rSCF0EvEMzmtILXQC8QzOa0gpdALxDM5rSCV0AvEMzmtIIXQC8QzOa0gtc/LxDM5rSClz8vEMzmtIJXPy8QzOa0ghc/LxDM5rQqm9MK3uy9QDCb06psTqsam2A2pxW8vn2BYDanFbzAfYFgNqcVvMJ9gWA2pxW8xH2BYDanFbzGfYFgNqcVvMh9gWA2pxW89n2BYDanxdYRP9g64gdbR/xg64gfbB3xg60jfrB1xA+2jvjB1hE/2DriB1tH/GDriB9sHfGDrSN+sHXED7aO+MHWET/IOuLtkapB/Pv77U/Bmd7DU4IzPaW/vzD6FJzpKT0lONNTekpwpqf0lOBMeXhKcKY8PCM4Vb/0lOBU7+EZwZny8JTgTHl4SrCxCWZzWsD90i8icN3Ti4jQjuj5yevXBznP85t/e++/94vi0JZoheLYTdBLFIc2RUsUh3ZFSxSHtkVLFBud4tDGaIni0M5oieLQNmqJYjrPFbsSeoXi2J3QSxTTea7YrdBLFNN5rti90EsU03mu2M3QSxTTea7Y3dBLFNN5rtjt0EsU03mu2P3QSxTTea7YDdFLFNN5rtgd0UsU03mu2C3RSxTTea7YPdFLFNN5rthN0UsU03mu2F3RSxTTea7YbdFLFNN5rth90UsU03mu2I3RSxTTea7YndFLFNN5rtit0UsU03mu2L3RSxTTea7YzdFLFNN5rtjd0UsU03mu2O3RSxTTea7Y/dFLFNN5rtgN0ksU03mu2B3SSxTTea7YLdJLFNN5rtg90ksU03mu2E3SSxTTea7YXdJLFNN5rtht0ksU03mu2H3SSxTTea7YjdJLFNN5rtid0ksU03mu2K3SSxTTea5B57kGm+c6YneHL1HM5rme34ZOcaq3U7GPhvhibxWnejvNKI7dtvxjxeWjubTU9k5xqifXlOJUT64pxanS4pRio1OcKi1OKU71Pq5H/fXV9TrfKU71Pp5SnCotTilOlRZnFOdqc55SnMpzTSlO5bmmFKfyXFOKjU5xKs81pZjOc+Vqc55SDOy5XlQA+6gvFdFbl8/avlT0xzf/+ma2rNFblxcoDu6Nfqb4PD8/iJV3ioN7owWKjU5xcG+0QHFwb7RAcXBvtEBxcG/0Q8WlfHyQdrxTHNxH+SuO3rq8QHEqzzWlOJfnmlGcy3PNKDY6xbk814zi4J7rOq6XD3J9o/gZjD7WM0///PJJnvuBF83BXdcSzcF91xLNwZ3XCs3R25eXaA7uvpZoDu6/lmgO7sCWaDZCzcFd2BLNhD4sehfzEs2EPix6H/MKzdEbmZdoJvRh0VuZl2gm9GHRm5mXaCb0YdHbmZdoJvRh0Rual2gm9GHRW5qXaCb0YdGbmpdoJvRh0dual2gm9GHRG5uXaCb0YdFbm5doJvRh0Zubl2gm9GHR25uXaCb0YdEbnJdoJvRh0Vucl2gm9GHRm5yXaCb0YdHbnJdoJvRh0dt+f6Z5tI/mudF+/94vilO9nacUp3pmj/7RWDXGu8aq6E2w7orP6E2wCxSnelpPKU6VmacUp0rMU4pzvY9nFOd6H88oTpWVpxSnSspTitk81/mg81zRO6zvFL+oAPZRLyqCeyOr9vVBWvvmX99Em9EZvWt6gWKjUxzcG/1M8UTvyxm9a3qB4uDeaIHi4N5ogeLg3shfcfSu6QWKg/uoBYpTea6JFpQzetf0AsVGpziX55pRnMtzzSjO5blmFOfyXDOKkTxXtzd7jei91JMqkLzRexXB/U45vzZl5aoO+4fo/dELFFsmxTMuPnp/9ALFwf3OAsXB/c4CxcH9zgLFwf2Ov+Lo/dE/VDzhaaP3Ry9QnMpzTSlO5bmmFBud4lyea0ZxLs81oxjJc9m736uI3gc9qQLJG71VEb2zufTy+UHq+O43rHqxx8c3L6W+fJL6qjm641mhObrnWaE5uutZodkINUd3Pis0R/c+KzRHdz8rNEf3Sis0R3dWCzRH72xeopnQh0XvbF6imdCHRe9sXqKZ0IdF72xeopnQh0XvbF6imdCHRe9sXqKZ0IdF72xeopnQh0XvbF6imdCHRe9sXqKZ0IdF72xeopnQh0XvbF6imdCHRe9sXqKZ0IdF72xeopnQh0XvbF6imdCHRe9sXqKZ0IdF72xeopnQhw1CHzYIfVj0bu4lmgl92CD0YYPQh0XvYV+imc+HXdG72Jdo5vNhV/Q+9iWa+XzY9TBCzXw+7Irey75EM58Pu6J3sy/RTOjDovezL9FM6MOid78v0Uzow6L3vy/RTOjDonfAL9FM6MOi98Av0Uzow6J3wS/RTOjDovfBL9FM6MOid8Iv0Uzow6L3wi/RTOjDonfDL9FM6MOid8kv0Uzow8L31K/QTOjDwnfVr9BM6MPC99Wv0Ezow8J31q/QTOjDwvfWr9BM6MPCd9ev0Ezow8L316/QTOjDwnfYr9BM6MPCd96v0Ezowwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPv2LsE//IuzTvwj79C/CPn0j7NM3wj59I+zTN8I+fXsYoWY+H2aEffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36Rtinb4R9+kbYp2+EffpG2KdvhH36RtinXwj79Athn34h7NMvhH365WGEmvl8WCHs0y+EffqFsE+/EPbpF8I+/ULYp18I+/QLYZ9+IezTL4R9+oWwT78Q9ukXwj79QtinXwj79Athn34h7NMvhH36hbBPvxD26RfCPv1C2KdfcvWsj3b++urRfv/eL4pTvZ2nFKd6Zo/ePxSP9k5xqif2lOJUz+spxame1lOKU2XmKcWpEvOM4lx921OKc72PZxSnyspTilMl5SnFRqeYznMhd2y/qAD2US8qgnujdj0+P0i37/71/dOJ++vL/6mie5Pdo/dgr9AcvQd7iebgDmmJ5uAeaYnm4C5piWYj1BzcKS3RHNwrLdEc3Fkt0Uzow6L3YK/QHL0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWZCHxa9B3uJZkIfFr0He4lmQh8WvQd7iWY+H1aj92Av0cznw2r0Huwlmvl8WH0YoWY+H1aj92Av0cznw2r0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl92Enow05CHxa973yJZkIfdhH6sIvQh0XvPf+Z5ok2/xq999xfcfRO7B8q/r5ZtkbvxF6gONXzekpxqqf1lGKjU5wqMU8pzvU+nlGc6308ozhVVp5SnCopzyjO1bM9pZjOcyF3bL+oAPZRLyostorez88PMtr45l/fcY1P0dcYb7J79B7sJZqD+6MlmoM7pCWag3ukJZqDu6QVmqP3YC/RHNwpLdEc3Cst0RzcWS3RbISaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmgl9WPQe7CWaCX1Y9B7sJZoJfVj0Huwlmvl8WIveg71EM58Pa9F7sJdo5vNh7WGEmvl8WIveg71EM58Pa9F7sJdoJvRh0Xuwl2gm9GHRe7CXaCb0YdF7sJdoJvRh0Xuwl2gm9GHRe7CXaCb0YdF7sJdoJvRh0Xuwl2gm9GHR+5F/pnmijbBFb0f2Vxy9M/eHir9vxmnRG3MXKE71vJ5SnOppPaXY6BSnSsxTinO9j2cU53ofzyhOlZWnFKdKyjOKo3deL1BM57mid17fKX5RAeyjXlRYaBXH4/hUcTzK8c2/vvKpufT+9b3P41VxbG+0QnFsb/RDxa2Pz+99fvO933+OFzqxfdRuOrE91246sf3ZZjrBu7R304nt+3bTie0Rd9OJ7T130zHRuaGTyv+605FXvqMjr3xHR175jo688g2d4H3qu+nIK9/RkVe+oyOvfEfHROeGjrzyHR155Ts68sp3dOSV7+jIK9/QCd55v5uOvPIdHXnlOzryynd0THRu6Mgr39GRV76jI698R0de+Y6OvPINneB3CXbTkVe+oyOvfEdHXvmOjonODR155Ts68sp3dOSV7+jIK9/RkVe+oRP8dsRuOvLKd3Tkle/oyCvf0THRuaEjr3xHR175jo688h0deeU7OvLK7+n04Pc9dtORV76jI698R0de+Y6Oic4NHXnlOzryynd05JXv6Mgr39GRV76hE/wGy2468sp3dOSV7+jIK9/RMdG5oSOvfEdHXvmOjrzyHR155Ts68so3dILfydlNR175jo688h0deeU7OiY6N3Tkle/oyCvf0ZFXvqMjr3xHR175hk7w+2S76cgr39GRV76jI698R8dE54aOvPIdHXnlOzryynd05JXv6Mgr39AJflduNx155Ts68sp3dOSV7+iY6NzQkVe+oyOvfEdHXvmOjrzyHR155Rs6utt3S0de+Y6OvPIdHXnlOzomOjd05JXv6Mgr39GRV76jI698Q4f3ulixj+9c7C0d2jf6FB3ap3Ip/YNObe/o0D6Vp+jQPpWn6NBuMGbo8F6ImqJDu8GYokPrd+pRf31tvc53dGj9zhQdE50bOrQbjCk6tF55ig6tV56iQ+uVp+jQeuUZOrwXoqbo0HrlKTryynd05JXv6Jjo3NCRV76jI698R0de+Y6OvPIdHXnlGzrJLkT95HvX+rE6ff5/x9dXX/2VTy637M8nl1/255PLMfvzMfG55ZPLNf/ke7fHx+vraO13Pn/4OVj//N2N3r++9jxeWeby2HtZ5nLke1nm8u97WeZy+ztZjmQXsfay5M0R/ix5M4c/S9584s/SxNKNpXKPH0vlHj+Wyj1+LJV7/Fgq97ixTHbdbC9L5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUv5yjmX5+P2c0o43LJNdBNvLUu9xt/8bT3Yxai9Lvcf9WOo97sdS+0s/ltpf/oHlCx95xls+ya5d+fMh3h2Oz98N7ddbPsT7wCk+xNlgio+Jzy0fYg8/xYfYl0/x4fXa/dM+H8P6b3z+nddOdilrL0teX+7OMtkVrr0sef2+P0vebODPkjdH+LM0sXRjyZtP/FnyZhl/lso9fiyVe/xYKve4sUx2UW0vS+UeP5bKPX4slXv8WJpYurFU7vFjqdzjx1K5x4+lco8fS+UeN5ZVucePpXKPH0vlHj+Wyj1+LE0s3Vgq9/ixVO5xY5nsNuU6lhN/z5jskuVelnr3+P3fuN49fiz17vFjqZ2bH0vt3PxYauf2B5ZffJLdaPTnIx94z4d33zXqxxefT7nv+PDusOb4mPjc8uH1+3N8eD38HB9eXz7Hh9ZrPz/d8cln2G98/uC1q3167ZevfYxXlrRe258l7z3IBSxpPfwClrR+fwFL2mywgKWJpRtL2syxgCVtPlnAkjbLLGCp3OPHUrnHiWV58N66XMBSucePpXKPH0vlHj+WJpZuLJV7/Fgq9/ixVO7xY6nc48dSuceNJe+tywUslXv8WCr3+LFU7vFjaWLpxlK5x4+lco8fS+UeP5bKPX4slXvcWPLeYF3AUrnHj6Vyjx9L5R4/liaWbiyVe/xYKvf4sVTu8WOp3OPHUrnHjSXvzeEFLJV7/Fgq9/ixVO7xYylPNMfy2z62J0t5IjeWvLcyf8jy266mJ0u9e/xY6t3jx9LE0o2ldm5+LLVz+wPLFz7yjPd85APv+fDuu47j81Mf9o4P7+3JST682WCOD6/fn+PD6+Hn+Jj43PLh9dpHL5+f2sZvfP7d/pH3PuMClry+3J8lr4f3Z0ns971Z8t5nXMCSOEe4syTOHO4sifOJO0sTSzeWyj1+LJV7/Fgq9/ixVO7xY6nc48aS9wbrApbKPX4slXv8WCr3+LE0sXRjqdzjx1K5x4+lco8fS+UeP5bKPW4see8IL2Cp3OPHUrnHj6Vyjx9LE0s3lso9fiyVe/xYKvf4sVTu8WOp3OPGkvhOsz9L5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R4vlgfxnWZ/liaWUyy/72M7iG+4+rPUu2eO5fddTQfxrUx3lsS3Mv1Zaufmx1I7Nz+W2rn9geULHxOfWz7ygfd8ePddZ+0fn/p6PN7x4d1hzfHhzQZzfHj9/hQf4ruPc3x4ffkcH16vfZ1ffKy+48Prn+f4mPjc8uH1z3N8eP3zHB9e/zzHh9c/X+PjW59m/Tc+f9gVnZ+7oqu8KHz9+RnxXUJ3lsR3Cf1Z8np4f5bEft+dJXE2cGdpYunGkjhz/Ijl1+8UtfaOJXE+cWdJnGXcWSr3+LFU7nFjaco9fiyVe/xYKvf8lOXb37Mmvonrz9LE0o0lb+6xz18FPMv13e8N9k8g/Xi9eVZeWfLmHn+WvLnHnyVv7vFnyZt73FkS3/D1Z8mbe37G0j48US/tHUve3OPPkjf3+LM0sXRjqdzjx1K5x4+lcs8cy/bxi259HO9YKvf4sVTucWNJfJ/Yn6Vyjx9L5R4/lso9fixNLGdYjuND4jjrO5bKPX4slXv8WCr3+LFU7vFjqdzjxpL4PrE/S97cU+rj41PXx/ENy+P5Zvn8IPXlN2bs9S8iiS8Ur6DJm31W0DTRdKTJm39+RvM8Pn5YcZy9/UbzP796plWP+KrxbvK82Wo3ed4ktps8b27bTJ74GvNu8sqEu8grP+4ir6y5i7yJ/CbyyrC7yCvD7iKvDLuLvDLsLvLKsJvIE1/W3k1eGXYXeWXYXeSVYXeRN5HfRF4Zdhd5Zdhd5OXnV5D//prsSXwxejd5eZs9T5vzYSK/iby8zS7y8ja7yGs/v4u89vP/NfkXmvLojjQP+W5PmtqNz9G8HvXjg1z2lqb23Z40lfM8aZpoOtJUHvOkqYzlSVO5aZJm+1g2HlYev9H8w1c3+2Tf7eWT2OOVvZLTPvbKWdvYn0pl+9grw+1jr8S3j73y4T72Jvbb2Ct77mOvpLqPvXLtPvbKtfvYK9duY38p1+5jr1y7j71y7T72yrX72JvYb2OvXLuPvXLtPvbKtfvYK9fuY69cu429KdfuY69cu4+9cu0+9sq1+9ib2G9jr1y7j71y7T72yrX72CvX7mOvXLuNfVGu3cdeuXYfe+XafeyVa/exN7Hfxl4ecwH7mQa0Ioe5iXzVe3YF+YlOoqq37C7yesfuIq/N8S7y2hvvIq+t8X9N/oWmPLonTfnuOZrl+NB4lNa/eyqcn0+Fq7zwGC/km/a6u8hrq7uLvLLmLvLKmrvIm8hvIq+suYu8suYK8tU+t7ntHXllzV3klUt3kVeG3US+K8PuIq8Mu4u8Muwu8sqwa8l3e0feRH4TeWXYXeSVYefI1y8i9eVzvPk9vGKfN3xKee37f/09vK4Uu4+9cuw+9kqy29gPZdl97JVm97FXnl3C/vNXr59+9HzHXol2H3sT+23slWr3sVeu3cdeuXYfe+XaFextPD7Z99895r/buw1lYIQ5XQ/lZYw5KVuvmFNtX1/9yv71nXM9lK33sVe23sfexH4be2XrfeyVrfexV7bex17Zegn7/tlZVMd4x155eRv7Qxl4H3vl2n3slWv3sVeu3cfexH4be+XaJeyPjw9ytON3f//v9s2HMjDGnJSXMeakbL1iTv3x+XO23z7J7+8cZett7E9l633sla33sVe23sde2XofexP7beyVrZewP8on+7O/Y6+8vI+9MvA+9sq1+9gr125jfynX7mOvXLuPvXLtCvY3d83+3b75UgbGmJNpThBz4s3W9fr81M8f8X87p+PzrzjrK5H2538DH6+c8/WyXf3tjcObrHeT583Vu8nzpurd5HkztRv5L5rGm5JX0OTNvSto8ibZFTR58+YKmiaajjSV3TxpKo950lTGmqQ5Pj9Ie5TfaP7hc5T+64vbeNnonK/gFbE2gVfCWgD+PD+/tZU32bYoje0ir+S2i7xS3i7ySoS7yJvIbyKvpLmC/MTeviiV7iKvBDtHvp39k7wd/32QKkqwm8ArwS4AP/N+rUqwu8grwe4irwS7i7wS7C7yJvKbyCvBriA/kaOqEuwu8kqwk+Tr50+0W//uty0nglRVgt0EXgl2AfiZ92tTgt1FXgl2F3kl2F3klWB3kTeR30ReCXYF+Ykc1ZRgd5FXgp0j3x+fvb79fPz3QaopwW4CrwS7APzM+7Urwe4irwS7i7wS7C7ySrC7yJvIbyKvBLuC/ESO6kqwu8grwf4L8u038i80FUs9aSprOtIcyo+TNJt90uzt//2vVyZD8XETeKXHBeBnnPRQetxF3kR+E3mlx13klR53kVd63EVeSXMF+YmNyVAq3UPeHkqwk+TL8UW+f0N+XB+/FDPqy/X4/u9Clz2UdgGGpGQMMCSFaIAhmYYUf0iK5gBDUooHGJICP8CQtBsAGJLWCPGHdGjjADAkbRzmhjTs84OM8t83ytuhLcIm8NoMLAA/8WMXO0zkN5FXht9FXsF8F3ml7V3kFaF3kVcuXkF+4sfrp8LuLvJKsLvIK8LuIq8MO0m+Pz6++vHtn/zdffULexP7beyVYxewb318fo7zm8/x/jO/TEmZF2FKyscIU1KWRpiScjfAlC5ldIQpKc8jTEnZH2FK2hMgTMk0JYApafeAMCXtHhCmpN0DwpS0e0CYknYPAFMy7R4QpqTdA8KUtHtAmJJ2DwhTMk0JYEraPSBMSbsHhClp94AwJe0eEKak3QPAlIp2DwhT0u4BYUraPSBMSbsHhCkpL22eUvn8w6Tnz5HeTUl5CWBKVR5v95Q+q2dKbe+mJI+HMCV5PIQpyeMhTMk0JYAp6edLCFNSXto8pXrUX19br/PdlJSXEKakny8hTEk/XwKYUtPuAWFK2j0gTEm7B4QpafeAMCXTlACmpN0DwpS0e0CYknYPCFPS7gFhSto9rJjSDz7HV23ub625tb5MqWv3gDAl7R4QpqTdA8KUtHtAmJJpSgBT0u4BYUraPeyeUvn42tEe76ak3QPClLR7QJiSdg8AUxraPSBMSbsHhClp94AwJe0e/uqUXsibyG8irx3BLvLK/bvIK8vvIq98vou8Mvce8uVBkqNfFJNk0hfFJPnuRTFJVnpRbHSKSbLBi2IST/6iOLoX/vzq4/n/xjeKj/LxQY5i7xRH96D+iqN7vx8pdu5pK0d0f7aXTnQvt5dOdN+3l050j7iXjonODZ3o3nMvneg+dS+dVJ7WnU4q/+tOR175hs4pr3xHR175jo688h0deeU7OiY6N3Tkle/oyCvf0ZFXvqMjr3xHR175hs4lr3xHR175jo688h0deeU7OiY6N3Tkle/oyCvf0ZFXvqMjr3xHR175ho7JK9/RkVe+oyOvfEdHXvmOjonODR155Ts68sp3dOSV7+jIK9/RkVe+oVPkle/oyCvf0ZFXvqMjr3xHx0Tnho688h0deeU7OvLKd3Tkle/oyCvf0Knyynd05JXv6Mgr39GRV76jY6JzQ0de+Y4Ord8pn235zx9bvaND63dm6IS/r7uOTukfdGp7R4f2nTVFh/adNUWH9p01RYd2vzNFh3a/M0WH1u9M3Oks4e90bqUT/j7mXjq0+50pOrReeYoOrVeeomOic0OH1itP0aH1ylN0aL3yFB155Ts68so3dMLfc9tLR175jo688h0deeU7OiY6N3Tkle/o5PLKP/nepXxW/T9/+PD11fZHjaV8SGzHO5a5nPVelrl8+F6WuVz7TpY1/K2pLSxf+ORy+f58cvl8fz65nL4/HxOfWz653L4/H/n9ez7y8Pd8eH15PT+i91FfNP7ZS05k75rsathWlslujC1jeZ6fEq28Y8nr4f1Z8vp9f5a82cCfpYmlG0vezOHPkjef+LPkzTI/Yzmx9012020vS+LcU8sny9Ydck+ye3F7WRLnnp+wnHn3JLtFt5clce5xZ2li6caSOPe4syTOPe4siXOPO0vi3PMjlhO5J9k1v60sk93+28tSucePJW/uaY+PiH208viG5VE+JB7F3rHkzT3+LE0sZ1g6d83VZNcQcbjz5qm93Hmz117uvDltL3feTLeVe7J7ljjcebPiXu7KlXu4K4Pu4W7ivoW78uoe7sqre7grr+7hrry6h7vy6hbuyW7K4nBXXt3DXXl1D3fl1T3cTdy3cFde3cNdeXUPd+XVPdyVV/dwV17dwj3ZXWcc7sqre7grr+7hrry6h7uJ+xbuyqt7uCuv7uGuvLqHu/LqHu7Kq1u4N+XVPdyVV/dwV17dw115dQ93E/ct3JVX93BXXt3DXXl1D3fl1T3clVe3cO/Kq3u4K6/u4a68uoe7/Ls792Ifh7KKveUu/76Hu/yMP/fSP7jX9ob7kJ/Zw11+Zg93+Zk93LV/38PdxH0Ld/l3d+4zt2CG/Pse7tq/7+Gu/fse7sqrO7i3h/LqHu7Kq3u4K6/u4a68uoe7ifsW7sqre7grr+7hrry6h7vy6h7uyqtbuB/Kq3u4K6/u4a68uoe78uoc9x985/O8Hl88vr76GPaj7/wyJdOUAKakLIwwJSVnhCkpZ//VKb2QV9LeRV5ZexP5U2l7F3nl7V3klbh3kVfm3kXeRH4TeWXjXeSVd3eRV4ZdQL5/kr+O+hv5P3wO6/bxOcr18tX1ep2TEi/GnJSPN8/Jua2gXcrd2SaqPJ9totoTZJuo9g/ZJmqaaLKJal+SbaLaw2SbqPY72SaqTVC2iWpnlGyipp1RtolqZ5RtotoZZZuodkbZJmqaaLKJameUbaLaGWWbqHZG2SaqnVG2iWpnlGyiRTujbBPVzijbRLUzyjZR7YyyTdQ00WQT1c4o20S1M8o2Ue2Mkk20Ko8CTXTiDmWryqPZJmqaKNBEv7+t1qq8braJyutmm6i8braJ6uej2Saqn48mm2hTHgWa6Eyve1MezTZR/Xw020T189FsEzVNNNlEtTPKNlHtjLJNVDujbBPVzijbRLUzSjbRrp1RtolqZ5RtotoZZZuodka7J/qTz2yfpI/yeNdr3k0zTTdT7Y3yzVSbo3wz1e4o30y1Pco3U+2P0s10aIOEOtOXr/6/ZqodUr6ZaouUb6baIyHNtBzlc6ZnfzdT00zTzVR7pHwz1R4p30y1R8o3U+2R8s1Ue6RsM+0P7ZFQZ3qVdzPVHinfTLVHyjdT7ZHCzvRlSqYpAUxJux7/KV1H/5xSsW+mdFi3r2defffM0/4GY07ayWyek3NvZn9oI5NtotrHJJvooW1MtolqF5NtotrEZJuo9jDZJmqaaLKJar+TbaLaBGWbqHZG2SaqnVG2iWpnlGyip3ZG2SaqnVG2iWpnlG2i2hllm6hposkmqp1RtolqZ5RtotoZZZuodkbZJqqdUbKJXtoZZZuodkbZJqqdUbaJameUbaKmiSabqHZG2SaqPAo00WLnr68t9naiyqPJJmryukgT/f4qejd53WwTNU002UTldbNNVD8fzTZR/Xw020SVR4EmOnFXsJvyaLKJFv18NNtE9fPRbBPVzijbRLUzyjZR00STTVQ7o2wT1c4o20S1M8o2Ue2Msk1UO6NkE63aGWWbqHZGuyf6k888cze7V22N8s1Ue6N8MzXNNN1MtTvKN1Ntj/LNVPujfDPVBgl1pi9f/X/NVDukdDNt2iLlm6n2SEgznbqb3bRHyjdT7ZHyzdQ003Qz1R4p30y1R8o3U+2R8s1UeyTUmV7l3Uy1R0o30649Ur6Zao8UdqYvU9JmCGFK2vUsmFKpn1Ma9ZspjfPjtzVHO1701dcpmaYEMCXtYzZPybszs2sbk22i2sVkm6g2Mdkmqj1MsokObWGyTVQ7mGwT1b4m20S128k2UdNEk01UO6NsE9XOKNtEtTPKNlHtjLJNVDujXBMdD+2Msk1UO6NsE9XOKNtEtTPKNlHTRJNNVDujbBPVzijbRLUzyjZR7YyyTVQ7o2QTPbQzyjZR7YyyTVQ7o2wT1c4o20SVR4EmWuz89bXF3k5UeTTZRE95XaSJfn8RfZzyutkmKq+bbaLyutkmapposonq56PZJqo8CjTRiZuC41QezTZR/Xw020T189FkE720M8o2Ue2Msk1UO6NsE9XOKNtETRNNNlHtjLJNVDujbBPVzijbRLUz2j3RH3zn8flbKaO83maorxPVzijZRE07o2wT1c4o20S1M8o2Ue2Msk3UNNFkE9XOCGmi5eNrR3u8m6h2Rtkmqp1RtolqZ5RtotoZJZto0c4o20S1M8o2Ue2Mwk70ZUraAyFMyTQl/ymNz1vXdhzfTOk86/X11edvX/0yJ21sMOakPcz2OX2Nqbx76mm3gjAl7UsQpqQdCMCUqvYaCFPSrgJhSto/7J5SKR9f3I53U9L+AWFKpikBTEnbB4QpafeAMCXtHhCmpN0DwpS0ewCYUtPuAWFK2j0gTEm7B4QpafeAMCXTlP67Kb2w1IbAj6VyvB9LpW0/lsrEfiyVXN1YduVLP5ZKgX4sldX8WCpR+bE0sXRjqdzjx1K55w8sX/gQZ5l2fvLp7Zt/a89PYp8f5LJ3/9qI08wCmsR5xp/mIE40C2gSZ5oFNIlTzQKaxLlmAU0TTUeaxNlmAU3idLOAprKQJ01lIU+aykJuNOvjoSzkSVNZyJOmspAnTWUhT5ommo40lYU8aSoLedJUFvKkqSzkSVNZyJHmoSzkSVNZyJOmspAnTWUhT5ommo40lYU8aSoLedJUFvKkqSzkSVNZyJHmqSzkSVNZyJOmspAnTWUhT5ommo40lYU8aSoLedJUFvKkqSzkSVNZyJHmpSzkSVNZyJOmspAnTWUhT5ommo40lYU8aSoLedJUFvKkqSzkSVNZyJGmKQt50lQW8qSpLORJU1nIk6aJpiNNZSFPmspC/48jTWUhT5rKQp40lYUcaRZlIU+aykKeNJWFPGkqC3nSNNF0pKks5ElTWciTprKQJ01lIU+aykKONKuykCdNZSFPmspCnjSVhTxpmmg60lQW8qSpLORJU1nIk6aykCdNZSFHmk1ZyJOmspAnTWUhT5rKQp40TTQdaSoLedJUFvKkqSzkSVNZyJOmspAjza4s5ElTWciTprKQJ01lIU+aJpqONJWFPGkqC3nSVBbypKks5ElTWciR5lAW8qSpLORJU1nIk6aykCdNE01HmspCnjSVhTxpKgt50lQW8qSpLORH84lNNB1pKgt50lQW8qSpLORJ00TTkaaykCdNZSFPmspCnjSVhTxpKgs50jyUhTxpKgt50lQW8qSpLORJ00TTkaaykCdNZSFPmspCnjSVhTxpKgs50jyVhTxpKgt50lQW8qSpLORJ00TTkaaykCdNZSFPmspCnjSVhTxpKgs50ryUhTxpKgt50lQW8qSpLORJ00TTkaaykCdNZSFPmspCnjSVhTxpKgs50jRlIU+aykKeNEmy0ItikrzyotjoFJP4/hfFJN78RTGJf35RTOJxXxST+NAvxYXEK74oJvFzL4rpPBfLDfoXxYar+EUFsI96UQHsjV5UAPudFxXAHuZFBbAv+VKBfPf6RQWwf3hRAewJXlQAv+dfVKR4dyPfE35RkeLdjXw/90VFinc38r3YLxXId1pfVKR4dyPfJX1RkeLdjXyH80VFinc38t3JFxXB393PH4h/qSj1NxX/9qfC0a8yLtEc3Bes0Bz9wuESzcE9xxLNwR3KEs3B/cwSzUaoObhXWqI5uLNaopnQh0W/CLdEM6EPi35dbYlmQh8W/VLZEs2EPiz61a8lmgl9WPQLWks0E/qw6Neolmjm82Fn9MtOSzTz+bAz+pWkJZr5fNj5MELNfD7sjH69Z4lmPh92Rr+Es0QzoQ+LflVmiWZCHxb9QssSzYQ+LPq1kyWaCX1Y9MshSzQT+rDoVziWaCb0YdEvWizRTOjDol+HWKKZ0IdFv7SwRDOhD4t+tWCJZkIfFv0CwBLNhD4sepv+Es2EPix6M/0SzYQ+LHrL+xLNhD4semP6Es2EPix6+/gSzYQ+LHqT9xLNhD4seiv2Es2EPix6M/YSzYQ+LHo79hLNhD4sekP2Es2EPix6S/YSzYQ+LHpT9hLNhD4selv2Es2EPix6E/cSzYQ+LHrL9xLNhD4seoP4Es2EPix6O/kSzYQ+LHrz+RLNhD4seqv6Es2EPix6Y/sSzYQ+LHob/BLNhD4setP8Es2EPix6i/0SzYQ+LHpD/hLNhD6MsE//JOzTPwn79E/CPv2TsE//JOzTPwn79E/CPv2TsE//JOzTPwn79E/CPv2TsE//JOzTPwn79E/CPv2TsE//JOzTPwn79E/CPv2TsE//JOzTvwj79C/CPv2LsE//IuzTvx5GqJnPh12EffoXYZ/+RdinfxH26V+EffoXYZ/+RdinfxH26V+EffoXYZ/+RdinfxH26V+EffoXYZ/+Rdinf0Xq03/5VIGc0sunCuRlXj6VhfxUgfzAy6cK9MZ++VSB3qkvnyrQW+/lUwV6L319qkgN4C+fKuSzPVKL9sunCvlsj9RE/fKpQj7bI7U5v3yqkM/2SI3IL58q5LM9Uqvwy6cK+WyP1Mz78qlCPtsjtdu+fKqQz/ZIDbEvnyrksz1Sy+rLpwr5bI/UVPryqUI+2yO1fb58qpDP9kiNmS+favGz/eW/VP/af6n9tf9S/2v/pfG3/kurGwJf/kvHX/svnX/tv3T9tf+S/bX/0l97RtS/9oyof+0ZUf/aM6L+tWdE+2vPiPbXnhHtrz0j2l97RrS/9oxof+0Z0f7aM6L9tWdE+2vPiPbXnhH9rz0j+l97RvS/9ozof+0Z0f/aM6L/tWdE/2vPiP7XnhH9rz0j+l97Roy/9owYf+0ZMf7aM2L8tWfE+GvPiPHXnhHjrz0jxl97Roy/9owYf+sZYS5/kXo2+/wv9fHbf+lf/pacufzV6IrPdQb9XFfQz2VBP1cJ+rlq0M/Vgn6uHvRzjZif6wj6vD+CPu+PoM/7I+jz/gj6vD+CPu+PoM/7I+jz/gj6vD+CPu/PoM/7M+jz/gz6vD+DPu/PoM/7M+jz/gz6vD+DPu/PoM/7M+jz/gr6vL+CPu+voM/7K+jz/gr6vL+CPu+voM/7K+jz/gr6vL+CPu8t6PPegj7vLejz3oI+7y3o896CPu8t6PPegj7vLejz3oI+70vQ530J+rwvQZ/3JejzvgR93pegz/sS9Hlfgj7vS9DnfQn6vK9Bn/c16PO+Bn3e16DP+xr0eV+DPu9r0Od9Dfq8r0Gf9zXo874Ffd63oM/7FvR534I+71vQ530L+rxvQZ/3LejzvgV93regz/se9Hnfgz7ve9DnfQ/6vO9Bn/c96PO+B33e96DP+x70ed+DPu9H0Of9CPq8H0Gf9yPo834Efd6PoM/7EfR5P4I+70fQ5/2I+bwvQf++tgT9+9oS9O9rS9C/ry2PmM/7EvTva0vQv68tQf++tgT9+9oS9O9rS9C/ry1B/762BP372hL072tL0L+vLUH/vrYE/fvaEvTva0vQv68tQf++tgT9+9oS9O9rS9C/ry1B/762BP372hL072tL0L+vLUH/vrYE/fvaEvTva0vQv68tQf++tgT9+9oS9O9rS9C/ry1B/762BP372hL072tL0L+vLUH/vrYE/fvaEvTva0vQv68tQf++tq5ug/7Pr/7ZBfTH51cfz//3pfnPF9B/9L3bo35861YeX19t53/5nc+rfHzn8xovV9uH/ek79/H5nc9vvvPzn/evr33+g3oz0dWt25roX59ooOtwmqjLRANd1tNEXSYa6CqhJuoyUdNEk0000KVjTdRlooGuRGuiLhMNdGFbE3WZaKDr5Jqoy0S1M8o10fbQzghpov3xMdFR3k1UO6NsE9XOKNtEtTPKNlHTRIEm2r4mWt9NVDujbBPVzijbRLUzyjZR7YyyTVQ7o2QTPbQzQppo6R8Tre3dRLUzyjZR7YyyTVQ7o2wTNU002US1M8o2Ue2Msk1UO6NsE9XOKNtEtTNKNtFTO6NsE9XOKNtEtTPKNlHtjLJN1DTRZBPVzijbRLUzyjZR7YyyTVQ7o2wT1c4o2UQv7YyyTVQ7o2wT1c4o20S1M8o2UdNEk01UO6NsE9XOKNtEtTPKNlHtjLJNVDujZBM17YyyTVQ7o2wT1c4o20S1M8o2UdNEk01UO6NsE9XOKNtEtTPKNlHtjJJNtCiPLpjo0T8nWsxzohMd2EV5NNtElUezTdQ00WQTVR7NNlHl0WwTVR7NNlHl0WwT1e8wJJto1e8wZJuodkbZJqqdEdJEJy74VO2Msk3UNNFkE9XOKNtEtTNCmujEdZCqnVG2iWpnlG2i2hklm2jTzijbRLUzyjZR7YyQJjrxu4BNO6NsEzVNNNlEtTPKNlHtjLJNVDujbBPVzijbRLUzSjbRrp1RtolqZ5RtotoZZZuodkbZJmqaaLKJameUbaLaGWWbqHZG2SaqnVG2iWpnlGyiQzujbBPVzijbRLUzyjZR7YyyTdQ00WQT1c4o20S1M8o2Ue2Msk1UO6NsE9XOKNdE+0M7o2wT1c4o20S1M8o2Ue2Msk3UNNFkE9XOKNtEtTPKNlHtjLJNVDujbBPVzijZRA/tjLJNVHnUf6LnZ8Xmc7iul/C+78Duh2miySaqPJptosqj2SaqPJptosqj2SaqPJpsoqfyaLaJ6ncYsk1Uv8OQbaLaGWWbqGmiQBP9/oJPP7UzyjZR7YyyTVQ7o2wT1c4IaaLfXwfpp3ZGySZ6aWeUbaLaGWWbqHZG2SaqnVG2iZomCjTRid8FvLQzyjZR7YyyTVQ7o2wT1c4o20S1M0o2UdPOKNtEtTPKNlHtjLJNVDujbBM1TTTZRLUzyjZR7YyyTVQ7o2wT1c4o20S1M0o20aKdUbaJameUbaLaGWWbqHZG2SZqmmiyiWpnlG2i2hllm6h2Rtkmqp1RtolqZ5RsolU7o2wT1c4o20S1M8o2Ue2Msk3UNNFkE9XOKNtEtTPKNlHtjLJNVDujbBPVzijZRJt2Rtkmqp1RtolqZ5RtosqjcxN1bqpuSo17uCvb7eGuBLaHu3LSFu5daWYPd2WOPdyVDPZw189893A3cd/CXXl1D3flVX/uE5c4uvLqHu7Kq3u4K69u4T6UV/25T7TPD+XVPdyVV/dwV17dw93EfQt35dU93JVX/blP/D7BUF7dw115dQ935dUd3MdDeXUPd+XVPdyVV/dwV17dw93EfQt35dU93JVX93BXXt3DXXl1D3fl1S3cD+XVPdyVV/dwV17dw115dQ93E/ct3JVX93BXXt3DXXl1D3fl1T3clVe3cD+VV/dwV17dw115dQ935dU93E3ct3BXXt3DXXl1D3fl1T3clVf3cFde3cL9Ul7dw115dQ935dU93JVX93A3cd/CPZd/921FGlcul+1NJ5cXdqZjuRyrN51cvtKbTi73500nl0fzpmOic0Mn137em06uLbo3HXnlOzq8Xvn7/r1hvF55gk7h9cozdHi98gwdXq/8fU/WKLxeeYaOic4NHV6vPEOH1yvP0OH1yjN0eL3yxM8kCq9XnqBTeb3yDB1erzxDh9crz9Dh9cozdEx0bujweuUZOrxeeYYOr1eeoSOvfEdHXvmGTpNXvqMjr3xHR175jo688h0dE50bOvLKd3Tkle/oyCvf0ZFXvqMjr3xDp8sr39GRV76jI698R0de+Y6Oic4NHXnlOzryynd05JXv6Mgr39GRV76hk+yaujcdeeU7OvLKd3Tkle/omOjc0JFXvqMjr3xHJ7rfOc5POo9yfEfnB9/7rNfnp6795TeWrz9952N8/knO+Ti/2kqO9vhvp/Tt3xi2R/irwJrSP1OK7v80pX+mFN2Hakr/TCm6H9aU/pmSaUoAU4qeDzSlf6YUPadoSv9MKfrPFjSlf6YU/WccmtI/U9LuAWBK4S8855/St20wzylp94AwJe0eEKak3QPClExT2jylbxtfnlPS7gFhSto9IExJuweEKWn3gDAl7R4AphT+Wnf+KX37O0TPKWn3gDAl7R4QpqTdA8KUTFMCmJJ2DwhT0u4BYUraPSBMSbsHhClp9wAwpfCX1zWlf6ak3QPClLR7QJiSdg8IUzJNCWBK2j0gTEm7B4QpafeAMCXtHhCmpN0DwJRMuweEKWn3gDAl7R4QpqTdA8KUTFMCmJJ2DwhT0u4BYUraPSBMSbsHhClp9wAwpaLdA8KUtHtAmJJ2DwhT0u4BYUqmKQFMSbsHhClp94AwJe0eEKak3QPAlCpvXir1k3t9HN9N6Wof4A8rX1M6rf+R/McXl/bync/jlTxvBtpNnjfX7CZvIr+JPG/+2E2eN1OsJD/Kry+uj/KOPG9O2E2e1/vvJs/7s8TN5BvvzweXkj8+ydd35JVhd5FXht1FXhl2F3kT+U3klWF3kVeGXUG+f14Z6v0deWXYXeSVYXeRV4bdRL4rw+4irwy7i7wy7C7yyrC7yJvIbyKvDLuLvDLsLvLKsLvIK8PuIq8Mu4n8UIbdRV4Zdhd5Zdhd5JVhd5E3kd9EXhl2F3ll2F3klWF3kVeG3UVeGXYP+Sdikd9EXhl2F3ll2F3klWF3kTeR30ReGXYXeWXYXeSVYXeRV4bdRV4ZdhP5Qxl2F3ll2F3klWF3kVeG3UXeRH4Tefn5OfLnYR8f5OztO/Lfdzodh/z8LvLy85vIn/Lzu8jLz+8iLz+/gvz3jRPHKT+/i7yJ/Cby+pnULvL6mdQu8sqwu8grw64gP7G3OZVhN5G/lGF3kVeG3UVeGXYXeWXYXeRN5DeRV4bdRV4Zdhd5Zdhd5JVhd5FXht1E3pRhd5FXht1FXhl2F3ll2F3kTeQ3kVeG3UVeGXYXeWXYXeSVYXeRV4bdRL4ow+4irwy7i7wy7C7yyrC7yJvIbyKvDLuLvDLsLvLKsLvIK8PuIq8Mu4l8VYbdRV4Zdhd5Zdhd5JVhd5E3kd9EXhl2F3ll2F3kef380cvnp7bxDfmZ9o7G69D9WfJ6bn+WvC7anyWvL/ZnaWI5xXJ8fHF9lHcseb2rP0teN+rPkvdnJP4seX/q8UOW37fRNOUeN5ZducePpXKPH0vlHj+Wyj1+LE0sp1hO7C+7co8fS+UeP5bKPX4slXv8WCr3uLEcyj1+LJV7/Fgq9/ixVO7xY2li6cZSucePpXKPH0vlHj+Wyj1+LJV7vFieD+UeP5bKPX4slXv8WCr3+LE0sXRjqdzjx1K5x4+lco8fS+UeP5bKPW4sD+UeP5bKPX4slXv8WCr3+LE0sXRjqdzjx1K5x4+lco8fS+UeP5bKPW4sT+UeP5bKPX4slXv8WPL6y8f1ofG5LbPvWH7fa3CevP7SnyWvv/Rnyesv/Vny+kt3lhevv/wZy+87Is6L11/6s+T1l/4seffq/ixNLOdYfvu3+Oel3OPHUrnHj6Vyjx9L5R4/lso9bixNuWeO5cT+0pR7/Fgq9/ixVO7xY2li6cZSucePpXKPH0vlHj+Wyj1+LJV73FgW5R4/lso9fiyVe/xYKvf4sTSxdGOp3OPHUrnHj6Vyjx9L5R4/lso9biyJL7j7s1Tu8WOp3OPHUrnHj6WJpRtL5R4/lso9fiyVe/xYKvf4sVTucWPZlHv8WCr3+LFU7vFjqdzjx9LE0o2lco8fS+UeP5bKPX4slXvcWPLeHz/6J55jWP+O5USvAe/98QUsaf3lApYmlm4saf3lApa0/vKHLCc6Injvjy9gSesvF7Ck3av7s+S9P/5Tlt//LT7v/fEFLJV7/Fgq9/ixNLF0Y6nc48dSuWeO5cT+kvf++AKWyj1+LJV7vFhevPfHF7BU7vFjqdzjx1K5x4+liaUbS+UeP5bKPX4slXv8WCr3+LFU7nFjyXt/fAFL5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lrz3xxewVO7xY6nc48dSucePpYmlG0vlHj+Wyj1+LJV7/Fgq9/ixVO5xY3kp9/ixVO7xY6nc48dSucePpYmlG0tef9ke9eNbtza+Y/l9r8HFe398AUtef+nOkvf++AKWvP7SnyWvv/wZy+//tvTivT++gKWJpRtL3r26P0vevbo/S+UeP5bKPXMsJ/I47/1xf5a898cXsFTu8WOp3OPHUrnHj6WJpRtL5R4/lso9fiyVe/xYKvf4sVTucWPJe398AUvlHj+Wyj1+LJV7/FiaWLqxVO7xY6nc48dSucePpXKPH0vlHjeWvPfHF7BU7vFjqdzjx1K5x4+liaUbS+UeP5bKPX4slXv8WCr3+LFU7nFj2ZV7/Fgq9/ixVO7xY6nc48fSxNKNpXKPH0vlHj+WufxlH5/f+/zmexf7pGO/f44vOskuinvTyeUBvenkcnXedHL5NG86Jjo3dHJ5KW86udyRN51ce15vOrk2t9505JXf07FkV6h/Qqc/PuiM8o4Or1eeocPrlWfo8HrlGTpGS6d90anv6PB65Rk6vF55hg6vV56hw+uVZ+jweuUJOskuF/+ETukfdGp7R4fXK8/Q4fXKM3R4vfIMHROdGzq8XnmGDq9XnqHD65Vn6PB65Rk6vF55gk6ya7fedOSV7+jIK9/RkVe+o2Oic0NHXvmOjrzyHR155Ts68sp3dOSVb+gku5DqTUde+Y6OvPIdHXnlOzomOjd05JXv6Mgr39GRV76jI698R0de+YZOsmuv3nTkle/oyCvf0ZFXvqNjonNDR175jo688h0deeU7OvLKN3SC32189M8uj+MxXpo//kxntI+vHu3d3+sFv664QnFsX7JCsdEpju0fViiO7Ql+qPj5uR+fX36Ob7776B9P9jHePtlju4L9fGL7gv18Ym/RtvMJfkVvP59UznIBn1Q+dAGfVK71Z3x+kvLef+oXliaWbixTOe3NLIk9vDtLYr/vzpI4G7izJM4R3iyDX7DDYkmcT9xZEmcZd5bKPX4sTSzdWCr3+LFU7vFjqdzjx1K5x4+lco8by+AX7LBYKvf4sVTu8WOp3OPH0sTSjaVyjx9L5R4/lso9fiyVe/xYKve4sQx+hxGLpXKPH0vlHj+Wyj1+LE0s3Vgq9/ixlCeaYjlxb68Ev7eHxVLvnjmW3/8lbXno3ePHUu8eP5baufmx1M7Nj6V2bn4s5S+nWNaj/vraep1vWAa/UYfFUjs3P5baufmxVO7xY2li6cZSucePpXKPH0vlHj+Wyj1+LJV73FgGvzeIxVK5x48lc+75ySe5zs/vfL1+50d9pcmcfPxpmmg60mROP/40mfOPP03mBORPkzkD+dNkTkE/olk+P8hVjzc0g9+SRKPJnIT8aSoLedJUFvKkaaLpSFNZyJOmstC/oNnf0VQW8qSpLORJU1lokub4SpbjXbIMfisUjaaykCdNZSFPmspCnjRNNB1pKgt50lQW+p+bv9Utwa+p7uejvHLPRwnklk9Rprjno5Rwz0e+/55Prmu/31+KK8mu/c4oznXtd0ZxKtc6pTiVD51SnMpZTilO5RVnFOe6mjulOJWfm1KcyqFNKabzXLkuyk4ppvNcua6zTimm81y5Lp1OKabzXLmuhk4ppvNcuS5wTimm81y5rllOKabzXLkuQ04ppvNcua4sTimm81y5LhZOKabzXLmu/00ppvNcuS7pTSmm81y5rtJNKabzXLkuvE0ppvNcua6lTSmm81y5Lo9NKabzXLmueE0ppvNcg85zDTrPNeg8V647bxOKa65rbFOK2TxXfbB5rprrLt6UYqNTzOa5aq5LcFOK2TxXzXVVbUoxnefKdaFsSjGd58p17WtKMZ3nynU5a0oxnefKdYVqSjGd58p10WlKMZ3nynUdaUoxnefKdWloSjGd58p1sWdKMZ3nynX5ZkoxnefKdUFmSjGd58p1iWVKMZ3nynXRZEoxnefKdRlkSjGd58p1YWNKMZ3nynWpYkoxnefKdfFhSjGd58p1OWFKMZ3nynWBYEoxnefK1eQ/pZjOc+Vq259STOe5cjXiTymm81y5WuunFNN5Lroe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66GuujvIf3r/q4/OTnN98bbGPz1HseseS+ZahN0vmu4fOLHM1tm9myXxP0Zsl8+1Fb5bMF9e9WZpYurFkvrbuzZL51ro3S+UeP5bKPXMs+8c3LqO8Y6nc48Yy19WEzSyVe/xYKvfMsWxfLOs7lso9fixNLN1YKvf4sVTu8WOp3OPHUrlnjmX5+Dlkqe9+Dpnrvshelrkul2xmqdzjx1K5x4+lco8fSxNLN5bKPX4slXv8WCr3+LFU7vFjqdzjxbLluh60maVyjx9L5R4/lso9fixNLN1YKvf4sVTu8WOp3OPHUrnHj6VyjxvLXBe8NrNU7vFjqdzjx1K5x4+liaUbS+UeP5bKPX4slXv8WCr3+LFU7nFjmeuK3maWyj1+LJV7/seNpXKPH0sTSzeWyj1+LJV7/FgG95ft+oLTXxoF3jTYtQ/yo71pH2jR7/otUBzcqy1QHNxRLVAc3PcsUGyZFP/sLTDR1NmiXwHczie4i9jOJ/hGdDuf4FvO7XxSOUt/PtFvHW7nk8q1rkt57z/1C8tUfngzy1ROezNLE0s3lsR+350lcTZwZ0mcI9xZEmcOd5bE+cSbZfQbolAslXv8WCr3+LFU7vFjaWLpxlK5x4+lco8fS+UeP5bKPX4slXvcWEa/4wvFUrnHj6Vyjx9L5R4/liaWbiyVe/xYKvf4sVTu8WOp3OPHUrnHjWX0C+FQLJV7/Fgq9/ixVO7xY2li6cZSucePpXKPH0vlHjeW0a8HR2E5cW29Rb8eDMVS7545lhPNA9GvtEKx1LvHj6V2bn4stXNzYxn9SisUS/nLKZb1qL++tl7nO5byl34stXPzY2li6cZSucePpXKPH0vlHj+Wyj1+LJV7vFj26FdaoVgq9/ixVO7xY6nc48fSiFn+4JPYZR+LIrvKy6boUV9pMicff5rM2cefJnP68afJnH/8aTInIHea0S+2gtFkTkE/otkfnzT7eEeTOQf502ROQv40TTQdaSoLedJUFvKkqSzkSVNZ6Oc0R31HU1nIkWb0K65gNJWF5mja8Zks7XyXLKNfcgWjqSzkSdNE05GmspAnTWUhT5rKQp40lYUmaZbrk2Y939FUFnKkmeuW8XaaykKeNJWFPGkqC3nSNNF0pKks9D83bSad+dL0FB/llXs+SiD3fJQpbvkwX5qe4iPff88nlZOfuD3ec914nlJsdIpTudYpxal86JTiVM5ySnEqrzilOJX7m1Gc69rulOJUDm1KMZ3nynVfdkqx0Smm81y5LqpOKabzXLmuk04ppvNcuS59Timm81y5rmZOKabzXLkuUE4ppvNcua45Timm81y5LiNOKabzXLmuDE4ppvNcuS72TSmm81y5rt9NKabzXLkuyU0ppvNcjc5zNTrP1ek8V65bg1OK6TxXp/Nc3egU03muXBcUpxTTea5c1winFNN5rlyX/aYU03muXFfyphTTea5cF+emFNN5rlzX26YU03muXJfQphSzea6R66rYlGI2zzVyXeiaUszmucbD6BSzea6R62rUlGI2zzVyXV+aUkznuXJdMZpSTOe5cl0DmlJM57lyXdWZUkznuXJdp5lSTOe5cl15mVJM57lyXUuZUkznuXJdHZlSTOe5cl3vmFJM57lyXcGYUkznuXJdk5hSTOe5cl1lmFJM57lyXTeYUkznuXJdCZhSTOe5cnXzTymm81y5+vOnFNN5rlwd91OK6TwXXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQj1wd5c/P/fXl5/jmu7c+Pj/J+c3XFjt/fW2x6w3LXO3nm1mm8hCbWaZyJ5tZpvI9m1maWLqxTOXVNrNM5QI3s0y109vMMtW2cDNL5R4nlv2R6wLBQpb94xuXUd6xVO7xY6nc48dSucePpYnlFMv2xbK+Y6nc48dSucePpXKPH0vlHj+Wyj1uLHNdAVnIsnz8HLLU9o6lco8fS+UeP5bKPX4sTSzdWCr3+LFU7vFjqdzjx1K5x4+lco8by1yXeDazVO7xY6nc48dSucePpYmlG0vl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8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vE77H64Tv8Trhe7xO+B6v84H+Tj7he7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Lv8brge7wu+B6vC77H63qgv5Mv+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8TL4Hi+D7/Ey+B4vg+/xsgf6O9nge7wMvsfL4Hu8DL7Hy+B7vAy+x8vge7wMvsfL4Hu8DL7Hy+B7vAy+x8vge7wM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fpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keuinSh3l5z4/vnj//Tv/6K3UUG7SW+g5fR7PLz73d3oLPaVNegs9o016Cz2hTXoLZWKT3kKJ2KS30vvXoLdSW7VJb6EsbNJbKAmb9Ir5q0ot1Sa9w/qrFw3DeqYXDbl90NoeWfvczuNTMl8fH+O+VHr37y63D/LXm9sHuetN3iDtrze3D/LXm9sH+evN7YP89TYxvbl9kL/e3J7JX6+Yv0reGO2vV8xfJW+L9tcr5q+SN0X76xXzV8lbov31ivmr5A3R/nrF/FXydmh/vVr+ak7eDO2vV8tfzclbof31avmr+dbE9Gr5qzl5G7S/Xi1/NSdvgvbXK+avkrdA++sV81fJG6D99Yr5q+Ttz/56xfxV8uZnf71i/ip567O/XjF/lbzx2V+vmL9K3vbsr1fMXyVvevbXK+avkrc8++sV81fJG5799Yr5q+Ttzv56xfxV8mZnf71i/ip5q7O/XjF/lbzR2V+vmL9K3ubsr1fMXyVvcvbXK+avkrc4++sV81fJG5z99Yr5q+Ttzf56xfxV8uZmf71i/ip5a7O/XjF/lbyx2V+vmL9K3tbsr1fMXyVvavbXK+avVjF/lbyH211v8h5uf71i/moT81fJe9b99TYxvWL+KnnPur9eMX+VvGfdX6+Yv0res+6vV8xfJe9Z99cr5q+S96z76xXzV8k72f31ivkrsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRHrb1/E+tsXsf72Ray/fbk1Mb1a/moR629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629f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4dr6nv168FAseffYWBqaB7JfaR2KJe8eP5bs3PxYsnNzY5n9SutQLPGXJpbbtP362m2Z37HEX/qxZOfmx7LB0o0lucePJbnHjyW5x48lucePJbnHi+WR/UrrUCzJPX4syT1+LMk9fiybMMsvPklb2mNR1Jb1ZVN0215pKicff5rK2cefpnL68aepnH/8aSonIHea2S+2DkZTOQV9RfO4PWke5zuayjnIn6ZyEvKn2aDpSJMs5EmTLORJkyzkSZMs9D3Nc3tHkyzkSDP7FdfBaJKFbDTb9EyWbX6XLLNfch2MJlnIk2aDpiNNspAnTbKQJ02ykCdNspCR5ro8aW7zO5pkIUeatW4Zh9MkC3nSJAt50iQLedJs0HSkSRb6zxdtJofypWkTH/LKNR8SyDUfMsUlH+VL0yY++P5rPqWcvOH2+FHrxrNJcZNTXMq1mhSX8qEmxaWcpUlxKa9oUlzK/VkU17q2a1JcyqGZFMt5rlr3ZU2Km5xiOc9V66KqSbGc56p1ndSkWM5z1br0aVIs57lqXc00KZbzXLUuUJoUy3muWtccTYrlPFety4gmxXKeq9aVQZNiOc9V62KfSbGc56p1/c6kWM5z1bokZ1Is57l2Oc+1y3muQ85z1bo1aFIs57kOOc91NDnFcp6r1gVFk2I5z1XrGqFJsZznqnXZz6RYznPVupJnUiznuWpdnDMplvNcta63mRTLea5al9BMitU811nrqphJsZrnOmtd6DIpVvNc563JKVbzXGetq1EmxWqe66x1fcmkWM5z1bpiZFIs57lqXQMyKZbzXLWu6pgUy3muWtdpTIrlPFetKy8mxXKeq9a1FJNiOc9V6+qISbGc56p1vcOkWM5z1bqCYVIs57lqXZMwKZbzXLWuMpgUy3muWtcNTIrlPFetKwEmxXKeq1Y3v0mxnOeq1Z9vUiznuWp13JsUy3kuuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76s1ZH+f1z/3z5fH747vtxPj/J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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"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","debug_symbols":"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1//eWvQ6S+3rLHWss9S5zFLzy0xLx0t9mWnp6LuaLb/MtHS81JeZlo6Xai+y1MNvybb8MtPS0VcwW36Zael4qa8yLR1+XaflV5mWPrHUV5mWjpdaXmVa+sRSX2Va+sRSX2Va+sRSX2VaOvxuVXPYIvZplvoq09Inlvoq09Lht9paeZlp6fC7PuVlpqXjpb7MtHS4VHuVaen4Q0d7lWnpE0t9lWnpE0t9lWnpE0u1dZb6KtPSJ5b6KtPSJ5b6KtPS8VIdNvtK6TZoWxrbQfm5bLf6c0m7udJhOyz3krJeSUWvJNMrqUaXZPdvtv3379spqemV1PVKGnolTbmSWnj3LuWjpN0TSkt6JWW9kopeSaZXUtUrqemV1PVKGnolTbmSenj3zu1eUtm9JN6TXklZr6SiV5LplVT1Smp6JXW9koZeSVOupKHXvYde9x563Xvode+h172HXvceet176HXvode9h173nnrde+p176nXvade95563Xvqde+p172nXveeet17ynXvvsl1777Jde++yXXvvsl1775F96X0UVLKY7ekrlfS0CtpypWUNr2SovtSqv1eUsu7JWW9kopeSaZXUtUrKbx7fzy6KLWyW1LXK2nolTTlSsqbXklJr6SsV1LRK8n0Sqp6JYV37/vXct/+2XdL6nolDb2SplxJZdMrKemVlPVKKnolmV5JVa8kve5d9Lp30eveRa97m173Nr3ubXrd2/S6t+l1b9Pr3qbXvU2ve5te9za97l31unfV695Vr3tXve5d9bp31eveVa97V73uXfW6d9Xr3h73x5WPko43dKi323brN883zzndCypqBZlaQVWtoKZWUA8u6P4Mrra13YKGWkFTrCCP++F8C0pqBWW1gqI79bg97bmOsVuQqRVU1QpqagV1tYKGWkFTrKCxqRWU1ArKagWpdeqh1qmHWqceap16qHXqodaph1qnnmqdeqp16qnWqadap55qnXqqdeqp1qmnWqeeap16inXqsYl16rGJdeqxiXXqsYl16rGJdeqxiXXqsYl16rGJdeqxiXXqsal16qTWqZNOp377T//xu3/7w+/+8Y+///PbT/z0P/77j//0lz/86cf3//iX//zX//lf3l77Xw=="},{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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mgKgaRqApqkAmqYDaJoSoGlagKapAZqmB2iaIqBpmoCmqQKapgtomjKgadqApqkDmqYPaJpCoGkagaapBJqmE2iaUqBpWoGmqQWaphdommKgaZqBpqkGmqYbaJpyoGnagaapB5qmH2iagqBpGoKmqQiapiNompKgaVqCpqkJmqYnaJqioGmagqapCpqmK2iasqBp2oKmqQuapi9omsKgaRqDpqkMmqYzaJrSoGlag6apDZqmN2ia4qBpmoOmqQ6apjvomu6ga7qDrukOuqY76GNqlknNMqVZpjXLLM0yGgpouoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOhqY7GJruYGi6g6HpDsaYmmVSs0xplmnNMpq/ZEzTHQxNdzA03cHQdAdD0x0MTXcwNN3B0HQHQ9MdDE13MDTdwdB0B0PTHQxNdzA03cHQdAdD0x0MTXcwNN3B0HQHQ9MdDE13MDTdwdB0B0PTHQxNdzA03cHQdAdD0x0M0V87rOkOhqY7GJruYGi6g6HpDoamOxia7mBouoOh6Q6GpjsYmu5gaLqDoekOhqY7GJruYGi6g6HpDoamOxia7mBouoOh6Q6GpjsYmu5gaLqDoekOhqY7GJruYGi6g6HpDoamOxiP6A6+fBezT0dHR70eHXnj6Fz+6eBc63qsu10iPaJn+OhIxovkvEjBizR5kZIXqXiRmhdp8SLx6L149F48ei8evReP3otH78Wj9+LRe/HovXj0Xjx6bx69N4/em0fvzaP35tF78+i9efTePHpvHr03jt5z4Og9B47ec+DoPQeO3nPg6D0Hjt5z4Og9B47ec+DoPQeP3sajt/HobTx6G4/e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"}],"outputs":{"globals":{"notes":[{"fields":[{"kind":"integer","sign":false,"value":"00000000000000000000000000000000000000000000000000000000906cb9c3"},{"kind":"string","value":"EcdsaPublicKeyNote"}],"kind":"tuple"}],"storage":[{"fields":[{"name":"public_key","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"EcdsaAccount::entrypoint_parameters"}}],"kind":"struct","path":"EcdsaAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"EcdsaAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"EcdsaAccount::verify_private_authwit_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"signing_pub_key_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"signing_pub_key_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}}],"kind":"struct","path":"EcdsaAccount::constructor_parameters"}}],"kind":"struct","path":"EcdsaAccount::constructor_abi"}]}},"file_map":{"100":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash\n};\n\nuse dep::std::aes128::aes128_encrypt;\nuse dep::std::println;\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogOutgoingBody {\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint,\n}\n\nimpl EncryptedLogOutgoingBody {\n pub fn new(\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint\n ) -> Self {\n Self { eph_sk, recipient, recipient_ivpk_app }\n }\n\n pub fn compute_ciphertext(self, ovsk_app: GrumpkinPrivateKey, eph_pk: GrumpkinPoint) -> [u8; 176] {\n // Again, we could compute `eph_pk` here, but we keep the interface more similar\n // and also make it easier to optimise it later as we just pass it along\n\n let mut buffer: [u8; 160] = [0; 160];\n\n let serialized_eph_sk: [Field; 2] = self.eph_sk.serialize();\n let serialized_eph_sk_high = serialized_eph_sk[0].to_be_bytes(32);\n let serialized_eph_sk_low = serialized_eph_sk[1].to_be_bytes(32);\n\n let address_bytes = self.recipient.to_field().to_be_bytes(32);\n let serialized_recipient_ivpk_app = self.recipient_ivpk_app.serialize();\n let serialized_recipient_ivpk_app_x = serialized_recipient_ivpk_app[0].to_be_bytes(32);\n let serialized_recipient_ivpk_app_y = serialized_recipient_ivpk_app[1].to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = serialized_eph_sk_high[i];\n buffer[i + 32] = serialized_eph_sk_low[i];\n buffer[i + 64] = address_bytes[i];\n buffer[i + 96] = serialized_recipient_ivpk_app_x[i];\n buffer[i + 128] = serialized_recipient_ivpk_app_y[i];\n }\n\n // We compute the symmetric key using poseidon.\n let full_key: [u8; 32] = poseidon2_hash(\n [\n ovsk_app.high, ovsk_app.low, eph_pk.x, eph_pk.y,\n GENERATOR_INDEX__SYMMETRIC_KEY as Field\n ]\n ).to_be_bytes(32).as_array();\n\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(buffer, iv, sym_key).as_array()\n }\n}\n\nmod test {\n use crate::encrypted_logs::outgoing_body::EncryptedLogOutgoingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash\n };\n\n use crate::context::PrivateContext;\n\n #[test]\n fn test_encrypted_log_outgoing_body() {\n let eph_sk = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb,\n 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe\n );\n let recipient_ivsk_app = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31,\n 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022\n );\n let sender_ovsk_app = GrumpkinPrivateKey::new(\n 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b,\n 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e\n );\n\n let eph_pk = eph_sk.derive_public_key();\n let recipient_ivpk_app = recipient_ivsk_app.derive_public_key();\n\n let recipient = AztecAddress::from_field(0xdeadbeef);\n\n let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app);\n\n let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk);\n\n let expected_outgoing_body_ciphertext = [\n 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 122, 191, 158, 69, 35, 255, 215, 171, 196, 45, 91, 184, 83, 80, 238, 201, 1, 233, 235, 159, 171, 130, 158, 64, 176, 165, 132, 30, 84, 81, 71, 195, 145, 47, 82, 247, 210, 192, 23, 4, 220, 90, 56, 109, 46, 105, 79, 251, 165, 141, 185, 233, 191, 118, 219, 153, 191, 162, 99, 238, 241, 249, 9, 74, 210, 241, 54, 28, 126, 226, 85, 235, 174, 75, 239, 207, 100, 184, 248, 194\n ];\n\n for i in 0..expected_outgoing_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_outgoing_body_ciphertext[i]);\n }\n assert_eq(expected_outgoing_body_ciphertext.len(), ciphertext.len());\n }\n}\n"},"101":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nuse dep::std::aes128::aes128_encrypt;\n\nstruct EncryptedLogHeader {\n address: AztecAddress,\n}\n\nimpl EncryptedLogHeader {\n fn new(address: AztecAddress) -> Self {\n EncryptedLogHeader { address }\n }\n\n fn compute_ciphertext(self, secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 48] {\n let full_key = point_to_symmetric_key(secret, point);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n\n let input: [u8; 32] = self.address.to_field().to_be_bytes(32).as_array();\n aes128_encrypt(input, iv, sym_key).as_array()\n }\n}\n\n#[test]\nfn test_encrypted_log_header() {\n let address = AztecAddress::from_field(0xdeadbeef);\n let header = EncryptedLogHeader::new(address);\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let ciphertext = header.compute_ciphertext(secret, point);\n\n let expected_header_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 23, 131, 32, 226, 26, 176, 43, 39, 239, 177, 177, 192, 85, 216, 17, 15, 18, 187, 35, 225, 135, 192, 63, 88, 29, 173, 232, 46, 72, 82, 187, 139\n ];\n\n assert_eq(ciphertext, expected_header_ciphertext);\n}\n"},"102":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr","source":"use crate::note::note_interface::NoteInterface;\nuse crate::event::event_interface::EventInterface;\nuse dep::protocol_types::{grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse dep::std::aes128::aes128_encrypt;\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogIncomingBody {\n plaintext: [u8; M]\n}\n\nimpl EncryptedLogIncomingBody {\n pub fn from_note(note: T, storage_slot: Field) -> Self where T: NoteInterface {\n let mut plaintext = note.to_be_bytes(storage_slot);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface {\n let mut plaintext = event.private_to_be_bytes(randomness);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn compute_ciphertext(self, eph_sk: GrumpkinPrivateKey, ivpk_app: GrumpkinPoint) -> [u8] {\n let full_key = point_to_symmetric_key(eph_sk, ivpk_app);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(self.plaintext, iv, sym_key)\n }\n}\n\nmod test {\n use crate::encrypted_logs::incoming_body::EncryptedLogIncomingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, traits::Serialize,\n abis::event_selector::EventSelector\n };\n\n use crate::{\n note::{note_header::NoteHeader, note_interface::NoteInterface},\n event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand,\n context::PrivateContext\n };\n\n struct AddressNote {\n address: AztecAddress,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n }\n\n global ADDRESS_NOTE_LEN: Field = 3;\n global ADDRESS_NOTE_BYTES_LEN = 32 * 3 + 64;\n\n impl NoteInterface for AddressNote {\n fn compute_note_content_hash(self) -> Field {1}\n\n fn get_note_type_id() -> Field {\n 1\n }\n\n fn get_header(self) -> NoteHeader { self.header}\n\n fn set_header(&mut self, header: NoteHeader) {self.header = header; }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n (1, 1)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {(1,1)}\n\n fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]}\n\n fn deserialize_content(fields: [Field; ADDRESS_NOTE_LEN]) -> Self {\n AddressNote { address: AztecAddress::from_field(fields[0]), owner: AztecAddress::from_field(fields[1]), randomness: fields[2], header: NoteHeader::empty() }\n }\n\n fn to_be_bytes(self, storage_slot: Field) -> [u8; ADDRESS_NOTE_BYTES_LEN] {\n let serialized_note = self.serialize_content();\n\n let mut buffer: [u8; ADDRESS_NOTE_BYTES_LEN] = [0; ADDRESS_NOTE_BYTES_LEN];\n\n let storage_slot_bytes = storage_slot.to_be_bytes(32);\n let note_type_id_bytes = AddressNote::get_note_type_id().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = storage_slot_bytes[i];\n buffer[32 + i] = note_type_id_bytes[i];\n }\n\n for i in 0..serialized_note.len() {\n let bytes = serialized_note[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n buffer\n }\n }\n\n impl AddressNote {\n pub fn new(address: AztecAddress, owner: AztecAddress, randomness: Field) -> Self {\n AddressNote { address, owner, randomness, header: NoteHeader::empty() }\n }\n }\n\n #[test]\n fn test_encrypted_note_log_incoming_body() {\n let note = AddressNote::new(\n AztecAddress::from_field(0x1),\n AztecAddress::from_field(0x2),\n 3\n );\n\n let storage_slot = 2;\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let body = EncryptedLogIncomingBody::from_note(note, storage_slot);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_note_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100\n ];\n\n assert_eq(expected_note_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_note_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_note_body_ciphertext[i]);\n }\n }\n\n struct TestEvent {\n value0: Field,\n value1: Field,\n value2: Field,\n }\n\n impl Serialize<3> for TestEvent {\n fn serialize(self) -> [Field; 3] {\n [self.value0, self.value1, self.value2]\n }\n }\n\n global TEST_EVENT_LEN: Field = 3;\n global TEST_EVENT_BYTES_LEN = 32 * 3 + 64;\n global TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS = 32 * 3 + 32;\n\n impl EventInterface for TestEvent {\n fn get_event_type_id() -> EventSelector {\n EventSelector::from_signature(\"TestEvent(Field,Field,Field)\")\n }\n\n fn private_to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN] = [0; TEST_EVENT_BYTES_LEN];\n\n let randomness_bytes = randomness.to_be_bytes(32);\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = randomness_bytes[i];\n buffer[32 + i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn to_be_bytes(self) -> [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] = [0; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS];\n\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[32 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n }\n\n #[test]\n fn test_encrypted_log_event_incoming_body() {\n let test_event = TestEvent { value0: 1, value1: 2, value2: 3 };\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let randomness = 2;\n\n let body = EncryptedLogIncomingBody::from_event(test_event, randomness);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_event_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160\n ];\n\n assert_eq(expected_event_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_event_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_event_body_ciphertext[i]);\n }\n }\n}\n"},"107":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/utils.nr","source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n constants::GENERATOR_INDEX__INNER_NOTE_HASH,\n hash::{\n pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash,\n compute_siloed_nullifier as compute_siloed_nullifier_from_preimage\n},\n utils::arr_copy_slice\n};\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n pedersen_hash(\n [header.storage_slot, note_hash],\n GENERATOR_INDEX__INNER_NOTE_HASH\n )\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let (_, inner_nullifier) = note_with_header.compute_note_hash_and_nullifier(context);\n\n compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier)\n}\n\nfn compute_note_hash_for_read_request_from_innter_and_nonce(\n inner_note_hash: Field,\n nonce: Field\n) -> Field {\n // TODO(#1386): This if-else can be nuked once we have nonces injected from public\n if (nonce == 0) {\n // If nonce is zero, that means we are reading a public note.\n inner_note_hash\n } else {\n compute_unique_note_hash(nonce, inner_note_hash)\n }\n}\n\npub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface {\n let inner_note_hash = compute_inner_note_hash(note);\n let nonce = note.get_header().nonce;\n\n compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n if (header.note_hash_counter != 0) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n inner_note_hash\n } else {\n // If a note is not transient, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the siloed_note_hash which has already been hashed with\n // nonce and then contract address. This hash will match the existing leaf in the note hash\n // tree, so the kernel can just perform a membership check directly on this hash/leaf.\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce);\n compute_siloed_note_hash(header.contract_address, unique_note_hash)\n // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is\n // \"siloed\" by contract address. When a note hash is computed solely for the purpose of\n // nullification, it is not strictly necessary to silo the note hash before computing\n // its nullifier. In other words, it is NOT NECESSARY for protocol security that a nullifier\n // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are\n // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be\n // used for nullifier computation, and this achieves the (arguably unnecessary) property that\n // nullifiers are computed from a note hash's fully-computed note hash tree leaf.\n }\n}\n\npub fn compute_note_hash_and_optionally_a_nullifier(\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n compute_nullifier: bool,\n serialized_note: [Field; S]\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n note.set_header(note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, note_header.nonce);\n let siloed_note_hash = compute_siloed_note_hash(note_header.contract_address, unique_note_hash);\n\n let inner_nullifier = if compute_nullifier {\n let (_, nullifier) = note.compute_note_hash_and_nullifier_without_context();\n nullifier\n } else {\n 0\n };\n // docs:start:compute_note_hash_and_optionally_a_nullifier_returns\n [inner_note_hash, unique_note_hash, siloed_note_hash, inner_nullifier]\n // docs:end:compute_note_hash_and_optionally_a_nullifier_returns\n}\n"},"108":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr","source":"use dep::protocol_types::grumpkin_point::GrumpkinPoint;\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note\n) -> NoteEmission where Note: NoteInterface {\n let contract_address = (*context).this_address();\n let note_hash_counter = context.side_effect_counter;\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n let serialized_note = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash,\n note_hash_counter\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n NoteEmission::new(*note)\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(\n context: &mut PrivateContext,\n note: Note\n) where Note: NoteInterface {\n let (note_hash, nullifier) = note.compute_note_hash_and_nullifier(context);\n\n let note_hash_counter = note.get_header().note_hash_counter;\n let note_hash_for_consumption = if (note_hash_counter == 0) {\n // Counter is zero, so we're nullifying a non-transient note and we don't populate the note_hash with real\n // value (if we did so the `notifyNullifiedNote` oracle would throw).\n 0\n } else {\n // A non-zero note hash counter implies that we're nullifying a transient note (i.e. one that has not yet been\n // persisted in the trees and is instead in the pending new note hashes array). In such a case we populate its\n // hash with real value to inform the kernel which note we're nullifyng so that it can find it and squash both\n // the note and the nullifier.\n note_hash\n };\n\n let nullifier_counter = context.side_effect_counter;\n assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0);\n\n context.push_new_nullifier(nullifier, note_hash_for_consumption)\n}\n"},"109":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_emission.nr","source":"/**\n * A note emission struct containing the information required for emitting a note.\n * The exact `emit` logic is passed in by the application code\n */\nstruct NoteEmission {\n note: Note\n}\n\nimpl NoteEmission {\n pub fn new(note: Note) -> Self {\n Self { note }\n }\n\n pub fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n\n pub fn discard(self) {}\n}\n\n/**\n * A struct wrapping note emission in `Option`.\n * This is the struct provided to application codes, which can be used to emit\n * only when a note was actually inserted.\n * It is fairly common to have cases where a function conditionally inserts,\n * and this allows us to keep the same API for emission in both cases (e.g. inserting \n * a change note in a token's transfer function only when there is \"change\" left).\n */\nstruct OuterNoteEmission {\n emission: Option>,\n}\n\nimpl OuterNoteEmission {\n pub fn new(emission: Option>) -> Self {\n Self { emission }\n }\n\n pub fn emit(self, _emit: fn[Env](NoteEmission) -> ()) {\n if self.emission.is_some() {\n _emit(self.emission.unwrap());\n }\n }\n\n pub fn discard(self) {}\n}\n"},"112":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_getter.nr","source":"use dep::protocol_types::{constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTES_ORACLE_RETURN_LENGTH}};\nuse crate::context::PrivateContext;\nuse crate::note::{\n constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH},\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_request\n};\nuse crate::oracle;\n\nmod test;\n\nfn extract_property_value_from_selector(\n serialized_note: [Field; N],\n selector: PropertySelector\n) -> Field {\n // Selectors use PropertySelectors in order to locate note properties inside the serialized note. \n // This allows easier packing and custom (de)serialization schemas. A note property is located\n // inside the serialized note using the index inside the array, a byte offset and a length.\n let value = serialized_note[selector.index].to_be_bytes(32);\n let offset = selector.offset;\n let length = selector.length;\n let mut value_field = 0 as Field;\n let mut acc: Field = 1;\n for i in 0..32 {\n if i < length {\n value_field += value[31 + offset - i] as Field * acc;\n acc = acc * 256;\n }\n }\n value_field\n}\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note: Note\n) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address), \"Mismatch note header contract address.\");\n assert(header.storage_slot == storage_slot, \"Mismatch note header storage slot.\");\n}\n\nfn check_note_fields(serialized_note: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n let value_field = extract_property_value_from_selector(serialized_note, select.property_selector);\n\n // Values are computed ahead of time because circuits evaluate all branches\n let is_equal = value_field == select.value.to_field();\n let is_lt = value_field.lt(select.value.to_field());\n\n if (select.comparator == Comparator.EQ) {\n assert(is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(is_lt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(is_lt | is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!is_lt & !is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!is_lt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let field_0 = extract_property_value_from_selector(fields_0, sort.property_selector);\n let field_1 = extract_property_value_from_selector(fields_1, sort.property_selector);\n let eq = field_0 == field_1;\n let lt = field_0.lt(field_1);\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n\n context.push_note_hash_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n\n constrain_get_notes_internal(context, storage_slot, opt_notes, options)\n}\n\nfn constrain_get_notes_internal(\n context: &mut PrivateContext,\n storage_slot: Field,\n opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let mut returned_notes = BoundedVec::new();\n\n // The filter is applied first to avoid pushing note read requests for notes we're not interested in. Note that\n // while the filter function can technically mutate the contents of the notes (as opposed to simply removing some),\n // the private kernel will later validate that these note actually exist, so transformations would cause for that\n // check to fail.\n let filter_fn = options.filter;\n let filter_args = options.filter_args;\n let filtered_notes = filter_fn(opt_notes, filter_args);\n\n let mut prev_fields = [0; N];\n for i in 0..filtered_notes.len() {\n let opt_note = filtered_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_note_hash_read_request(note_hash_for_read_request);\n\n // The below code is used to collapse a sparse array into one where the values are guaranteed to be at the \n // front of the array. This is highly useful because the caller knows that the returned array won't have\n // more than option.limits notes, and can therefore loop over this limit value instead of the entire array,\n // resulting in a smaller circuit and faster proving times.\n // We write at returned_notes[num_notes] because num_notes is only advanced when we have a value in \n // filtered_notes.\n returned_notes.push(note);\n };\n }\n\n assert(returned_notes.len() <= options.limit, \"Got more notes than limit.\");\n assert(returned_notes.len() != 0, \"Cannot return zero notes\");\n\n returned_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n // This function simply performs some transformations from NoteGetterOptions into the types required by the oracle.\n\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> BoundedVec where Note: NoteInterface {\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n let notes_array = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let mut notes = BoundedVec::new();\n for i in 0..notes_array.len() {\n if notes_array[i].is_some() {\n notes.push(notes_array[i].unwrap_unchecked());\n }\n }\n\n notes\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [u8; N], [u8; N], [Field; N], [u8; N], [u8; N], [u8; N], [u8; N], [u8; N]) {\n let mut num_selects = 0;\n let mut select_by_indexes = [0; N];\n let mut select_by_offsets = [0; N];\n let mut select_by_lengths = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by_indexes[num_selects] = select.unwrap_unchecked().property_selector.index;\n select_by_offsets[num_selects] = select.unwrap_unchecked().property_selector.offset;\n select_by_lengths[num_selects] = select.unwrap_unchecked().property_selector.length;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by_indexes = [0; N];\n let mut sort_by_offsets = [0; N];\n let mut sort_by_lengths = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by_indexes[i] = sort.unwrap_unchecked().property_selector.index;\n sort_by_offsets[i] = sort.unwrap_unchecked().property_selector.offset;\n sort_by_lengths[i] = sort.unwrap_unchecked().property_selector.length;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (\n num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order\n )\n}\n"},"113":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_header.nr","source":"use dep::protocol_types::address::AztecAddress;\nuse dep::protocol_types::traits::{Empty, Eq, Serialize};\n\nstruct NoteHeader {\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)\n // Check the nonce to see whether a note is transient or not.\n note_hash_counter: u32, // a note_hash_counter of 0 means non-transient\n}\n\nimpl Empty for NoteHeader {\n fn empty() -> Self {\n NoteHeader { contract_address: AztecAddress::zero(), nonce: 0, storage_slot: 0, note_hash_counter: 0 }\n }\n}\n\nimpl Eq for NoteHeader {\n fn eq(self, other: Self) -> bool {\n (self.contract_address == other.contract_address) & \n (self.nonce == other.nonce) & \n (self.storage_slot == other.storage_slot)& \n (self.note_hash_counter == other.note_hash_counter)\n }\n}\n\nimpl NoteHeader {\n pub fn new(contract_address: AztecAddress, nonce: Field, storage_slot: Field) -> Self {\n NoteHeader { contract_address, nonce, storage_slot, note_hash_counter: 0 }\n }\n}\n\nimpl Serialize<4> for NoteHeader {\n fn serialize(self) -> [Field; 4] {\n [self.contract_address.to_field(), self.nonce, self.storage_slot, self.note_hash_counter as Field]\n }\n}\n"},"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"118":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/initializer.nr","source":"use dep::protocol_types::{\n address::AztecAddress, hash::{compute_siloed_nullifier, pedersen_hash},\n constants::GENERATOR_INDEX__CONSTRUCTOR, abis::function_selector::FunctionSelector\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext}, oracle::get_contract_instance::get_contract_instance,\n oracle::get_contract_instance::get_contract_instance_avm\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn assert_is_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_contract_initialization_nullifier(context.this_address());\n let header = context.get_header();\n header.prove_nullifier_inclusion(init_nullifier);\n}\n\nfn compute_contract_initialization_nullifier(address: AztecAddress) -> Field {\n compute_siloed_nullifier(\n address,\n compute_unsiloed_contract_initialization_nullifier(address)\n )\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let instance = get_contract_instance_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn compute_initialization_hash(init_selector: FunctionSelector, init_args_hash: Field) -> Field {\n pedersen_hash(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n"},"120":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr","source":"use dep::protocol_types::{\n abis::nullifier_leaf_preimage::{NullifierLeafPreimage, NULLIFIER_LEAF_PREIMAGE_LENGTH},\n constants::NULLIFIER_TREE_HEIGHT, hash::pedersen_hash, utils::arr_copy_slice\n};\n\n// INDEX_LENGTH + NULLIFIER_LEAF_PREIMAGE_LENGTH + NULLIFIER_TREE_HEIGHT\nglobal NULLIFIER_MEMBERSHIP_WITNESS: Field = 24;\n\nstruct NullifierMembershipWitness {\n index: Field,\n leaf_preimage: NullifierLeafPreimage,\n path: [Field; NULLIFIER_TREE_HEIGHT],\n}\n\nimpl NullifierMembershipWitness {\n pub fn deserialize(fields: [Field; NULLIFIER_MEMBERSHIP_WITNESS]) -> Self {\n let leaf_preimage_fields = arr_copy_slice(fields, [0; NULLIFIER_LEAF_PREIMAGE_LENGTH], 1);\n Self {\n index: fields[0],\n leaf_preimage: NullifierLeafPreimage::deserialize(leaf_preimage_fields),\n path: arr_copy_slice(\n fields,\n [0; NULLIFIER_TREE_HEIGHT],\n 1 + NULLIFIER_LEAF_PREIMAGE_LENGTH\n )\n }\n }\n}\n\n#[oracle(getLowNullifierMembershipWitness)]\nunconstrained fn get_low_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_low_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n\n#[oracle(getNullifierMembershipWitness)]\nunconstrained fn get_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"126":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr","source":"use dep::protocol_types::{\n grumpkin_point::GrumpkinPoint,\n abis::validation_requests::{KeyValidationRequest, key_validation_request::KEY_VALIDATION_REQUEST_LENGTH}\n};\n\n#[oracle(getKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field\n) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {}\n\nunconstrained fn get_key_validation_request_internal(npk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n let result = get_key_validation_request_oracle(npk_m_hash, key_index);\n KeyValidationRequest::deserialize(result)\n}\n\npub fn get_key_validation_request(pk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n get_key_validation_request_internal(pk_m_hash, key_index)\n}\n\n"},"130":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/unsafe_rand.nr","source":"#[oracle(getRandomField)]\nunconstrained fn rand_oracle() -> Field {}\n\n// Called `unsafe_rand` because we do not constrain in circuit that we are dealing with an actual random value.\n// Instead we just trust our PXE.\nunconstrained pub fn unsafe_rand() -> Field {\n rand_oracle()\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"133":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/keys.nr","source":"use crate::keys::PublicKeys;\nuse dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {}\n\nunconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] {\n get_public_keys_and_partial_address_oracle(address)\n}\n\nfn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle_wrapper(address);\n\n let keys = PublicKeys {\n npk_m: GrumpkinPoint::new(result[0], result[1]),\n ivpk_m: GrumpkinPoint::new(result[2], result[3]),\n ovpk_m: GrumpkinPoint::new(result[4], result[5]),\n tpk_m: GrumpkinPoint::new(result[6], result[7])\n };\n\n let partial_address = PartialAddress::from_field(result[8]);\n\n (keys, partial_address)\n}\n"},"135":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/notes.nr","source":"use crate::note::{note_header::NoteHeader, note_interface::NoteInterface};\n\nuse dep::protocol_types::{address::AztecAddress, utils::arr_copy_slice};\n\n#[oracle(notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field,\n _counter: u32\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_created_note_oracle(\n storage_slot,\n note_type_id,\n serialized_note,\n inner_note_hash,\n counter\n )\n}\n\n#[oracle(notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field, _counter: u32) -> Field {}\n\nunconstrained pub fn notify_nullified_note(\n nullifier: Field,\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash, counter)\n}\n\n#[oracle(getNotes)]\nunconstrained fn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by_indexes: [u8; N],\n _select_by_offsets: [u8; N],\n _select_by_lengths: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u8; N],\n _sort_by_indexes: [u8; N],\n _sort_by_offsets: [u8; N],\n _sort_by_lengths: [u8; N],\n _sort_order: [u8; N],\n _limit: u32,\n _offset: u32,\n _status: u8,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; N],\n select_by_offsets: [u8; N],\n select_by_lengths: [u8; N],\n select_values: [Field; N],\n select_comparators: [u8; N],\n sort_by_indexes: [u8; N],\n sort_by_offsets: [u8; N],\n sort_by_lengths: [u8; N],\n sort_order: [u8; N],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; M],\n select_by_offsets: [u8; M],\n select_by_lengths: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by_indexes: [u8; M],\n sort_by_offsets: [u8; M],\n sort_by_lengths: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i < num_notes {\n // lengths named as per typescript.\n let return_header_length: u32 = 2; // num_notes & contract_address.\n let extra_preimage_length: u32 = 2; // nonce & note_hash_counter.\n let read_offset: u32 = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let note_hash_counter = fields[read_offset + 1] as u32;\n let header = NoteHeader { contract_address, nonce, storage_slot, note_hash_counter };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n note.set_header(header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n// Only ever use this in private!\n#[oracle(checkNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\n// Only ever use this in private!\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"154":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header};\n\nuse crate::context::PrivateContext;\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange}\n};\n\nstruct SharedMutablePrivateGetter {\n context: &mut PrivateContext,\n // The contract address of the contract we want to read from\n other_contract_address: AztecAddress,\n // The storage slot where the SharedMutable is stored on the other contract\n storage_slot: Field,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numberic value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\n// We have this as a view-only interface to reading Shared Mutables in other contracts.\n// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date\nimpl SharedMutablePrivateGetter {\n pub fn new(\n context: &mut PrivateContext,\n other_contract_address: AztecAddress,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n assert(other_contract_address.to_field() != 0, \"Other contract address cannot be 0\");\n Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] }\n }\n\n pub fn get_value_in_private(self, header: Header) -> T where T: FromField {\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header);\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // If our context has the same header as the one we pass in via the parameter, we are trying to read the \"current\" value\n // and thus need to set the tx max block number below. If the context header is not the same as the one we pass in, this means\n // we are trying to read a historical value and thus have no constraint on the max block number that this transaction can be included in.\n if (self.context.historical_header.global_variables.block_number.eq(header.global_variables.block_number)) {\n self.context.set_tx_max_block_number(block_horizon);\n }\n\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n header: Header\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n self.other_contract_address\n );\n }\n\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"159":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash\n};\n\nuse crate::context::{PrivateContext, UnconstrainedContext};\nuse crate::note::{\n lifecycle::create_note, note_getter::{get_note, view_notes}, note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions, note_emission::NoteEmission\n};\nuse crate::oracle::notes::check_nullifier_exists;\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct PrivateImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:struct\n\nimpl Storage for PrivateImmutable {}\n\nimpl PrivateImmutable {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. \n // e.g. the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n}\n\nimpl PrivateImmutable {\n // docs:start:initialize\n pub fn initialize(\n self,\n note: &mut Note\n ) -> NoteEmission where Note: NoteInterface {\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_new_nullifier(nullifier, 0);\n\n create_note(self.context, self.storage_slot, note)\n }\n // docs:end:initialize\n\n // docs:start:get_note\n pub fn get_note(self) -> Note where Note: NoteInterface {\n let storage_slot = self.storage_slot;\n get_note(self.context, storage_slot)\n }\n // docs:end:get_note\n}\n\nimpl PrivateImmutable {\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // view_note does not actually use the context, but it calls oracles that are only available in private\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let mut options = NoteViewerOptions::new();\n view_notes(self.storage_slot, options.set_limit(1)).get(0)\n }\n // docs:end:view_note\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"187":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr","source":"global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3;\n\nuse crate::{\n abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::compute_siloed_nullifier,\n merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash}\n};\n\nstruct NullifierLeafPreimage {\n nullifier : Field,\n next_nullifier :Field,\n next_index : u32,\n}\n\nimpl Empty for NullifierLeafPreimage {\n fn empty() -> Self {\n Self {\n nullifier : 0,\n next_nullifier : 0,\n next_index : 0,\n }\n }\n}\n\nimpl Hash for NullifierLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash(self.serialize())\n }\n }\n}\n\nimpl LeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl IndexedTreeLeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn get_next_key(self) -> Field {\n self.next_nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl Readable for NullifierLeafPreimage {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n let siloed_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.nullifier, siloed_value, \"Value of the nullifier leaf does not match read request\");\n }\n}\n\nimpl NullifierLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.nullifier == 0) & (self.next_nullifier == 0) & (self.next_index == 0)\n }\n\n pub fn serialize(self) -> [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH] {\n [self.nullifier, self.next_nullifier, self.next_index as Field]\n }\n\n pub fn deserialize(fields: [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH]) -> Self {\n Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u32 }\n }\n}\n\nimpl Eq for NullifierLeafPreimage {\n fn eq(self, other: Self) -> bool {\n (self.nullifier == other.nullifier) &\n (self.next_nullifier == other.next_nullifier) &\n (self.next_index == other.next_index)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NullifierLeafPreimage::empty();\n let serialized = item.serialize();\n let deserialized = NullifierLeafPreimage::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"20":{"path":"std/embedded_curve_ops.nr","source":"use crate::ops::arith::{Add, Sub, Neg};\nuse crate::cmp::Eq;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct EmbeddedCurvePoint {\n x: Field,\n y: Field,\n is_infinite: bool\n}\n\nimpl EmbeddedCurvePoint {\n fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n fn neg(self) -> EmbeddedCurvePoint { \n EmbeddedCurvePoint {\n x: self.x,\n y: -self.y,\n is_infinite: self.is_infinite\n }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\n// Scalar represented as low and high limbs\nstruct EmbeddedCurveScalar {\n lo: Field,\n hi: Field,\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the \n// underlying proof system.\n#[foreign(multi_scalar_mul)]\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N]\n) -> [Field; 3]\n// docs:end:multi_scalar_mul\n{}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(\n scalar_low: Field,\n scalar_high: Field\n) -> [Field; 3]\n// docs:end:fixed_base_scalar_mul\n{\n let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false };\n let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high };\n multi_scalar_mul([g1], [scalar])\n}\n\n// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray\n// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format.\n// docs:start:embedded_curve_add\nfn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint\n) -> EmbeddedCurvePoint\n// docs:end:embedded_curve_add\n{\n let point_array = embedded_curve_add_array_return(point1, point2);\n let x = point_array[0];\n let y = point_array[1];\n EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"220":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr","source":"use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash};\nuse dep::std::cmp::Eq;\n\nglobal GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct GrumpkinPoint {\n x: Field,\n y: Field,\n}\n\nimpl Serialize for GrumpkinPoint {\n fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] {\n [self.x, self.y]\n }\n}\n\nimpl Deserialize for GrumpkinPoint {\n fn deserialize(serialized: [Field; GRUMPKIN_POINT_SERIALIZED_LEN]) -> Self {\n Self {\n x: serialized[0],\n y: serialized[1],\n }\n }\n}\n\nimpl Eq for GrumpkinPoint {\n fn eq(self, point: GrumpkinPoint) -> bool {\n (point.x == self.x) & (point.y == self.y)\n }\n}\n\nimpl Hash for GrumpkinPoint {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl GrumpkinPoint {\n pub fn new(x: Field, y: Field) -> Self {\n Self { x, y }\n }\n\n pub fn zero() -> Self {\n Self { x: 0, y: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.x == 0) & (self.y == 0)\n }\n\n // TODO(David): Would be quite careful here as (0,0) is not a point\n // on the curve. A boolean flag may be the better approach here,\n // would also cost less constraints. It seems like we don't need to \n // group arithmetic either. \n fn assert_is_zero(self) {\n assert(self.x == 0);\n assert(self.y == 0);\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 64] {\n let mut result = [0 as u8; 64];\n let x_bytes = self.x.to_be_bytes(32);\n let y_bytes = self.y.to_be_bytes(32);\n for i in 0..32 {\n result[i] = x_bytes[i];\n result[i + 32] = y_bytes[i];\n }\n result\n }\n}\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"225":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr","source":"use dep::std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul};\nuse crate::{grumpkin_point::GrumpkinPoint, traits::Empty};\n\nglobal GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN: Field = 2;\n\nstruct GrumpkinPrivateKey {\n high: Field,\n low: Field,\n}\n\nimpl Eq for GrumpkinPrivateKey {\n fn eq(self, key: GrumpkinPrivateKey) -> bool {\n (key.high == self.high) & (key.low == self.low)\n }\n}\n\nimpl Empty for GrumpkinPrivateKey {\n fn empty() -> Self {\n Self { high: 0, low: 0 }\n }\n}\n\nimpl GrumpkinPrivateKey {\n pub fn new(high: Field, low: Field) -> Self {\n GrumpkinPrivateKey { high, low }\n }\n\n pub fn zero() -> Self {\n Self { high: 0, low: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.high == 0) & (self.low == 0)\n }\n\n pub fn serialize(self) -> [Field; GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN] {\n [self.high, self.low]\n }\n\n pub fn derive_public_key(self) -> GrumpkinPoint {\n let public_key = fixed_base_scalar_mul(self.low, self.high);\n GrumpkinPoint { x: public_key[0], y: public_key[1] }\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"345":{"path":"/usr/src/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr","source":"mod ecdsa_public_key_note;\n\n// Account contract that uses ECDSA signatures for authentication on the same curve as Ethereum.\n// The signing key is stored in an immutable private note and should be different from the signing key.\ncontract EcdsaAccount {\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, PrivateImmutable};\n use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;\n\n use dep::aztec::protocol_types::abis::call_context::CallContext;\n use dep::std;\n\n use dep::authwit::{\n entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions,\n auth_witness::get_auth_witness\n };\n\n use crate::ecdsa_public_key_note::EcdsaPublicKeyNote;\n\n #[aztec(storage)]\n struct Storage {\n public_key: PrivateImmutable,\n }\n\n // Creates a new account out of an ECDSA public key to use for signature verification\n #[aztec(private)]\n #[aztec(initializer)]\n fn constructor(signing_pub_key_x: [u8; 32], signing_pub_key_y: [u8; 32]) {\n let this = context.this_address();\n let header = context.get_header();\n let this_npk_m_hash = header.get_npk_m_hash(&mut context, this);\n // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we\n // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that\n // important.\n\n let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash);\n storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this));\n }\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(noinitcheck)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n // Load public key from storage\n let storage = Storage::init(context);\n let public_key = storage.public_key.get_note();\n\n // Load auth witness\n let witness: [Field; 64] = get_auth_witness(outer_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n\n // Verify payload signature using Ethereum's signing scheme\n // Note that noir expects the hash of the message/challenge as input to the ECDSA verification.\n let outer_hash_bytes: [u8; 32] = outer_hash.to_be_bytes(32).as_array();\n let hashed_message: [u8; 32] = std::hash::sha256(outer_hash_bytes);\n let verification = std::ecdsa_secp256k1::verify_signature(public_key.x, public_key.y, signature, hashed_message);\n assert(verification == true);\n\n true\n }\n}\n"},"346":{"path":"/usr/src/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr","source":"use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteInterface, NoteGetterOptions, PrivateContext};\n\nuse dep::aztec::{\n note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app,\n protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}\n};\n\nglobal ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5;\n// ECDSA_PUBLIC_KEY_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)\nglobal ECDSA_PUBLIC_KEY_NOTE_BYTES_LEN: Field = 5 * 32 + 64;\n\n// Stores an ECDSA public key composed of two 32-byte elements\n// TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value?\n#[aztec(note)]\nstruct EcdsaPublicKeyNote {\n x: [u8; 32],\n y: [u8; 32],\n // We store the npk_m_hash only to get the secret key to compute the nullifier\n npk_m_hash: Field,\n}\n\nimpl NoteInterface for EcdsaPublicKeyNote {\n // Cannot use the automatic serialization since x and y don't fit. Serialize the note as 5 fields where:\n // [0] = x[0..31] (upper bound excluded)\n // [1] = x[31]\n // [2] = y[0..31]\n // [3] = y[31]\n // [4] = npk_m_hash\n fn serialize_content(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] {\n let mut x: Field = 0;\n let mut y: Field = 0;\n let mut mul: Field = 1;\n\n for i in 1..32 {\n let byte_x: Field = self.x[31 - i] as Field;\n x = x + (byte_x * mul);\n let byte_y: Field = self.y[31 - i] as Field;\n y = y + (byte_y * mul);\n mul *= 256;\n }\n\n let last_x = self.x[31] as Field;\n let last_y = self.y[31] as Field;\n \n [x, last_x, y, last_y, self.npk_m_hash]\n }\n\n // Cannot use the automatic deserialization for the aforementioned reasons\n fn deserialize_content(serialized_note: [Field; ECDSA_PUBLIC_KEY_NOTE_LEN]) -> EcdsaPublicKeyNote {\n let mut x: [u8; 32] = [0; 32];\n let mut y: [u8; 32] = [0; 32];\n\n let part_x = serialized_note[0].to_be_bytes(32);\n for i in 0..31 {\n x[i] = part_x[i + 1];\n }\n x[31] = serialized_note[1].to_be_bytes(32)[31];\n\n let part_y = serialized_note[2].to_be_bytes(32);\n for i in 0..31 {\n y[i] = part_y[i + 1];\n }\n y[31] = serialized_note[3].to_be_bytes(32)[31];\n\n EcdsaPublicKeyNote { x, y, npk_m_hash: serialized_note[4], header: NoteHeader::empty() }\n }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n}\n\nimpl EcdsaPublicKeyNote {\n pub fn new(x: [u8; 32], y: [u8; 32], npk_m_hash: Field) -> Self {\n EcdsaPublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() }\n }\n}\n"},"35":{"path":"std/option.nr","source":"use crate::hash::{Hash, Hasher};\nuse crate::cmp::{Ordering, Ord, Eq};\nuse crate::default::Default;\n\nstruct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some { self._value } else { default }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some { self } else { other }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some { self } else { default() }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some { Option::none() } else { self }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option where T: Eq {\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option where T: Ord {\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else {\n if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"62":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_private_key::GrumpkinPrivateKey,\n grumpkin_point::GrumpkinPoint, utils::arr_copy_slice\n};\nuse dep::std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}};\n\n// TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since\n// point is not the only input of the function. Unify naming with TS once we have a better name.\npub fn point_to_symmetric_key(secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 32] {\n let shared_secret_fields = multi_scalar_mul(\n [EmbeddedCurvePoint { x: point.x, y: point.y, is_infinite: false }],\n [EmbeddedCurveScalar { lo: secret.low, hi: secret.high }]\n );\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly\n let shared_secret = GrumpkinPoint::new(shared_secret_fields[0], shared_secret_fields[1]);\n let mut shared_secret_bytes_with_separator = [0 as u8; 65];\n shared_secret_bytes_with_separator = arr_copy_slice(shared_secret.to_be_bytes(), shared_secret_bytes_with_separator, 0);\n shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY;\n sha256(shared_secret_bytes_with_separator)\n}\n\n#[test]\nfn check_point_to_symmetric_key() {\n // Value taken from \"derive shared secret\" test in encrypt_buffer.test.ts\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let key = point_to_symmetric_key(secret, point);\n // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1\n let expected_key = [\n 49, 167, 146, 222, 151, 129, 138, 184, 87, 210, 245, 249, 99, 100, 1, 59, 223, 180, 5, 99, 14, 7, 177, 236, 159, 203, 231, 72, 220, 180, 241, 23\n ];\n assert_eq(key, expected_key);\n}\n"},"63":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/getters.nr","source":"use dep::protocol_types::{\n header::Header, abis::validation_requests::KeyValidationRequest, address::AztecAddress,\n constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint,\n storage::map::derive_storage_slot_in_map\n};\nuse crate::{\n context::PrivateContext,\n oracle::{keys::get_public_keys_and_partial_address, key_validation_request::get_key_validation_request},\n keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}},\n state_vars::{shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter}\n};\n\nglobal DELAY = 5;\n\n// docs:start:key-getters\ntrait KeyGetters {\n fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;\n}\n\nimpl KeyGetters for Header {\n fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, NULLIFIER_INDEX, self)\n }\n\n fn get_ivpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, INCOMING_INDEX, self)\n }\n\n fn get_ovpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, OUTGOING_INDEX, self)\n }\n\n fn get_tpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, TAGGING_INDEX, self)\n }\n\n fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {\n get_master_key(context, address, NULLIFIER_INDEX, self).hash()\n }\n}\n// docs:end:key-getters\n\nfn get_master_key(\n context: &mut PrivateContext,\n address: AztecAddress,\n key_index: Field,\n header: Header\n) -> GrumpkinPoint {\n let key = fetch_key_from_registry(context, key_index, address, header);\n if key.is_zero() {\n // Keys were not registered in registry yet --> fetch key from PXE\n let keys = fetch_and_constrain_keys(address);\n // Return the corresponding to index\n keys.get_key_by_index(key_index)\n } else {\n // Keys were registered --> return the key\n key\n }\n}\n\nfn fetch_key_from_registry(\n context: &mut PrivateContext,\n key_index: Field,\n address: AztecAddress,\n header: Header\n) -> GrumpkinPoint {\n let x_coordinate_map_slot = key_index * 2 + 1;\n let y_coordinate_map_slot = x_coordinate_map_slot + 1;\n let x_coordinate_derived_slot = derive_storage_slot_in_map(x_coordinate_map_slot, address);\n let y_coordinate_derived_slot = derive_storage_slot_in_map(y_coordinate_map_slot, address);\n\n let x_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n x_coordinate_derived_slot\n );\n let y_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n y_coordinate_derived_slot\n );\n let x_coordinate = x_coordinate_registry.get_value_in_private(header);\n let y_coordinate = y_coordinate_registry.get_value_in_private(header);\n\n GrumpkinPoint::new(x_coordinate, y_coordinate)\n}\n\n// Passes only when keys were not rotated - is expected to be called only when keys were not registered yet\nfn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys {\n let (public_keys, partial_address) = get_public_keys_and_partial_address(address);\n\n let computed_address = AztecAddress::compute(public_keys.hash(), partial_address);\n\n assert(computed_address.eq(address));\n\n public_keys\n}\n\n// A helper function since requesting nsk_app is very common\n// TODO(#6543)\npub fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"80":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr","source":"use dep::std::merkle::compute_merkle_root;\nuse dep::protocol_types::header::Header;\n\nuse crate::{\n context::PrivateContext, oracle::get_nullifier_membership_witness::get_nullifier_membership_witness,\n note::{utils::compute_siloed_nullifier, note_interface::NoteInterface}\n};\n\ntrait ProveNullifierInclusion {\n fn prove_nullifier_inclusion(header: Header, nullifier: Field);\n}\n\nimpl ProveNullifierInclusion for Header {\n fn prove_nullifier_inclusion(self, nullifier: Field) {\n // 1) Get the membership witness of the nullifier\n let witness = get_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier);\n\n // 2) Check that the witness we obtained matches the nullifier\n assert(witness.leaf_preimage.nullifier == nullifier, \"Nullifier does not match value in witness\");\n\n // 3) Compute the nullifier tree leaf\n let nullifier_leaf = witness.leaf_preimage.hash();\n\n // 4) Prove that the nullifier is in the nullifier tree\n assert(\n self.state.partial.nullifier_tree.root\n == compute_merkle_root(nullifier_leaf, witness.index, witness.path), \"Proving nullifier inclusion failed\"\n );\n // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier\n // was included in the nullifier tree.\n }\n}\n\ntrait ProveNoteIsNullified {\n fn prove_note_is_nullified(header: Header, note: Note, context: &mut PrivateContext) where Note: NoteInterface;\n}\n\nimpl ProveNoteIsNullified for Header {\n fn prove_note_is_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface {\n let nullifier = compute_siloed_nullifier(note, context);\n\n self.prove_nullifier_inclusion(nullifier);\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"98":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash\n};\n\nuse dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field};\n\nuse crate::oracle::unsafe_rand::unsafe_rand;\n\nuse crate::event::event_interface::EventInterface;\nuse crate::note::note_interface::NoteInterface;\n\nuse crate::encrypted_logs::{\n header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody,\n outgoing_body::EncryptedLogOutgoingBody\n};\n\npub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n event: Event\n) -> [u8; OB] where Event: EventInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; OB] = [0; OB];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = OB - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\npub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n note: Note\n) -> [u8; M] where Note: NoteInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; M] = [0; M];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = M - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\nfn fr_to_private_key(r: Field) -> GrumpkinPrivateKey {\n let r_bytes = r.to_be_bytes(32);\n\n let mut high_bytes = [0; 32];\n let mut low_bytes = [0; 32];\n\n for i in 0..16 {\n high_bytes[16 + i] = r_bytes[i];\n low_bytes[16 + i] = r_bytes[i + 16];\n }\n\n let low = bytes32_to_field(low_bytes);\n let high = bytes32_to_field(high_bytes);\n\n GrumpkinPrivateKey::new(high, low)\n}\n\nfn compute_ivpk_app(ivpk: GrumpkinPoint, contract_address: AztecAddress) -> GrumpkinPoint {\n // It is useless to compute this, it brings no value to derive fully.\n // Issue(#6955)\n ivpk\n /*\n // @todo Just setting infinite to false, but it should be checked.\n // for example user could define ivpk = infinity using the registry\n assert((ivpk.x != 0) & (ivpk.y != 0), \"ivpk is infinite\");\n\n let i = fr_to_private_key(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M]));\n let I = i.derive_public_key();\n\n let embed_I = EmbeddedCurvePoint { x: I.x, y: I.y, is_infinite: false };\n let embed_ivpk = EmbeddedCurvePoint { x: ivpk.x, y: ivpk.y, is_infinite: false };\n\n let embed_result = embedded_curve_add(embed_I, embed_ivpk);\n\n GrumpkinPoint::new(embed_result.x, embed_result.y)*/\n}\n"},"99":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr","source":"use crate::{\n context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},\n encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog\n};\nuse dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash,\n constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index\n};\n\nfn emit_with_keys(\n context: &mut PrivateContext,\n note: Note,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n let note_header = note.get_header();\n let note_hash_counter = note_header.note_hash_counter;\n let storage_slot = note_header.storage_slot;\n\n let note_exists_index = find_index(\n context.new_note_hashes.storage,\n |n: NoteHash| n.counter == note_hash_counter\n );\n assert(\n note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, \"Can only emit a note log for an existing note.\"\n );\n\n let contract_address: AztecAddress = context.this_address();\n let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());\n\n let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);\n\n context.emit_raw_note_log(note_hash_counter, encrypted_log);\n}\n\npub fn encode_and_encrypt_note(\n context: &mut PrivateContext,\n ov: AztecAddress,\n iv: AztecAddress\n) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n let header = context.get_header();\n let ovpk = header.get_ovpk_m(context, ov);\n let ivpk = header.get_ivpk_m(context, iv);\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n\npub fn encode_and_encrypt_note_with_keys(\n context: &mut PrivateContext,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/accounts/src/artifacts/SchnorrAccount.json b/yarn-project/accounts/src/artifacts/SchnorrAccount.json new file mode 100644 index 000000000000..954e40db2de0 --- /dev/null +++ b/yarn-project/accounts/src/artifacts/SchnorrAccount.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"SchnorrAccount","functions":[{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2dBXQU1xfGd2MEAoFgwVmkSI2dCElKBagL9ZYapQkkhUIJhUBL3d3dnbpRo27UqLu7GzVqVOj/Xniv3Dw2QnLf7H7nnznnO5PZvHnz3Ttv32925E00snxqnRGJzM1Y/neUlE5KI8XEcrr52y5nOv9v5Sy3c5bbO8t5znInZzmfNFIs93X+H3OW+znL/Z3lQWZZTlEzH2nmhfHhRUWVJQWVQWFQHi8oqygtjhcVVwwvDUqD4tLiiQWlhYWVpUWlJWUVZSXxsqCosDKoKi4rrIovn36Krqgr3syJvbUW3gaTlpJ4Gy3z/7/5mqSfo8vbrGwXP7fk5/++XSyORmpNaWY+0szjzZuCQRG9PvKXqJ4vDpv7dq4zVjsFK/Xt8eZNQYZiDux3OEP45X3Z28z7mLnt89cm/RpdzlwZW6JppFK8rUSdv5kN/m7mf5j5EjP/08z/MvO/owk8jlQyZnf63wl2utvwNXaUlu8leg0/LmPWbuh/RfUberpoSEtNQ1pqGhLPS0j/OC0mqrwvlyp3PK1Fe1tq4vjHzIeT/jVf2PRI4i+s9n77M6p78PnflObxy+wrEdK02k5P02uMvuKOpqnvo7jb2P80jfxfM1/2a1FsNxLRPwL5RbFTSk/ThxHXGYss/8JHI+F84X/18IWXwMugmDJJWaRWpGxSa1IbUg6pLakdKZfUntSBlEfqSOpE6kzqQupKyid1I3Un9SD1JPUi9Sb1IfXl/JH6kfqTBpAGklYjDSINJg0hDSWtTlqDtCZpLdLapGGkOCkgFZAKSUWkYtJwUgmplFRGWoc0grQuaT3S+qQNuE2QRpFGkzb02elxI8kQXxKfjSQjzc9Rh2pOgnhc5mIjs7BxWgiHkbyx3yIrzhPxRrOdbaZ73ClN7c0qq3iKBxspUmljT41FmwaaMW9Sqy4qW15QNLyyOD68srSstLKspKq4JD6hvKpqYkm8aEJFvKKiaHi8MCisqigpiFcUlNFmyyqLJwTLfIV5uLdJmn7vz9OmaId7nIhNPRzubZbih3sc92Zp6vsooVeNjmWzNP16N1f+EvCXl+vkw90wKZ0JSOktzMKWYVB6C4fSW4ZA6UxFSm+h2JlsCUJpzZi3AqX0Vp4oPQaN0pyIMR4ovXWKU5rj3hqE0lsar9r1buOB0tskgdJZgJTe1ixsFwalt3UovV0IlM5SpPS2ip3JdiCU1ox5e1BKb++J0jugUZoTsYMHSu+Y4pTmuHcEofR2xqt2vTt5oPROSaB0K0BK72wWxoZB6Z0dSo8NgdKtFCm9s2JnMhaE0pox7wJK6V08UXpXNEpzInb1QOndUpzSHPduIJQea7xq17u7B0rvngRKZwNSeg+zMC4MSu/hUHpcCJTOVqT0HoqdyTgQSmvGvCcopff0ROnxaJTmRIz3QOm9UpzSHPdeIJQeZ7xq11vugdLlSaB0a0BKV5iFCWFQusKh9IQQKN1akdIVip3JBBBKa8Y8EZTSEz1RuhKN0pyISg+UrkpxSnPcVSCUnmC8ate7twdK750ESrcBpPQkszA5DEpPcig9OQRKt1Gk9CTFzmQyCKU1Y94HlNL7eKL0FDRKcyKmeKD01BSnNMc9FYTSk41X7Xr39UDpfZNA6RxASk8zC9VhUHqaQ+nqECido0jpaYqdSTUIpTVjng5K6emeKL0fGqU5Eft5oPSMFKc0xz0DhNLVxqt2vTM9UHpmEijdFpDSNWZhVhiUrnEoPSsESrdVpHSNYmcyC4TSmjHPBqX0bE+U3h+N0pyI/T1Q+oAUpzTHfQAIpWcZr9r1zvFA6TlJoHQ7QEofaBYOCoPSBzqUPigESrdTpPSBip3JQSCU1oz5YFBKH+yJ0oegUZoTcYgHSh+a4pTmuA8FofRBxqt2vYd5oPRhSaB0LiClDzcLR4RB6cMdSh8RAqVzFSl9uGJncgQIpTVjPhKU0kd6ovRRaJTmRBzlgdJHpzilOe6jQSh9hPGqXe8xHih9TBIo3R6Q0seahePCoPSxDqWPC4HS7RUpfaxiZ3IcCKU1Yz4elNLHe6L0CWiU5kSc4IHSJ6Y4pTnuE0EofZzxql3vSR4ofVISKN0BkNInm4VTwqD0yQ6lTwmB0h0UKX2yYmdyCgilNWM+FZTSp3qi9GlolOZEnOaB0qenOKU57tNBKH2K8apd7xkeKH1GEiidB0jpM83CWWFQ+kyH0meFQOk8RUqfqdiZnAVCac2Yzwal9NmeKH0OGqU5Eed4oPS5KU5pjvtcEEqfZbxq13ueB0qflwRKdwSk9Plm4YIwKH2+Q+kLQqB0R0VKn6/YmVwAQmnNmC8EpfSFnih9ERqlOREXeaD0xSlOaY77YhBKX2C8atd7iQdKX5IESncCpPSlZuGyMCh9qUPpy0KgdCdFSl+q2JlcBkJpzZgvB6X05Z4ofQUapTkRV3ig9JUpTmmO+0oQSl9mvGrXe5UHSl+VBEp3BqT01WZhbhiUvtqh9NwQKN1ZkdJXK3Ymc0EorRnzNaCUvsYTpa9FozQn4loPlL4uxSnNcV8HQum5xqt2vdd7oPT1SaB0F0BK32AWbgyD0jc4lL4xBEp3UaT0DYqdyY0glNaM+SZQSt/kidI3o1GaE3GzB0rfkuKU5rhvAaH0jcardr23eqD0rUmgdFdASt9mFuaFQenbHErPC4HSXRUpfZtiZzIPhNKaMd8OSunbPVH6DjRKcyLu8EDpO1Oc0hz3nSCUnme8atd7lwdK35UESucDUvpuszA/DErf7VB6fgiUzlek9N2Kncl8EEprxnwPKKXv8UTpe9EozYm41wOl70txSnPc94FQer7xql3v/R4ofX8SKN0NkNIPmIUHw6D0Aw6lHwyB0t0UKf2AYmfyIAilNWN+CJTSD3mi9MNolOZEPOyB0o+kOKU57kdAKP2g8apd76MeKP1oEijdHZDSj5mFBWFQ+jGH0gtCoHR3RUo/ptiZLAChtGbMj4NS+nFPlH4CjdKciCc8UPrJFKc0x/0kCKUXGK/a9T7lgdJPJYHSPQAp/bRZWBgGpZ92KL0wBEr3UKT004qdyUIQSmvG/AwopZ/xROln0SjNiXjWA6WfS3FKc9zPgVB6ofGqXe/zHij9fBIo3ROQ0i+YhRfDoPQLDqVfDIHSPRUp/YJiZ/IiCKU1Y34JlNIveaL0y2iU5kS87IHSr6Q4pTnuV0Ao/aLxql3vqx4o/WoSKN0LkNKvmYXXw6D0aw6lXw+B0r0UKf2aYmfyOgilNWN+A5TSb3ii9JtolOZEvOmB0m+lOKU57rdAKP268apd79seKP12EijdG5DS75iFd8Og9DsOpd8NgdK9FSn9jmJn8i4IpTVjfg+U0u95ovT7aJTmRLzvgdIfpDilOe4PQCj9rvGqXe+HHij9YRIo3QeQ0h+ZhY/DoPRHDqU/DoHSfRQp/ZFiZ/IxCKU1Y/4ElNKfeKL0p2iU5kR86oHSn6U4pTnuz0Ao/bHxql3v5x4o/XkSKN0XkNJfmIUvw6D0Fw6lvwyB0n0VKf2FYmfyJQilNWP+CpTSX3mi9NdolOZEfO2B0t+kOKU57m9AKP2l8apd77ceKP1tEigdA6T0d2ZhURiU/s6h9KIQKB1TpPR3ip3JIhBKa8b8PSilv/dE6R/QKM2J+MEDpX9McUpz3D+CUHqR8apd708eKP1TEijdD5DSP5uFxWFQ+meH0otDoHQ/RUr/rNiZLAahtGbMv4BS+hdPlP4VjdKciF89UPq3FKc0x/0bCKUXG6/a9f7ugdK/J4HS/QEp/YdZWBIGpf9wKL0kBEr3V6T0H4qdyRIQSmvG/Ccopf/0ROm/0CjNifjLA6X/TnFKc9x/g1B6ifGqXe8/Hij9TxIoPQCQ0kvNwr9hUHqpQ+l/Q6D0AEVKL1XsTP4FobRmzLxzV9SFQ2npO97MSfqNpoNRmhMhTWvVm5ae2pTmuNPS1feRF0pzx5KWrl9vero+pbnOsCk9EJDSGabtZaaHQGnemKQ0b9Q3pQcqUjpDsTPJTMegtGbMWaCUzvJE6VZolOZEtPJA6ewUpzTHnQ1C6UzjVbve1h4o3ToJlF4NkNJtTNvLCYPSbRxK54RA6dUUKd1GsTPJAaG0ZsxtQSnd1hOl26FRmhPRzgOlc1Oc0hx3Lgilc4xX7Xrbe6B0+yRQehAgpTuYtpcXBqU7OJTOC4HSgxQp3UGxM8kDobRmzB1BKd3RE6U7oVGaE9HJA6U7pzilOe7OIJTOM1616+3igdJdkkDpwYCU7mraXn4YlO7qUDo/BEoPVqR0V8XOJB+E0poxdwOldDdPlO6ORmlORHcPlO6R4pTmuHuAUDrfeNWut6cHSvdMAqWHAFK6l2l7vcOgdC+H0r1DoPQQRUr3UuxMeoNQWjPmPqCU7uOJ0n3RKM2J6OuB0rEUpzTHHQOhdG/jVbvefh4o3S8JlB4KSOn+pu0NCIPS/R1KDwiB0kMVKd1fsTMZAEJpzZgHglJ6oCdKr4ZGaU7Eah4oPSjFKc1xDwKh9ADjVbvewR4oPTgJlF4dkNJDTNsbGgalhziUHhoCpVdXpPQQxc5kKAilNWNeHZTSq3ui9BpolOZErOGB0mumOKU57jVBKD3UeNWudy0PlF4rCZReA5DSa5u2NywMSq/tUHpYCJReQ5HSayt2JsNAKK0ZcxyU0nFPlA7QKM2JCDxQuiDFKc1xF4BQepjxql1voQdKFyaB0msCUrrItL3iMChd5FC6OARKr6lI6SLFzqQYhNKaMQ8HpfRwT5QuQaM0J6LEA6VLU5zSHHcpCKWLjVftess8ULosCZReC5DS65i2NyIMSq/jUHpECJReS5HS6yh2JiNAKK0Z87qglF7XE6XXQ6M0J2I9D5ReP8UpzXGvD0LpEcardr0beKD0Bkmg9NqAlB5p2t6oMCg90qH0qBAovbYipUcqdiajQCitGfNoUEqP9kTpDdEozYnY0AOlN0pxSnPcG4FQepTxql3vxh4ovXESKD0MkNKbmLa3aRiU3sSh9KYhUHqYIqU3UexMNgWhtGbMm4FSejNPlN4cjdKciM09UHqLFKc0x70FCKU3NV61693SA6W3TAKl44CU3sq0vTFhUHorh9JjQqB0XJHSWyl2JmNAKK0Z89aglN7aE6W3QaM0J2IbD5TeNsUpzXFvC0LpMcardr3beaD0dkmgdABI6e1N29shDEpv71B6hxAoHShSenvFzmQHEEprxrwjKKV39ETpndAozYnYyQOld05xSnPcO4NQegfjVbvesR4oPTYJlC4ApPQupu3tGgald3EovWsIlC5QpPQuip3JriCU1ox5N1BK7+aJ0rujUZoTsbsHSu+R4pTmuPcAofSuxqt2veM8UHpcEihdCEjpPU3bGx8Gpfd0KD0+BEoXKlJ6T8XOZDwIpTVj3guU0nt5onQ5GqU5EeUeKF2R4pTmuCtAKD3eeNWud4IHSk9IAqWLACk90bS9yjAoPdGhdGUIlC5SpPRExc6kEoTSmjFXgVK6yhOl90ajNCdibw+UnpTilOa4J4FQutJ41a53sgdKT04CpYsBKb2PaXtTwqD0Pg6lp4RA6WJFSu+j2JlMAaG0ZsxTQSk91ROl90WjNCdiXw+UnpbilOa4p4FQeorxql1vtQdKVyeB0sMBKT3dtL39wqD0dIfS+4VA6eGKlJ6u2JnsB0JpzZhngFJ6hidKz0SjNCdipgdK16Q4pTnuGhBK72e8atc7ywOlZyWB0iWAlJ5t2t7+YVB6tkPp/UOgdIkipWcrdib7g1BaM+YDQCl9gCdKz0GjNCdijgdKH5jilOa4DwSh9P7Gq3a9B3mg9EFJoHQpIKUPNm3vkDAofbBD6UNCoHSpIqUPVuxMDgGhtGbMh4JS+lBPlD4MjdKciMM8UPrwFKc0x304CKUPMV616z3CA6WPSAKlywApfaRpe0eFQekjHUofFQKlyxQpfaRiZ3IUCKU1Yz4alNJHe6L0MWiU5kQc44HSx6Y4pTnuY0EofZTxql3vcR4ofVwSKL0OIKWPN23vhDAofbxD6RNCoPQ6ipQ+XrEzOQGE0poxnwhK6RM9UfokNEpzIk7yQOmTU5zSHPfJIJQ+wXjVrvcUD5Q+JQmUHgFI6VNN2zstDEqf6lD6tBAoPUKR0qcqdiangVBaM+bTQSl9uidKn4FGaU7EGR4ofWaKU5rjPhOE0qcZr9r1nuWB0mclgdLrAlL6bNP2zgmD0mc7lD4nBEqvq0jpsxU7k3NAKK0Z87mglD7XE6XPQ6M0J+I8D5Q+P8UpzXGfD0Lpc4xX7Xov8EDpC5JA6fUAKX2haXsXhUHpCx1KXxQCpddTpPSFip3JRSCU1oz5YlBKX+yJ0pegUZoTcYkHSl+a4pTmuC8FofRFxqt2vZd5oPRlSaD0+oCUvty0vSvCoPTlDqWvCIHS6ytS+nLFzuQKEEprxnwlKKWv9ETpq9AozYm4ygOlr05xSnPcV4NQ+grjVbveuR4oPTcJlN4AkNLXmLZ3bRiUvsah9LUhUHoDRUpfo9iZXAtCac2YrwOl9HWeKH09GqU5Edd7oPQNKU5pjvsGEEpfa7xq13ujB0rfmARKjwSk9E2m7d0cBqVvcih9cwiUHqlI6ZsUO5ObQSitGfMtoJS+xROlb0WjNCfiVg+Uvi3FKc1x3wZC6ZuNV+1653mg9LwkUHoUIKVvN23vjjAofbtD6TtCoPQoRUrfrtiZ3AFCac2Y7wSl9J2eKH0XGqU5EXd5oPTdKU5pjvtuEErfYbxq1zvfA6XnJ4HSowEpfY9pe/eGQel7HErfGwKlRytS+h7FzuReEEprxnwfKKXv80Tp+9EozYm43wOlH0hxSnPcD4BQ+l7jVbveBz1Q+sEkUHpDQEo/ZNrew2FQ+iGH0g+HQOkNFSn9kGJn8jAIpTVjfgSU0o94ovSjaJTmRDzqgdKPpTilOe7HQCj9sPGqXe8CD5ReYCjt0ll7//0a1fMeM/U8Tt6fID1Jeor0NGkh6RnSs6TnSM+TXiC9SHqJ9DLpFdKrpNdIr5PeIL1Jeov0Nukd0ruk90jvkz4gfUj6iPQx6RPSp6bns3l83IDULj/hLD/pLD/lLD/tLC90lp9xlp91lp9zlp93ll9wll90ll9yll92ll9xll91ll9zll93lt9wlt90lt9ylt92lt9xlt91lt9zlt93lj9wlj90lj9ylj92lj9xlj9NX/nAKcPMR5p5vHlTre9Mc/uOx9P1DsKeUGTFV54Owtx90ZyYeV88qZK/5fv1qebXVWDyFzytuC++TuV9UfSfz2Bh82KOi5iDZ5pTV0Gt/AXPKu6Lb1JzX8Qdn8FzTYx5eNVKMQfPN62u0gT5C15Q3Bffptq+KE3oM3hx1WMuqSPm4KVVraukzvwFLyvui+9SZ18U1OMzeGVVYi6pN+bg1cbXNaGB/AWvKe6LRamwL0oa9Bm83riY442IOXijMXXFG5W/4E3FffF9cvdFcSN9Bm81FHNRo2MO3q63rqKqVchf8I7ivvghWfuiZJV8Bu/WHXPpKsYcvFdHXWVVq5y/4H3FffFj+Psi3gSfwQeJYo43Kebgw5XrCpqYv+AjxX3xU5j7YmKTfQYf1465sBkxB5+IugqqmpW/4FPFffFzSPsi3rwpUDw/ECj+vg2+UdwXi0H2heLvoEDxOD5YpLgvfgHZF4rHe4Hi8Urwo+K++BVkXyhyLVDsl4PFivviN0/7Il15Xyh+fwPF9hdo5o+vQbQi/UZ/LKX572a+cdryaxJbmvl2Zj7WzMeZ+QQzn2zm1WY+y8wPMvMjzPw4Mz/FzM8y8wvM/DIzn2vmN5r5PDOfb+YPmvkCM19o5i+a+etm/q6Zf2zmX5r5IjNfbOZLzPxfM88012RyzDzPzPPNvLeZDzDzoWY+zMyLzXyEmY8y803NfIyZ72Dmu5r5eDOvNPMpZr6fme9v5vZ1vPaFf/aVQvalBXZYZDvwoh3ayQ4eYR9PtQ/A2Fts7U08MdO+7LUpe83KXsuy17jstS97TcxeK7PX0Oy1NXvNzV6Ls9fo7LU7e03PXuuz1wDttUF7zdBeS7TXGO21R3tN0l6rtNcw7bVNe83TXgu110jttVN7TdVea7XXYD+znYqZtK9lf6bYr/JNNGmRxHfHRZR9RyOJb9bR2EZ5Bf24KZ9Y5OZcPYhIPTu2uTvj83S9RLC31sIb182d9E/Rlvn/43xN0hfpy9usbBdftLSL//t28aUDLAuDkWaucUOerSvevCkYEvHzQ0A75qhizENBYk5TjHl1kJjTFWNew1PMUSfmePOmYM2Ibt/ga99kKsa8ViSc9hhv3hSsrZi/xVGMmIcpxvxlOsZ3MB7B8BmA+CwA8Vmo7NP119zvz79UYTRNv96sDL9xx5s3BRxzmoe4W2X4aZfaFyGKFGPmPGr5Umw3ga99oc3DYsV98UsUo18cHsHwWQLisxTEZxmIz3VAfI4A8bkuiM/1QHyuD+JzAxCfI0F8jgLxORrE54YgPjcC8bkxiM9NQHxuCuJzMxCfm4P43ALE55YgPrcC8TkGxOfWID63AfG5LYjP7UB8bg/icwcQnzuC+NwJxOfOID7HgvjcBcTnriA+dwPxuTuIzz1AfI4D8bkniM/xID73AvFZDuKzAsTnBBCfE0F8VoL4rALxuTeIz0kgPieD+NwHxOcUEJ9TQXzuC+JzGojPahCf00F87gficwaIz5kgPmtAfM4C8TkbxOf+ID4PAPE5B8TngSA+DwLxeTCIz0NAfB4K4vMwEJ+Hg/g8AsTnkSA+jwLxeTSIz2NAfB4L4vM4EJ/Hg/g8AcTniSA+TwLxeTKIz1NAfJ4K4vM0EJ+ng/g8A8TnmSA+zwLxeTaIz3NAfJ4L4vM8EJ/ng/i8AMTnhSA+LwLxeTGIz0tAfF4K4vMyEJ+Xg/i8AsTnlSA+rwLxeTWIz7kgPq8B8XktiM/rQHxeD+LzBhCfN4L4vAnE580gPm8B8XkriM/bQHzOA/F5O4jPO0B83gni8y4Qn3eD+JwP4vMeEJ/3gvi8D8Tn/SA+HwDx+SCIz4dAfD4M4vMREJ+Pgvh8DMTnAhCfj4P4fALE55MgPp8C8fk0iM+FID6fAfH5LIjP50B8Pg/i8wUQny+C+HwJxOfLID5fAfH5KojP10B8vg7i8w0Qn2+C+HwLxOfbID7fAfH5LojP90B8vg/i8wMQnx+C+PwIxOfHID4/AfH5KYjPz0B8fg7i8wsQn1+C+PwKxOfXID6/AfH5LYjP70B8LgLx+T2Izx9AfP4I4vMnEJ8/g/hcDOLzFxCfv4L4/A3E5+8gPv8A8bkExOefID7/AvH5N4jPf0B8LgXx+S+IT64QwWcUxGcaiM90EJ8ZID4zQXxmgfhsBeIzG8RnaxCfbUB85oD4bAvisx2Iz1wQn+1BfHYA8ZkH4rMjiM9OID47g/jsAuKzK4jPfBCf3UB8dgfx2QPEZ08Qn71AfPYG8dkHxGdfEJ8xEJ/9QHz2B/E5AMTnQBCfq4H4HATiczCIzyEgPoeC+FwdxOcaID7XBPG5FojPtUF8DgPxGQfxGYD4LADxWQjiswjEZzGIz+EgPktAfJaC+CwD8bkOiM8RID7XBfG5HojP9UF8bgDicySIz1EgPkeD+NwQxOdGID43BvG5CYjPTUF8bgbic3MQn1uA+NwSxOdWID7HgPjcGsTnNiA+twXxuR2Iz+1BfO4A4nNHEJ87gfjcGcTnWBCfu4D43BXE524gPncH8bkHiM9xID73BPE5HsTnXiA+y0F8VoD4nADicyKIz0oQn1UgPvcG8TkJxOdkEJ/7gPicAuJzKojPfUF8TgPxWQ3iczqIz/1AfM7w5DPN8VkYH15UVFlSUBkUBuXxgrKK0uJ4UXHF8NKgNCguLZ5YUFpYWFlaVFpSVlFWEi8Ligorg6rissIqU/cgxZhnhhRzvHlTUBPVy196GkZ7nAXyvZkN4nN/EJ8HgPicA+LzQBCfB4H4PBjE5yEgPg8F8XkYiM/DQXweAeLzSBCfR4H4PBrE5zEgPo8F8XkciM/jQXyeAOLzRBCfJ4H4PBnE5ykgPk8F8XkaiM/TQXyeAeLzTBCfZ4H4PBvE5zkgPs8F8XkeiM/zQXxeAOLzQhCfF4H4vBjE5yUgPi8F8XkZiM/LQXxeAeLzShCfV4H4vBrE51wQn9eA+LwWxOd1ID6vB/F5A4jPG0F83gTi82YQn7eA+LwVxOdtID7ngfi8HcTnHSA+7wTxeReIz7tBfM4H8XkPiM97QXzeB+LzfhCfD4D4fBDE50MgPh8G8fkIiM9HQXw+BuJzAYjPx0F8PgHi80kQn0+B+HwaxOdCEJ/PgPh8FsTncyA+nwfx+QKIzxdBfL7kyWea47O5z0FnKcb8MkjMrRRjfgUk5mzFmF8Fibm1YsyvgcTcRjHm10FizlGM+Q2QmNsqxvwmSMztFGN+CyTmXMWY3waJub1izO+AxNxBMeZ3QWLOU4z5PZCYOyrG/D5IzJ0UY/4AJObOijF/CBJzF8WYPwKJuatizB+DxJyvGPMnIDF3U4z5U5CYuyvG/BlIzD0UY/4cJOaeijF/ARJzL8WYvwSJubdizF+BxNxHMeavQWLuqxjzNyAxxxRj/hYk5n6KMX8HEnN/xZgXgcQ8QDHm70FiHqgY8w8gMa+mGPOPijHztfEMU9cQEX/U5CDd/D+TxNeT+foqX2/k6298PYqvz/D1Cj5/z+ez+fwun+/k8398PozPD/H5Ej5/wL+n+fcl/97i3x98PM7Hp3y8xscvzHPmW4zE/R/3B/z94PbC+eNx0QcLjwujK3wPJa1OWoO0Jmkt0tqkYZwjUkAq4P1IKiIVk4aTSkilpDLSOqQRpHVJ65HWJ21g9tso0mjShqSNSBuTNiFtStqMtDlpC9KWpK1IY0hbk7YhbUvajrQ9aQfSjqSdSDuTxpJ2Ie1K2o20O2kP0jjSnqTxpL1I5aQK0gTSRFIlqYq0N2kSaTJpH9IU0lTSvqRppGrSdNJ+pBmkmaQa0izSbNL+pANIc0gHkg4iHUw6hHQo6TDS4aQjSEeSjiIdTTqGdCzpONLxpBNIJ5JOIp1MOoV0Kuk00umkM0hnks4inU06h3Qu6TzS+aQLSBeSLiJdTLqEdCnpMtLlpCtIV5KuIl1Nmku6hnQt6TrS9aQbSDeSbiLdTLqFdCvpNtI80u2kO0h3ku4i3U2aT7qHdC/pPtL9pAdID5IeIj1MeoT0KOkx0gLS46QnSE+SniI9TVpIeob0LOk50vOkF0gvkl4ivUx6hfQq6TXS66Q3SG+S3iK9TXqH9C7pPdL7pA9IH5I+In1M+oT0Kekz0uekL0hfkr4ifU36hvQt6TvSItL3pB9IP5J+Iv1MWkz6hfQr6TfS76Q/SEtIf5L+Iv1N+oe0lPQviTuDKCmNlE7KIGWSskitSNmk1qQ2pBxSW1I7Ui6pPakDKY/UkdSJ1JnUhdSVlE/qRupO6kHqSepF6k3qQ+pLipH6kfqTBpAGklYjDSINJg0hDSWtTlqDtCZpLdLapGEk7uQCUgGpkFREKiYNJ5WQSkllpHVII0jrktYjrU/agPta0ijSaNKGpI1IG5M2IfG76Pk97/wOdX4/Ob/7m9+rze+s5vdB87uW+T3G/I5gfv8uv9uW3xvL72Tl953yu0T5PZ38Dkx+vyS/u5Hfi8jvHOT3+fG78vYi8Tve+P1p/G4yfu8Xv1OL31fF74Li9yzxO4z4/UD87h1+rw2/M4bfx8LvOuH3iPA7Ovj9F/w+CH7XAr97gMf15zHzeTx6Huudx1HnMcp5/G8eW5vHreYxoQ8n8VjGPE4wj8HL49vy2LE8LiuPecrjifJYnTwOJo8xyeM38tiIPO4gj+nH4+XxWHQ8zhuPocbjk/HYXzyuFo9ZxeNB8VhLPI4RjxHE4+/w2DY8bgyPyXI5iccS4XE6eAwMHl+Cx27gcRF4zAF+np+flefn0PkZb35+mp9N5ud++Zlafl6VnwXl5yz5GUZ+PpCfvePn2viZMX4ei5914ueI+Bkdfv6Fny3h5zb4mQh+3oDv5ef75PkedL6/m++d5vuS+Z5fvp+WWcT3gfI9lnz/It8byPfd8T1tfL8Y3z/F9xPx/TV8vwnff8H3I/D1eb5ezddv+XomX9/j6118/Yevh/D1AT5fzueP+Xwqn1/k8218/onPx/D5Cf69zr9f+fcc/77h430+/uXjQT4+4uMF5qGdOoq/e5l5eU1N5b7Ta2I11bHyiRNj+0+umRSrnl05o2pqNSNiGcfttJ6ZbzJr2oSaydXTYlRuctWc8dNnTJ5dXlM5vnxWzSSqIDahfFqsetrUObGKSvp76tTKibGZNeU1k/lv5s2ygwE7DTLzMZNn7lteM2FSbFp1TWVsUmX5xMoZsQnV02pmlE+oYW8zKmfOZLIvO4ywU//61p5ZUz2jfO/K2Myp1TXL1uy3igmg/C07gOGJOwI7dbefzZhRPic2edrEygNi1bNqYtVVsYrqWdMmzpQrbtHUFfdo6ooTmrriPk1dcb+mrnhAU1c8rKkrHtvUFU9p6oq3iBVtCxStbt9ZU2smT6dvS51N7w5Rwao22/lNdf1QMzb6WFM3+mwzNvpHUzf6b1NXzEpr4ooFYsUmtYiSpm55x7SmJ3iXpm50VjM2OqepGz23GRu9sKkbnd+Mjd7f1I2+1YyNvtfUjS5pxkb/aepGe6Q3faN90pu40dHN2OiYZqy7XVMNj23qirNW1W2mKXSIWTF7xfqRWETpZFVpvDRLVC4662UTn4j6rz2ZMnyyqq34f9R8nibXMZ+li8/SzWcZ4rMM81mm+CzTfJYlPssS27aftcquZWvZybGoUy5b1B2LqJ3gK8gRcdjJzV1M/J0p/LTS91OaI7bRGD8yP1n6fgJPcS57KCNbxKdVL9fV2slVppOrXFEmW8xbe8hfVGzX1m2XWyfY9tKIbi7aNCIXbRL4aRNyLuz2Wjy3eG7xnFzPnra9rD/KaUQuchL4yQk5FznCjz0+kMc2tlxGini0n2X59VOQ4/jhqb7jkxzhp526n6AkJ1K7TTXkp53w01bdz/LjJf04l393cp2YcpyYckUZ2Y/keogzKrZr65Y+7H5o8dziucVzi+cWzy2eWzy3eG7x3OK5xXOL5xbPLZ5bPPvxLM8H5Yi5LdcqRTzaz9oKP9LbSB0/y641tdePM57jxMlT1FmOib/be867rzi53jxP+WsfaXz+8kT+OnjKn484ud5OnvKXF2l8/jqJ/HX0lD8fcXK9XTzlr1Ok8fnrIvLX2VP+fMTJ9eZ7yl+XSOPzly/y19VT/nzEyfV295S//Ejj89dd5K+bp/z5iJPr7ekpf90jjc9fT5G/Hp7y5yNOrre3p/z1jDQ+f71F/np5yp+POLnevp7y1zvS+Pz1Ffnr4yl/PuL0VO8yvzGRE816+6n7DUq43oEe6uV2ZJ/QaUw7GihyNsDTftGPc/k17NWcmPo7MeWKMvK39Goe4oyK7dq67fJqYj+0eG7x3OK5xXOL5xbPLZ5bPLd4bvHc4rnFc4vnFs8tnv145m0PUt/28nMtcts2PxHHj50Gec5Fm8iKZxD3rqzZurqmcmZU+LJe8x2v0Uht30tFmQ7i8zTxdyuxbqLr1omuxSa6vpjomlmi60CJrm0kOl+f6By0e16Vp77ib/eZKjv1E3XYNp4oL0vNPDuyci6zHS8a/1vqoU6N//EUc+bZYrm+dubnO7q8f3D7K7ssv4+D1bcd8Hhn/w30mGnqtm3Nbi9DlBltkiPblp1kXdan/T7bOtuJmGzZNLEtmd80Ucb+f6n53K2Dy/vM0VBTl81RX8dXhiizZQM5GiqWY5EVObJ1thNx2bLLxiEwf7cRXrYx2/J0bnzZOWwZY0z4GCA+t2Wuiq7wtkN0RTzpoqyNJ9P5zNcz/dFI7TEGYmLZbo89pom8Wj+Z+n7inuLkcQv/Y15mHXFmiDLjGmin7nOY6U5+2kVW7LswxmXI9pSz1k7O5DOlNme2zMQGcta6jpzJdpZoPAQPsRV4eq55Wc5ynJxZ/21EzmyZKQ3kLKeOnGWLnNlcyedrPcRW6Ok52VJ5DOpytq3ImS0zo4GctasjZ5Kz7n27nmIr8nR/Z6k8Rrc5s/5zRc5smTkN5Kx9HTlrK/Jkc+X53tViT/d0lsrfMDZn1n8HkTNb5vAGcpZXR85yRc5srjzfrzrc032cpfI3ns2Z9d9R5MyWOa6BnHWqI2cdRM5srjzfo1ri6d7NUvkb2ObM+u8scmbLnNpAzrrUkbOOImc2V/K+1HRRx0id2JYdL6aJGKKRFcc58jjWljm7ntjkPaPyGQWbI8m1ruJvO88X8dvP7L2Q7cVn9jxDnvjM3vPXSXxmPXcRn9mYOovPbLzSkz3uyxef2eOabuIzG2d38ZllufXEccvfFrYNWS/29538bXGN+G2xvhhbzp734PVHmr/jzZt4PPD/ft+kOd7s9uT9XIrbXvabq5+IPya20198bsvcavLCM3ufXbpZZ4CzHpfp69Qt17Gf93XqTtS2/dx3Fudx2f+L19ZttzMgsnKsWU6ZmIjDlrmzgTj0709cft7A5tG2b+utj/Boy9zTQB8pzwfGIrXvWeOJ+wibH9/3XibyE3Ni4zL2vGaWU0a2QVvm4Qb2kf49uMv3kT0f657b6SU82jILGthH8txuLJL43I6N15ZNE3/L+4HTxHr2//b8V2+n3lgkcRuJmb/7JfBY3z6xZZ5rYJ94uP972ZhLMWdbUWdZ/t/zfe6Fq3rfeA/hx9d94x7irPXch/a4jN2cXPV0cpUryvh+7iMqtmvrtst2ey2ew/GcG1nx3bFe5bFrLEU82s96CT8+voMcuz3etfUzl76Ortiuh2Mufg/Of8eIloPWhzwWtWU2Tl9RdpHx1i5S+/oLTzmRlY/LfD1fIY+bbd12WfK3vxOXp+P4QObU1i1/q9hte9ifvp5hKZTH3Zl15Fgedy9p4Hipj5Mft821i6x8XOnz+RwPvC5c1WNM+yO9sceYNmeyjdtcyWMjD7EV+Drm4ji7Ozmz/nuInNkyrRrIWfc6ctZL5MzmSnJR/3pyPFjV558GCz8enlcNJHMa40fmx8dzpav6nKs83vZxjCCPRxrjp5vw4+H57ECeA2yMH9/Poa/qc91dhR8Pz/8H8lxqY/xYD3yc5/KZP7PfjT7iM9s+e4rPbBsZIj6z+2mA+MzmKk18Zv3a3/XtxGfynoluzme+voOJfkvY5R7Co42lm18/pdKPez5Wfv899NdxyQ97ztQ9RpcsKjQ7ltezbSu9jhzKY0Rbt1zHft7fqbuu8zGDRb0jdeIPPJ1jX7ZP7TWHTCc/Mie2TGkDsfu4zuUp9mXfr04iRq47P0Hstsx6aSvytIH5W3Kyq8jj1gn+b6f6+sHOIpc+xgXibXcQPmNiO3Lb7YVXpW0HctvRSO37AeR1cfv3GPEddu8bsLm23rkftNcppXd3PfcaXa4o0zFB/DHl+N1r+XmOZ94no0U7s+3IF6ejkdovH5U5kudebBnZt+U769nyfUUZu5+ynDJ23QxRZqck9C2yD7DfB+tNXkO3ZXZtwKOHsahKPcVea9+73JOx2zJ7ina5l+jf3HOZ/P/qBP+3U339n7wXw8P9K3HZJ7j3mchty7EYlbYdyG3b/s9ux34u76WaJvo/W87mw+Y60f0s9Y0j2c1ZT44jmZcg/ljET/9v65Y+eOJ9MkG0s2rR//n43ZSoT3b7qNxIbRbb3Mac9Wx52f/990JSp4xdV96fM7uBvsXDeYeE/Z/1Jo+3bZkDk9T/+Tjnkqj/65ogdlvmMNEujxD9m/v7i/9/eoL/26ml/2tc/3daPf2f2481tv9zn8tKxf7vaNHOTg/h+C+vjhzFhDdbRt5X0tVZz5aX/Z/dT+59DvK8ii1zXgN9i4d7aBL2f12dWGX/d1GS+j9f9w/VdfwnY7dlLhft8krRv8XM//NFHucl+L+dWvq/xvV/t9XT/7n9WGP7v5izXir2f3NFO5sn+j9f9x7k1ZGjrsKbLdNT5Na9BmjL13f819WpRx7/3dNA3+LhOkbC/s96k7/RbZkHktT/+biGk6j/S3R+wpZ5VLTLBaJ/k79L7P9fSfB/O7X0f43r/16up/+Lmb9Xtf/r6qyXiv3fk6KdvZKE4z+3j5L93xCR27ruc5P9X8z8neWUkdfQbJm3k9C3yD7Avf4hrw3YMu834NHHs1GeYq+1793jPxm7LfOJaJefif7N7lN5/WNxgv/bqb7+z/M5+FrvNLX7O9H5/3bCq9K2A7lt2/+57yjJEH//LPo/91lTm2vrnf8v+8K61uvprCffidIhQfyxiJ/+39Yt/fPE++RL0c4Wi/4v5slThzpyJK9/2DLy2ZcBznqJrn+4x3/uvQjy+O/PBvoWD+c/E/Z/1pv8jW7LLE1S/+f73K/7jJeM3ZZJF/fbZpq/5fUNeX9h5wT/t1NL/9e4/q9T+oqyDfVjje3/3Oc2U7H/yxbtrLN4xtLX8V+HOnIk75eyZdJEbmPOeu5zb/I3cpZTxq4r77ntaWINs2+RfYB7/UP+NrRl+jbg0cM9G6WeYq+1793jPxm7LTNQtMtBon+z+1Re/yhO8H871df/ef4NFpd9gjs2g9x2W+FVadu13lFn+z857gVPcvyRItH/2XI2H/LYxK5v+xLp3V1vgLNerijTPkH8sYif/t/Wnet45n0yVLSzYtH/eXjOMWGf7PZR8h6h3uIze/+nLS/fzSLvDY158t3b8S2fW7Ue3edc3ef2fbzLg70Ndry545Vxmf7m7yynjBzrzJbZsJ5+NyfBunJcNvm8UUys08f5zNezotHIys/Y2GX57EM/87e8xlbXszmSsbaOLKeMvIZjy2zdAL/0v2PLn++Wz9HFIis/G5Mhymxfj0dZl/U50Im3XWTl51Q89R8Jn5EZnCA2W2aXBvLv4T6HQp99p3ser1+C2G2ZcaJfHy+OD+x+6y/yOC3B/+0UdZZj4m/5XIyH34xx+ZvevV4st91ZeFXadiC3bY8f7Hbs5/J8wr7i+MGWs/mwubbe5XME0ru7Xh9nvVxRJj9B/DHl+N17Dro6nnmfVIh2Nk2wztczGvl15GiwyJEtI59d7ufJTy/Hj/s8ZyL2us/iSfbOrqfPks+O27jls3UxEa+ve7j6R2rHa5e7C4/2sx7CoxuzfMZbvncwou27tCjIEpW7/ZkcI8qW4fGc5PW5DHVPy58x0R9rtWjZc9Ct1Otd3hdni30Xi9Qee9Xmyo7vpd0XZ4t6o5HaY4lGzD6yf3cUZd3xSe2+tt65L7ZjerWuZz133NdcUSYrQfwx5fjdsWndMVUzxWf82zpqkjFSePPR3uTvgYjIX8TxGxE+rR/175UZb9/+zt27smbUrJpJYyfXTKucWWvUfet4pOM4Gll5NHS3DE9pCT7jsnLUOLsNOWqcfLIxzcmIzKRskTYaP71jvED2jmmR2lOa3HD2im0n6jWzhX9Ff4GvluLnG7H8aVy7/2QbcPetr7i4F7BneLgnSJMNJ7J8xFw74uL08glTtq+smTVj2kzZlK1Ft3nL5pEm5u5g57JczCy7dXHTbuVsz90mT9miPs1BmiKRlQf4lt4zIol3WVTfSyDjTY+snIO8BPnJcubSe6SOeNw65N9pkcTdWrSez3ISbCcvwWf/AwRPDwoSDwQA","debug_symbols":"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"},{"name":"constructor","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(initializer)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"signing_pub_key_x","type":{"kind":"field"},"visibility":"private"},{"name":"signing_pub_key_y","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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KuvXCP56A7gaz67Ishc6ZwYDY9vd9vOm7vMt3d7W7R3d3tXtPd3e1+0D3T7U7SPdPtbtE90+1e0z3T7X7QvdvtTtK92+1u0b3b7V7TvdvtftB91+1O0n3X7W7RfdZun2q26/6fa7brN1+0O3Obr9afJIt78K5yddi6L5q9zsc4g3bfyz928592879+849+869+859+879x849x869x859x879584958695859587918491869185918799849986998599879z849z869z859z87978497Oc+1+d+9+c+9+d+9nO/R/O/Rzn/k/nfq5z/5dzPy/nAvctiv7/gmdJDwotiabDsuxNQF/pzPzrLeC4TvH87IO1OfU2zn/17+D6Uu8CY3GqiFik1Xsw/zWp92F9JdUHwFicJiIWUfUhyn/pqPoI1VdTVH0MjMXpEmKRjKpPUP7Tc8+noL7Suq/PgLE4Q0AsmrTNn4P8l9R9fQHqS5usvgTG4kz/Y5E2Nn+F8V+T6etrTF9J09c3wFic5X8sTNfqW4j/0vP6+g7SV9O8vr4HxmKq97FIzrP5B4j/5g1T/YjoKz2/r5+AsTjb91g0zbf5Z4T/kvP7+gXR13yT1SxgLM7xPBYpa/OvAJsbbV+/AfpK2L5+B8biXL9jEct+E3N2eJtVtq8/QveVzGT7mgOMxXlexyLZmLX5z/D+W/AN27mh+0os6OsvYCzO9zoWtblvKBeF7Ust6KtFEW7P8hTgd3Eu8OTLtou5FHDfTAH3fdTpwFhcKCQWwP0BBaxv1VnAWEwTEgtgHaSA63h1DjAWFwmJBXC9p4DrFXU+MBYXC4kFcF5TQC6racBYXCLkzTlA/Spg/imW/yKO/3x4rpztKwJch5o+0GdszPmlNwrx54wKi7CxRtu9ZWHufA3S7ts9P/Vv8rGwCG/3HULeMVAE1CMw1uoOz/PG6CVCyJu7PbfbMIKhl3uE6KUYqBdgrBXSf9lzv9l1hGGEOd9bXJQ751tiF8zo/BpemDvXiYzbDM/f6mlsLiHo6n4h9VJJEc7mUqBGgXmjpMRiOHC9X1bE0bBPunB5WWo5WRbgZTmJlyMKc+feg/2Gfhu057w0NpcTePmwEI2WA3VVAeQlMG+UlFiMAPKysoijYZ904fKywnKyMsDLKhIvRxbmvhcU7Desfx7znJfG5ioCLx8XotEq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","debug_symbols":"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vG5M3l/86PfPi8f+3b+tAi5fa/J17ndfXxrb24uXfZexvH7Hw1NtOZvajaptE0DtJtWeOksUatek9n7UQxmWv1PbJofajaptnUTtitQu66729PoT9k9fLar4eidfC1/5eiNfLdf4eidfre34WpGv8/D8o45hnvvji/t1GneXlvJGbjs+cjcrty0fue8q97btX7nr178rcFaC5sAcTL39oTkwB1Nv2WgObjoHQzfsbyPRTcPfzYHNpDkwB1Nv42kOvnkOtudXHrbu5NXL2R8mTH3hK18r8vW6R1x7y1FqN6q2PSq1a1L7ukdce1tUajeqth0qtStS++xprd6uk6838nWwk+TrnXy1O+TrnXy14+NrRb5e+oDrYHFH7mblLuQm903lvvBpvcFK0ByYg8ere3NgDszBYNloDm46B1c+tTrYTJoDczANNp7m4HvnYFv2TzbouuUvu85o48nXO/lq48nXiny98FZytByldqNqW41Su1G1C7Wp3abadp3UrkftKzPdaH1J7UbVtpGk9tfV3p/cfph9cvGlH2w6jTaHfK3J1+veZGG0DKR2m2oXe0NqN6q2FSO1a1L7uvcPKVaM1G5UbStGalek9tmfwpfCV77eyFfLQL7eyVcbPr7eyVdrO75W5Oul7x5S7PjI3azctnzkvqvcFz4uOlkJmgNzME32h+bAHEyTZaM5uOkcXPlA9mQzaQ7MwTQVc2AOvncOrvxg08nGk681+XrdI66T5Si1G1XbHpXaNal93SOuky0qtRtV2w6V2hWpffa01mzXydc7+Wonydc7+Wp3yNc7+WrHx9eKfL30Ade5kJvcrcpty0fuu8p94dN6s5WgOTAH02x/aA7MwTRbNpqDm87BlU+tzjaT5sAcTIuNpzn43jm49IMiFxtPvt7JVxtPvlbk64W3kovlKLUbVbtQm9ptqm0xSu1G1bbrpHY9al+a6awvqd2o2jaSv6v23O0/4jxPN1G7357f9ON/vnmXj8V+j1WXW7XalrHqeqvstFh1vVU2T6z6slXDtt8FjH33xipLH1Zdb1VhFau+nDf2ox4ffeOkWHztA0xP3kNytUTha02+XvdGe6slCrUbVdsShdqNqm2JQu2a1L7uPSRXmxxqt6n2Zp1E7YrUPns7tM2iiq938tUKjK938tVyja938rXwla/1+HrpO0hudnzkblZuWz5y31XuC/9kcLMSNAfmYNrsD82BOXg4YA7MwT3n4MI/yp07m0lzYA4eFMyBOfjeOfjSZ/Me/2HC3Nl48rUmXy97xHXuLEep3ajahdrUrkjtyx5xnTtbVGo3qrYdKrUrUvvkaa25s+vk6518tZPk6518tTvk64187e34+FqRr1c+4Dr3FnfkblZuWz5y31Xu657Wm3srQXNgDua+mANzYA56y0ZzcNM5uPKp1d5m0hyYg7m38TQH3zsHX/qs09OuY+PJ1zv5auPJ14p8vfBWcrAcpXajaluNUrtRtS1Gqd2o2nad1K5H7Ssz3VCoTe021baRpPbX1d6f3H6YfXLxpR9sOg82h3ytydfr3mRhsAykdqNq2xtSu1G1rRipXZPa171/yGjFSO1G1bZipHZFap/9Kfxob8jXO/lqGcjXO/la+MrXG/lqbcfXiny99N1DRjs+cjcrty0fue8q94WPi45WgubAHMyj/aE5MAdzsWw0BzedgysfyC42k+bAHMzFxtMcfPMcXPnBpsXGk681+XrdI66lUJvabaptj0rtmtS+7hHXYotK7UbVtkOldkVqnz2tVew6+XonX+0k+XojXye7Q77eyVc7Pr5W5OulD7hOFnfkblZuWz5y31XuC5/Wm4o5MAfmYLI/NAfmYJ4sG83BTefgyqdWJ5tJc2AO5snG0xx87xxc+kGRk40nX2/k62zjydeKfL3wVnK2HKV2o2pbjVK7UbUtRqndqNqF2tSuRu0rM91sfUntRtW2kfxltfd/gfulL69qfwCyKqsckB1O5YAsLX4X0NK/fO3hT0CLSl85IK25ckCK6S8D2j4XkcM7QLpf5YAKQL8LaBk+AY1vAGkwlQNSEn4X0NY949Qj689vACkJlQNSEioHpCTUDWhVEn4V0DCOn2//XE4WNWV7HsfUvaxpxvnNtdv+NH/f9d2/Lv4gL1Gkktc+UsmLKm2Sf/DeD7ob36Iv0KeiF4Ji0UtMrf5T/0l+mt6R167aJ7++nXlR7D7kp+m5I5in7uzX/dDt3/Tw8k0Pe8xR20LJbzLeL5PvP8kvZ+SH51eeXv7pHt/+ucn+iUQPgJ/Yn88ibxpeJHYBLxK7eheJvcCeiF21i8Su2EVil+sisWt1kdiFukDsS6fSRWJX6SKxq3SR2FW6SOwF9kTsKl0kdpUuErtKF4ldpYvErtIlYu9VukjsKl0kdpUuErtKF4m9wJ6IXaWLxK7SRWJX6SKxq3SR2FW6ROyDSheJXaWLxK7SRWJX6SKxF9gTsat0kdhVukjsKl0kdpUuErtKl4h9VOkisat0kdhVukjsKl0k9gJ7InaVLhK7SheJXaWLxK7SRWJX6RKxF5UuErtKF4ldpYvErtJFYi+wJ2JX6SKxq3SR2FW6SOwqXSR2lS4R+6TSRWJX6e6Dfennj2uXYX3F/sFSemuHpZ52H5br8DyOdRlOfh2ffNb6MhXgM8FraqHgVbVQ8LpaKHhlLRS8tpYJflbXQsHra6HgxbhQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywS/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhVuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywS/KXeh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5Hg1065CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBN8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAH5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qNyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCL8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+Em5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBD8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAX5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qtyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWC35S7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtI8Fun3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYLvlbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwg3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflTuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywRflLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yk3IWCV+5CwSt3oeCVu1DwBfhM8Mrd74IfpvIf4D8AKWxXAxr3n3AsZTy5el3KsE/b8nr1/O5nLPPzQB7j9nn1Y76fPIWztnjqYW3xlLma4jmrV23xFKXa4qk1tcVTQmqLZ8GzKZ6CT1s89aGreZZl2L/02J1cvX1+19swvfIc3lxdhvV51GXsPr/t8u5LL9P6ce2yfWIZhid5JSmVvOZ0J/LjsO7kx/mV/AdOyaklnIvi1BROwakpnHpTUzjlpqZwFjhbwik2NYVTa2oKp4DUFE5V6Hdxjuvza2+lm/6F84OQ0FM5oVW7qZ2QHFM7IYWldkKiSe2ECkKVE5I2aiekVtROSIConZCm8NuE1p1Qv74jpClUTmjTFGonpCnUTkhT+G1Cy05oWN4R0hRqJ1QQqpyQplA7IU3hdwmV/e1ytrKWd4Q0hdoJaQq1E9IUqiY0dJ2m8LuEpmEnNE1vCWkKtRPSFGonpCnUTqgg9MuExp3QPL8jpCnUTkhTqJ2QplA7IU3hdwnN3U5oHsd3hDSFygn1mkLthDSF2glpCr9MaNn/pHJ580Tjg5CmUDuhglDlhDSF2glpCr+9wdtfKZRteEdIU6idkKbw26+2h/3VdunfEdIUKic0aArnhJb9qcN+naaTM58f/7Z/XD1387t70EEl+Pkzd9//82fuTv7nz7w488r/xXVvXjsh9+a1E3JvXjsh9+a1E3JvXjmh0b157YTcyddOyH3/xfeg6+NUP65e++Vdlx/d9//8mRdn/uNn7k6+8g3h6E6+dkLu5Gsn5E6+dkLu5CsnVNzJ107InXzthNzJ107IfX/lNawUhConpCnUTkhTqJ2QplA7IU2hdkKaQuWEJk2hdkKawtU7uWF6ful17Kd3Z64S/PyZu+//+TMvzvzHz9y9+c+fubvtnz9z98+XP0u0X72Ow/avM39z9Vye3/U6Ty8n/fY1a/f8ZKaxDN3LtR8s3Wm3w9I9eTMsZ3fv7bB0n98OS/3gRix3KmN5pfJkqUu0w7Jg2QxLHaUdlu5JKmX5D5/FfUbdfNw71M3H/UDdfLzG//H9wFKc+Y+fudfMP3/mdo8/f+Z2jz9/5naEP3/m7pt//MxX98I/f+bub3/+zN2z/vyZuw/9+TMvzvzHz9x96M+fufvQyv/SZ3XXWjsh97i1E3JHXDmhzf1z7YTcbddOyL35OaH183ve5rPXz6UfnsdR+uWV0Pw8c/fmP3/mxZn/+Jm7N//5M3dvfvGZT/3yPI5p6Id3Z+5u++fP3P3zz5+5O+KfPvO+c4978Zkvc/+8epnH7d2Zu2v9+TN3H3r1mU9beZ750v/7teKbrc91f7Pad+5v22FZsGyGpfvxdli6z2+HpX5wI5aHf3/cd7pEOyz1jmZY9jpKOywLlnWy/ODjPqNuPu4d6ubjfqBuPl7jX74fmJ5/obDM2/wvPh9n7rX4j5/54DXzz5+53ePPn7nd48+fuR3hz595ceY/fubuhX/+zN3f/vyZu2f9+TN3H/rzZ+4+9MfPfHQf+vNn7j7058/cfejPn7n70B//m4axOPMfP3P3oT9/5u5Df/7M3Yf+/Jm7D/35M3cfenrmw9Q9X/0N07SenPk2js/vYyvd53ls/Vuc47ofxzTuFz8W1R+AipvWygG5w60ckNvhygG9v3ceh+ezVv348i/de0D9tv9LN3TD2so/z6U4mv86msnR/NfRzI7mv45mcTT/dTSro/mvo3GXdPX7T3bdfhz96dUPhs8v3a2f38eyffCZ3CTVzSf0Hmnef3eO88s3fQGfx3/7eXbDus5nNJey/+X4sp6+vH/8Fny+vJ9efsZh3HmG3lJ9H8+vzdvy+dEK6/I6bv9PMENXl7XAPP3lWfCpmk/oSrQWPo9Xf/t5THM5/nX4f7yeFw/D57+bw7y8zWL7v5vDtHy+7/nw7iOdx7LOz++6bOUldL27uN/6/UfclteLP6wKXfqy6lutCl1rs+pbrQpd3LPqW60KjW6s+hurhv0dGsbx5R0adqvm0FTIqm+1SuBk1ZetGvejHsfSHV88rPNn8F2Gk4sfp/e8eOzf/Ns6C7h8rcnXud99fWlsby9epufPt7x+x8NTbTmb2o2qXahN7TbVtkShdk1q70c9lGH5O7VtcqjdqNrWSdSuSO2y7mpPrz/hnj0sqvh6J1+twPh6I18XyzW+3slXazu+VuTrPAzPi+e5P774//6YendpKW/ktuMjd7Ny2/KR+65yb9v+lbt+/asCtxRzYA7MwWJ/aA7MQb9YNpqDm87B0O0Qh24a/m4ObCbNgTl4aGkOzMH3zsH2/MrD1p28ejn9w4TFxpOvNfl63SOuq+UotRtV2x6V2jWpfd0jrqstKrUbVdsOldoVqX32tNZa+MrXG/lqJ8nXO/lqd8jXO/lqx8fXiny99AHX1eKO3M3KbctH7rvKfeHTepuVoDkwB/1mf2gOzEG/WTaag5vOwZVPrW42k+bAHPRbMQfm4FvnYFv2o+665S+7zmbjydc7+WrjydeKfL3yVtJylNqNqm01Su1G1bYYpXaTag+dXSe161H7wkz3GA1qU7tNtW0kqf11tfcntx9mn1x86QebDp3NIV9r8vWyN1kYukJtareptr0htRtV24qR2jWpfdn7hwydFSO1G1XbipHaFal98qfwQ2dvyNcb+dpbBvL1Tr7a8PH1Tr5a2/G1Il+vfPeQobfjI3ezchdyk/umcl/4uGhvJWgOzMHQ2x+aA3Mw9JaN5uCmc3DlA9m9zaQ5MAdDb+NpDr55Di78YNPHip6vfK3I1+secR0sR6ndqNr2qNSuSe3rHnEdbFGp3ajahdrUrkfts6e1BrtOvt7JVztJvt7JV7tDvt7JVzs+vlbk66UPuA4Wd+RuVe7Rlo/cd5X7wqf1RitBc2AOhtH+0ByYg2G0bDQHN52DK59aHYs5MAfmYLTxNAffOwdXflDkMNp48vVOvtp48rUiX6+8lbQcpXajaluNUrtNtYvFKLUbVduuk9r1qH1lpivWl9RuVG0byd9Ve+72H3Gep5uo3W/9/iNub97loxRWsepyq2zLWHW9VXZarLreKpsnVn3ZqmHbT2/suzdWWfqw6nqr7FtY9fW8sR/1+OgbJ8Xiax9gevIekpMlCl9r8vW6N9qbLFGo3ajalijUblRtSxRq16T2de8hORVqU7tNta2TqF2R2mdvhzZZVPH1Tr5agfH1Tr5arvH1Tr5a2/G1Il8vfQfJ2Y6P3M3KbctH7rvKfeGfDM5WgubAHAyz/aE5MAfDXMyBObjnHFz5R7mzzaQ5MAeP/5g5MAffOwdf+mzekz9MmG08+VqTr9c94jpbjlK7UbXtUaldk9rXPeK62KJSu1G17VCpXZHaZ09rLXadfL2Tr3aSfL2Tr4WvfL2Rr3Z8fK3I10sfcF0s7sjdrNy2fOS+q9wXPq23WAmaA3MwLPaH5sAcDKtlozm46Rxc+dTqajNpDszBsNp4moPvnYMvfdbpWddZbTz5eidfC1/5Wo+vV95KWo5Su1G1rUap3ajaFqPUblRtu05q16P2pZnO+pLabaq92UhS++tq709uP8w+ufjaDzbdbA75WpOv173JwmYZSO1G1bY3pHajahdqU7sita97/5DNipHajaptxUjtitQ++1P4zd6Qr3fy1TKQr3fy1YaPr/fx9XG4fOVrPb5e+e4hY2fHR+5m5bblI/dd5b7ucdGxsxI0B+Zg7Io5MAfmoLNsNAc3nYMLH8geO5tJc2AOxs7G0xx88xxc+MGmY2fjydeafL3sEdexsxyldptq9/ao1K5J7csecR17W1RqN6q2HSq1K1L77Gmt3q6Tr3fytfCVrzfy1e6Qr3fy1Y6PrxX5eukDrr3FHbmblduWj9x3lfvCp/V6K0FzYA7Gwf7QHJiDcbBsNAc3nYMrn1odbCbNgTkYBxtPc/C9c3DlB0WOQ+ErX2/kq40nXyvy9cpbSctRajeqttUotRtV22KU2o2qbddJ7XrUvjLTjdaX1G5UbRvJX1Z7/xe4X/ryqvYHIKuyygHZ4VQOqAD0q4CW/uVrD28AqfSVA9KaKwekmP4yoO1zETm8A6T7VQ5IvfplQMvwCWj8E1DRYCoHpCT8LqCte8apR9af3wBSEioHpCRUDqgAVDcgJeFXAf3fquz5XT9gvAL68+KyPY9j6l7WNOP85tptf5q/7/ruXxd/kJcoUslrH6nkRZU2yT947wfdjW/RyzWp6CchKBa9xNTqP/Wf5KfpHXntqn3y69uZF8XuQ36anjuCeerOft0P3f5NDy/fxvCMOVNBPpS8jPfL5PtP8ssZ+eH5fUwv/3SPb//cZP9EogfAT+zPZ5EnDS8Su4AXiV29i8Su3CVin1W7SOyKXSR2uS4Su1YXib3AnohdpYvErtJFYlfpIrGrdJHYVbpE7ItKF4ldpYvErtJFYlfpIrEX2BOxq3SR2FW6SOwqXSR2lS4Su0qXiH1V6SKxq3SR2FW6SOwqXST2AnsidpUuErtKF4ldpYvErtJFYlfpErFvKl0kdpUuErtKF4ldpYvEXmBPxK7SRWJX6SKxq3SR2FW6SOwqXSD20ql0kdhVukjsKl0kdpUuEnuBPRG7SheJXaWLxK7SRWJX6SKxq3SJ2HuVLhK7SheJXaWLxK7SRWIvsCdiV+kisat098G+9PPHtcuwvmL/YCm9tcNST7sPy3V4Hse6DCe/jk8+a730ilom+EFTCwWvqoWC19VCwStroeAL8Jng1bVQ8PpaKHgxLhS8chcKXrnLBD8qd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meCLchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+Uu5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBz8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+EW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBL8qd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meA35S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhL81Cl3oeCVu1Dwyl0oeOUuFHwBPhO8chcKXrkLBa/chYJX7kLBK3eZ4HvlLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yg3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYIflbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwRbkLBa/chYJX7kLBK3eh4AvwmeCVu1Dwyl0oeOUuFLxyFwpeucsEPyl3oeCVu1Dwyl0oeOUuFHwBPhO8chcKXrkLBa/chYJX7kLBK3eZ4GflLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yi3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYJflbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwm3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8chcJfu6Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7TPC9chcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+UO5+F/wwlf8A/wFIYftVQMv0/NLruhzP5Tbtg7lNLz/gMO4wVbOGYCphvwpzm/fj6NbtzW/Ogk/VfHSlX+XTT91+HtNcjn8d9kO/XzwM8+evw3l5dyBTWZ8HMi3959XDu++6rPPzuy7b5/cxvHtBO/Zbv/+I2/J68YdVohWrrrdKEWPV9VbJbay63iotj1VftmrY9tN7tMg/rRqFQlZdb5W6yaovWzXuRz2OpTu+eFjnfbPyui55f/Hj9J4Xj/2bf1tHAZevNfk697uvL43t7cXL9Pz5ltfveHiqLWdTu1G1C7Wp3abalijUrknt/aiHMix/p7ZNDrUbVds6idoVqV3WXe3p9Sfcs4dFFV/v5KsVGF9v5GuxXOPrnXy1tuNrRb7Ow/C8eJ7744v7dRp3l5byRm47PnI3K7ctH7nvKve27V+569e/KnClmANzYA6K/aE5MAdzsWw0Bzedg6HbIQ7dNPzdHNhMmgNzMBcbT3PwzXOwPb/ysHUnr15O/zCh2HjytSZfr3vEdbIcpXajatujUrsmta97xHWyRaV2o2rboVK7IrXPntaaCl/5eiNf7ST5eidf7Q75eidf7fj4WpGvlz7gOlnckbtZuW35yH1XuS98Wm+2EjQH5uDx3zIH5sAczJaN5uCmc3DlU6uzzaQ5MAfzXMyBOfjWOdiW/ai7bvnLrjPbePL1Tr7aePK1Il+vvJW0HKV2o2pbjVK7UbUtRqndptqLXSe161H7yky3WF9Su1G1bSSp/XW19ye3H2afXHztB5suNod8rcnX695kYSnUpnabatsbUrtRta0YqV2T2te9f8hixUjtRtW2YqR2RWqf/Sn8Ym/I1xv5uloG8vVOvtrw8fVOvlrb8bUiXy9995DVjo/czcpdyE3um8p94eOiq5WgOTAH82p/aA7MwbxaNpqDm87BlQ9krzaT5sAczKuNpzn45jm48oNNNxtPvtbk63WPuG6Wo9RuVG17VGrXpPZ1j7hutqjUblTtQm1q16P22dNam10nX+/kq50kX+/kq90hX+/kqx0fXyvy9dIHXDeLO3I3KvfS2fKR+65yX/e03tJZCZoDc7B09ofmwBwsnWWjObjpHFz41OrSFXNgDsxBZ+NpDr53Dq78oMils/Hk6518tfHka0W+XnkraTlK7UbVthqldptq9xaj1G5UbbtOatej9pWZrre+pHajattI/q7ac7f/iPM83UTtfuv3H3H7810+lr6wilWXW2VbxqrrrbLTYtX1Vtk8serLVg3bfnpj372xytKHVddbZd/Cqq/njf2ox0ffOCkWX/sA0+P3kFwGSxS+1uTrZW+0twyWKNRuVG1LFGo3qrYlCrVrUvuy95BchkJtareptnUStStS++Tt0JbBooqvd/LVCoyvd/LVco2vd/LV2o6vFfl66TtIjnZ85G5Wbls+ct9V7gv/ZHC0EjQH5mAZ7Q/NgTlYxmIOzME95+DKP8odbSbNgTlYRhtPc/DNc/Clz+Y9+cOE0caTrzX5et0jrqPlKLUbVdseldo1qX3dI67FFpXajapth0rtitQ+e1qr2HXy9U6+2kny9U6+Fr7y9Ua+2vHxtSJfL33AtVjckbtZuW35yH1XuS98Wq9YCZoDc7AU+0NzYA6WybLRHNx0Dq58anWymTQH5mCZbDzNwffOwZc+6/Ss60w2nny9k6+Fr3ytx9crbyUtR6ndqNpWo9RuVG2LUWo3qrZdJ7XrUfvSTGd9Se021Z5tJKn9dbX3J7cfZp9cfO0Hm842h3ytydfr3mRhtgykdqNq2xtSu1G1C7WpXZHa171/yGzFSO1G1bZipHZFap/9Kfxsb8jXO/lqGcjXO/lqw8fXG/m6WNvxtSJfL333kMWOj9zNym3LR+67yn3h46KLlaA5MAfLUsyBOTAHi2WjObjpHFz5QPZiM2kOzMGy2Hiag2+egys/2HSx8eRrTb5e94jrYjlK7TbVXu1RqV2T2tc94rraolK7UbXtUKldkdpnT2utdp18vZOvha98vZGvdod8vZOvdnx8rcjXSx9wXS3uyN2s3LZ85L6r3Bc+rbdaCZoDc7Bs9ofmwBwsm2WjObjpHFz51OpmM2kOzMGy2Xiag++dg0s/KHIrfOXrjXy18eRrRb5eeStpOUrtRtW2GqV2o2pbjFK7UbXtOqldj9oXZrq1s76kdqNq20j+str7v8D90pdXtT8AWZVVDsgOp3JABaBfBbT0L197eANIpa8ckNZcOSDF9JcBbZ+LyOEdIN2vckDq1S8DWoZPQOOfgHoNpnJASsLvAtq6Z5x6ZP35DSAloXJASkLlgApAdQNSEn4V0DCOn2//XE4WNWV7HsfUvaxpxvnNtdv+NH/f9d2/Lv4gL1Gkktc+UsmLKm2Sf/DeD7ob36KXa1LRD0JQLHqJqdV/6j/JT9M78tpV++TXtzMvit2H/DQ9dwTz1J39uh+6/ZseXr6N4RlzhoJ8KHkZ75fJ95/klzPyw/P7mF7+6R7f/rnJ/olED4Cf2J/PIg8aXiR2AS8Su3oXiV25S8Q+qnaR2BW7SOxyXSR2rS4Se4E9EbtKF4ldpYvErtJFYlfpIrGrdInYi0oXiV2li8Su0kViV+kisRfYE7GrdJHYVbpI7CpdJHaVLhK7SpeIfVLpIrGrdJHYVbpI7CpdJPYCeyJ2lS4Su0oXiV2li8Su0kViV+kSsc8qXSR2lS4Su0oXiV2li8ReYE/ErtJFYlfpIrGrdJHYVbpI7CpdIvZFpYvErtJFYlfpIrGrdJHYC+yJ2FW6SOwqXSR2lS4Su0oXiV2lS8S+qnSR2FW6SOwqXSR2lS4Se4E9EbtKF4ldpbsP9qWfP65dhvUV+wdL6a0dlnrafViuw/M41mU4+XV89lnrq6KWCX7T1ELBq2qh4HW1UPDKWij4AnwmeHUtFLy+FgpejAsFr9yFglfuIsFvnXIXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJvlfuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywQ/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhRuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywRflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwk3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflbuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywS/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhVuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywS/KXeh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd4ngH9+kchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwm+V+5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBD8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+FG5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBF+Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7TPCTchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+Vu5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBL8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+FW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBL8pd78LfpjKf4D/AKSw/SqgZXp+6XVdjudym/bB3KaXH3AYd5iqWUMwlbBfhbnN+3E8Xr+8+c1Z8Kmaj670q3z6qdvPY5rL8a/Dfuj3i4dh/vx1OC/vDmQq6/NApqX/vHp4912XdX5+12X7/D6Gdy9ox37r9x9xW14v/rBKtGLV9VYpYqy63iq5jVXXW6XlserLVg3bfnqPFvmHVX0nFLLqeqvUTVZ92apxP+pxLN3xxcM675uV13XJ+4sfp/e8eOyXN74KuHytyde53319aWxvL16m58+3vH7Hw1NtOZvajapdqE3tNtW2RKF2TWrvRz2UYfk7tW1yqN2o2tZJ1K5I7bLuak+vP+GePSyq+HonX63A+HojX3vLNb7eyVdrO75W5Os8DM+L57k/vrhfp3F3aSlv5LbjI3ezctvykfuucm/b/pW7fv2rAtcXc2AOzEFvf2gOzEHfWzaag5vOwdDtEIduGv5uDmwmzYE56HsbT3PwzXOwPb/ysHUnr15O/zCht/Hka02+XveI62A5Su1G1bZHpXZNal/3iOtgi0rtRtW2Q6V2RWqfPa01FL7y9Ua+2kny9U6+2h3y9U6+2vHxtSJfL33AdbC4I3ezctvykfuucl/4tN5oJWgOzMHj/5kDc2AORstGc3DTObjyqdXRZtIcmIN+LObAHHzrHGzLftRdt/xl1xltPPl6J19tPPlaka9X3kpajlK7UbWtRqndqNoWo9RuU+1i10ntetS+MtMV60tqN6q2jSS1v672/uT2w+yTi6/9YNNic8jXmny97k0WSqE2tdtU296Q2o2qbcVI7ZrUvu79Q4oVI7UbVduKkdoVqX32p/DF3pCvN/J1sgzk6518teHj6518tbbja0W+XvruIZMdH7mblbuQm9w3lfvCx0UnK0FzYA4eZ28OzIE5mCwbzcFN5+DKB7Inm0lzYA76ycbTHHzzHFz5waazjSdfa/L1ukdcZ8tRajeqtj0qtWtS+7pHXGdbVGo3qnahNrXrUfvsaa3ZrpOvd/LVTpKvd/LV7pCvd/LVjo+vFfl66QOus8UduVuVe7HlI/dd5b7wab3FStAcmIN+sT80B+agXywbzcFN5+DKp1aXYg7MgTlYbDzNwffOwaUfFLnYePL1Tr7aePK1Il+vvJW0HKV2o2pbjVK7TbVXi1FqN6q2XSe161H7yky3Wl9Su1G1bSR/V+2523/EeZ5uona/9fuPuL15l4+1sIpVl1tlW8aq662y02LV9VbZPLHqy1YN2356Y9+9scrSh1XXW2Xfwqqv5439qMdH3zgpFl/7ANOT95DcLFH4WpOv173R3maJQu1G1bZEoXajaluiULsmta97D8mtUJvabaptnUTtitQ+ezu0zaKKr3fy1QqMr3fy1XKNr3fy1dqOrxX5euU7SA6dHR+5m5Xblo/cd5X7uj8ZHDorQXNgDobO/tAcmIOhK+bAHNxzDi78o9zH/705MAfmoLPxNAffPAdf+mze4z9MGDobT77W5Otlj7gOneUotRtV2x6V2jWpfdkjrkNvi0rtRtW2Q6V2RWqfPK019HadfL2Tr3aSfL2Tr4WvfL2Rr3Z8fK3I10sfcO0t7sjdrNy2fOS+q9wXPq3XWwmaA3Mw9PaH5sAcDINlozm46Rxc+dTqYDNpDszBQx5zYA6+dQ6+9FmnZ11nsPHk6518LXzlaz2+XnkraTlK7UbVthqldqNqW4xSu1G17TqpXY/al2Y660tqt6n2aCNJ7a+rvT+5/TD75OJLP9j08f/JV75W5Ot1b7IwWgZSu1G17Q2p3ajahdrUrkjt694/ZLRipHajalsxUrsitc/+FH60N+TrnXy1DOTrnXy14ePrjXwt1nZ8rcjXS989pNjxkbtZuW35yH1XuS98XLRYCZoDczCUYg7MgTkolo3m4KZzcOUD2cVm0hyYg6HYeJqDb56DKz/YtNh48rUmX697xLVYjlK7TbUne1Rq16T2dY+4Trao1G5UbTtUalek9tnTWpNdJ1/v5GvhK19v5KvdIV/v5KsdH18r8vXSB1wniztyNyu3LR+57yr3hU/rTVaC5sAcDLP9oTkwB8Ns2WgObjoHVz61OttMmgNzMMw2nubge+fg0g+KnAtf+XojX208+VqRr1feSlqOUrtRta1Gqd2o2haj1G5UbbtOatej9pWZbrG+pHajattI/rLa+7/A/dKXV7U/AFmVVQ7IDqdyQAWgXwW09C9fe3gDSKWvHJDWXDkgxfSXAW2fi8jhHSDdr3JA6tUvA1qGT0Djn4BWDaZyQErC7wLaumecemT9+Q0gJaFyQEpC5YAKQHUDUhJ+FdAwjp9v/1xOFjVlex7H1L2sacb5zbXb/jR/3/Xdvy7+IC9RpJLXPlLJiyptkn/w3g+6G9+il2tS0W9CUCx6ianVf+o/yU/TO/LaVfvk17czL4rdh/w0PXcE89Sd/bofuv2bHl6+jeEZc7aCfCh5Ge+Xyfef5Jcz8sPz+5he/uke3/65yf6JRA+An9ifzyJvGl4kdgEvErt6F4lduQvE/vgeYU/ErthFYpfrIrFrdZHYC+yJ2FW6SOwqXSR2lS4Su0oXiV2lS8Teq3SR2FW6SOwqXSR2lS4Se4E9EbtKF4ldpYvErtJFYlfpIrGrdInYB5UuErtKF4ldpYvErtJFYi+wJ2JX6SKxq3SR2FW6SOwqXSR2lS4R+6jSRWJX6SKxq3SR2FW6SOwF9kTsKl0kdpUuErtKF4ldpYvErtIlYi8qXSR2lS4Su0oXiV2li8ReYE/ErtJFYlfpIrGrdJHYVbpI7CpdIvZJpYvErtJFYlfpIrGrdJHYC+yJ2FW6SOwq3X2wL/38ce0yrK/YP1hKb+2w1NPuw3IdnsexLsPJr+OTz1ofJ0UtE/ysqYWCV9VCwetqoeCVtVDwBfhM8OpaKHh9LRS8GBcKXrkLBa/cZYJflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwq3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflPuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4iwZdOuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywTfK3eh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5ngB+UuFLxyFwpeuQsFr9yFgi/AZ4JX7kLBK3eh4JW7UPDKXSh45S4T/KjchYJX7kLBK3eh4JW7UPAF+Ezwyl0oeOUuFLxyFwpeuQsFr9xlgi/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhJuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywQ/K3eh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5ngF+UuFLxyFwpeuQsFr9yFgi/AZ4JX7kLBK3eh4JW7UPDKXSh45S4T/KrchYJX7kLBK3eh4JW7UPAF+Ezwyl0oeOUuFLxyFwpeuQsFr9xlgt+Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7SPBTp9yFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWC75W7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtM8INyFwpeuQsFr9yFglfuQsEX4DPBK3eh4JW7UPDKXSh45S4UvHKXCX5U7kLBK3eh4JW7UPDKXSj4AnwmeOUuFLxyFwpeuQsFr9yFglfuMsEX5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8pNyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCn5W73wU/TOU/wH8AUtiuBtRvw/NLP76Rs6vXaX1evW5nV2/TPpvb9PIzDuPOUzi7mucwP68ex6mcXL1Mz4vXdTn+Pfs/wBTDfhXmNu/H0a3bm1+eBZ+q+UhLv8qnn7r9PB7DcvzrsB/6/eJhmD9/Hc7LuwOZyvPfzWFa+s+rh3ffdVnn53ddts/vY+jf//vd7y+wtuX14g+rdCtWXW+VKMaq661S3Fh1vVVyHqu+bNWw7af3yJF/WrVohay63iqBk1Vftmrcj3ocS3d88bDO+3LldWPy/uJHv39ePPZv/m1dBFy+1uTr3O++vjS2txcv+y5jef2Oh6facja1G1W7UJvabaptiULtmtTej3oow/J3atvkULtRta2TqF2R2mXd1Z5ef8I9e1hU8fVOvlqB8fVGvq6Wa3y9k6/WdnytyNd5eP5RxzDP/fHF/TqNu0tLeSO3HR+5m5Xblo/cd5V72/av3PXrXxW4tZgDc2AOVvtDc2AOptWy0RzcdA6Gboc4dNPwd3NgM2kOzMG02niag2+eg+35lYetO3n1cvqHCauNJ19r8vW6R1w3y1FqN6q2PSq1a1L7ukdcN1tUajeqth0qtStS++xpra3wla838tVOkq938tXukK938tWOj68V+XrpA66bxR25m5Xblo/cd5X7uqf15s5K0ByYg7mzPzQH5mDuLBvNwU3n4MKnVufOZtIcmIO5K+bAHHzrHGzLftRdt/xd15k7G0++3slXG0++VuTrlbeSlqPUblRtq1FqN6q2xSi121S7t+ukdj1qX5npeutLajeqto0ktb+u9v7k9sPsk4sv/WDTubc55GtNvl72JgtzX6hN7TbVtjekdqNqWzFSuya1L3v/kLm3YqR2o2pbMVK7IrVP/hR+7u0N+XojXwfLQL7eyVcbPr7eyVdrO75W5OuV7x4yD3Z85G5W7kJuct9U7gsfFx2sBM2BOZgH+0NzYA7mwbLRHNx0Dq58IHuwmTQH5mAebDzNwTfPwYUfbDqPNp58rcnX6x5xHS1Hqd2o2vao1K5J7esecR1tUandqNqF2tSuR+2zp7VGu06+3slXO0m+3slXu0O+3slXOz6+VuTrpQ+4jhZ35G5V7mLLR+67yn3h03rFStAcmIO52B+aA3MwF8tGc3DTObjyqdVSzIE5MAfFxtMcfO8cXPpBkcXGk6938tXGk68V+XrlraTlKLUbVdtqlNptqj1ZjFK7UbXtOqldj9pXZrrJ+pLajaptI/m7as/d/iPO83QTtfvt+U0//uebd/mYCqtYdblVtmWsut4qOy1WXW+VzROrvmzVsO2nN/bdG6ssfVh1vVX2Laz6et7Yj3p89I2TYvG1DzA9eQ/J2RKFrzX5et0b7c2WKNRuVG1LFGo3qrYlCrVrUvu695CcC7Wp3aba1knUrkjts7dDmy2q+HonX63A+HonXy3X+HonX63t+FqRr5e+g+Rix0fuZuW25SP3XeW+8E8GFytBc2AO5sX+0ByYg4cD5sAc3HMOrvyj3MVm0hyYg3mx8TQH3zwHX/ps3pM/TFhsPPlak6/XPeK6WI5Su1G17VGpXZPa1z3iutqiUrtRte1QqV2R2mdPa612nXy9k692kny9k6+Fr3y9ka92fHytyNdLH3BdLe7I3azctnzkvqvcFz6tt1oJmgNzMK/2h+bAHMybZaM5uOkcXPnU6mYzaQ7MwbzZeJqD752DL33W6VnX2Ww8+XonXwtf+VqPr1feSlqOUrtRta1Gqd2o2haj1G5UbbtOatej9qWZzvqS2k2qvXQ2ktT+utr7k9sPs08uvvSDTZfO5pCvNfl62ZssLJ1lILUbVdvekNqNql2oTe2K1L7s/UOWzoqR2o2qbcVI7YrUPvlT+KWzN+TrnXy1DOTrnXy14ePrjXztre34WpGvV757yNLb8ZG7Wblt+ch9V7mve1x06a0EzYE5WPpiDsyBOegtG83BTefgygeye5tJc2AOlt7G0xx88xxc+MGmS2/jydeafL3uEdfecpTabao92KNSuya1r3vEdbBFpXajatuhUrsitc+e1hrsOvl6J18LX/l6I1/tDvl6J1/t+Phaka+XPuA6WNyRu1m5bfnIfVe5L3xab7ASNAfmYBntD82BOVhGy0ZzcNM5uPKp1dFm0hyYg2W08TQH3zsHV35Q5DIWvvL1Rr7aePK1Il+vvJW0HKV2o2pbjVK7UbUtRqndqNp2ndSuR+0rM12xvqR2o2rbSP6y2vu/wP3Sl1e1PwBZlVUOyA6nckAFoF8FtPQvX3t4A0ilrxyQ1lw5IMX0lwFtn4vI4R0g3a9yQOrVLwNahk9A45+AJg2mckBKwu8C2rpnnHpk/fkNICWhckBKQuWACkB1A1ISfhXQMI6fb/9cThY1ZXsex9S9rGnG+c212/40f9/13b8u/iAvUaSS1z5SyYsqbZJ/8N4PuhvfopdrUtHPQlAseomp1X/qP8lP0zvy2lX75Ne3My+K3Yf8ND13BPPUnf26H7r9mx5evunhGXPmgnwoeRnvl8n3n+SXM/LD8ytPL/90j2//3GT/RKIHwE/sz2eRZw0vEruAF4ldvYvErtwlYl9Uu0jsil0kdrkuErtWF4m9wJ6IXaWLxK7SRWJX6SKxq3SR2FW6ROyrSheJXaWLxK7SRWJX6SKxF9gTsat0kdhVukjsKl0kdpUuErtKl4h9U+kisat0kdhVukjsKl0k9gJ7InaVLhK7SheJXaWLxK7SRWJX6QKxr51KF4ldpYvErtJFYlfpIrEX2BOxq3SR2FW6SOwqXSR2lS4Su0qXiL1X6SKxq3SR2FW6SOwqXST2AnsidpUuErtKF4ldpYvErtJFYlfpErEPKl0kdpUuErtKF4ldpYvEXmBPxK7SRWJX6e6Dfennj2uXYX3F/sFSemuHpZ52H5aPG+OPa9dlOPl1fPJZ6+ugqGWCHzW1UPCqWih4XS0UvLIWCr4AnwleXQsFr6+FghfjQsErd6HglbtM8EW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBD8pd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meBn5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8otyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCX5W7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtM8JtyFwpeuQsFr9yFglfuQsEX4DPBK3eh4JW7UPDKXSh45S4UvHIXCX7rlLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwvXIXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflDuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywY/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvii3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYKflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zws3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflHuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywa/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhNuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65SwRfuk65CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBN8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAH5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qNz9LvhhKv8B/gOQwnY1oHH/CcdSxpOr16UM+7Qtr1fP737GMj8P5DFun1c/5vvJUzhri6ce1hbPgmdTPNWrtniKUm3x1Jra4ikhtcVTGWqKZxF82uKpD13NsyxPQuM0didXb5/f9TZMrzyHN1eXYX0edRn/73w/ri7vvvQyrR/XLtvnTzgMT/JKUip5zelO5Mdh3cmP8yv5D5wFzpZwKk5N4RScmsKpNzWFU25qCqfa1BLOSWxqCqfW1BROAakpnKrQ7+Ic1+fX3h40/oXzg1BBqHJC2k3thOSY2gkpLLUTEk1qJ6SDVE5oljZqJ6RW1E5IgKidkKbw24TWnVC/viNUEKqckKZQOyFNoXZCmsJvE1p2QsPyjpCmUDshTaFyQoumUDshTeF3CZX97XK2spZ3hDSF2glpCrUTKghVTkhT+F1C0/6NbNP0lpCmUDshTaF2QppC7YQ0hd8mNO6E5vkNoVVTqJ2QplA7IU2hdkKawu8Smrud0DyO7wgVhConpCnUTkhTqJ2QpvDLhJb9TyqXt080rppC7YQ0hcoJbZpC7YQ0hd/e4O2vFMo2vCOkKdROSFP47Vfbw/5qu/TvCBWEKiekKZwTWvanDvt1mk7OfO76+ePquZvf3YNuKsHPn7n7/p8/c3fyP3/m7s3r/he379yb107IvXnthNyb107IvXnthApClRNyb147IXfytRNy33/xPejaD8+zW/tleHfm7vt//szd9//4mffu5OveEPa9O/naCbmTr52QO/naCRWEKifkTr52Qu7kayfkTr52Qu77K69hvUpQOaFBU6idkKZQOyFNoXZCmkLthApClRPSFGonpClcvZMbpifPdeynd2euEvz8mbvv//kzdyf/42c+ujf/+TN3t/3zZ+7++fJnifar13HY/nXmb66ey/O7Xufp5aTfvmbtnp/MNJahe7n2g6U77XZYFiybYenuvR2W7vPbYakf3IjlTmUsr1SeLHWJdljqHc2wLDpKOywLlnWy/ODjPqNuPu4d6ubjfqBuPl7j//h+oHgt/uNnPnnN/PNnbvf482du9/jzZ25H+PNnXpz5j5+5e+GfP3P3tz9/5u5Zf/7M3Yf+/Jm7D/3xM5/dh/78mbsPrfwvfWZ3rbUTco9bO6GCUOWE3D/XTsjddu2E3JufE1o/v+dtPnv9/H/vJvFxdemXV0Lz88zdm//8mbs3//EzX9yb//yZuze/+MynfnkexzT0w7szd7f982fu/vnnz7w48x8/c/e4F5/5MvfPq5d53N6dubvWnz9z96FXn/m0Pb/0svT/fq34Zutz4d+sLu5v22HpvrkZlqv78XZYus9vh6V+cCOWx39/vOoS7bAsWDbDUkdph6V7kkpZ/sNnc59RNx/3DnXzcT9QNx+v8S/fD0zPv1BY5m3+F5+PMy/O/MfP3Gvmnz9zu8efP3O7x58/czvCnz9z980/feZD517458/c/e3Pn7l71p8/c/ehP3/mxZn/+Jm7D/35M3cf+vNn7j7058/cfehP/03D0LkP/fEz792H/vyZuw/9+TN3H/rzZ+4+9OfPvDjzszMfpu756m+YpvXkzLdxfH4fW+k+v/TWv8U5rvtxTON+8eN3/hOQm9bKAbnDrRyQ2+HKAb2/dx73778fX/6lew/osXx/EnrsENYrz3Eqz/fVGqdt++F/njdH8x9HM3SO5r+Opnc0/3U0g6P5r6MZHc1/HU3xEuLi95/suv04+tOrHwyfX7pbP9kv25OPm6S6+TR0j7T/BcAwdsvJkff9/ruzHz6/8uO1y/NgGro3ufZgGtqnXXswDS29Lj2YsaHN1LUH09D66NqDaWjH86WDGfcfsH95M++Xg2loEXPtwRQH8/5gGnoBfu3BpL7yPT2Y1Fe+pwfTzivfx27geTBlPDmYcSvPDcS4bf3xxdP0/DiKuX/5NIpxfJ5hOy+Sv+0Ml3H/U/YyvjnD0s7r6a+c4ePa/a3xu/nUw/0j7l7zy/tEsvfLbek+D24Y3/184yfI9bOi/l9Q/fPSZR+GcVmm44sfy7iXj/BbXi/+oN7OzQLq/zv1du6EUP/fqbdzm4f6fm7jvGf+cRveUC+oB1Jv5wYd9f+dejv1AfX/nXo7aQX1/dym/cGAxw5+Pr543d8ofB3WN4JkJiaC/M+CZPYzgvyvgkziIEEOBcksSl8q8PMyf1w7vzzp91ngJ33GkB0OWSEIQY4EUX0IciiIQESQQ0G0JIIcCqIlEeRQEC2JIEeCzFoSQQ4F8UwaQQ4F8fgaQQ4FUVIJcihIIQhBjgRRUglyKIiSSpBDQZRUghwKIpQR5EiQRSgjyKEgQhlBDgURyghyKIhQRpBDQQpBCHIkiFBGkENBhDKCHAoilBHkUBCPHBLkUBAllSBHgqxKKkEOBVFSCXIoiJJKkENBlFSCHApSCEKQI0F0kHBB+m58+Vyt8kYRJYQiJ4poIRQ5VmRTQyhyooi7mQYVWdb13SF/Ui+oB1L3BEcidY9lJFLXGBKpywaJ1JWAPOpj5+Y+kbrnFxKpeyghkbo2l0i9oB5IXZtLpK7NBVIfvIbP+1DmcfAaPpG61/CJ1AvqgdS9hk+k7jV8InX79UTq9uuJ1O3XA6mP9uuJ1L2GT6TuNXwida/hE6l7DZ9I3Wv4QOrFa/hE6vbridTt1xukPs7P76Ift+ENdfv1ROoF9UDq2lwidW3O2+k9f7o3b6f3+BYJQpAjQRQ/ghwKIg4S5EiQyStPghwK4kUqQQ4F8SKVIIeCeJFKkENBvEglyJEgs2U3QQ4FsRcnyKEgVugEORTEtp0gh4IUghDkSBAllSCHgiipBDkUREklyKEgSipBDgVRUglyJMiipBLkUBB3MQQ5FMRdDEEOBXEXQ5BDQdzFEORQEHcxBDkSZHUXQ5BDQTwPQpBDQTwPQpBDQTwPQpBDQQpBCHIkiJJKkENBlFSCHAqipBLkUBAllSCHgiipBDkSZFNSCXIoiLuYcEH6btwv7tbyRhH3MRQ5UcSdDEVOFHEvQ5ETRdzNUORQkdK5n6HIiSKeDaHIiSKeDqHIiSKeD6HIiSKFIhQ5VkRdpciJIrpIg4os6/r/sXdGSY7kOJC9y36PtQUQJIM8zB5l7r4CqxSVvROSsiQB6R7CX5t1Kv0VQRJJiKAfDfKfqGep4wOjLlm9+MSoZ0HiE6OeNYZPjHqWDT4x6iWj/oFRz8P9J0Y9b0N9YtTzgtMnRj1rc58Y9azNfWDUNWtznxj1rM19YNTX/Bv+hFHv67YPct0Oop5/w39i1PNv+E+Mev4N/4FRL/k3/CdGPf+G/8So5/frnxj1/H79E6NeMuofGPX8fv0Do14z6p8Y9azIfmLUsyL7iVHPiuwnRj0rsh8Y9ZYV2U+MelZkPzHqWZE9YdTXdqWQdehB1LMi+4lRLxn1D4x61uY+MepZm8s35K//Ou0HEyTLeDlB7k6QrPjlBLk7QbI4mBPk3gTZ8i/PnCB3J0j+kZoT5O4EyT9Sc4LcnSD5R2pOkLsTJP9IzQlyb4L0/LI7J8jdCZLfi+cEuTtB8iv0nCB3J0h+254T5O4EKTlBcoLcmyBZSc0JcneCZCU1J8jdCZKV1JwgdydIVlJzgtydIFlJzQlyb4KMrKTmBLk7QfIUkxPk7gTJU0xOkLsTJE8xOUHuTpA8xeQEuTtB8hSTE+TOBKlLnmJygtydIHkfJCfI3QmS90FygtydIHkfJCfI3QlScoLkBLk3QbKSmhPk7gTJSmpOkLsTJCupOUHuTpCspOYEuTtBspKaE+TeBJGspOYEuTtB8hTz4RNElnX/4aWXgymS55icIg+mSJ5kcoo8mCJ5lskp8mCK5Gkmp8j9KaJ5nskp8mCK5N2QnCIPpkjeDskp8mCK5P2QnCIPpkjJKZJT5P4UyepqTpEHUySrqzlFHkyRrK7mFHkwRbK6mlPkwRTJ6mpOkftTZM3qak6RB1Mk6yInnCJb70eD/CfqJaP+gVHP6sUnRj0LEp8Y9awxfGLUs2zwiVHPSsAHRr3k4f4To563oT4x6nnB6ROjnrW5T4x6yah/YNSzNveJUc/a3AdGveXf8CeMel+3fZDrdhD1/Bv+E6Oef8N/YtRLRv0Do55/w39i1PNv+E+Men6//olRz+/XPzHq+f36B0Z9y+/XPzDqPaP+iVHPiuwnRj0rsp8Y9azIfmLUS0b9A6OeFdlPjHpWZD8x6lmRPWHU13alkHXoQdSzIvuJUc+K7AdGfWRt7hOjnrW5tDy6/uu0H0yQLOPlBLk7QbLilxPk7gQpOUFygtyeIG3JvzxzgtydIPlHak6QuxMk/0jNCXJ3guQfqTlB7k6QkhMkJ8i9CZJfducEuTtB8nvxnCB3J0h+hZ4T5O4EyW/bc4LcnSD5xXxOkHsTRLKSmhPk7gTJSmpOkLsTJCupOUHuTpCspOYEuTtBSk6QnCD3JkhWUnOC3JsgmqeYnCB3J0ieYnKC3J0geYrJCXJ3guQpJifI3QlScoLkBLk3QfIUkxPk7gTJ+yA5Qe5OkLwPkhPk7gTJ+yA5Qe5OkLwPkhPk3gRZs5KaE+TuBMlKak6QuxMkK6k5Qe5OkKyk5gS5O0FKTpCcIPcmSFZSc4LcmyAlTzEfPkFkWfcfXno5mCJ5jskp8mCK5Ekmp8iDKZJnmZwiD6ZIySmSU+T+FMnzTE6RB1Mk74bkFHkwRfJ2SE6RB1Mk74fkFHkwRfKGSE6R+1OkZnU1p8iDKZLV1ZwiD6ZIVldzijyYIlldzSnyYIqUnCI5Re5Pkayu5hR5MEWyLnLCKbL1fjTIf6KepY4PjHrL6sUnRj0LEp8Y9awxfGLUs2zwiVEvGfUPjHoe7j8x6nkb6hOjnhecPjHqWZv7xKhnbe4Do75lbe4To561uQ+Mes+/4U8Y9b5u+yDX7SDq+Tf8J0Y9/4b/xKjn3/AfGPWRf8N/YtTzb/hPjHp+v/6JUc/v1z8x6iWj/oFRz+/XPy/q25JR/8SoZ0X2E6OeFdlPjHpWZD8x6lmR/cCoS1ZkPzHqWZH9xKhnRfaEUV/blULWoQdRz4rsJ0a9ZNQ/MOpZm/vEqGdtLi2Prv867QcTJMt4OUHuTpCs+OUEuTtBsjiYE+TeBNH8yzMnyN0Jkn+k5gS5O0Hyj9ScIHcnSP6RmhPk7gTJP1JzgtybIGt+2Z0T5O4Eye/Fc4LcnSD5FXpOkLsTJL9tzwlyd4KUnCA5Qe5NkKyk5gS5O0GykpoT5O4EyUpqTpC7EyQrqTlB7k6QrKTmBLk3QUpWUnOC3J0geYrJCXJ3guQpJifI3QmSp5icIHcnSJ5icoLcnSB5iskJcm+C1DzF5AS5O0HyPkhOkLsTJO+D5AS5O0HyPkhOkLsTpOQEyQlyb4JkJTUnyN0JkpXUnCB3J0hWUnOC3J0gWUnNCXJ3gmQlNSfIvQnSspKaE+TuBMlTzIdPEFnW/YeXXg6mSJ5jcoo8mCJ5kskp8mCK5Fkmp8iDKZKnmZwi96fIlueZnCIPpkjeDckp8mCK5O2QnCIPpkjeD8kp8mCKlJwiOUXuT5GsruYUeTBFsrqaU+TBFMnqak6RB1Mkq6s5RR5Mkayu5hS5P0V6VldzijyYIlkXOeEU2Xo/GuQ/US8Z9Q+MelYvPjHqWZD4xKhnjeETo55lg0+MelYCPjDqIw/3nxj1vA31iVHPC06fGPWszX1i1EtG/QOjnrW5T4x61uY+L+pd8m/4E0a9r9s+yHU7iHr+Df+JUc+/4T8x6iWj/oFRz7/hPzHq+Tf8J0Y9v1//xKjn9+ufGPX8fv0Do675/foHRn3NqH9i1LMi+4lRz4rsJ0Y9K7KfGPWSUf/AqGdF9hOjnhXZT4x6VmRPGPW1XSlkHXoQ9azIfmLUsyL7gVEvWZv7xKhnbS4tj67/Ou0HEyTLeDlB7k6QrPjlBLk7QUpOkJwgdyZIzb88c4LcnSD5R2pOkLsTJP9IzQlyd4LkH6k5Qe5OkJITJCfIvQmSX3bnBLk7QfJ78ZwgdydIfoWeE+TuBMlv23OC3J0g+cV8TpB7E6RlJTUnyN0JkpXUnCB3J0hWUnOC3J0gWUnNCXJ3gpScIDlB7k2QrKTmBLk3QbY8xeQEuTtB8hSTE+TuBMlTTE6QuxMkTzE5Qe5OkJITJCfIvQmSp5icIHcnSN4HyQlyd4LkfZCcIHcnSN4HyQlyd4LkfZCcIPcmSM9Kak6QuxMkK6k5Qe5OkKyk5gS5O0GykpoT5O4EKTlBcoLcmyBZSc0Jcm+CjDzFfPgEkWXdf3jp5WCK5Dkmp8iDKZInmZwiD6ZInmVyijyYIiWnSE6R+1MkzzM5RR5MkbwbklPkwRTJ2yE5RR5MkbwfklPkwRTJGyI5Re5OkbFkdTWnyIMpktXVnCIPpkhWV3OKPJgiWV3NKfJgipScIjlF7k+RrK7mFHkwRbIucsIpsvV+NMh/op6ljg+MumT14hOjngWJT4x61hg+MepZNvjEqJeM+gdGPQ/3nxj1vA31iVHPC06fGPWszX1i1LM294FRX0tG/XxR7+u2D3LdDqKef8N/YtTzb/hPjHr+Df+JUc+/4T8x6vk3/AdGveT3658Y9fx+/ROjnt+vf2LU8/v1D4x6zah/YtRLRv0Do54V2U+MelZkPzHqWZH9xKhnRfYTo54V2Q+MesuKLEXUi2zXX1xkPIi69v1fp72V+z98/7n00bJ4mxPk7gTJOm9OkLsTJIuDOUHuTpCsLeQEuTtBsgyRE+TuBMmKRU6QuxMkixs5Qe5NkC3rIDlB7k6QrIPkBLk7QbIOkhPk7gTJOkhOkLsTpOQEyQlyb4Lk1aucIHcnSFZSc4LcnSBZSc0JcneCZCU1J8jdCZKV1Jwg9yZIz0pqTpC7EyQrqTlB7k6QPMXkBLk7QfIUkxPk7gTJU0xOkLsTJE8xOUHuTZCRp5icIHcnSJ5icoLcnSB5HyQnyN0JkvdBcoLcnSAlJ0hOkHsTJO+D5AS5O0GykpoT5O4EyUpqTpC7EyQrqTlB7k6QrKTmBLk9QeqyZCU1J8jdCZKV1JwgdydInmI+fILIsu4RWXo5mCJ5jskp8mCK5Ekmp8iDKZJnmZwi96eI5Gkmp8iDKZLnmZwiD6ZI3g3JKfJgiuTtkJwiD6ZIySmSU+T+FMkbIjlFHkyRrK7mFHkwRbK6mlPkwRTJ6mpOkQdTJKurOUXuTxHN6mpOkQdTJKurOUUeTJGsrp5viqyyD/Iq4+CWkH5qwVRlj/o27v+wlNJ2jPp16cg59oYHN8m05BzJOfJgjnxqyTTnyPfnyKfWTHOOfH+OfGrRNOfI9+fIp1ZNc458f458atk058i358j6qXXTnCPfnyOfWjjNOfL9OfKpldOcI9+fI1lnzTnyaI6UnCM5Rx7Mkayz5hx5NEeyzppz5NEcyTprzpFHcyRraDlHHsyRkjW0nCOP5kjW0HKOPJojWUPLOfJojmQNLefIozlSco7kHHkwR7KGlnPk0RzJGlrOkUdzJGtoOUcezZG8q5hz5NEcyTprzpEHc6RmnTXnyKM5knXWnCOP5kjWWXOOPJojWWfNOfJojpScIzlHHsyRrI/kHHn47kzNCknOksezJGskOUsezpKWVZKcJY9nyafWScb+0pnov146+z0un1obeDQun3oefjQu5SPHZR1/drkxHrwYuK3XX7yV9c+/b93H8DPvorx3DD/zrsbfjWG5Im9fcv6XMYw+q3f9M4atPxhDqfsYStP7P9x35PH17xVdPuWvm56RPEkkR0byHJHclozkSSIpGcmTRFIzkieJ5JqRPEkkC3Qktf2J5Prgh5dLmXH/t07164/L8cj8IbmMktz/8Y+fJzXnif33l4G8/PjvsWk5NjfHBrvK8bNjg103+NmxwT6Je47NpmP/8W3b7v94G3+qjH/G48L3exw79jnYcRwvv/zPn4FSlo/O7w/ujXXsM3bOEoxZgn1+z1mCMUuwawM5SzBmScm/797y993Hnstztf3FavvYCkXOkr+YJR9bq8lZ8hez5GOrVjlL/mKWfGz9LmfJ92fJyOpkzpLHsySrkzlLHs+SrE7mLHk8S7I6mbPk8SwpOUtyljycJVl7zVnyeJZk7TVnyeNZkrXXnCWPZ0nWXnOWPJ4lWXvNWfJollyGNmdJzpKHsyRrrzlLHs+SrL3mLPk/D7vILv8/50nOk2/Mk5LzxP67rl9//PfYZNXx9thkre3m2Hzjmy9tD8ZGa99XeVu/vAxWj/8Nfb/pLOuX28vL0abQln0s21LK/X+vXga+7/uN9u3g31s+7N9bP+zf2z7s37t92L+3f9S/V2+ctFe9vk8o89949997mST7v3f5clA7fvpQ93+Aan/wTuJa978y1zrG/R++ZNk9LY4v0GIPIf7PT1fZoavKl2Gv7To0mkNza2jWHJpbQ1NyaG4NTc2huTU0LYfm1tBgf0c99uT9dRgPf3jV9XoUuwT2y9mqX/+p2F+0/tU/Vfr+T63L13/q0RzYD52X6dDv//DoXw6o65cq1RHyOvazb1n/9cO/Bxz7O8vzDbhgf/13wgHH/ibthAOO/aXUCQcc+9udEw54yQGPHXDs715OOODYX+iccMBPdMbjGPA8aQYPeJ40Ywdc86QZPOB50gwe8DxpBg94njSDB7zkgMcOeJ40gwc8T5rBA54nzeABz5Nm8IDnSTN2wNc8aQYPeJ40gwc8T5rBA54nzeABLzngsQOeJ83gAc+TZvCA50kzeMDzpBk84HnSjB3wkifN4AHPk2bwgOdJM3jA86QZPOAlBzx2wPOkGTzgedIMHvA8aQYPeJ40gwc8T5qxA17zpBk84HnSDB7wPGkGD3ieNIMHvOSAxw54njSDBzxPmsEDfqKTZtufNNIvzwwfj+Gff98iX19GPvr36Z/3/FRU/vz0ch3EE50ef24QT3Qi/LFBbCc65f3cIJ7o5PZzg3ii09jPDeKJTlg/N4glB/H1QTzRSejnBvFEp5ufG8Q8sbxhEPPE8oZBzBPL64O45YnlDYOYJ5Y3DGKeWN4wiHliecMglhzE1wfxPCeWur+ov7YvA3P8VYLq75+tZk6zIx+5ybSdeBt/RrBdvxvYznNc+akRPM9Z5adG8DwHlZ8awfOcUn5oBPt5jiheIyjyx9dG6r/G8OCH23KlkKb1S6I/9KV959fd/TwHpY8P5XmOax8fyvMcGj8+lCVDeZZQ5gH6NKHMk/xpQpklhdOEMmsbpwllFlnOEsqR1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7ThLKdclqz2lCmdWe04Qyqz2nCWVWe04TypKhPEsos9pzmlBmtec0ocxqz2lCmdWe04Qyqz1nCaVktec0ocxqz2lCmdWe04Qyqz2nCWXJUJ4llFntOU0os9pzmlBmtec0ocxqz2lCmdWes4RSs9pzmlBmtec0ocxqz2lCmdWe04SyZCjPEsqs9pwmlFntOU0os9pzmlBmtec0ocxqz5tDWXbktklkKNes9pwmlFntOU0os9pzmlBmtec0oSwZyrOEMqs9pwllVntOE8qs9pwmlFntOU0os9pzllCWrPacJpRZ7TlNKLPac5pQZrXnNKEsGcqzhDKrPacJZVZ7ThPKrPacJpRZ7TlNKLPac5ZQ1qz2nCaUWe05TSiz2nOaUGa15zShLBnKs4Qyqz2nCWVWe04Tyqz2nCaUWe05TSiz2nOWULas9pwmlFntOU0os9pzmlBmtec0oSwZyrOEMqs9pwllVntOE8qs9pwmlFntOU0os9pzllBuWe05TSiz2nOaUGa15zShzGrPaUJZMpRnCWVWe04Tyqz2nCaUWe05TSiz2vMwlLrtoVylfQ3l7zHMMsvLY9g/s76xtesv7kt/MIZvXff9M4sQPzfen1kp+Lnx/szj/M+Nd8nxDh3vzzwY/9x4f+bp9efG+zOPmD833p95Dvy58f7MM+OPjffI82XseOf5Mna883wZO955vowd75LjHTreeb6MHe88X8aOd54vY8c7z5ex453ny8jxLkueL2PHO8+XseOd58vY8c7zZex4lxzv0PHO82XseOf5Mna883wZO955vowd7zxfho635PkydrzzfBk73nm+jB3vPF/GjnfJ8Q4d7zxfxo53ni9jxzvPl7HjnefL2PHO82XoeGueL2PHO8+XseOd58vY8c7zZex4lxzv0PHO82XseOf5Mna883wZO955vowd7888X3bdx7ut/xrvX8OynucY2JrsGMtyf1j+5imjthNv41/vev0ewfMc7LxG8C/fRluugyGXof+ykr3fRivrec6MHx/K8xxHPz6UJUN5llCe5xD98aE8z/n840N5nqP/x4fyPFWFjw/leQoWnx7KkkWW04Qyqz2nCWVWe04Tyqz2nCaUJUN5llBmtec0ocxqz2lCmdWe04Qyqz2nCWVWe84SyprVntOEMqs9pwllVntOE8qs9pwmlCVDeZZQZrXnNKHMas9pQpnVntOEMqs9pwllVnvOEsqW1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7zhLKLas9pwllVntOE8qs9pwmlFntOU0oS4byLKHMas9pQpnVntOEMqs9pwllVntOE8qs9pwllD2rPW8OZdmR2yahocxqz2lCmdWe04Qyqz2nCWXJUJ4llFntOU0os9pzmlBmtec0ocxqz2lCmdWes4RyZLXnNKHMas9pQpnVntOEMqs9pwllyVCeJZRZ7TlNKLPac5pQZrXnNKHMas9pQpnVnpOEsi5Z7TlNKLPac5pQZrXnNKHMas9pQlkylGcJZVZ7ThPKrPacJpRZ7TlNKLPac5pQZrXnLKGUrPacJpRZ7TlNKLPac5pQZrXnNKEsGcqzhDKrPacJZVZ7ThPKrPacJpRZ7TlNKLPac5ZQalZ7ThPKrPacJpRZ7TlNKLPac5pQlgzlWUKZ1Z7ThDKrPacJZVZ7ThPKrPacJpRZ7XkYSt32UK7Svoby1xiun1lm2dr1F/elPxjDt87Z9TNrIT833p9ZsPi58f7MqsLPjXfJ8Q4d7888n//ceH/mIfrnxvszT7o/N96feRz9ufH+zDPjj413yfNl7Hjn+TJ2vPN8GTveeb6MHe+S4x063nm+jB3vPF/GjneeL2PHO8+XseOd58vQ8a55vowd7zxfxo53ni9jxzvPl7HjXXK8Q8c7z5ex453ny9jxzvNl7Hjn+TJ2vPN8GTreLc+XseOd58vY8c7zZex45/kydrxLjnfoeOf5Mna883wZO955vowd7zxfxo53ni9Dx3vL82XseOf5Mna883wZO955vowd75LjHTreeb6MHe88X8aOd54vY8c7z5ex4/2Z58uu+3i39V/j/WtY+nmOgdu67RhD7w9L3Yfl308ZHU2tbVyJL4P5ZSia95Tt5zkyni825zleni825zmKni82JWMDG5vzHHHPF5vzHIfPF5vzHJ3PF5vzHLPPF5vzHMlPF5uRdQHc2GRdADc2WRfAjU3WBXBjUzI2sLHJugBubLIugBubrAvgxibrArixyboAamzaknUB3NhkXQA3NlkXwI1N1gVwY1MyNrCxyboAbmyyLoAbm6wL4MYm6wK4scm6AGxsJOsCuLHJugBubLIugBubrAvgxqZkbGBjk3UB3NhkXQA3NlkXwI1N1gVwY5N1AdjYaNYFcGOTdQHc2GRdADc2WRfAjU3J2MDGJusCuLHJugBubLIugBubrAvgxibrArCxWbMugBubrAvgxibrArixyboAbmxKxgY2NlkXwI1N1gVwY5N1AdzYZF0ANzZZF4CNTcm6AG5ssi6AG5usC+DGJusCuLEpGRvY2GRdADc2WRfAjU3WBXBjk3UB3NhkXQA2NjXrArixyboAbmyyLoAbm6wL4MamZGxgY5N1AdzYZF0ANzZZF8CNTdYFcGOTdQHY2LSsC+DGJusCuLHJugBubLIugBubkrGBjU3WBXBjk3UB3NhkXQA3NlkXwI1N1gVgY7NlXQA3NlkXwI1N1gVwY5N1AdzYlIwNbGyyLoAbm6wL4MYm6wK4scm6AG5ssi4AG5uedQHc2GRdADc2WRfAjU3WBXBjUzI2sLHJugBubLIugBubrAvgxibrArixyboAbGxG1gVwY5N1AdzYZF0ANzZZF8CNTcnYwMYm6wK4scm6AG5ssi6AG5usC+DGJusCqLHZlqwL4MYm6wK4scm6AG5ssi6AG5uSsYGNTdYFcGOTdQHc2GRdADc2WRfAjU3WBWBjI1kXwI1N1gVwY5N1AdzYZF0ANzYlYwMbm6wL4MYm6wK4scm6AG5ssi6AG5usC8DGRrMugBubrAvgxibrArixyboAbmxKxgY2NlkXwI1N1gVwY3PKusDXQTyMzajXnx1jexCbthNvQ/afbfsInvL0/tYRFNFypZD6rzE8+OG2XAdDLkP/Zcou7ovhlIf9jwzlesrawGeG8pSlhM8M5SkrD58ZylMWKj4zlCVDeZZQnrIM8pmhPGXV5DNDmUWW04Qyqz2nCWVWe84SypLVntOEMqs9pwllVntOE8qs9pwmlCVDeZZQZrXnNKHMas9pQpnVntOEMqs9pwllVnvOEsqa1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7zhLKltWe04Qyqz2nCWVWe04Tyqz2nCaUJUN5llBmtec0ocxqz2lCmdWe04Qyqz2nCWVWe84Syi2rPacJZVZ7ThPKrPacJpRZ7TlNKEuG8iyhzGrPaUKZ1Z7ThDKrPW8OZdmR2yahocxqz2lCmdWes4SyZ7XnNKHMas9pQpnVntOEMqs9pwllyVCeJZRZ7TlNKLPac5pQZrXnNKHMas9pQpnVnrOEcmS15zShzGrPaUKZ1Z7ThDKrPacJZclQniWUWe05TSiz2nOaUGa15zShzGrPaUKZ1Z6ThLIvWe05TSiz2nOaUGa15zShzGrPaUJZMpRnCWVWe04Tyqz2nCaUWe05TSiz2nOaUGa15yyhlKz2nCaUWe05TSiz2nOaUGa15zShLBnKs4Qyqz2nCWVWe04Tyqz2nCaUWe05TSiz2nOWUGpWe04Tyqz2nCaUWe05TSiz2nOaUJYM5VlCmdWe04Qyqz0PQ6nbHspV2tdQ/h7DzyyziPR9XFT/PYq/B+YzixbfGJjPLAE8Hpj1Mw/U3xiYzzyefmNgznPYG/X6m9fxhflwYKq0618BVbb+INu98y+G9TxHMpIBLzngsQN+nuMNyYCf5xBCMuDnObGQDPh5TkIkA36eExbHgJfznNxIBvw8J0KSAc+TZvCA50kzeMBLDnjsgOdJM3jA86QZPOB50gwe8DxpBg94njRjB7zmSTN4wPOkGTzgedIMHvA8aQYPeMkBjx3wPGkGD3ieNIMHPE+awQOeJ83gAc+TZuyAtzxpBg94njSDBzxPmsEDnifN4AEvOeCxA54nzeABz5Nm8IDnSTN4wPOkGTzgedKMHfAtT5rBA54nzeABz5Nm8IDnSTN4wEsOeOyA50kzeMDzpBk84HnSDB7wPGkGD3ieNGMHvOdJM3jA86QZPODnOWle/gDYB3zI/TEU0f03S6tfoN0fEeznOWqyjHjJEQ8e8fMcNllG/DynTZYRP89xk2XEz3PeZBnx8xw4SUZ8nOfEyTLi5zlysox4njmjRzzPnNEjXnLEg0c8z5zRI55nzugRzzNn9IjnmTN6xPPMGTviY8kzZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BGXPHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwecc0zZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BFf88wZPeIfeubUZd1/8zpCR/xDz5w/OOIfeub8wREvOeLBI/6hZ84fHPEPPXP+4Ih/6JnzB0f8Q8+cPzjiH3rm/LkRLx965vzBEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnMEjXvPMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMRbnjmjRzzPnNEjnmfO6BHPM2f0iJcc8eARzzNn9IjnmTN6xPPMGT3ieeaMHvE8cwaP+JZnzugRzzNn9IjnmTN6xPPMGT3iJUc8eMTzzBk94nnmjB7xPHNGj3ieOaNHPM+cwSPeP/TMWcr+Dyy9h474h545f3DEP/TM+YMj/qFnzh8c8ZIjHjziH3rm/MER/9Az5w+O+IeeOX9wxD/0zPmDI/6hZ86fG/GRZ87oEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnKEj3pYlz5zRI55nzugRzzNn9IjnmTN6xEuOePCI55kzesTzzBk94nnmjB7xPHNGj3ieOYNHXPLMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMQ1z5zRI55nzugRzzNn9IjnmTN6xEuOePCI55kzesTzzBk94nnmjB7xPHNGj/iHnjnruo9L7SVyxNcPPXP+4Ih/6JnzB0f8Q8+cPzjiH3rm/MERLzniwSP+oWfOHxzxDz1z/uCIf+iZ8wdH/EPPnD844nnmDB7xkmfO6BHPM2f0iOeZM3rE88wZPeIlRzx4xPPMGT3ieeaMHvE8c0aPeJ45o0c8z5zBI17zzBk94nnmjB7xPHNGj3ieOaNHvOSIB494njmjRzzPnNEjnmfO6BHPM2f0iOeZM3jEW545o0c8z5zRI55nzugRzzNn9IiXHPHgEc8zZ/SI55kzesTzzBk94nnmjB7xPHMGj/iWZ87oEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo/4h545xz4uehnyRyPeypVjbMuf4dD1EKTsHF9eJ9IjjHWrug/dVu//sNQ/Q1dLe/DDy7r/8PJlSl1++HfgP/To+/GB7x96As/Af2ghIAP/ofWIDPyHlkUy8CUD/5mB/9AiUQb+Q2tVGfgPLZll4LNy96GBz8rdZwZ+ZOXuQwOflbsfDHyR7fqLi4wHgdderuOsvZVXA5+Vuw8NfFbuPjTwJQO/hd6AGFkyix7xrFVFj3gWiaJHPKsz0SOeZZHYEb8o5IgHj3gWAqJHPE/g0SOeR9/oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwecckzZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BHXPHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwe8TXPnNEjnmfO6BHPM2f0iOeZM3rES4548IjnmTN6xPPMGT3ieeaMHvE8c0aPeJ45g0e85JkzesTzzBk94nnmjB7xzzxz6rrtzwKV5d9PGf0emHKWgSmyXOdAuXwD9WAqtuXKLE2/PK6k/lPxNEdDmhE/zdGQZsRPczSkGfHTHA1pRvw0R0OWEa+nORrSjPhpjoY0I36aoyHNiJ/maEgz4iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnMEj3vLMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMS3PHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwe8Z5nzugRzzNn9IjnmTN6xPPMGT3iJUc8eMTzzBk94nnmjB7xPHNGj3ieOaNHPM+cwSM+8swZPeJ55owe8TxzRo/4p545y/6b2yahI15yxINH/FPPnD834p965vy5Ef/UM+fPjfinnjl/bsQ/9cz5UyOuy6eeOX9uxD/1zPlzI/6pZ86fG/E8c0aPeMkRDx7xPHNGj3ieOaNHPM+c0SOeZ87oEc8zZ/CIS545o0c8z5zRI55nzugRzzNn9IiXHPHgEc8zZ/SI55kzesTzzBk94nnmjB7xPHMGj7jmmTN6xPPMGT3ieeaMHvE8c0aPeMkRDx7xPHNGj3ieOaNHPM+c0SOeZ87oEc8zZ/CIr3nmjB7xPHNGj3ieOaNHPM+c0SNecsSDRzzPnNEjnmfO6BHPM2f0iOeZM3rE88wZPOIlz5zRI55nzugRhz5z6tDrD69VHvxwbX3/6botX35cDn5cLyD9949f/rtvX3/899hAnw5/eGzKecZm2/o+Nn3p98fmsua2ffmtf374kp+vQwN94Pq7oRl/hqYtpRzMg8OzzvVfujz4Z/4Zky5/NlSRo02ylXL9Z7bSyuszeKMl72Hk656YLuTbffJar6mmbn8yTblCD0LoujBCCyO0QkK35brZNx3/C70yQhdG6MoI3RihN0ZozIz4ABozI96HbpgZ8QE0ZkZ8AM2YERtjRmx0GVGXf47bXlovvz+z6Z/Dnazt96eOWzcefkqe+pQ+9an1rz/V9J/ja56bXE9S25c/OUXr9VPbU5/qT31qPPOp42tPDz8lT31Kn/rUYby6XOPV9fBT5alP1ac+1Z761PbUp/pTnxrPfOr464ner5WjPvToU/LUp/SpT61Pfao89an61KfaU586nBtjudblhyxHn+pPfWo886njwsXDT8lTn9KnPrU+9anDuTH0ulLGerRSjk+PDz/VnvrU9tSn+lOfGs986vhP+IefkgefKkfxOv4j9uGn1qc+dTw36nUtj3a0llt96lPtqU9tT32qP/Wp8cyntuWpTx3Pjb5/4bHU/q+P/edvfvi3hgZorAEaJUCjBmi0AI0tQKMHaAx/jWOT5TdrBKzzHrDOe8A67wHrvAes8x6wznvAOu8B67wHrPMRsM5HwDofAet8BKzzEbDOR8A6HwHrfASs8xGwzkfAOpdliRCRCBGNEFkjREqESI0QaREiW4RIjxCJWPESseIlYsVLxIqXiBUvESteIla8RKx4iVjxErHiJWLFa8SK14gVrxErXiNWvEaseI1Y8Rqx4jVixWvEiteIFb9GrPg1YsWvESt+jVjxa8SKXyNW/Bqx4teIFb9GrPg1YsWXiBVfIlZ8iVjxJWLFl4gVXyJWfIlY8SVixZeIFV8iVnyNWPE1YsXXiBVfI1Z8jVjxNWLF14gVXyNWfI1Y8TVixbeIFd8iVnyLWPEtYsW3iBXfIlZ8i1jxLWLFt4gV3yJW/Bax4iPu1UnExTqJuFknEVfrJOJunURcrpOI23UScb1OIu7XScQFO4m4YScRV+wk4o6dRFyyk4hbdhJxzU4i7tlJxEU7ibhpJxFX7STirp1EXLaTiNt2EnHdTiLu20nEhTuJuHEnEVfuJOLOnUbcudOIO3cacedOI+7c6VIiRGqESIsQ2SJEeoRIxIqPuHOnEXfuNOLOnUbcudOIO3cacedOI+7cacSdO424c6cRd+404s6dRty504g7dxpx504j7txpxJ07jbhzpxF37jTizp1G3LnTiDt3GnHnTiPu3GnEnTuNuHOnEXfuNOLOnUbcudOIO3cacedOI+7cacSdO424c6cRd+404s6dvuGmWq3XJ/rqv6wYZNfo/hpvuN1V9xf/a++HGhqgsQZolACNGqDxt4nk+rntuc+94Tv5h/P4DV/JP9aoARotQCNg73rD1/F17GYGSz3UGP4ab/gy/rGGBGhogMYb1vmQXaMdapQAjRqg0QI0tgCNHqAx/HPiG76Cf6wR8LfWCPhbawT8rfWGr98fawT8rfWGL98fa2wBGj1Aw3+dr8sSoCEBGhqgsQZolACNGqDRAjS2AI0eoBGwziVgnUvAOpeAdS4B61wC1rkErHMJWOcSsM4lYJ1LwDrXgHWuAetcA9a5BqxzDVjnGrDONWCdq/c67/8cKkgtu7Ns/WIOpEfmQL1eFXqX+z8q0ncPaNX/3wP6QtOhaAYUzfEfLD+HI1g4ioWzYuEULJyKhdOwcLD2ZMHalAVrV1asXVmxdmXF2pUVa1dWrF1ZsXZlddyVfyts7gqv751ffMjW5dUhHVA464KFI1g4ioWzYuEULJyKhdOwcDYsHKxdecXalQvWrlywduWCtSsXrF25YO3KBWtXLli7cnHclX8rdHeF4a1QF3cFcVdQd4XVXaG4K1R3heau4L6m2+uzVZbl6uIri+iBhgZovB5t0fJnh20Hx/82/P8d2xKgERDzrbxBo41do7cDjRqg0QI0tgCNHqDxjvXR5I/G9r8afQnQkAANDdBYAzRKgEYN0GgBGluARg/QeMM6FynXH5Zy8HfJWAI0JEBDAzTWAI0SoFEDNFqAxhag8YZ1LpvuGl9vk+0aw1/jhhvxu0VW/9PBDQ/fd4vUCJEWITICRN5wy+4bIhIhohEi3utkW46vqG77h7btQSG0LP33jxat93+07/vCWMp/v1RM/7a8esHunNiDE/t43RJwCym3knKvpNyFlLuScjdSbtJsKaTpUkjzpZLmSyXNl0qaL5U0XyppvlTSfKlu+fL379+cf//L+adev98stRz8/uH7+9fF+feL8+9X59//8j62N9KWvh78/uL8+6vz72/Ov//V9VuXa0mpLv3g93fn3z98f39ZnH+/OP/+V+dn1euPVj36/c35978a37Ze7zq0qv/7++vi/Pudx6e+vH73knCt28Hv786/f/j+/rY4/35x/v3q/PtX599fnH9/df79zfn3v3H9tnbw+7vz7399/e7723bw+7eX1+867v5+cf796vz7X12/bb//2ZZx8PuL8++vzr+/Of/+zfn3v7x+/zz+LMvB7x++v78vzr9fnH+/Ov/+1fn3F+ffX51/f3P+/dsbf//B+u3d+fe/vn6v99OaHvz+8fL63QuUx79fnH+/Ov/+l/Pv/fPjKM6/vzr//ub8+zfn39+df79zfePGtcw3CfQbt8Ckrfut11YffN0hZblucVJE/lfixt2/v9MofdfYHn3/8q7Xcvqte0Qk7ErMvhKzF2L2SszeiNk3YvZOzD542ZU4rypxXlXivKrEeVWJ86oS51UlzqtKnFeVOK8qSl79hbOipMrfOMHZ723PW/VbN8pI2Fdi9kLMXonZGzH7RszeidkHL3tZiNmJ82ohzquFOK8W4rxaiPNqIc6rhTivFuK8WojzakXJq79xUFLlbxyU7PcbByWh/cZByVG/cVDSzm8clEzyGwclOfzGQdnvf+OgbOG/cBrWrtyCF/r954P7rf6MnwQKns73n9HqtzoQfnCENkUDWtGAWjTQvQeb+60uhJ8E6mhAAwyoL2hA4fvQvdeJ+63Wi58EWtGAChpQRQNqaEAbGlBHAxpgQGNBA4reqe++Yd1vNdn8JNCKBlTQgCoaUEMD2tCAOhrQAAO69Qa9I9G9B+snkcARKRxRBSvJ3Ho3/yeJNjgitEKaRPfafYNI4YhWOKICR4S1H22UTgsXbManoy/YjC9HX7ApnRaMm/HlaONmfDnauBlfjjbuQsrN+HK0cTM6LRg3abakdFowbtJ8Sem0YNyk+ZLSacG4SfMlpdOCcZPmS1enBfv9m/Pv93RasN8/fH+/q9OC/X5x/v3q/Ps9nRbs9xfn31+df39z/v2eTgv2+7vz7x++v9/VacF+vzj/fk+nBfv9zfn3e75EePn9rk4L9vudx8fVacF+f3f+/cP397s6LdjvF+ffr86/f3X+/cX591fn39+cf7+n04L9/u78+z2dFuxLJk+nBfv94vz71fn3ezot2O8vzr+/Ov/+5vz7N+ff7+m0YL9/+P5+V6cF+/3i/PvV+fevzr+/OP/+6vz7m/Pv93RasN/fnX+/p9OCXTvwdFqw3y/Ov1+df7+n04L9/uL8+6vz72/Ov39z/v3d+fc71zd8nRZGc3dauEjQOi0YO+uL0MbO+iK0sbO+CG3shZid9UVoY2d9EdrYWV+ENnbWF6GNndVp4cJO67Rg7MR5ldZpwdiJ8yqt04KxE+dVWqcFYyfOq7ROC8YO5LRwwUFyWjAc1hehjZ31RWhjZ30R2tgLMTvri9DGzvoitLGzvght7KwvQhs764vQF3ZapwVjJ86rtE4Lxk6cV2mdFoydOK/SOi0YO3FepXVaMHbivIrktGA4QE4LhgPktGA4QE4LhoOSo37jADktGA6Q04LhADktGA6Q04LhADktXHCQnBYMJ3ih33+U3oCgnBYMCOqBOLtABeW0YEBQTgsGBOW0YEBQTgsGBOW0YEBQTgsGBOW0cAHCclowICinBQOCclowICinBQMqaEBQTgsGBOW0YEBQTgsGBOW0YEBQTgsXICynBQOCclowICinBQOCclowoIIGBOW0YEBQTgsGBOW0YEBQTgsGBOW0MBuFoJwWJhGU08IkgnJamERQL5tPIiinhUkE5bQwidAKaWBOC5MIymlhEkE5LUyiAkcEtR/Jsro32ZoGbZfthGdtB5rwrP1AE561IWjCF2Z41pagCc/aEzThWZuCJjxrV9CEZ223NXjaftsJz5xhaTtuJzxzhqXtuZ3wzBmWtut2wjNnWNq+2wkP1HhrPEidt5OHtUVowrP2CE141iahCV+Y4VnbhCY8a5/QhGdtFJrwrJ1CE561VcjgaXtwJzxzhqXtwp3wzBmWtg93wjNnWNpO3AnPnGFpe3EnPHOGRerGnTxA7biTB6gfd/IANeROHpRsdeUBasmdPEA9uZMHqCl38gB15U4eoLZc40Hqy508wev9fg/jJILqzJ1EUDcK570rqN7cSQTVnDuJoLpzJxFUe+4kgurPnURQDbqTCKpD14iwWnQnEVSP7iSCatKdRFBdupOowBFB9elOIqhG3UkE1ak7iaBadScRVK+uEWE1604iqG7dSQTVrjuJoPp1J1GBI4Lq2J1EUC27kwiqZ3cSQTXtTiKort1fnUdQbbu/kKD6dn8hQTXu/kKC65QDa939hQTVu/sLCa7UBta9+wsJqn33FxJU/+4vpIKHhLUvifzzqk1xWa40RR/A9H3bHkv586P6999zX7g7Kfcg5ZaFFVxYwZUVfGUFL6zglRW8sYKz5k1hTZzCmjmVNXMqa+ZU1syprJlTWTOnsmZOdcucV4HNW+DlTFSv921KLUcCw1lgXbwFxFtAvQVe3tH6ddGUvh4JFG+B6i3QvAVeXcl12X7/aF36kUD3FhjOAmXxFhBvgVenadXrj1Y9FGjeAq8Gua3XW2qt6oFAXbwFvIeovrySyz6L6nYk0L0FhrNAW7wFxFtAvQVWb4HiLVC9BZq3wBtXcmtHAt1b4PWVvG9225HA9vJK3rfrGwLiLaDeAq+u5La3LLRlHAkUb4HqLdC8BTZvgZdX8ri+sNxkORIYzgJ98RYQbwH1Fli9BYq3QPUWaN4C2xsFjlZy794Cr6/k60WUpkcC4+WVvNc1bwiIt4B6C7yckx+cMkfxFqjeAs1bYPMW6N4C3sWQG3eb36Wg4u8NoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaGC5Q2hguUNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A1h8MwZltcbwuCZMyyvN4QKsTeEwTNnWF5vCBVibwgVLG8I40HyhjAeJG8I40HyhjAelGx15UHyhlDB8oZQwfKGUMHyhlDB8oZQwfKGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUIHzhphIWN4QEwnLG2IiYb3BPpGwvCEmEpY3xESCK7WheUNMJCxviImE5Q0xkQoeEti+1Dm9IS7clE9cX7gpX7i+cHN6Qxg45QvXBk75wrWBU75wbeCFFZzyhWsDp/SGMHDWvMnpDWHgrJmT0xvCwFkzJ6c3hIGzZk5ObwgDZ82cvt4QJrB5C7h6Q5jAcBbw9YYwAfEWUG8BV28IEyjeAtVboHkLuHpDmED3FhjOAr7eECYg3gKu3hAm0LwFXJ9DvAj4ekOYgPcQ+XpDmED3FhjOAr7eECYg3gLqLbB6CxRvgeot0LwFXL0hTKB7C7h6Q9g3U67eECYg3gLqLeDqDWECxVugegs0b4HNW8DVG8IEhrOArzeECYi3gHoLrN4CxVugegs0bwFXbwgT6N4Crt4QdnvB1RvCBMRbQL0FXL0hTKB4C1RvgeYtsHkLdG8B72KIszfEuvl7Q1w0eL0hDJ725WqDp3252uBpX642+MIMT/tytcHTvlxt8LQvVxs87cvVBk/rDXGB5/WGMHjmDMvrDWHwzBmW1xvC4JkzLK83hMEzZ1hebwiDR/KGuPBAeUMYD+3L1QZP+3K1wdO+XG3whRme9uVqg6d9udrgaV+uNnjal6sNnvbl6gs8rzeEwTNnWF5vCINnzrC83hAGz5xheb0hDJ45w/J6Qxg8c4aF8oYwHiRvCONB8oYwHiRvCONByVZXHiRvCONB8oYwHiRvCONB8oYwHiRviAsPlDeE8QSv9wcv6BsRljeEEWE9WGf3rrC8IYwIyxvCiLC8IYwIyxvCiLC8IYwIyxvCiLC8IS5EYN4QRoTlDWFEWN4QRoTlDWFEBY4IyxvCiLC8IYwIyxvCiLC8IYwIyxviQgTmDWFEWN4QRoTlDWFEWN4QRlTgiLC8IYwIyxvCiLC8IYwIyxvCiLC8IWbnEZY3xETC8oaYSFjeEBMJ6w32iYTlDTGRsLwhJhJcqQ3NG2IiYXlDTCQsb4iJVPCQsPalUvw7eC8avB28Bk/bX2TwtP1FBk/bX2TwhRmetr/I4Gn7iwyetr/I4Gn7iwyetoP3As/bwWvwzBmWt4PX4JkzLG8Hr8EzZ1jeDl6DZ86wvB28Bo/UwXvhgergNR7a/iKDp+0vMnja/iKDL8zwtP1FBk/bX2TwtP1FBk/bX2TwtP1FF3jeDl6DZ86wvB28Bs+cYXk7eA2eOcPydvAaPHOG5e3gNXjmDAvVwWs8SB28xoPUwWs8SB28xoOSra48SB28xoPUwWs8SB28xoPUwWs8SB28Fx6oDl7jCV7vD/ocjQirg9eIsK4V2r0rrA5eI8Lq4DUirA5eI8Lq4DUirA5eI8Lq4DUirA7eCxFYB68RYXXwGhFWB68RYXXwGlGBI8Lq4DUirA5eI8Lq4DUirA5eI8Lq4L0QgXXwGhFWB68RYXXwGhFWB68RFTgirA5eI8Lq4DUirA5eI8Lq4DUirA7e2XmE1cE7kbA6eCcSVgfvRILrlEPr4J1IWB28Ewmu1IbWwTuRsDp4JxJWB+9EKnhIWPtSbTc6eGvZrh+rbbuv8b5b3hecjoUzsHButEL/HI+A8SgYzwrGU8B4KhhPA+MB250FbHsWsP1ZwfZnBdufFWx/VrD9WcH2ZwXbn9Vxf75KbP4Sr++i77syajwDi2ddwHgEjEfBeFYwngLGU8F4GhjPBsYDtj+vYPtzAdufC9j+XMD25wK2Pxew/bmA7c8FbH8ujvvzVaL7Swx3ibr4S4i/hPpLrP4SxV+i+ks0fwn/1d1en7QPLtebiEaIvB7yx1/JtRHwL9mWCJGIwG/lDSJ3L7ibSI0QaREiW4RIjxB5xzq5e0v2ItKXCBGJENEIkTVCpESI1AiRFiGyRYj0CJE3rPj7tz4vImOJEJEIEY0QWSNESoRIjRBpESJbhMgbVvz9m7wmMgJEbt3zfrfKGnB4kKWEqNQQlRaiMiJU3nB37zsqEqKiISr+66Uf33/d9k9t24PyaVmut3GLPriM2/cdYizlv1/qrH9flO3HF2UJuAcp9/HyZQAXVnBlBV9ZwQsreGUFb6zgrHlTWBOnsGZOZc2cypo5lTVzKmvmVNbMqayZU90y51Vg8xZ4ORPV6zejpZYjgeEssC7eAuItoN4CL+9o/bpoSl+PBIq3QPUWaN4Cr67kulwrTnXpRwLdW2A4C5TFW0C8BV6dplWvP1r1UKB5C7wa5LZeL0y0qgcCdfEW8B6i+vJK3mvHtW5HAt1bYDgLtMVbQLwF1Ftg9RYo3gLVW6B5C7xxJbd2JNC9BV5fyftmtx0JbC+v5H27viEg3gLqLfDqSm775dK2jCOB4i1QvQWat8DmLfDySh71KiDLkcBwFuiLt4B4C6i3wOotULwFqrdA8xbY3ihwtJJ79xZ4fSVfL701PRIYL6/kva55Q0C8BdRb4OWc/OCUOYq3QPUWaN4Cm7dA9xbwLobcuPP5LoV242bZXz71uFz3OykiBxqCYkL/11/htFs3k1jglRl+ZYYvzPCVGb4xw2/M8J0ZfhDDK3OGVeYMq8wZVpkzrDJnWGXOsMqcYZU5wypzhlWUDPubZ0VJmlceFBP6Z4K7ojjWPwWPYm//FHxhhq/M8I0ZfmOG78zwgxi+LMzwzBm2MGfYwpxhC3OGLcwZtjBn2MKcYQtzhi3MGbaiZNgrD0rSvPKg5MErD0pqu/KgZKsrD0oCuvKg5JQrD0qauPKg7PxXHpTN/DdPA9ufW/B6f/DWcbvV+PGjRFiGze1WW8NPjtGmcEQrHFG0Pfr956XbrcaGHyXqcEQDjagvcETh+9HdZ5TbrW6OHyVa4YgKHFGFI2pwRBscUYcjGmhEY4Ejit6z77+23W717fwo0QpHVOCIKhxRgyPa4Ig6HNFAI7r1Zr4j0t0H9ieS4CEpHlJFq9jceuf/R5E2PCS4UptEt/B9B0nxkFY8pIKHhLUvbZXTG+LCTfnE9YWb8oXrCzenN4SBU75wbeCUL1wbOOUL1wZeWMEpX7g2cEpvCANnzZuc3hAGzpo5Ob0hDJw1c3J6Qxg4a+bk9IYwcNbM6esNYQKbt4CrN4QJDGcBX28IExBvAfUWcPWGMIHiLVC9BZq3gKs3hAl0b4HhLODrDWEC4i3g6g1hAs1bwPU5xIuArzeECXgPka83hAl0b4HhLODrDWEC4i2g3gKrt0DxFqjeAs1bwNUbwgS6t4CrN4R9M+XqDWEC4i2g3gKu3hAmULwFqrdA8xbYvAVcvSFMYDgL+HpDmIB4C6i3wOotULwFqrdA8xZw9YYwge4t4OoNYbcXXL0hTEC8BdRbwNUbwgSKt0D1FmjeApu3QPcW8C6GOHtD9OLvDXHR4PWGMHjal6sNnvblaoOnfbna4AszPO3L1QZP+3K1wdO+XG3wtC9XGzytN8QFntcbwuCZMyyvN4TBM2dYXm8Ig2fOsLzeEAbPnGF5vSEMHskb4sID5Q1hPLQvVxs87cvVBk/7crXBF2Z42perDZ725WqDp3252uBpX642eNqXqy/wvN4QBs+cYXm9IQyeOcPyekMYPHOG5fWGMHjmDMvrDWHwzBkWyhvCeJC8IYwHyRvCeJC8IYwHJVtdeZC8IYwHyRvCeJC8IYwHyRvCeJC8IS48UN4QxhO83h+8oG9EWN4QRoT1YJ3du8LyhjAiLG8II8LyhjAiLG8II8LyhjAiLG8II8LyhrgQgXlDGBGWN4QRYXlDGBGWN4QRFTgiLG8II8LyhjAiLG8II8LyhjAiLG+ICxGYN4QRYXlDGBGWN4QRYXlDGFGBI8LyhjAiLG8II8LyhjAiLG8II8LyhpidR1jeEBMJyxtiImF5Q0wkrDfYJxKWN8REwvKGmEhwpTY0b4iJhOUNMZGwvCEmUsFDwtqXhvh38F40eDt4DZ62v8jgafuLDJ62v8jgCzM8bX+RwdP2Fxk8bX+RwdP2Fxk8bQfvBZ63g9fgmTMsbwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DR6pg/fCA9XBazy0/UUGT9tfZPC0/UUGX5jhafuLDJ62v8jgafuLDJ62v8jgafuLLvC8HbwGz5xheTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGRaqg9d4kDp4jQepg9d4kDp4jQclW115kDp4jQepg9d4kDp4jQepg9d4kDp4LzxQHbzGE7zeH/Q5GhFWB68RYV0rtHtXWB28RoTVwWtEWB28RoTVwWtEWB28RoTVwWtEWB28FyKwDl4jwurgNSKsDl4jwurgNaICR4TVwWtEWB28RoTVwWtEWB28RoTVwXshAuvgNSKsDl4jwurgNSKsDl4jKnBEWB28RoTVwWtEWB28RoTVwWtEWB28s/MIq4N3ImF18E4krA7eiQTXKYfWwTuRsDp4JxJcqQ2tg3ciYXXwTiSsDt6JVPCQwPal8c+rPshludIUfQDT9217LOXPj+oT33OPfzop9yDlloUVXFjBlRV8ZQUvrOCVFbyxgrPmTWFNnMKaOZU1cypr5lTWzKmsmVNZM6eyZk51y5xXgc1b4OVMVK/3bUotRwLDWWBdvAXEW0C9BV7e0fp10ZS+HgkUb4HqLdC8BV5dyXXZfv9oXfqRQPcWGM4CZfEWEG+BV6dp1euPVj0UaN4Crwa5rddbaq3qgUBdvAW8h6i+vJLLPovqdiTQvQWGs0BbvAXEW0C9BVZvgeItUL0FmrfAG1dya0cC3Vvg9ZW8b3bbkcD28kret+sbAuItoN4Cr67ktrcstGUcCRRvgeot0LwFNm+Bl1fyuL6w3GQ5EhjOAn3xFhBvAfUWWL0FirdA9RZo3gLbGwWOVnLv3gKvr+TrRZSmRwLj5ZW81zVvCIi3gHoLvJyTH5wyR/EWqN4CzVtg8xbo3gLexZAbd5vfpKDLcPeGMA1ab4gJz/py9YRnfbl6wrO+XD3hCzM868vVE5715eoJz/py9YRnfbl6wrN6Qxg8rTfEhGfOsLTeEBOeOcPSekNMeOYMS+sNMeGZMyytN8SEB/KGMB4kb4jJw/py9YRnfbl6wrO+XD3hCzM868vVE5715eoJz/py9YRnfbl6wrO+XG3wtN4QE545w9J6Q0x45gxL6w0x4ZkzLK03xIRnzrC03hATnjnDInlDTB4gb4jJA+QNMXmAvCEmD0q2uvIAeUNMHiBviMkD5A0xeYC8ISYPkDeE8SB5Q0ye4PV+/wX9SQTlDTGJoB6sm/euoLwhJhGUN8QkgvKGmERQ3hCTCMobYhJBeUNMIihvCCPC8oaYRFDeEJMIyhtiEkF5Q0yiAkcE5Q0xiaC8ISYRlDfEJILyhphEUN4QRoTlDTGJoLwhJhGUN8QkgvKGmEQFjgjKG2ISQXlDTCIob4hJBOUNMYmgvCF+dR5BeUP8QoLyhviFBOUN8QsJ6g32X0hQ3hC/kKC8IX4hwZXawLwhfiFBeUP8QoLyhviFVPCQsPYlaZTeEMbN+MS1cTO+cG3clN4QE5zxhesJzvjC9QRnfOF6ghdWcMYXric4ozfEBGfNm5TeEBOcNXNSekNMcNbMSekNMcFZMyelN8QEZ82crt4QU2DzFvD0hpgCw1nA1RtiCoi3gHoLeHpDTIHiLVC9BZq3gKc3xBTo3gLDWcDVG2IKiLeApzfEFGjeAp7PIZqAqzfEFPAeIldviCnQvQWGs4CrN8QUEG8B9RZYvQWKt0D1FmjeAp7eEFOgewt4ekPMb6Y8vSGmgHgLqLeApzfEFCjeAtVboHkLbN4Cnt4QU2A4C7h6Q0wB8RZQb4HVW6B4C1RvgeYt4OkNMQW6t4CnN8S8veDpDTEFxFtAvQU8vSGmQPEWqN4CzVtg8xbo3gLexRBnbwit/t4QFw1ebwiDp3252uBpX642eNqXqw2+MMPTvlxt8LQvVxs87cvVBk/7crXB03pDXOB5vSEMnjnD8npDGDxzhuX1hjB45gzL6w1h8MwZltcbwuCRvCEuPFDeEMZD+3K1wdO+XG3wtC9XG3xhhqd9udrgaV+uNnjal6sNnvblaoOnfbn6As/rDWHwzBmW1xvC4JkzLK83hMEzZ1hebwiDZ86wvN4QBs+cYaG8IYwHyRvCeJC8IYwHyRvCeFCy1ZUHyRvCeJC8IYwHyRvCeJC8IYwHyRviwgPlDWE8wev9wQv6RoTlDWFEWA/W2b0rLG8II8LyhjAiLG8II8LyhjAiLG8II8LyhjAiLG+ICxGYN4QRYXlDGBGWN4QRYXlDGFGBI8LyhjAiLG8II8LyhjAiLG8II8LyhrgQgXlDGBGWN4QRYXlDGBGWN4QRFTgiLG8II8LyhjAiLG8II8LyhjAiLG+I2XmE5Q0xkbC8ISYSljfERMJ6g30iYXlDTCQsb4iJBFdqQ/OGmEhY3hATCcsbYiIVPCSsfWlV/w7eiwZvB6/B0/YXGTxtf5HB0/YXGXxhhqftLzJ42v4ig6ftLzJ42v4ig6ft4L3A83bwGjxzhuXt4DV45gzL28Fr8MwZlreD1+CZMyxvB6/BI3XwXnigOniNh7a/yOBp+4sMnra/yOALMzxtf5HB0/YXGTxtf5HB0/YXGTxtf9EFnreD1+CZMyxvB6/BM2dY3g5eg2fOsLwdvAbPnGF5O3gNnjnDQnXwGg9SB6/xIHXwGg9SB6/xoGSrKw9SB6/xIHXwGg9SB6/xIHXwGg9SB++FB6qD13iC1/uDPkcjwurgNSKsa4V27wqrg9eIsDp4jQirg9eIsDp4jQirg9eIsDp4jQirg/dCBNbBa0RYHbxGhNXBa0RYHbxGVOCIsDp4jQirg9eIsDp4jQirg9eIsDp4L0RgHbxGhNXBa0RYHbxGhNXBa0QFjgirg9eIsDp4jQirg9eIsDp4jQirg3d2HmF18E4krA7eiYTVwTuR4Drl0Dp4JxJWB+9Egiu1oXXwTiSsDt6JhNXBO5EKHhLUvlRv3sbf5KqxbX++ZRat+8e25z7Wn/vYeOpjx1e0H39MnvuYPvexw4XT979Nuh5/rDz3sfrcx9pzH9ue+1h/7mPjqY8d30ns/VrM70MPPybPfUyf+9j63MfKcx+rz32sPfexw1ny5YtLWQ4/1p/72HjqY8f3ah5/TJ77mD73sfW5jx3OkqHXhTPWw4VzfDXj8cfacx/bnvtYf+5j46mPHX+7//hj8uBj5TBuTZ/72Prcx45nSb2u7tEOV/fx1/mPP9ae+9j23Mf6cx8bT31sW5772PEs6cte5639X5/7z9/88FVEI0TWCJESIVIjRFqEyBYh0iNERoDI8Xfw7xaJWPE9YsX3iBXfI1Z8j1jxPWLF94gV3yNWfI9Y8SNixY+IFT8iVvyIWPEjYsWPiBU/Ilb8iFjxI2LFj4gVf+P7v7erSIiKhqisISolRKWGqLQQlS1EpYeohKx9CVn7ErL2JWTtS8jal5C1LyFrX0LWvoSsfQlZ+xKy9jVk7WvI2teQta8ha19D1r6GrH0NWfsasvY1ZO1ryNpfQ9b+GrL215C1v4as/TVk7a8ha38NWftryNpfQ9b+GrL2S8jaLyFrv4Ss/RKy9kvI2i8ha7+ErP0SsvZLyNovIWu/hqz9GrL2a8jaryFrv4as/Rqy9mvI2q8ha7+GrP0asvZbyNpvIWu/haz9FrL2W8jabyFrv4Ws/Ray9lvI2m8ha38LWfshd/ck5PKehNzek5DrexJyf09CLvBJyA0+CbnCJyF3+CTkEp+E3OKTkGt8EnKPT0Iu8knITT4JuconIXf5JOQyn4Tc5pOQ63wScp9PQi70SciNPgm50ichd/ok5FKfhNzqk5BrfRJyr09D7vVpyL0+DbnXpyH3+nQpISo1RKWFqGwhKj1EJWTth9zr05B7fRpyr09D7vVpyL0+DbnXpyH3+jTkXp+G3OvTkHt9GnKvT0Pu9WnIvT4NudenIff6NORen4bc69OQe30acq9PQ+71aci9Pg2516ch9/o05F6fhtzr05B7fRpyr09D7vVpyL0+DbnXpyH3+jTkXp+G3OvTkHt9GnKvT99wF67WqwFC3b68ovflGb03XIV7LPKG22O1X99OrV+fTv0qohEia4RIiRCpESJ/m1j2D25PfvANX/I/ns9v+I7/GyI1QqRFiERsZG/4fr+O+vuH21KPRUaAyBu+3f+GiESIaITIG1b8kF2kHYuUCJEaIdIiRLYIkR4hMgLS5Bu+0/+GSMQfYSPij7AR8UfYG77P/4ZIxB9hb/g2/xsiW4RIjxAJWPHrskSISISIRoisESIlQqRGiLQIkS1CpEeIRKx4iVjxErHiJWLFS8SKl4gVLxErXiJWvESseIlY8RKx4jVixWvEiteIFa8RK14jVrxGrHiNWPHqvuL7P8dmXrVsV43a/mUD+r8SvV4lepf7PyrS/xgLffFVUb3idCycgYVz/FfMD/IIGI+C8axgPAWMp4LxNDAesN1ZwLZnAdufFWx/VrD9WcH2ZwXbnxVsf1aw/Vkd9+erxOYv8fou+sWcbV1eHtWBxbMuYDwCxqNgPCsYTwHjqWA8DYxnA+MB259XsP25gO3PBWx/LmD7cwHbnwvY/lzA9ucCtj8Xx/35KtH9JYa7RF38JcRfQv0lVn+J4i9R/SWav4T/6m6vT1pZlqvPsSyiRyIaIfJ6yEXLn/22HdUH2gj4l2xLhEhE4LfyBpE2dpHejkRqhEiLENkiRHqEyDvWSZM/ItuBSF8iRCRCRCNE1giREiFSI0RahMgWIdIjRN6w4kXK9YelHP21MpYIEYkQ0QiRNUKkRIjUCJEWIbJFiLxhxcumu8jX+2l/REaAyA3H5rerrAGHhxsux29XqSEqLURlRKi84e7ed1QkREVDVNzXS1mO779u+6e27UH5tCz9948Wrfd/tO87xFjKf7/UWf+6KHvh7qTcg5T7ePkygAsruLKCr6zghRW8soI3VnDWvCmsiVNYM6eyZk5lzZzKmjmVNXMqa+ZU1sypbpnzKrB5C7ycier1m9FSy5HAcBZYF28B8RZQb4GXd7S9gbf09UigeAtUb4HmLfDqSq7LteJUl34k0L0FhrNAWbwFxFvg1Wla9fqjVQ8FmrfAq0Fu6/XCRKt6IFAXbwHvIaovr+S9dlzrdiTQvQWGs0BbvAXEW0C9BVZvgeItUL0FmrfAG1dya0cC3Vvg9ZW8b3bbkcD28kpex30B8RZQb4FXV3LbL5e2ZRwJFG+B6i3QvAU2b4GXV/KfR6xlORIYzgJ98RYQbwH1Fli9BYq3QPUWaN4C2xsFjlZy794Cr6/k66W3pkcC4+WVvNc1bwiIt4B6C7yckx+cMkfxFqjeAs1bYPMW6N4C3sWQG3c+36VQb9wsk7bu12pbffCFiZTlut9JETnQuHGp8O9ESt9Ftkdf4bztNZ9662YSC7wyw6/M8IUZvjLDN2b4jRm+M8MPYnhlzrDKnGGVOcMqc4ZV5gyrzBlWmTOsMmdYZc6wipJhf/OsKEnzyhOcB9/3/Fa9dUeNBX5lhi/M8JUZvjHDb8zwnRl+EMOXhRmeOcMW5gxbmDNsYc6whTnDFuYMW5gzbGHOsIU5w1aUDHvlQUmaVx6UPHjlQUltVx6UbHXlQUlAVx6UnHLlQUkTVx6Unf/Kg7KZ/+ZpYPtzC17vD946rrcaP36UKHhOP3jRq95qa/jJMdoUjmiFI2rRRHefl663Ght+lKjDEQ00or7AEYXvR3efUa63ujl+lGiFIypwRBWOqMERbXBEHY5ooBGNBY4oes++/9p2vdW386NEKxxRgSOqcEQNjmiDI+pwRAON6Nab+Y5Idx/Yn0iCh6R4SBWtYnPrnf8fRdrwkOBKbRLdwvcdJMVDWvGQCh4S2L60cXpDXLgpn7i+cFO+cH3h5vSGMHDKF64NnPKFawOnfOHawAsrOOUL1wZO6Q1h4Kx5k9MbwsBZMyenN4SBs2ZOTm8IA2fNnJzeEAbOmjl9vSFMYPMWcPWGMIHhLODrDWEC4i2g3gKu3hAmULwFqrdA8xZw9YYwge4tMJwFfL0hTEC8BVy9IUygeQu4Pod4EfD1hjAB7yHy9YYwge4tMJwFfL0hTEC8BdRbYPUWKN4C1VugeQu4ekOYQPcWcPWGsG+mXL0hTEC8BdRbwNUbwgSKt0D1FmjeApu3gKs3hAkMZwFfbwgTEG8B9RZYvQWKt0D1FmjeAq7eECbQvQVcvSHs9oKrN4QJiLeAegu4ekOYQPEWqN4CzVtg8xbo3gLexRBnb4jW/L0hLhq83hAGT/tytcHTvlxt8LQvVxt8YYanfbna4GlfrjZ42perDZ725WqDp/WGuMDzekMYPHOG5fWGMHjmDMvrDWHwzBmW1xvC4JkzLK83hMEjeUNceKC8IYyH9uVqg6d9udrgaV+uNvjCDE/7crXB075cbfC0L1cbPO3L1QZP+3L1BZ7XG8LgmTMsrzeEwTNnWF5vCINnzrC83hAGz5xheb0hDJ45w0J5QxgPkjeE8SB5QxgPkjeE8aBkqysPkjeE8SB5QxgPkjeE8SB5QxgPkjfEhQfKG8J4gtf7gxf0jQjLG8KIsB6ss3tXWN4QRoTlDWFEWN4QRoTlDWFEWN4QRoTlDWFEWN4QFyIwbwgjwvKGMCIsbwgjwvKGMKICR4TlDWFEWN4QRoTlDWFEWN4QRoTlDXEhAvOGMCIsbwgjwvKGMCIsbwgjKnBEWN4QRoTlDWFEWN4QRoTlDWFEWN4Qs/MIyxtiImF5Q0wkLG+IiYT1BvtEwvKGmEhY3hATCa7UhuYNMZGwvCEmEpY3xEQqeEhY+9K2+nfwXjR4O3gNnra/yOBp+4sMnra/yOALMzxtf5HB0/YXGTxtf5HB0/YXGTxtB+8FnreD1+CZMyxvB6/BM2dY3g5eg2fOsLwdvAbPnGF5O3gNHqmD98ID1cFrPLT9RQZP219k8LT9RQZfmOFp+4sMnra/yOBp+4sMnra/yOBp+4su8LwdvAbPnGF5O3gNnjnD8nbwGjxzhuXt4DV45gzL28Fr8MwZFqqD13iQOniNB6mD13iQOniNByVbXXmQOniNB6mD13iQOniNB6mD13iQOngvPFAdvMYTvN4f9DkaEVYHrxFhXSu0e1dYHbxGhNXBa0RYHbxGhNXBa0RYHbxGhNXBa0RYHbwXIrAOXiPC6uA1IqwOXiPC6uA1ogJHhNXBa0RYHbxGhNXBa0RYHbxGhNXBeyEC6+A1IqwOXiPC6uA1IqwOXiMqcERYHbxGhNXBa0RYHbxGhNXBa0RYHbyz8wirg3ciYXXwTiSsDt6JBNcph9bBO5GwOngnElypDa2DdyJhdfBOJKwO3olU8JCw9qUu/7zqg1yWK03RBzB937bHUv78qP7999wX7k7KPUi5ZWEFF1ZwZQVfWcELK3hlBW+s4Kx5U1gTp7BmTmXNnMqaOZU1cypr5lTWzKmsmVPdMudVYPMWeDkT1et9m1LLkcBwFlgXbwHxFlBvgZd3tH5dNKWvRwLFW6B6CzRvgVdXcl223z9al34k0L0FhrNAWbwFxFvg1Wla9fqjVQ8FmrfAq0Fu6/WWWqt6IFAXbwHvIaovr+Syz6K6HQl0b4HhLNAWbwHxFlBvgdVboHgLVG+B5i3wxpXc2pFA9xZ4fSXvm912JLC9vJL37fqGgHgLqLfAqyu57S0LbRlHAsVboHoLNG+BzVvg5ZU8ri8sN1mOBIazQF+8BcRbQL0FVm+B4i1QvQWat8D2RoGjldy7t8DrK/l6EaXpkcB4eSXvdc0bAuItoN4CL+fkB6fMUbwFqrdA8xbYvAW6t4B3MeTG3eZ3KQzx94YYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEECxviCFY3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYweOYMy+sNYfDMGZbXG2IIsTeEwTNnWF5viCHE3hBDsLwhjAfJG8J4kLwhjAfJG8J4ULLVlQfJG2IIljfEECxviCFY3hBDsLwhhmB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD4LwhJhKWN8REwvKGmEhYb7BPJCxviImE5Q0xkeBKbWjeEBMJyxtiImF5Q0ykgocEti91Tm+ICzflE9cXbsoXri/cnN4QBk75wrWBU75wbeCUL1wbeGEFp3zh2sApvSEMnDVvcnpDGDhr5uT0hjBw1szJ6Q1h4KyZk9MbwsBZM6evN4QJbN4Crt4QJjCcBXy9IUxAvAXUW8DVG8IEirdA9RZo3gKu3hAm0L0FhrOArzeECYi3gKs3hAk0bwHX5xAvAr7eECbgPUS+3hAm0L0FhrOArzeECYi3gHoLrN4CxVugegs0bwFXbwgT6N4Crt4Q9s2UqzeECYi3gHoLuHpDmEDxFqjeAs1bYPMWcPWGMIHhLODrDWEC4i2g3gKrt0DxFqjeAs1bwNUbwgS6t4CrN4TdXnD1hjAB8RZQbwFXbwgTKN4C1VugeQts3gLdW8C7GOLrDdGWzd0bwjRovSEmPOvL1ROe9eXqCc/6cvWEL8zwrC9XT3jWl6snPOvL1ROe9eXqCc/qDWHwtN4QE545w9J6Q0x45gxL6w0x4ZkzLK03xIRnzrC03hATHsgbwniQvCEmD+vL1ROe9eXqCc/6cvWEL8zwrC9XT3jWl6snPOvL1ROe9eXqCc/6crXB03pDTHjmDEvrDTHhmTMsrTfEhGfOsLTeEBOeOcPSekNMeOYMi+QNMXmAvCEmD5A3xOQB8oaYPCjZ6soD5A0xeYC8ISYPkDfE5AHyhpg8QN4QxoPkDTF5gtf7/Rf0JxGUN8Qkgnqwbt67gvKGmERQ3hCTCMobYhJBeUNMIihviEkE5Q0xiaC8IYwIyxtiEkF5Q0wiKG+ISQTlDTGJChwRlDfEJILyhphEUN4QkwjKG2ISQXlDGBGWN8QkgvKGmERQ3hCTCMobYhIVOCIob4hJBOUNMYmgvCEmEZQ3xCSC8ob41XkE5Q3xCwnKG+IXEpQ3xC8kqDfYfyFBeUP8QoLyhviFBFdqA/OG+IUE5Q3xCwnKG+IXUsFDwtqXpPh38F40eDt4DZ62v8jgafuLDJ62v8jgCzM8bX+RwdP2Fxk8bX+RwdP2Fxk8bQfvBZ63g9fgmTMsbwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DR6pg/fCA9XBazy0/UUGT9tfZPC0/UUGX5jhafuLDJ62v8jgafuLDJ62v8jgafuLLvC8HbwGz5xheTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGRaqg9d4kDp4jQepg9d4kDp4jQclW115kDp4jQepg9d4kDp4jQepg9d4kDp4LzxQHbzGE7zeH/Q5GhFWB68RYV0rtHtXWB28RoTVwWtEWB28RoTVwWtEWB28RoTVwWtEWB28FyKwDl4jwurgNSKsDl4jwurgNaICR4TVwWtEWB28RoTVwWtEWB28RoTVwXshAuvgNSKsDl4jwurgNSKsDl4jKnBEWB28RoTVwWtEWB28RoTVwWtEWB28s/MIq4N3ImF18E4krA7eiQTXKYfWwTuRsDp4JxJcqQ2tg3ciYXXwTiSsDt6JVPCQsPYlbTc6eGvZrh+rbbuv8b5b3hecjoUzsHButEL/HI+A8SgYzwrGU8B4KhhPA+MB250FbHsWsP1ZwfZnBdufFWx/VrD9WcH2ZwXbn9Vxf75KbP4Sr++i77syajwDi2ddwHgEjEfBeFYwngLGU8F4GhjPBsYDtj+vYPtzAdufC9j+XMD25wK2Pxew/bmA7c8FbH8ujvvzVaL7Swx3ibr4S4i/hPpLrP4SxV+i+ks0fwn/1d1en7QPLtebiEaIvB7yx1/JtRHwL9mWCJGIwG/lDSJ3L7ibSI0QaREiW4RIjxB5xzq5e0vWvpBeIkQkQkQjRNYIkRIhUiNEWoTIFiHSI0TesOLv3/q0Ox9LhIhEiGiEyBohUiJEaoRIixDZIkTesOLv3+Q1kREgcuue97tV1oDDgywlRKWGqLQQlRGh8oa7e99RkRAVDVHxXy/9+P7rtn9q2x6UT8tyvY1b9MFl3L7vEGMp//1SZ/37omw/vihLwD1IuY+XLwO4sIIrK/jKCl5YwSsreGMFZ82bwpo4hTVzKmvmVNbMqayZU1kzp7JmTmXNnOqWOa8Cm7fAy5moXr8ZLbUcCQxngXXxFhBvAfUWeHlH69dFU/p6JFC8Baq3QPMWeHUl1+VacapLPxLo3gLDWaAs3gLiLfDqNK16/dGqhwLNW+DVILf1emGiVT0QqIu3gPcQ1ZdX8l47rnU7EujeAsNZoC3eAuItoN4Cq7dA8Rao3gLNW+CNK7m1I4HuLfD6St43u+1IYHt5Je/b9Q0B8RZQb4FXV3LbL5e2ZRwJFG+B6i3QvAU2b4GXV/KoVwFZjgSGs0BfvAXEW0C9BVZvgeItUL0FmrfA9kaBo5Xcu7fA6yv5eumt6ZHAeHkl73XNGwLiLaDeAi/n5AenzFG8Baq3QPMW2LwFureAdzHkxp3PdymsN26W/eVTj8t1v5MicqAhKCb0f/0VznrrZhILvDLDr8zwhRm+MsM3ZviNGb4zww9ieGXOsMqcYZU5wypzhlXmDKvMGVaZM6wyZ1hlzrCKkmF/86woSfPKg2JC/0xwVxTH+qfgUeztn4IvzPCVGb4xw2/M8J0ZfhDDl4UZnjnDFuYMW5gzbGHOsIU5wxbmDFuYM2xhzrCFOcNWlAx75UFJmlcelDx45UFJbVcelGx15UFJQFcelJxy5UFJE1celJ3/yoOymf/maWD7cwte7w/eOl5vNX78KBGWYfN6q63hJ8doUziiFY4o2h79/vPS663Ghh8l6nBEA42oL3BE4fvR3WeU11vdHD9KtMIRFTiiCkfU4Ig2OKIORzTQiMYCRxS9Z99/bXu91bfzo0QrHFGBI6pwRA2OaIMj6nBEA43o1pv5jkh3H9ifSIKHpHhIFa1ic+ud/x9F2vCQ4EptEt3C9x0kxUNa8ZAKHhLWvlQqpzfEhZvyiesLN+UL1xduTm8IA6d84drAKV+4NnDKF64NvLCCU75wbeCU3hAGzpo3Ob0hDJw1c3J6Qxg4a+bk9IYwcNbMyekNYeCsmdPXG8IENm8BV28IExjOAr7eECYg3gLqLeDqDWECxVugegs0bwFXbwgT6N4Cw1nA1xvCBMRbwNUbwgSat4Drc4gXAV9vCBPwHiJfbwgT6N4Cw1nA1xvCBMRbQL0FVm+B4i1QvQWat4CrN4QJdG8BV28I+2bK1RvCBMRbQL0FXL0hTKB4C1RvgeYtsHkLuHpDmMBwFvD1hjAB8RZQb4HVW6B4C1RvgeYt4OoNYQLdW8DVG8JuL7h6Q5iAeAuot4CrN4QJFG+B6i3QvAU2b4HuLeBdDHH2hqjF3xviosHrDWHwtC9XGzzty9UGT/tytcEXZnjal6sNnvblaoOnfbna4GlfrjZ4Wm+ICzyvN4TBM2dYXm8Ig2fOsLzeEAbPnGF5vSEMnjnD8npDGDySN8SFB8obwnhoX642eNqXqw2e9uVqgy/M8LQvVxs87cvVBk/7crXB075cbfC0L1df4Hm9IQyeOcPyekMYPHOG5fWGMHjmDMvrDWHwzBmW1xvC4JkzLJQ3hPEgeUMYD5I3hPEgeUMYD0q2uvIgeUMYD5I3hPEgeUMYD5I3hPEgeUNceKC8IYwneL0/eEHfiLC8IYwI68E6u3eF5Q1hRFjeEEaE5Q1hRFjeEEaE5Q1hRFjeEEaE5Q1xIQLzhjAiLG8II8LyhjAiLG8IIypwRFjeEEaE5Q1hRFjeEEaE5Q1hRFjeEBciMG8II8LyhjAiLG8II8LyhjCiAkeE5Q1hRFjeEEaE5Q1hRFjeEEaE5Q0xO4+wvCEmEpY3xETC8oaYSFhvsE8kLG+IiYTlDTGR4EptaN4QEwnLG2IiYXlDTKSCh4S1LzXx7+C9aPB28Bo8bX+RwdP2Fxk8bX+RwRdmeNr+IoOn7S8yeNr+IoOn7S8yeNoO3gs8bwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DZ45w/J28Bo8UgfvhQeqg9d4aPuLDJ62v8jgafuLDL4ww9P2Fxk8bX+RwdP2Fxk8bX+RwdP2F13geTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGZa3g9fgmTMsVAev8SB18BoPUgev8SB18BoPSra68iB18BoPUgev8SB18BoPUgev8SB18F54oDp4jSd4vT/oczQirA5eI8K6Vmj3rrA6eI0Iq4PXiLA6eI0Iq4PXiLA6eI0Iq4PXiLA6eC9EYB28RoTVwWtEWB28RoTVwWtEBY4Iq4PXiLA6eI0Iq4PXiLA6eI0Iq4P3QgTWwWtEWB28RoTVwWtEWB28RlTgiLA6eI0Iq4PXiLA6eI0Iq4PXiLA6eGfnEVYH70TC6uCdSFgdvBMJrlMOrYN3ImF18E4kuFIbWgfvRMLq4J1IWB28E6ngIYHtS+OfV32Qy3KlKfoApu/b9ljKnx/VJ77nHv90Uu5Byi0LK7iwgisr+MoKXljBKyt4YwVnzZvCmjiFNXMqa+ZU1syprJlTWTOnsmZOZc2c6pY5rwKbt8DLmahe79uUWo4EhrPAungLiLeAegu8vKP166IpfT0SKN4C1VugeQu8upLrsv3+0br0I4HuLTCcBcriLSDeAq9O06rXH616KNC8BV4Ncluvt9Ra1QOBungLeA9RfXkll30W1e1IoHsLDGeBtngLiLeAegus3gLFW6B6CzRvgTeu5NaOBLq3wOsred/stiOB7eWVvG/XNwTEW0C9BV5dyW1vWWjLOBIo3gLVW6B5C2zeAi+v5HF9YbnJciQwnAX64i0g3gLqLbB6CxRvgeot0LwFtjcKHK3k3r0FXl/J14soTY8Exssrea9r3hAQbwH1Fng5Jz84ZY7iLVC9BZq3wOYt0L0FvIshN+42v0thG/7eENsg9obYBrE3xDaIvSG2QewNsQ1ib4htEHtDbIPYG2IbxN4Q2yD2htgGsTfENoi9IbZB7A2xDWJviG0Qe0Nsg9gbYhvE3hDbIPaG2AaxN8Q2iL0htoHlDbENLG+IbRB7Q2yD2BtiG8TeENsg9obYBrE3xDaIvSG2QewNsQ1ib4htEHtDbIPYG2IbxN4QBs+cYXm9IQyeOcPyekNsg9gbwuCZMyyvN8Q2iL0htoHlDWE8SN4QxoPkDWE8SN4QxoOSra48SN4Q28DyhtgGljfENrC8IbaB5Q2xDSxviG2geUNsA80bYhto3hDbQPOG2AaaN8Q20LwhtoHmDbENNG+IbaB5Q2wDzRtiG2jeENtA84bYBpo3xDbQvCG2geYNsQ00b4htoHlDbAPNG2IbaN4Q20DzhtgGmjfENtC8IbaB5g2xDTRviG2geUNsA80bYhto3hDbQPOG2AaaN8Q20LwhtgHnDTGRsLwhJhKWN8REwnqDfSJheUNMJCxviIkEV2pD84aYSFjeEBMJyxtiIhU8JKx9qTdOb4gLN+UT1xduyheuL9yc3hAGTvnCtYFTvnBt4JQvXBt4YQWnfOHawCm9IQycNW9yekMYOGvm5PSGMHDWzMnpDWHgrJmT0xvCwFkzp683hAls3gKu3hAmMJwFfL0hTEC8BdRbwNUbwgSKt0D1FmjeAq7eECbQvQWGs4CvN4QJiLeAqzeECTRvAdfnEC8Cvt4QJuA9RL7eECbQvQWGs4CvN4QJiLeAegus3gLFW6B6CzRvAVdvCBPo3gKu3hD2zZSrN4QJiLeAegu4ekOYQPEWqN4CzVtg8xZw9YYwgeEs4OsNYQLiLaDeAqu3QPEWqN4CzVvA1RvCBLq3gKs3hN1ecPWGMAHxFlBvAVdvCBMo3gLVW6B5C2zeAt1bwLsY4uwNMaq/N8RFg9cbwuBpX642eNqXqw2e9uVqgy/M8LQvVxs87cvVBk/7crXB075cbfC03hAXeF5vCINnzrC83hAGz5xheb0hDJ45w/J6Qxg8c4bl9YYweCRviAsPlDeE8dC+XG3wtC9XGzzty9UGX5jhaV+uNnjal6sNnvblaoOnfbna4Glfrr7A83pDGDxzhuX1hjB45gzL6w1h8MwZltcbwuCZMyyvN4TBM2dYKG8I40HyhjAeJG8I40HyhjAelGx15UHyhjAeJG8I40HyhjAeJG8I40HyhrjwQHlDGE/wen/wgr4RYXlDGBHWg3V27wrLG8KIsLwhjAjLG8KIsLwhjAjLG8KIsLwhjAjLG+JCBOYNYURY3hBGhOUNYURY3hBGVOCIsLwhjAjLG8KIsLwhjAjLG8KIsLwhLkRg3hBGhOUNYURY3hBGhOUNYUQFjgjLG8KIsLwhjAjLG8KIsLwhjAjLG2J2HmF5Q0wkLG+IiYTlDTGRsN5gn0hY3hATCcsbYiLBldrQvCEmEpY3xETC8oaYSAUPCWpf2hZ17+A1DdoO3gnP2l804Vn7iyY8a3/RhC/M8Kz9RROetb9owrP2F0141v6iCc/awWvwtB28E545w9J28E545gxL28E74ZkzLG0H74RnzrC0HbwTHqiD13iQOngnD2t/0YRn7S+a8Kz9RRO+MMOz9hdNeNb+ognP2l804Vn7iyY8a3+RwdN28E545gxL28E74ZkzLG0H74RnzrC0HbwTnjnD0nbwTnjmDIvUwTt5gDp4Jw9QB+/kAergnTwo2erKA9TBO3mAOngnD1AH7+QB6uCdPEAdvMaD1ME7eYLX+/0+x0kE1cE7iaCuFc57V1AdvJMIqoN3EkF18E4iqA7eSQTVwTuJoDp4JxFUB68RYXXwTiKoDt5JBNXBO4mgOngnUYEjgurgnURQHbyTCKqDdxJBdfBOIqgOXiPC6uCdRFAdvJMIqoN3EkF18E6iAkcE1cE7iaA6eCcRVAfvJILq4J1EUB28vzqPoDp4fyFBdfD+QoLq4P2FBNcpB9bB+wsJqoP3FxJcqQ2sg/cXElQH7y8kqA7eX0gFDwlqX7rkt1vX8Te5imzbn6+ZReufz21Pfq4/+bnx3OeO72l/43Py5Of0yc8dLqC+/43S9cbnypOfq09+rj35ue3Jz/UnPzee+9zxFcXer7X9PvT4c/Lk5/TJz61Pfq48+bn65Ofak587nC9fvs6U5fhz/cnPjec+d3zh5hufkyc/p09+bn3yc4fzZeh1HY31eB0dX9z4xufak5/bnvxcf/Jz47nPHV8A+Mbn5MHnynH8mj75ufXJzx3Pl3pd76Mdr/fjr/2/8bn25Oe2Jz/Xn/zceO5z2/Lk547nS1/2qnDt//rgf/7mh3cVDVFZQ1RKiEoNUWkhKluISg9RGREqx1/dv10lZO33kLXfQ9Z+D1n7PWTt95C130PWfg9Z+z1k7Y+QtT9C1v4IWfsjZO2PkLU/Qtb+CFn7I2Ttj5C1P0LW/o2vEt8vIzEyGiOzxsiUGJkaI9NiZLYYmR4jE7MLSMwuIDG7gMTsAhKzC0jMLiAxu4DE7AISswtIzC4gMbuAxuwCGrMLaMwuoDG7gMbsAhqzC2jMLqAxu4DG7AIaswusMbvAGrMLrDG7wBqzC6wxu8AaswusMbvAGrMLrDG7wBqzC5SYXaDE7AIlZhcoMbtAidkFSswuUGJ2gRKzC5SYXaDE7AI1ZheoMbtAjdkFaswuUGN2gRqzC9SYXaDG7AI1ZheoMbtAi9kFWswu0GJ2gRazC7SYXaDF7AItZhdoMbtAi9kFWswusMXsAjH3AyXmgqDE3BCUmCuCEnNHUGIuCUrMLUGJuSYoMfcEJeaioMTcFJSYq4ISc1dQYi4LSsxtQYm5Ligx9wUl5sKgxNwYlJgrgxJzZ1BiLg1KzK1Bibk2KDH3BiXm4qDE3ByUmKuDEnN3UGPuDmrM3UGNuTuoMXcHdSkxMjVGpsXIbDEyPUYmZheIuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gvuG2Xa1Xc4e6fXkh8OsTgW+4bPcNlTfcTqv9+jJs/fow7L9UNERlDVEpISo1ROVvE82fT27PfvINtwa+Ma/fcGngOyo1RKWFqITsam+4MFBH/f3Dbak3VEaEyhuuC3xHRUJUNETlDWt/yK7SbqiUEJUaotJCVLYQlR6iMiIy5xsuCXxHJeSvsxHy19kI+evsDRcEvqMS8tfZG64HfEdlC1HpISoRa39dlhAVCVHREJU1RKWEqNQQlRaisoWo9BCVkLUvIWtfQta+hKx9CVn7ErL2JWTtS8jal5C1LyFrX0LWvoasfQ1Z+xqy9jVk7WvI2teQta8ha1/9137/59jorJbtKlLbvyxS/1ej16tG73L/R0X6H9OlLy4zqjtPB+MZYDzHf9r8JJCgASka0IoGVNCAKhpQQwNC26cFbaMWtJ1a0XZqRdupFW2nVrSdWtF2akXbqdVxp941tgCN1/fTL4516/L6wA4woHVBAxI0IEUDWtGAChpQRQNqaEAbGhDaTr2i7dQFbacuaDt1QdupC9pOXdB26oK2Uxe0nbo47tS7Rg/QGP4adQnQkAANDdBYAzRKgEYN0GgBGgHrvL0+dy+/5+oELYvooYqGqLwed9HyZ/dthwWENiL+LdsSohIS/a28QaWNXaW3Q5UaotJCVLYQlR6i8o710uSPynak0pcQFQlR0RCVNUSlhKjUEJUWorKFqPQQlTesfZFy/WEph3/DjCVERUJUNERlDVEpISo1RKWFqGwhKm9Y+7LprvL1xtsXlRGhIssSI7NGnC1u+EC/X6bGyLQYmREi84Ybgd+SkRgZjZHxXzeyHF+u3faPbduDomtZ+u8fLVrv/2jf94qxlP9+qc7+fSn3At5ZwQcr+PEqpiAXWnKlJV9pyQsteaUlb7TktBlUaFOo0OZQpc2hSptDlTaHKm0OVdocqrQ5VN1y6K6wuSu8nJPq9TvVUsuhwvBWWBd3BXFXUHeFl/e2vXG49PVQobgrVHeF5q7w6pquy7UgVZd+qNDdFYa3QlncFcRd4dXZWvX6o1WPFZq7wquRbuv11kWreqRQF3cF91GqL6/pvchc63ao0N0VhrdCW9wVxF1B3RVWd4XirlDdFZq7whvXdGuHCt1d4fU1ve9826HC9vKaXscDBXFXUHeFV9d022+utmUcKhR3hequ0NwVNneFl9f0n8e4ZTlUGN4KfXFXEHcFdVdY3RWKu0J1V2juCtsbFQ7XdO/uCq+v6etNuqaHCuPlNb2XQ28piLuCuiu8nKcfnUVHcVeo7grNXWFzV+juCu6VkxsXSt8moTduq0lb93u7rT74ykXKct38pIgcidy4rfh3KqXvKtujb4He99qQ3rrrREOv1PQrNX2hpq/U9I2afqOm79T0g5leqXOtUudapc61Sp1rlTrXKnWuVepcq9S5VqlzraLk2ivQipI+d6DgjPjG58H01q03GvqVmr5Q01dq+kZNv1HTd2r6wUxfFmp66lxbqHNtoc61hTrXFupcW6hzbaHOtYU61xbqXFtRcu0OhJI+dyCUjLgDoSS5HQglb+1AKKloB0LJLjsQSsLYgVBywA6Esq1fgRraTt2Cl/2jh5n1VkfJzyIFT+xHj4vprV6JHx2lTfGQVjykFo10/zFsvdUr8bNIHQ9pwCH1BQ8pfF+6/96z3moQ+VmkFQ+p4CFVPKSGh7ThIXU8pAGHNBY8pOjd+8G74HqrFehnkVY8pIKHVPGQGh7ShofU8ZAGHNKtN/4dme4bAkwmAWRSQKYKV9C55Uvws0wbIBNeMU6iOwO/xaSATCsgUwFkQtufNlI3iws451PcF3DOl7gv4KRuFkbO+RK3kXO+xG3knC9xG3mhJed8idvIOd0sjJw2g5K6WRg5bQ4ldbMwctocSupmYeS0OZTUzcLIaXOos5uFKWzuCr5uFqYwvBWc3SxMQdwV1F3B183CFIq7QnVXaO4Kvm4WptDdFYa3grObhSmIu4Kvm4UpNHcF3zcZLwrObham4D5Kzm4WptDdFYa3grObhSmIu4K6K6zuCsVdoborNHcFXzcLU+juCr5uFvZ1lq+bhSmIu4K6K/i6WZhCcVeo7grNXWFzV/B1szCF4a3g7GZhCuKuoO4Kq7tCcVeo7grNXcHXzcIUuruCr5uFXYLwdbMwBXFXUHcFXzcLUyjuCtVdobkrbO4K3V3BvXLi7WaxtgA3i4sIsZuF0fO+sG30vC9sGz3vC9tGX6jpeV/YNnreF7aNnveFbaPnfWHb6HndLC70xG4WRk+da4ndLIyeOtcSu1kYPXWuJXazMHrqXEvsZmH0UG4WFyAsNwsD4n1h2+h5X9g2et4Xto2+UNPzvrBt9LwvbBs97wvbRs/7wrbR876wfaEndrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0VPnWmI3C6OnzrVYbhYGBOVmYUBQbhYGBOVmYUAoeWsHgnKzMCAoNwsDgnKzMCAoNwsDgnKzuABhuVkYUPCyf/TcvyGBuVkYEtgDenZdC8zNwpDA3CwMCczNwpDA3CwMCczNwpDA3CwMCczN4oKE5mZhSGBuFoYE5mZhSGBuFoZU8JDA3CwMCczNwpDA3CwMCczNwpDA3CwuSGhuFoYE5mZhSGBuFoYE5mZhSAUPCczNwpDA3CwMCczNwpDA3CwMCczNYrYygblZTCYwN4vJBOZmMZnAXoufTGBuFpMJzM1iMuEV4+DcLCYTmJvFZAJzs5hMBZAJbH8qa0B/8EWEuD/Y6Hl7loyet2fJ6Hl7loy+UNPz9iwZPW/PktHz9iwZPW/PktHz9gdf6In7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LmWuD/Y6KH6gy9AWP3BBsTbs2T0vD1LRs/bs2T0hZqet2fJ6Hl7loyet2fJ6Hl7loyet2fpQk/cH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da7H6gw0Iqj/YgKD6gw0Iqj/YgFDy1g4E1R9sQFD9wQYE1R9sQFD9wQYE1R98AcLqDzag4GX/qIHSkMD6gw0J7EqiXdcC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w+erUxg/cGTCaw/eDKB9QdPJrz+O7j+4MkE1h88mfCKcXD9wZMJrD94MoH1B0+mAsgEtj9V+edVH+eyXHGKPqDp+wY+lvLnR/WJb8cv4J0VfLCCy0JLLrTkSku+0pIXWvJKS95oyWkzqNCmUKHNoUqbQ5U2hyptDlXaHKq0OVRpc6i65dBdYXNXeDkn1etNnVLLocLwVlgXdwVxV1B3hZf3tn5dPKWvhwrFXaG6KzR3hVfXdF223z9al36o0N0VhrdCWdwVxF3h1dla9fqjVY8VmrvCq5Fu6/WqW6t6pFAXdwX3Uaovr+myz6W6HSp0d4XhrdAWdwVxV1B3hdVdobgrVHeF5q7wxjXd2qFCd1d4fU3vO992qLC9vKb33fuWgrgrqLvCq2u67f0QbRmHCsVdoborNHeFzV3h5TU9ro8/N1kOFYa3Ql/cFcRdQd0VVneF4q5Q3RWau8L2RoXDNd27u8Lra/p6o6XpocJ4eU3v5dBbCuKuoO4KL+fpR2fRUdwVqrtCc1fY3BW6u4J75eTG1em3STQJcLNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFEzA3iyZgbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrMweupcS+xmYfTUuZbYzaIJs5uF0VPnWmI3iybMbhZNwNwsDAjKzcKAoNwsDAjKzcKAUPLWDgTlZtEEzM2iCZibRRMwN4smYG4WTcDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smeG4WkwnMzWIygblZTCaw1+InE5ibxWQCc7OYTHjFODg3i8kE5mYxmcDcLCZTAWRC2586qZvFBZzzKe4LOOdL3BdwUjcLI+d8idvIOV/iNnLOl7iNvNCSc77EbeScbhZGTptBSd0sjJw2h5K6WRg5bQ4ldbMwctocSupmYeS0OdTZzcIUNncFXzcLUxjeCs5uFqYg7grqruDrZmEKxV2huis0dwVfNwtT6O4Kw1vB2c3CFMRdwdfNwhSau4Lvm4wXBWc3C1NwHyVnNwtT6O4Kw1vB2c3CFMRdQd0VVneF4q5Q3RWau4Kvm4UpdHcFXzcL+zrL183CFMRdQd0VfN0sTKG4K1R3heausLkr+LpZmMLwVnB2szAFcVdQd4XVXaG4K1R3heau4OtmYQrdXcHXzcIuQfi6WZiCuCuou4Kvm4UpFHeF6q7Q3BU2d4XuruBeOfF2s9i2ADeLiwixm4XR876wbfS8L2wbPe8L20ZfqOl5X9g2et4Xto2e94Vto+d9Ydvoed0sLvTEbhZGT51rid0sjJ461xK7WRg9da4ldrMweupcS+xmYfRQbhYXICw3CwPifWHb6Hlf2DZ63he2jb5Q0/O+sG30vC9sGz3vC9tGz/vCttHzvrB9oSd2szB66lxL7GZh9NS5ltjNwuipcy2xm4XRU+daYjcLo6fOtVhuFgYE5WZhQFBuFgYE5WZhQCh5aweCcrMwICg3CwOCcrMwICg3CwOCcrO4AGG5WRhQ8LJ/9Ny/IYG5WRgS2AN6dl0LzM3CkMDcLAwJzM3CkMDcLAwJzM3CkMDcLAwJzM3igoTmZmFIYG4WhgTmZmFIYG4WhlTwkMDcLAwJzM3CkMDcLAwJzM3CkMDcLC5IaG4WhgTmZmFIYG4WhgTmZmFIBQ8JzM3CkMDcLAwJzM3CkMDcLAwJzM1itjKBuVlMJjA3i8kE5mYxmcBei59MYG4WkwnMzWIy4RXj4NwsJhOYm8VkAnOzmEwFkAlsf+oloD/4IkLcH2z0vD1LRs/bs2T0vD1LRl+o6Xl7loyet2fJ6Hl7loyet2fJ6Hn7gy/0xP3BRk+da4n7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z0UP3BFyCs/mAD4u1ZMnreniWj5+1ZMvpCTc/bs2T0vD1LRs/bs2T0vD1LRs/bs3ShJ+4PNnrqXEvcH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861WP3BBgTVH2xAUP3BBgTVH2xAKHlrB4LqDzYgqP5gA4LqDzYgqP5gA4LqD74AYfUHG1Dwsn/UQGlIYP3BhgR2JdGua4H1BxsSWH+wIYH1BxsSWH+wIYH1BxsSWH+wIYH1B1+Q0PqDDQmsP9iQwPqDDQmsP9iQCh4SWH+wIYH1BxsSWH+wIYH1BxsSWH/wBQmtP9iQwPqDDQmsP9iQwPqDDangIYH1BxsSWH+wIYH1BxsSWH+wIYH1B89WJrD+4MkE1h88mcD6gycTXv8dXH/wZALrD55MeMU4uP7gyQTWHzyZwPqDJ1MBZALbn0a70R9cy3b9XG3bfZE3Xhi/8HQwngHGc6PV+geBBA1I0YBWNKCCBlTRgBoaENo+LWgbtaDt1Iq2UyvaTq1oO7Wi7dSKtlMr2k6tjjv1rrEFaLy+n77x9qkBDTCgdUEDEjQgRQNa0YAKGlBFA2poQBsaENpOvaLt1AVtpy5oO3VB26kL2k5d0HbqgrZTF7Sdujju1LtGD9AY/hp1CdCQAA0N0FgDNEqARg3QaAEaAeu8vT53H13aNxUNUXk97t/4Iq+NiH/LtoSohER/K29QuX9z3lRqiEoLUdlCVHqIyjvWy/2bt/Z19hKiIiEqGqKyhqiUEJUaotJCVLYQlR6i8oa1/+AqqV0dWUJUJERFQ1TWEJUSolJDVFqIyhai8oa1/+CSsKmMCJVb18jfLrNGnC1kKTEyNUamxciMEJk33Aj8lozEyGiMTMC66ceXa7f9Y9v2oOhalutd36IPrvr2fa8YS/nvl+rsE6XcfnwLlwF8sIIfr2IKcqElV1rylZa80JJXWvJGS06bQYU2hQptDlXaHKq0OVRpc6jS5lClzaFKm0PVLYfuCpu7wss5qV6/Uy21HCoMb4V1cVcQdwV1V3h5b+vXxVP6eqhQ3BWqu0JzV3h1TdflWpCqSz9U6O4Kw1uhLO4K4q7w6mytev3RqscKzV3h1Ui39XrrolU9UqiLu4L7KNWX1/ReZK51O1To7grDW6Et7grirqDuCqu7QnFXqO4KzV3hjWu6tUOF7q7w+pred77tUGF7eU3vu/ctBXFXUHeFV9d022+utmUcKhR3hequ0NwVNneFl9f0qFcFWQ4VhrdCX9wVxF1B3RVWd4XirlDdFZq7wvZGhcM13bu7wutr+nqTrumhwnh5Te/l0FsK4q6g7gov5+lHZ9FR3BWqu0JzV9jcFbq7gnvl5MaF0ndJyHLjttpfPk65XDc/KSJHIhL8vPL7Xhua9EJNr9T0KzV9oaav1PSNmn6jpu/U9IOZXqlzrVLnWqXOtUqda5U61yp1rlXqXKvUuVapc62i5Nor0IqSPneg4Iz4vufBJr1S06/U9IWavlLTN2r6jZq+U9MPZvqyUNNT59pCnWsLda4t1Lm2UOfaQp1rC3WuLdS5tlDn2oqSa3cglPS5A6FkxB0IJcntQCh5awdCSUU7EEp22YFQEsYOhJIDdiCUbf0K1NB26ha87B88zDyRKh4Sljv1vK4lcKO0KR7SiocU7Qh//zHsibThIXU8pAGH1Bc8pPB96e57zxNJ8ZBWPKSCh1TxkBoe0oaH1PGQBhzSWPCQonfv+++CTyTFQ1rxkAoeUsVDanhIGx5Sx0MacEi33vh3ZLprCPCLSQCZFJCpwhV0bvkS/CzTBsiEV4yT6M7AbzEpINMKyFQAmcD2J6mcbhYGTvkUt4FTvsRt4JxuFpOc8iXuSU75Evckp3yJe5IXWnLKl7gnOaWbxSSnzaCcbhaTnDaHcrpZTHLaHMrpZjHJaXMop5vFJKfNob5uFlNhc1dwdbOYCsNbwdfNYiqIu4K6K7i6WUyF4q5Q3RWau4Krm8VU6O4Kw1vB181iKoi7gqubxVRo7gqubzKagq+bxVRwHyVfN4up0N0VhreCr5vFVBB3BXVXWN0VirtCdVdo7gqubhZTobsruLpZzK+zXN0spoK4K6i7gqubxVQo7grVXaG5K2zuCq5uFlNheCv4ullMBXFXUHeF1V2huCtUd4XmruDqZjEVuruCq5vFvATh6mYxFcRdQd0VXN0spkJxV6juCs1dYXNX6O4K7pUTbzcLLQFuFhcRYjcLo+d9YdvoeV/YNnreF7aNvlDT876wbfS8L2wbPe8L20bP+8K20fO6WVzoid0sjJ461xK7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoodwsLkBYbhYGxPvCttHzvrBt9LwvbBt9oabnfWHb6Hlf2DZ63he2jZ73hW2j531h+0JP7GZh9NS5ltjNwuipcy2xm4XRU+daYjcLo6fOtcRuFkZPnWux3CwMCMrNwoCg3CwMCMrNwoBQ8tYOBOVmYUBQbhYGBOVmYUBQbhYGBOVmcQHCcrMwoOBl/+i5f0MCc7MwJLAH9Oy6FpibhSGBuVkYEpibhSGBuVkYEpibhSGBuVkYEpibxQUJzc3CkMDcLAwJzM3CkMDcLAyp4CGBuVkYEpibhSGBuVkYEpibhSGBuVlckNDcLAwJzM3CkMDcLAwJzM3CkAoeEpibhSGBuVkYEpibhSGBuVkYEpibxWxlAnOzmExgbhaTCczNYjKBvRY/mcDcLCYTmJvFZMIrxsG5WUwmMDeLyQTmZjGZCiAT2P60SkB/8EWEuD/Y6Hl7loyet2fJ6Hl7loy+UNPz9iwZPW/PktHz9iwZPW/PktHz9gdf6In7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LmWuD/Y6KH6gy9AWP3BBsTbs2T0vD1LRs/bs2T0hZqet2fJ6Hl7loyet2fJ6Hl7loyet2fpQk/cH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da7H6gw0Iqj/YgKD6gw0Iqj/YgFDy1g4E1R9sQFD9wQYE1R9sQFD9wQYE1R98AcLqDzag4GX/qIHSkMD6gw0J7EqiXdcC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w+erUxg/cGTCaw/eDKB9QdPJrz+O7j+4MkE1h88mfCKcXD9wZMJrD94MoH1B0+mAsiEtj+Nf171cS7LFafoA5q+b+BjKX9+VJ/5dnz801nBByu4LLTkQkuutOQrLXmhJa+05I2WnDaDCm0KFdocqrQ5VGlzqNLmUKXNoUqbQ5U2h6pbDt0VNneFl3NSvd7UKbUcKgxvhXVxVxB3BXVXeHlv69fFU/p6qFDcFaq7QnNXeHVN12X7/aN16YcK3V1heCuUxV1B3BVena1Vrz9a9VihuSu8Gum2Xq+6tapHCnVxV3Afpfrymi77XKrboUJ3VxjeCm1xVxB3BXVXWN0VirtCdVdo7gpvXNOtHSp0d4XX1/S+822HCtvLa3rfvW8piLuCuiu8uqbb3g/RlnGoUNwVqrtCc1fY3BVeXtPj+vhzk+VQYXgr9MVdQdwV1F1hdVco7grVXaG5K2xvVDhc0727K7y+pq83WpoeKoyX1/ReDr2lIO4K6q7wcp5+dBYdxV2huis0d4XNXaG7K7hXTm5cnX6bRBkBbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZzG4WZTC7WZTB7GZRBrObRRnMbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZYG4WZYC5WZTB7GZRBrObRRnMbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZzG4WRk+da4ndLIyeOtcSu1mUwexmYfTUuZbYzaIMZjeLMsDcLAwIys3CgKDcLAwIys3CgFDy1g4E5WZRBpibRRlgbhZlgLlZlAHmZlEGmJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZQB52ZRBpybRRlwbhZlwLlZlAHnZlEGnJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZQB52ZRBpybRRlwbhZlwLlZlAHnZlEGnJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZSB52YxmcDcLCYTmJvFZAJ7LX4ygblZTCYwN4vJhFeMg3OzmExgbhaTCczNYjIVQCaw/ak2UjeLCzjnU9wXcM6XuC/gpG4WRs75EreRc77EbeScL3EbeaEl53yJ28g53SyMnDaDkrpZGDltDiV1szBy2hxK6mZh5LQ5lNTNwshpc6izm4UpbO4Kvm4WpjC8FZzdLExB3BXUXcHXzcIUirtCdVdo7gq+bham0N0VhreCs5uFKYi7gq+bhSk0dwXfNxkvCs5uFqbgPkrObham0N0VhreCs5uFKYi7grorrO4KxV2huis0dwVfNwtT6O4Kvm4W9nWWr5uFKYi7gror+LpZmEJxV6juCs1dYXNX8HWzMIXhreDsZmEK4q6g7gqru0JxV6juCs1dwdfNwhS6u4Kvm4VdgvB1szAFcVdQdwVfNwtTKO4K1V2huSts7grdXcG9cuLtZtFqgJvFRYTYzcLoeV/YNnreF7aNnveFbaMv1PS8L2wbPe8L20bP+8K20fO+sG30vG4WF3piNwujp861xG4WRk+da4ndLIyeOtcSu1kYPXWuJXazMHooN4sLEJabhQHxvrBt9LwvbBs97wvbRl+o6Xlf2DZ63he2jZ73hW2j531h2+h5X9i+0BO7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0VPnWiw3CwOCcrMwICg3CwOCcrMwIJS8tQNBuVkYEJSbhQFBuVkYEJSbhQFBuVlcgLDcLAwoeNk/eu7fkMDcLAwJ7AE9u64F5mZhSGBuFoYE5mZhSGBuFoYE5mZhSGBuFoYE5mZxQUJzszAkMDcLQwJzszAkMDcLQyp4SGBuFoYE5mZhSGBuFoYE5mZhSGBuFhckNDcLQwJzszAkMDcLQwJzszCkgocE5mZhSGBuFoYE5mZhSGBuFoYE5mYxW5nA3CwmE5ibxWQCc7OYTGCvxU8mMDeLyQTmZjGZ8IpxcG4WkwnMzWIygblZTKYCyAS2P20a0B98ESHuDzZ63p4lo+ftWTJ63p4loy/U9Lw9S0bP27Nk9Lw9S0bP27Nk9Lz9wRd64v5go6fOtcT9wUZPnWuJ+4ONnjrXEvcHGz11riXuDzZ6qP7gCxBWf7AB8fYsGT1vz5LR8/YsGX2hpuftWTJ63p4lo+ftWTJ63p4lo+ftWbrQE/cHGz11riXuDzZ66lxL3B9s9NS5lrg/2Oipcy1xf7DRU+darP5gA4LqDzYgqP5gA4LqDzYglLy1A0H1BxsQVH+wAUH1BxsQVH+wAUH1B1+AsPqDDSh42T9qoDQksP5gQwK7kmjXtcD6gw0JrD/YkMD6gw0JrD/YkMD6gw0JrD/YkMD6gy9IaP3BhgTWH2xIYP3BhgTWH2xIBQ8JrD/YkMD6gw0JrD/YkMD6gw0JrD/4goTWH2xIYP3BhgTWH2xIYP3BhlTwkMD6gw0JrD/YkMD6gw0JrD/YkMD6g2crE1h/8GQC6w+eTGD9wZMJr/8Orj94MoH1B08mvGIcXH/wZALrD55MYP3Bk6kAMmHtT+Xm1f5NriLb9ue7adH653Pbk5/rT35uPPe54/ve3/icPPk5ffJzh0uo73+vdL3xufLk5+qTn2tPfm578nP9yc+N5z53fMGx92v9vw89/pw8+Tl98nPrk58rT36uPvm59uTnDufLly8+ZTn+XH/yc+O5zx1f0vnG5+TJz+mTn1uf/NzhfBl6XUdjPV5Hx/c8vvG59uTntic/15/83Hjuc8dXBb7xOXnwuXIcv6ZPfm598nPH86Ve1/tox+v9+HrANz7Xnvzc9uTn+pOfG899blue/NzxfOnLXiqu/V8f/M/f/PCuoiEqa4hKCVGpISotRGULUekhKiNC5fib/berhKz9HrL2e8ja7yFrv4es/R6y9nvI2u8ha7+HrP0RsvZHyNofIWt/hKz9EbL2R8jaHyFrf4Ss/RGy9kfI2r/xreL7ZSRGRmNk1hiZEiNTY2RajMwWI9NjZGJ2AYnZBSRmF5CYXUBidgGJ2QUkZheQmF1AYnYBidkFJGYX0JhdQGN2AY3ZBTRmF9CYXUBjdgGN2QU0ZhfQmF1AY3aBNWYXWGN2gTVmF1hjdoE1ZhdYY3aBNWYXWGN2gTVmF1hjdoESswuUmF2gxOwCJWYXKDG7QInZBUrMLlBidoESswuUmF2gxuwCNWYXqDG7QI3ZBWrMLlBjdoEaswvUmF2gxuwCNWYXaDG7QIvZBVrMLtBidoEWswu0mF2gxewCLWYXaDG7QIvZBbaYXSDmfqDEXBCUmBuCEnNFUGLuCErMJUGJuSUoMdcEJeaeoMRcFJSYm4ISc1VQYu4KSsxlQYm5LSgx1wUl5r6gxFwYlJgbgxJzZVBi7gxKzKVBibk1KDHXBiXm3qDEXByUmJuDEnN1UGLuDmrM3UGNuTuoMXcHNebuoC4lRqbGyLQYmS1GpsfIxOwCMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Dfctqv16v1Qty8vBH59IvANl+2+ofKG22m1X5+IrV9fiP2XioaorCEqJUSlhqj8baL588nt2U++4dbAN+b1Gy4NfEelhqi0EJWQXe0NFwbqqL9/uC31hsqIUHnDdYHvqEiIioaovGHtD9lV2g2VEqJSQ1RaiMoWotJDVEZE5nzDJYHvqIT8dTZC/jobIX+dveGCwHdUQv46e8P1gO+obCEqPUQlYu2vyxKiIiEqGqKyhqiUEJUaotJCVLYQlR6iErL2JWTtS8jal5C1LyFrX0LWvoSsfQlZ+xKy9iVk7UvI2teQta8ha19D1r6GrH0NWfsasvY1ZO2r/9rv/xzbndWyXUVq+5dv6v9q9HrV6F3u/6hI/2O69MVlRnXn6WA8A4zn+E+bnwQSNCBFA1rRgAoaUEUDamhAaPu0oG3UgrZTK9pOrWg7taLt1Iq2UyvaTq1oO7U67tS7xhag8fp++sWxbl1eH9gBBrQuaECCBqRoQCsaUEEDqmhADQ1oQwNC26lXtJ26oO3UBW2nLmg7dUHbqQvaTl3QduqCtlMXx5161+gBGsNfoy4BGhKgoQEaa4BGCdCoARotQCNgnbfX564sy9UJWhbRQxUNUXk97qLlz+7bDgsIbUT8W7YlRCUk+lt5g0obu0pvhyo1RKWFqGwhKj1E5R3rpckfle1IpS8hKhKioiEqa4hKCVGpISotRGULUekhKm9Y+yLl+sNSDv+GGUuIioSoaIjKGqJSQlRqiEoLUdlCVN6w9mXTXeXrjbcvKiNC5Yar9ftl1oizxQ0f6PfL1BiZFiMzQmTecCPwWzISI6MxMv7rpi/Hl2u3/WPb9qDoWpb++0eL1vs/2ve9Yizlv1+qs39fyr2Ad1bwwQp+vIopyIWWXGnJV1ryQkteackbLTltBhXaFCq0OVRpc6jS5lClzaFKm0OVNocqbQ5Vtxy6K2zuCi/npHr9TrXUcqgwvBXWxV1B3BXUXeHlvW1vHC59PVQo7grVXaG5K7y6putyLUjVpR8qdHeF4a1QFncFcVd4dbZWvf5o1WOF5q7waqTber110aoeKdTFXcF9lOrLa3ovMte6HSp0d4XhrdAWdwVxV1B3hdVdobgrVHeF5q7wxjXd2qFCd1d4fU3vO992qLC9vKbX8UBB3BXUXeHVNd32m6ttGYcKxV2huis0d4XNXeHlNf3nMW5ZDhWGt0Jf3BXEXUHdFVZ3heKuUN0VmrvC9kaFwzXdu7vC62v6epOu6aHCeHlN7+XQWwrirqDuCi/n6Udn0VHcFaq7QnNX2NwVuruCe+XkxoXSt0mMG7fVpK37vd1WH3zlImW5bn5SRI5EbtxW/DuV0neV7dG3QO97bWjcuutEQ6/U9Cs1faGmr9T0jZp+o6bv1PSDmV6pc61S51qlzrVKnWuVOtcqda5V6lyr1LlWqXOtouTaK9CKkj53oOCM+MbnwcatW2809Cs1faGmr9T0jZp+o6bv1PSDmb4s1PTUubZQ59pCnWsLda4t1Lm2UOfaQp1rC3WuLdS5tqLk2h0IJX3+3ysQSkbcgVCS3A6Ekrd2IJRUtAOhZJcdCCVh7EAoOWAHQtnWr0ANbaduwcv+0cPM41ZHyc8iBU/sR4+LjVu9Ej86SpviIa14SC0a6f5j2ONWr8TPInU8pAGH1Bc8pPB96f57z+NWg8jPIq14SAUPqeIhNTykDQ+p4yENOKSx4CFF794P3gUft1qBfhZpxUMqeEgVD6nhIW14SB0PacAh3Xrj35HpviHAZBJAJgVkqnAFnVu+BD/LtAEy4RXjJLoz8FtMCsi0AjIVQCa0/WkjdbO4gHM+xX0B53yJ+wJO6mZh5JwvcRs550vcRs75EreRF1pyzpe4jZzTzcLIaTMoqZuFkdPmUFI3CyOnzaGkbhZGTptDSd0sjJw2hzq7WZjC5q7g62ZhCsNbwdnNwhTEXUHdFXzdLEyhuCtUd4XmruDrZmEK3V1heCs4u1mYgrgr+LpZmEJzV/B9k/Gi4OxmYQruo+TsZmEK3V1heCs4u1mYgrgrqLvC6q5Q3BWqu0JzV/B1szCF7q7g62ZhX2f5ulmYgrgrqLuCr5uFKRR3hequ0NwVNncFXzcLUxjeCs5uFqYg7grqrrC6KxR3hequ0NwVfN0sTKG7K/i6WdglCF83C1MQdwV1V/B1szCF4q5Q3RWau8LmrtDdFdwrJ85uFnVp/m4WJsLrZjHpaV/YnvS0L2xPetoXtid9oaanfWF70tO+sD3paV/YnvS0L2xPelo3C6PndbOY9NS5ltfNYtJT51peN4tJT51red0sJj11ruV1s5j0SG4WBgTlZjGBaF/YnvS0L2xPetoXtid9oaanfWF70tO+sD3paV/YnvS0L2xPetoXto2e181i0lPnWl43i0lPnWt53SwmPXWu5XWzmPTUuZbXzWLSU+daKDeLCYTkZjGBkNwsJhCSm8UEQslbOxCSm8UEQnKzmEBIbhYTCMnNYgIhuVkYEJSbxQQKXvYPnvufSFhuFhMJ6wG9eV0Ly81iImG5WUwkLDeLiYTlZjGRsNwsJhKWm8VEwnKzMCQwN4uJhOVmMZGw3CwmEpabxUQqeEhYbhYTCcvNYiJhuVlMJCw3i4mE5WZhSGBuFhMJy81iImG5WUwkLDeLiVTwkLDcLCYSlpvFRMJys5hIWG4WEwnLzeJXKxOWm8UvJiw3i19MWG4Wv5iwXov/xYTlZvGLCcvN4hcTXjEOzc3iFxOWm8UvJiw3i19MBZAJbH+SNaA/+CJC3B9s9Lw9S0bP27Nk9Lw9S0ZfqOl5e5aMnrdnyeh5e5aMnrdnyeh5+4Mv9MT9wUZPnWuJ+4ONnjrXEvcHGz11riXuDzZ66lxL3B9s9FD9wRcgrP5gA+LtWTJ63p4lo+ftWTL6Qk3P27Nk9Lw9S0bP27Nk9Lw9S0bP27N0oSfuDzZ66lxL3B9s9NS5lrg/2Oipcy1xf7DRU+da4v5go6fOtVj9wQYE1R9sQFD9wQYE1R9sQCh5aweC6g82IKj+YAOC6g82IKj+YAOC6g++AGH1BxtQ8LJ/1EBpSGD9wYYEdiXRrmuB9QcbElh/sCGB9QcbElh/sCGB9QcbElh/sCGB9QdfkND6gw0JrD/YkMD6gw0JrD/YkAoeElh/sCGB9QcbElh/sCGB9QcbElh/8AUJrT/YkMD6gw0JrD/YkMD6gw2p4CGB9QcbElh/sCGB9QcbElh/sCGB9QfPViaw/uDJBNYfPJnA+oMnE17/HVx/8GQC6w+eTHjFOLj+4MkE1h88mcD6gydTAWQC259U/nnVx7ksV5yiD2j6voGPpfz5UX3i2/ELeGcFH6zgstCSCy250pKvtOSFlrzSkjdactoMKrQpVGhzqNLmUKXNoUqbQ5U2hyptDlXaHKpuOXRX2NwVXs5J9XpTp9RyqDC8FdbFXUHcFdRd4eW9rV8XT+nroUJxV6juCs1d4dU1XZft94/WpR8qdHeF4a1QFncFcVd4dbZWvf5o1WOF5q7waqTber3q1qoeKdTFXcF9lOrLa7rsc6luhwrdXWF4K7TFXUHcFdRdYXVXKO4K1V2huSu8cU23dqjQ3RVeX9P7zrcdKmwvr+l9976lIO4K6q7w6ppuez9EW8ahQnFXqO4KzV1hc1d4eU2P6+PPTZZDheGt0Bd3BXFXUHeF1V2huCtUd4XmrrC9UeFwTffurvD6mr7eaGl6qDBeXtN7OfSWgrgrqLvCy3n60Vl0FHeF6q7Q3BU2d4XuruBeOblxdfptEqsEuFmswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbharMLtZrMLsZrEKs5vFKsxuFqswu1mswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbhargLlZrALmZrEKs5vFKsxuFqswu1mswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbharMLtZGD11riV2szB66lxL7GaxCrObhdFT51piN4tVmN0sVgFzszAgKDcLA4JyszAgKDcLA0LJWzsQlJvFKmBuFquAuVmsAuZmsQqYm8UqYG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnJvFKnBuFqvAuVmsAudmsQqcm8UqcG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnJvFKnBuFqvAuVmsAudmsQqcm8UqcG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnpvFZAJzs5hMYG4WkwnstfjJBOZmMZnA3CwmE14xDs7NYjKBuVlMJjA3i8lUAJnQ9qdO6mZxAed8ivsCzvkS9wWc1M3CyDlf4jZyzpe4jZzzJW4jL7TknC9xGzmnm4WR02ZQUjcLI6fNoaRuFkZOm0NJ3SyMnDaHkrpZGDltDnV2szCFzV3B183CFIa3grObhSmIu4K6K/i6WZhCcVeo7grNXcHXzcIUurvC8FZwdrMwBXFX8HWzMIXmruD7JuNFwdnNwhTcR8nZzcIUurvC8FZwdrMwBXFXUHeF1V2huCtUd4XmruDrZmEK3V3B183Cvs7ydbMwBXFXUHcFXzcLUyjuCtVdobkrbO4Kvm4WpjC8FZzdLExB3BXUXWF1VyjuCtVdobkr+LpZmEJ3V/B1s7BLEL5uFqYg7grqruDrZmEKxV2huis0d4XNXaG7K7hXTrzdLMoW4GZxESF2szB63he2jZ73hW2j531h2+gLNT3vC9tGz/vCttHzvrBt9LwvbBs9r5vFhZ7YzcLoqXMtsZuF0VPnWmI3C6OnzrXEbhZGT51rid0sjB7KzeIChOVmYUC8L2wbPe8L20bP+8K20Rdqet4Xto2e94Vto+d9YdvoeV/YNnreF7Yv9MRuFkZPnWuJ3SyMnjrXErtZGD11riV2szB66lxL7GZh9NS5FsvNwoCg3CwMCMrNwoCg3CwMCCVv7UBQbhYGBOVmYUBQbhYGBOVmYUBQbhYXICw3CwMKXvaPnvs3JDA3C0MCe0DPrmuBuVkYEpibhSGBuVkYEpibhSGBuVkYEpibhSGBuVlckNDcLAwJzM3CkMDcLAwJzM3CkAoeEpibhSGBuVkYEpibhSGBuVkYEpibxQUJzc3CkMDcLAwJzM3CkMDcLAyp4CGBuVkYEpibhSGBuVkYEpibhSGBuVnMViYwN4vJBOZmMZnA3CwmE9hr8ZMJzM1iMoG5WUwmvGIcnJvFZAJzs5hMYG4Wk6kAMoHtT7UE9AdfRIj7g42et2fJ6Hl7loyet2fJ6As1PW/PktHz9iwZPW/PktHz9iwZPW9/8IWeuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da4n7g40eqj/4AoTVH2xAvD1LRs/bs2T0vD1LRl+o6Xl7loyet2fJ6Hl7loyet2fJ6Hl7li70xP3BRk+da4n7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LkWqz/YgKD6gw0Iqj/YgKD6gw0IJW/tQFD9wQYE1R9sQFD9wQYE1R9sQFD9wRcgrP5gAwpe9o8aKA0JrD/YkMCuJNp1LbD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4NnKBNYfPJnA+oMnE1h/8GTC67+D6w+eTGD9wZMJrxgH1x88mcD6gycTWH/wZCqATGD7U2s3+oNr2a6fq227L/LGC+MXng7GM8B4brRa/yCQoAEpGtCKBlTQgCoaUEMDQtunBW2jFrSdWtF2akXbqRVtp1a0nVrRdmpF26nVcafeNbYAjdf30zfePjWgAQa0LmhAggakaEArGlBBA6poQA0NaEMDQtupV7SduqDt1AVtpy5oO3VB26kL2k5d0HbqgrZTF8edetfoARrDX6MuARoSoKEBGmuARgnQqAEaLUAjYJ231+fuo0v7pqIhKq/H/Rtf5LUR8W/ZlhCVkOhv5Q0q92/Om0oNUWkhKluISg9Recd6uX/z1r7OXkJUJERFQ1TWEJUSolJDVFqIyhai0kNU3rD2H1wltasjS4iKhKhoiMoaolJCVGqISgtR2UJU3rD2H1wSNpURoXLrGvnbZdaIs4UsJUamxsi0GJkRIvOGG4HfkpEYGY2RCVg3/fhy7bZ/bNseFF3Lcr3rW/TBVd++7xVjKf/9Up19opTbj2/hMoAPVvDjVUxBLrTkSku+0pIXWvJKS95oyWkzqNCmUKHNoUqbQ5U2hyptDlXaHKq0OVRpc6i65dBdYXNXeDkn1et3qqWWQ4XhrbAu7grirqDuCi/vbf26eEpfDxWKu0J1V2juCq+u6bpcC1J16YcK3V1heCuUxV1B3BVena1Vrz9a9VihuSu8Gum2Xm9dtKpHCnVxV3Afpfrymt6LzLVuhwrdXWF4K7TFXUHcFdRdYXVXKO4K1V2huSu8cU23dqjQ3RVeX9P7zrcdKmwvr+l9976lIO4K6q7w6ppu+83VtoxDheKuUN0VmrvC5q7w8poe9aogy6HC8Fboi7uCuCuou8LqrlDcFaq7QnNX2N6ocLime3dXeH1NX2/SNT1UGC+v6b0cektB3BXUXeHlPP3oLDqKu0J1V2juCpu7QndXcK+c3LhQ+jaJ7cZttb98nHK5bn5SRI5EJPh55Te+NrTduutEQ6/U9Cs1faGmr9T0jZp+o6bv1PSDmV6pc61S51qlzrVKnWuVOtcqda5V6lyr1LlWqXOtouTaK9CKkj53oOCM+MbnwbZbt95o6Fdq+kJNX6npGzX9Rk3fqekHM31ZqOmpc22hzrWFOtcW6lxbqHNtoc61hTrXFupcW6hzbUXJtTsQSvrcgVAy4g6EkuR2IJS8tQOhpKIdCCW77EAoCWMHQskBOxDKtn4Famg7dQte9o8eZt5udZT8LBKYO/V2q1fiR0dpUzykFQ8p2hH+wWPY261eiZ9F6nhIAw6pL3hI4fvS/feet1sNIj+LtOIhFTykiofU8JA2PKSOhzTgkMaChxS9ez94F3y71Qr0s0grHlLBQ6p4SA0PacND6nhIAw7p1hv/jkz3DQEmkwAyKSBThSvo3PIl+FmmDZAJrxgn0Z2B32JSQKYVkKkAMoHtT72SullcwDmf4r6Ac77EfQEndbMwcs6XuI2c8yVuI+d8idvICy0550vcRs7pZmHktBmU1M3CyGlzKKmbhZHT5lBSNwsjp82hpG4WRk6bQ53dLExhc1fwdbMwheGt4OxmYQrirqDuCr5uFqZQ3BWqu0JzV/B1szCF7q4wvBWc3SxMQdwVfN0sTKG5K/i+yXhRcHazMAX3UXJ2szCF7q4wvBWc3SxMQdwV1F1hdVco7grVXaG5K/i6WZhCd1fwdbOwr7N83SxMQdwV1F3B183CFIq7QnVXaO4Km7uCr5uFKQxvBWc3C1MQdwV1V1jdFYq7QnVXaO4Kvm4WptDdFXzdLOwShK+bhSmIu4K6K/i6WZhCcVeo7grNXWFzV+juCu6VE283i1EC3CwuIsRuFkbP+8K20fO+sG30vC9sG32hpud9YdvoeV/YNnreF7aNnveFbaPndbO40BO7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0UO5WVyAsNwsDIj3hW2j531h2+h5X9g2+kJNz/vCttHzvrBt9LwvbBs97wvbRs/7wvaFntjNwuipcy2xm4XRU+daYjcLo6fOtcRuFkZPnWuJ3SyMnjrXYrlZGBCUm4UBQblZGBCUm4UBoeStHQjKzcKAoNwsDAjKzcKAoNwsDAjKzeIChOVmYUDBy/7Rc/+GBOZmYUhgD+jZdS0wNwtDAnOzMCQwNwtDAnOzMCQwNwtDAnOzMCQwN4sLEpqbhSGBuVkYEpibhSGBuVkYUsFDAnOzMCQwNwtDAnOzMCQwNwtDAnOzuCChuVkYEpibhSGBuVkYEpibhSEVPCQwNwtDAnOzMCQwNwtDAnOzMCQwN4vZygTmZjGZwNwsJhOYm8VkAnstfjKBuVlMJjA3i8mEV4yDc7OYTGBuFpMJzM1iMhVAJqz9qS3i3x9sIrz9wZOetmdp0tP2LE162p6lSV+o6Wl7liY9bc/SpKftWZr0tD1Lk562P9joefuDJz11ruXtD5701LmWtz940lPnWt7+4ElPnWt5+4MnPVJ/sAFB9QdPINqepUlP27M06Wl7liZ9oaan7Vma9LQ9S5Oetmdp0tP2LE162p4lo+ftD5701LmWtz940lPnWt7+4ElPnWt5+4MnPXWu5e0PnvTUuRaqP3gCIfUHTyCk/uAJhNQfPIFQ8tYOhNQfPIGQ+oMnEFJ/8ARC6g+eQEj9wQYE1R88gYKX/YMGyomE1R88kbCuJM7rWlj9wRMJqz94ImH1B08krP7giYTVHzyRsPqDJxJWf7AhgfUHTySs/uCJhNUfPJGw+oMnUsFDwuoPnkhY/cETCas/eCJh9QdPJKz+YEMC6w+eSFj9wRMJqz94ImH1B0+kgoeE1R88kbD6gycSVn/wRMLqD55IWP3Bv1qZsPqDfzFh9Qf/YsLqD/7FhNd/h9Yf/IsJqz/4FxNeMQ6tP/gXE1Z/8C8mrP7gX0wFkAltfxr/vOrjXJYrTtEHNH3fwMdS/vyoPvPt+Pins4IPVnBZaMmFllxpyVda8kJLXmnJGy05bQYV2hQqtDlUaXOo0uZQpc2hSptDlTaHKm0OVbccuits7gov56R6valTajlUGN4K6+KuIO4K6q7w8t7Wr4un9PVQobgrVHeF5q7w6pquy/b7R+vSDxW6u8LwViiLu4K4K7w6W6tef7TqsUJzV3g10m29XnVrVY8U6uKu4D5K9eU1Xfa5VLdDhe6uMLwV2uKuIO4K6q6wuisUd4XqrtDcFd64pls7VOjuCq+v6X3n2w4VtpfX9L5731IQdwV1V3h1Tbe9H+Ly6w4VirtCdVdo7gqbu8LLa3pcH39ushwqDG+FvrgriLuCuius7grFXaG6KzR3he2NCodrund3hdfX9PVGS9NDhfHymt7LobcUxF1B3RVeztOPzqKjuCtUd4XmrrC5K3R3BffKyY2r02+TkBHgZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZYG4WMsDcLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZmH01LmW2M3C6KlzLbGbhQxmNwujp861xG4WMpjdLGSAuVkYEJSbhQFBuVkYEJSbhQGh5K0dCMrNQgaYm4UMMDcLGWBuFjLA3CxkgLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLw3CwmE5ibxWQCc7OYTGCvxU8mMDeLyQTmZjGZ8IpxcG4WkwnMzWIygblZTKYCyAS2P2kjdbO4gHM+xX0B53yJ+wJO6mZh5JwvcRs550vcRs75EreRF1pyzpe4jZzTzcLIaTMoqZuFkdPmUFI3CyOnzaGkbhZGTptDSd0sjJw2hzq7WZjC5q7g62ZhCsNbwdnNwhTEXUHdFXzdLEyhuCtUd4XmruDrZmEK3V1heCs4u1mYgrgr+LpZmEJzV/B9k/Gi4OxmYQruo+TsZmEK3V1heCs4u1mYgrgrqLvC6q5Q3BWqu0JzV/B1szCF7q7g62ZhX2f5ulmYgrgrqLuCr5uFKRR3hequ0NwVNncFXzcLUxjeCs5uFqYg7grqrrC6KxR3hequ0NwVfN0sTKG7K/i6WdglCF83C1MQdwV1V/B1szCF4q5Q3RWau8LmrtDdFdwrJ95uFmsNcLO4iBC7WRg97wvbRs/7wrbR876wbfSFmp73hW2j531h2+h5X9g2et4Xto2e183iQk/sZmH01LmW2M3C6KlzLbGbhdFT51piNwujp861xG4WRg/lZnEBwnKzMCDeF7aNnveFbaPnfWHb6As1Pe8L20bP+8K20fO+sG30vC9sGz3vC9sXemI3C6OnzrXEbhZGT51rid0sjJ461xK7WRg9da4ldrMweupci+VmYUBQbhYGBOVmYUBQbhYGhJK3diAoNwsDgnKzMCAoNwsDgnKzMCAoN4sLEJabhQEFL/tHz/0bEpibhSGBPaBn17XA3CwMCczNwpDA3CwMCczNwpDA3CwMCczNwpDA3CwuSGhuFoYE5mZhSGBuFoYE5mZhSAUPCczNwpDA3CwMCczNwpDA3CwMCczN4oKE5mZhSGBuFoYE5mZhSGBuFoZU8JDA3CwMCczNwpDA3CwMCczNwpDA3CxmKxOYm8VkAnOzmExgbhaTCey1+MkE5mYxmcDcLCYTXjEOzs1iMoG5WUwmMDeLyVQAmcD2p6IB/cEXEeL+YKPn7Vkyet6eJaPn7Vky+kJNz9uzZPS8PUtGz9uzZPS8PUtGz9sffKEn7g82eupcS9wfbPTUuZa4P9joqXMtcX+w0VPnWuL+YKOH6g++AGH1BxsQb8+S0fP2LBk9b8+S0Rdqet6eJaPn7Vkyet6eJaPn7Vkyet6epQs9cX+w0VPnWuL+YKOnzrXE/cFGT51rifuDjZ461xL3Bxs9da7F6g82IKj+YAOC6g82IKj+YANCyVs7EFR/sAFB9QcbEFR/sAFB9QcbEFR/8AUIqz/YgIKX/aMGSkMC6w82JLAriXZdC6w/2JDA+oMNCaw/2JDA+oMNCaw/2JDA+oMNCaw/+IKE1h9sSGD9wYYE1h9sSGD9wYZU8JDA+oMNCaw/2JDA+oMNCaw/2JDA+oMvSGj9wYYE1h9sSGD9wYYE1h9sSAUPCaw/2JDA+oMNCaw/2JDA+oMNCaw/eLYygfUHTyaw/uDJBNYfPJnw+u/g+oMnE1h/8GTCK8bB9QdPJrD+4MkE1h88mQogE9T+pKLjxtX+Ta4i2/bnu2nR+udz25Of609+bjz3ueP73t/4nDz5OX3yc4dLqO9/r3S98bny5Ofqk59rT35ue/Jz/cnPjec+d3zBsfdr/b8PPf6cPPk5ffJz65OfK09+rj75ufbk5w7ny5cvPmU5/lx/8nPjuc8dX9L5xufkyc/pk59bn/zc4XwZel1HYz1eR8f3PL7xufbk57YnP9ef/Nx47nPHVwW+8Tl58LlyHL+mT35uffJzx/OlXtf7aMfr/fh6wDc+15783Pbk5/qTnxvPfW5bnvzc8Xzpy14qrv1fH/zP3/zwrqIhKmuISglRqSEqLURlC1HpISojQuX4m/23q4Ss/R6y9nvI2u8ha7+HrP0esvZ7yNrvIWu/h6z9EbL2R8jaHyFrf4Ss/RGy9kfI2h8ha3+ErP0RsvZHyNq/8a3i+2UkRkZjZNYYmRIjU2NkWozMFiPTY2RidgGJ2QUkZheQmF1AYnYBidkFJGYXkJhdQGJ2AYnZBSRmF9CYXUBjdgGN2QU0ZhfQmF1AY3YBjdkFNGYX0JhdQGN2gTVmF1hjdoE1ZhdYY3aBNWYXWGN2gTVmF1hjdoE1ZhdYY3aBErMLlJhdoMTsAiVmFygxu0CJ2QVKzC5QYnaBErMLlJhdoMbsAjVmF6gxu0CN2QVqzC5QY3aBGrML1JhdoMbsAjVmF2gxu0CL2QVazC7QYnaBFrMLtJhdoMXsAi1mF2gxu0CL2QW2mF0g5n6gxFwQlJgbghJzRVBi7ghKzCVBibklKDHXBCXmnqDEXBSUmJuCEnNVUGLuCkrMZUGJuS0oMdcFJea+oMRcGJSYG4MSc2VQYu4MSsylQYm5NSgx1wYl5t6gxFwclJibgxJzdVBi7g5qzN1Bjbk7qDF3BzXm7qAuJUamxsi0GJktRqbHyMTsAjF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdQ33Lar9er9ULcvLwR+fSLwDZftvqHyhttptV+fiK1fX4j9l4qGqKwhKiVEpYao/G2i+fPJ7dlPvuHWwDfm9RsuDXxHpYaotBCVkF3tDRcG6qi/f7gt9YbKiFB5w3WB76hIiIqGqLxh7Q/ZVdoNlRKiUkNUWojKFqLSQ1RGROZ8wyWB76iE/HU2Qv46GyF/nb3hgsB3VEL+OnvD9YDvqGwhKj1EJWLtr8sSoiIhKhqisoaolBCVGqLSQlS2EJUeohKy9iVk7UvI2peQtS8ha19C1r6ErH0JWfsSsvYlZO1LyNrXkLWvIWtfQ9a+hqx9DVn7GrL2NWTtq/vaX+s/x3ZntWxXkdr+5Zv6vxq9XjV6l/s/KtL/mC59cZlR3Xk6GM8A4zn+0+YngQQNSNGAVjSgggZU0YAaGhDaPi1oG7Wg7dSKtlMr2k6taDu1ou3UirZTK9pOrY479a6xBWi8vp9+caxbl9cHdoABrQsakKABKRrQigZU0IAqGlBDA9rQgNB26hVtpy5oO3VB26kL2k5d0HbqgrZTF7SduqDt1MVxp941eoDG8NeoS4CGBGhogMYaoFECNGqARgvQCFjn7fW5K8tydYKWRfRQRUNUXo+7aPmz+7bDAkIbEf+WbQlRCYn+Vt6g0sau0tuhSg1RaSEqW4hKD1F5x3pp8kdlO1LpS4iKhKhoiMoaolJCVGqISgtR2UJUeojKG9a+SLn+sJTDv2HGEqIiISoaorKGqJQQlRqi0kJUthCVN6x92XRX+Xrj7YvKiFC54Wr9fpk14mxxwwf6/TI1RqbFyIwQmTfcCPyWjMTIaIxMwLrZji/XbvvHtu1B0bUs/fePFq33f7Tve8VYyn+/VGefKOVux7dwGcAHK/jxKqYgF1pypSVfackLLXmlJW+05LQZVGhTqNDmUKXNoUqbQ5U2hyptDlXaHKq0OVTdcuiusLkrvJyT6vU71VLLocLwVlgXdwVxV1B3hZf3tr1xuPT1UKG4K1R3heau8Oqarsu1IFWXfqjQ3RWGt0JZ3BXEXeHV2Vr1+qNVjxWau8KrkW7r9dZFq3qkUBd3BfdRqi+v6b3IXOt2qNDdFYa3QlvcFcRdQd0VVneF4q5Q3RWau8Ib13RrhwrdXeH1Nb3vfNuhwvbyml7HAwVxV1B3hVfXdNtvrrZlHCoUd4XqrtDcFTZ3hZfX9J/HuGU5VBjeCn1xVxB3BXVXWN0VirtCdVdo7grbGxUO13Tv7gqvr+nrTbqmhwrj5TW9l0NvKYi7grorvJynH51FR3FXqO4KzV1hc1fo7grulZMbF0rfJlFu3FaTtu73dlt98JWLlOW6+UkRORK5cVvx71RK31W2R98Cve+1oXLrrhMNvVLTr9T0hZq+UtM3avqNmr5T0w9meqXOtUqda5U61yp1rlXqXKvUuVapc61S51qlzrWKkmuvQCtK+tyBgjPiG58HK7duvdHQr9T0hZq+UtM3avqNmr5T0w9m+rJQ01Pn2kKdawt1ri3UubZQ59pCnWsLda4t1Lm2UOfaipJrdyCU9LkDoWTEHQglye1AKHlrB0JJRTsQSnbZgVASxg6EkgN2IJRt/QrU0HbqFrzsHz3MXG51lPwsUvDEfvS4WLnVK/Gjo/T/qDvb5MZxptlu6MYEUcRHYXHP3i8LHrF74qVablFZzvxvzjljGyg3hUQO41Pa+ZR6ttKfL8Ouz7ISP6vkfEqTTsk3PqX0fenP9z3XZwGRn1Xa+ZQqn1LjU+p8SoNPyfmUJp3S3PiUsnfvF/eC12dRoJ9V2vmUKp9S41PqfEqDT8n5lCad0rM7/oFOfy4EWE6F0MkInRrdC51nvQQ/6zQInfhexpXsZOC3nIzQaSd0qoROZPtTq6JtFoe45lXch7jmTdyHuGibRZhr3sQd5po3cYe55k3cYV5lzTVv4g5zzTaLMJedoKJtFmEuO0NF2yzCXHaGirZZhLnsDBVtswhz2RkKbrMIwoATsG0WQZhoArjNIggFTjA4AdtmEYQKJzQ4ocMJ2DaLIDicMNEEcJtFEAqcgG2zCEKHE7B3Mh4EcJtFEODfJXCbRRAcTphoArjNIggFTjA4YYcTKpzQ4IQOJ2DbLILgcAK2zSI+zsK2WQShwAkGJ2DbLIJQ4YQGJ3Q4YcAJ2DaLIEw0AdxmEYQCJxicsMMJFU5ocEKHE7BtFkFwOAHbZhGHILBtFkEocILBCdg2iyBUOKHBCR1OGHCCwwnwNyfoNou+J7RZHBDhNouw171hO+x1b9gOe90btsO+Stvr3rAd9ro3bIe97g3bYa97w3bY67ZZHPbCbRZhLz1rhdsswl561gq3WYS99KwVbrMIe+lZK9xmEfZUbRaHEFebRQjp3rAd9ro3bIe97g3bYV+l7XVv2A573Ru2w173hu2w171hO+x1b9g+7IXbLMJeetYKt1mEvfSsFW6zCHvpWSvcZhH20rNWuM0i7KVnLVebRQhRtVmEEFWbRQhRtVmEEMvcOoWo2ixCiKrNIoSo2ixCiKrNIoSo2iwOIa42ixBKXvavrvsPJbI2i1Aiu0AvjmuRtVmEElmbRSiRtVmEElmbRSiRtVmEElmbRSiRtVkcSmxtFqFE1mYRSmRtFqFE1mYRSpVPiazNIpTI2ixCiazNIpTI2ixCiazN4lBia7MIJbI2i1Aia7MIJbI2i1CqfEpkbRahRNZmEUpkbRahRNZmEUpkbRYrykTWZrGcyNoslhNZm8VyIrstfjmRtVksJ7I2i+XE9zKOrs1iOZG1WSwnsjaL5VQJncj2p7El5IMPiHA+OOx1M0thr5tZCnvdzFLYV2l73cxS2OtmlsJeN7MU9rqZpbDXzQcf9sL54LCXnrXC+eCwl561wvngsJeetcL54LCXnrXC+eCwp8oHH0Jc+eAQ0s0shb1uZinsdTNLYV+l7XUzS2Gvm1kKe93MUtjrZpbCXjezdNgL54PDXnrWCueDw1561grng8NeetYK54PDXnrWCueDw1561nLlg0OIKh8cQlT54BCiygeHEMvcOoWo8sEhRJUPDiGqfHAIUeWDQ4gqH3wIceWDQyh52b8KUIYSWT44lMiOJMZxLbJ8cCiR5YNDiSwfHEpk+eBQIssHhxJZPjiUyPLBhxJbPjiUyPLBoUSWDw4lsnxwKFU+JbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwfvKJMZPng5USWD15OZPng5cSXv6PLBy8nsnzwcuJ7GUeXD15OZPng5USWD15OldCJbX/yf+72ONftoVPthY2fG/jc6q8vtXc+Hfd/XFV8qoqXTda8yJqbrPkua15lzZuseZc1l52gRXaEFtkZarIz1GRnqMnOUJOdoSY7Q012hhpshp6EASfcnkntcVKntnpJmGjCvsEJBU4wOOH23uaPxVN9vyRUOKHBCR1OuLum2zb+/dK2+SXB4YSJJtQNTihwwt3f1maPL212Tehwwt2fdN8fR916sytC2+AE+Hep3V7T9fxdauOS4HDCRBP6BicUOMHghB1OqHBCgxM6nPDBNd37JcHhhPtr+tz5xiVh3F7T5+79jFDgBIMT7q7pfuYh+jYvCRVOaHBChxMGnHB7Tc/H5c+9bJeEiSb4BicUOMHghB1OqHBCgxM6nDA+SLhc0+5wwv01/TjR0u2SMG+v6fN16DNCgRMMTrg9p1/9W3RWOKHBCR1OGHCCwwnwNydPjk5/DOGe0Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4U7WZuFO1mbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZhH20rNWuM0i7KVnrXCbhbtym0XYS89a4TYLd+U2C3eyNosQomqzCCGqNosQomqzCCGWuXUKUbVZuJO1WbiTtVm4k7VZuJO1WbiTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm487VZLCeyNovlRNZmsZzIbotfTmRtFsuJrM1iOfG9jKNrs1hOZG0Wy4mszWI5VUInsv1pNtE2i0Nc8yruQ1zzJu5DXLTNIsw1b+IOc82buMNc8ybuMK+y5po3cYe5ZptFmMtOUNE2izCXnaGibRZhLjtDRdsswlx2hoq2WYS57AwFt1kEYcAJ2DaLIEw0AdxmEYQCJxicgG2zCEKFExqc0OEEbJtFEBxOmGgCuM0iCAVOwLZZBKHDCdg7GQ8CuM0iCPDvErjNIggOJ0w0AdxmEYQCJxicsMMJFU5ocEKHE7BtFkFwOAHbZhEfZ2HbLIJQ4ASDE7BtFkGocEKDEzqcMOAEbJtFECaaAG6zCEKBEwxO2OGECic0OKHDCdg2iyA4nIBts4hDENg2iyAUOMHgBGybRRAqnNDghA4nDDjB4QT4mxNwm4VtFd9mERDdNotlL3vD9rKXvWF72cvesL3sq7S97A3by172hu1lL3vD9rKXvWF72cu2WYS9bpvFspeetbptFsteetbqtlkse+lZq9tmseylZ61um8WyZ2qzCCGqNoslJHvD9rKXvWF72cvesL3sq7S97A3by172hu1lL3vD9rKXvWF72cvesB32um0Wy1561uq2WSx76Vmr22ax7KVnrW6bxbKXnrW6bRbLXnrWUrVZLCGmNoslxNRmsYSY2iyWEMvcOoWY2iyWEFObxRJiarNYQkxtFkuIqc0ihKjaLJZQ8rJ/cd3/UuJqs1hKXBforeNaXG0WS4mrzWIpcbVZLCWuNoulxNVmsZS42iyWElebRSiRtVksJa42i6XE1WaxlLjaLJZS5VPiarNYSlxtFkuJq81iKXG1WSwlrjaLUCJrs1hKXG0WS4mrzWIpcbVZLKXKp8TVZrGUuNoslhJXm8VS4mqzWEpcbRZfUSauNosvJ642iy8nrjaLLyeu2+K/nLjaLL6cuNosvpz4XsaxtVl8OXG1WXw5cbVZfDlVQiey/amUhHzwARHOB4e9bmYp7HUzS2Gvm1kK+yptr5tZCnvdzFLY62aWwl43sxT2uvngw144Hxz20rNWOB8c9tKzVjgfHPbSs1Y4Hxz20rNWOB8c9lT54EOIKx8cQrqZpbDXzSyFvW5mKeyrtL1uZinsdTNLYa+bWQp73cxS2Otmlg574Xxw2EvPWuF8cNhLz1rhfHDYS89a4Xxw2EvPWuF8cNhLz1qufHAIUeWDQ4gqHxxCVPngEGKZW6cQVT44hKjywSFElQ8OIap8cAhR5YMPIa58cAglL/tXAcpQIssHhxLZkcQ4rkWWDw4lsnxwKJHlg0OJLB8cSmT54FAiyweHElk++FBiyweHElk+OJTI8sGhRJYPDqXKp0SWDw4lsnxwKJHlg0OJLB8cSmT54EOJLR8cSmT54FAiyweHElk+OJQqnxJZPjiUyPLBoUSWDw4lsnxwKJHlg1eUiSwfvJzI8sHLiSwfvJz48nd0+eDlRJYPXk58L+Po8sHLiSwfvJzI8sHLqRI6ke1Ptj/JB7c6Hs+1Pv4M+eCB8cPHyXwmmc+TqPUPChU2IWMT2tmEKptQYxPqbEJs+3Rh26gL205tbDu1se3UxrZTG9tObWw7tbHt1AbcqU/GSGDc308/ePo0hCaZ0L6xCRU2IWMT2tmEKptQYxPqbEKDTYhtp97ZdurKtlNXtp26su3UlW2nrmw7dWXbqSvbTl2BO/XJ8ATGxDPalsAoCQxLYOwJjJrAaAmMnsBIWOf9/u/uq0P7QbEUyv2f+zc+yOsz4/9lbCmUlJ/+qB+g/PnkfFBaCqWnUEYKxVMon1gvfz55Gx9nbymUkkKxFMqeQqkplJZC6SmUkULxFMoH1v6Lo6RxdGRLoZQUiqVQ9hRKTaG0FEpPoYwUygfW/otDwkGZGZRnx8g/jtkz/m1RtpqDaTmYnoOZKZgPnAj8FqbkYCwHk7Bu2vXh2nE+NsaLl651e5z1rfbiqK+fe8Xc6v9+ezv7xqvcdn0KV0F8qopfr2IJ8yJrbrLmu6x5lTVvsuZd1lx2ghbZEVpkZ6jJzlCTnaEmO0NNdoaa7Aw12RlqsBl6EgaccHsmtcdnqrXVS8JEE/YNTihwgsEJt/c2fyye6vslocIJDU7ocMLdNd22xwuptvklweGEiSbUDU4ocMLd39Zmjy9tdk3ocMLdn3TfH6cuerMrQtvgBPh3qd1e0+dL5tbGJcHhhIkm9A1OKHCCwQk7nFDhhAYndDjhg2u690uCwwn31/S5841Lwri9ps/d+xmhwAkGJ9xd0/08udq3eUmocEKDEzqcMOCE22t6tgehbJeEiSb4BicUOMHghB1OqHBCgxM6nDA+SLhc0+5wwv01/ThJ1+2SMG+v6fN16DNCgRMMTrg9p1/9W3RWOKHBCR1OGHCCwwnwNydPDpR+DLE/Oa32l5dTbo/Nr9RSriAl+XrlD942tD876yRjb9L2u7R9lbZv0vZd2n5I27u0/VS2N+lZa9Kz1qRnrUnPWpOetSY9a0161pr0rDXpWWsss/YhtLOMz1MoeSJ+8Hqw/dmpNxn7Xdq+Sts3afsubT+k7V3afirb103aXnrWVulZW6VnbZWetVV61lbpWVulZ22VnrVVetY2lll7CrGMz1OIZSKeQixD7hRimVunEMsoOoVYpsspxDIwTiGWGXAKsWzrD6HOtlP35GX/6mLm/Vmi5GeVyNqp92dZiR/9Lg3jU9r5lLIb4V9chr0/y0r8rJLzKU06Jd/4lNL3pT/f97w/C4j8rNLOp1T5lBqfUudTGnxKzqc06ZTmxqeUvXu/uBd8fxYF+lmlnU+p8ik1PqXOpzT4lJxPadIpPbvjH+j050KA5VQInYzQqdG90HnWS/CzToPQie9lXMlOBn7LyQiddkKnSuhEtj9VE22zOMQ1r+I+xDVv4j7ERdsswlzzJu4w17yJO8w1b+IO8yprrnkTd5hrtlmEuewEFW2zCHPZGSraZhHmsjNUtM0izGVnqGibRZjLzlBwm0UQBpyAbbMIwkQTwG0WQShwgsEJ2DaLIFQ4ocEJHU7AtlkEweGEiSaA2yyCUOAEbJtFEDqcgL2T8SCA2yyCAP8ugdssguBwwkQTwG0WQShwgsEJO5xQ4YQGJ3Q4AdtmEQSHE7BtFvFxFrbNIggFTjA4AdtmEYQKJzQ4ocMJA07AtlkEYaIJ4DaLIBQ4weCEHU6ocEKDEzqcgG2zCILDCdg2izgEgW2zCEKBEwxOwLZZBKHCCQ1O6HDCgBMcToC/OUG3WbSS0GZxQITbLMJe94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gv22Zx2Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2FO1WRxCXG0WIaR7w3bY696wHfa6N2yHfZW2171hO+x1b9gOe90btsNe94btsNe9YfuwF26zCHvpWSvcZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561XG0WIUTVZhFCVG0WIUTVZhFCLHPrFKJqswghqjaLEKJqswghqjaLEKJqsziEuNosQih52b+67j+UyNosQonsAr04rkXWZhFKZG0WoUTWZhFKZG0WoUTWZhFKZG0WoUTWZnEosbVZhBJZm0UokbVZhBJZm0UoVT4lsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WawoE1mbxXIia7NYTmRtFsuJ7Lb45UTWZrGcyNoslhPfyzi6NovlRNZmsZzI2iyWUyV0YtufPCMf7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0PtjZ8sHOlg926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7Gz5YGfLBztbPtjZ8sHOlg92tnyws+WDnS0f7Gz5YGfLBztbPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YCfMBzthPtgJ88FOmA92wnywE+aDnTAf7IT5YCfMBzthPtgJ88HOlw/u/Z+7Pc51e+hUe2Hj5wY+t/rrS+2NT8cPcVcVn6riZZM1L7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe5zUqa1eEiaasG9wQoETDE64vbf5Y/FU3y8JFU5ocEKHE+6u6baNf7+0bX5JcDhhogl1gxMKnHD3t7XZ40ubXRM6nHD3J933x1G33uyK0DY4Af5darfXdD1/l9q4JDicMNGEvsEJBU4wOGGHEyqc0OCEDid8cE33fklwOOH+mj53vnFJGLfX9Ll7PyMUOMHghLtrup95iL7NS0KFExqc0OGEASfcXtPzcflzL9slYaIJvsEJBU4wOGGHEyqc0OCEDieMDxIu17Q7nHB/TT9OtHS7JMzba/p8HfqMUOAEgxNuz+lX/xadFU5ocEKHEwac4HAC/M3Jk6PTH0OMntBmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjK7cZjG6cpvF6MptFqMrt1mMrtxmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjE7WZjE6WZvF6MptFqMrt1mMrtxmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjK7cZhH20rNWuM0i7KVnrXCbxejKbRZhLz1rhdssRldusxidrM0ihKjaLEKIqs0ihKjaLEKIZW6dQlRtFqOTtVmMTtZmMTpZm8XoZG0Wo5O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HRtFqPTtVmMTtdmMTpdm8XodG0Wo9O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HRtFqPTtVmMTtdmMTpdm8XodG0Wo9O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HxtFsuJrM1iOZG1WSwnstvilxNZm8VyImuzWE58L+Po2iyWE1mbxXIia7NYTpXQiWx/8l20zeIQ17yK+xDXvIn7EBdtswhzzZu4w1zzJu4w17yJO8yrrLnmTdxhrtlmEeayE1S0zSLMZWeoaJtFmMvOUNE2izCXnaGibRZhLjtDwW0WQRhwArbNIggTTQC3WQShwAkGJ2DbLIJQ4YQGJ3Q4AdtmEQSHEyaaAG6zCEKBE7BtFkHocAL2TsaDAG6zCAL8uwRuswiCwwkTTQC3WQShwAkGJ+xwQoUTGpzQ4QRsm0UQHE7AtlnEx1nYNosgFDjB4ARsm0UQKpzQ4IQOJww4AdtmEYSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yziEAS2zSIIBU4wOAHbZhGECic0OKHDCQNOcDgB/uYE3WYxLaHN4oAIt1mEve4N22Gve8N22OvesB32Vdpe94btsNe9YTvsdW/YDnvdG7bDXrfN4rAXbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWuE2i7CnarM4hLjaLEJI94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gve8P2YS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a7naLEKIqs0ihKjaLEKIqs0ihFjm1ilE1WYRQlRtFiFE1WYRQlRtFiFE1WZxCHG1WYRQ8rJ/dd1/KJG1WYQS2QV6cVyLrM0ilMjaLEKJrM0ilMjaLEKJrM0ilMjaLEKJrM3iUGJrswglsjaLUCJrswglsjaLUKp8SmRtFqFE1mYRSmRtFqFE1mYRSmRtFocSW5tFKJG1WYQSWZtFKJG1WYRS5VMia7MIJbI2i1Aia7MIJbI2i1Aia7NYUSayNovlRNZmsZzI2iyWE9lt8cuJrM1iOZG1WSwnvpdxdG0Wy4mszWI5kbVZLKdK6MS2P82MfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdPtnzwZMsHT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88GTLB0+2fPBkywdPtnzwZMsHT7Z88GTLB0+2fPBkywdPtnzwZMsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT8J88CTMB0/CfPAkzAdPwnzwJMwHT8J88CTMB0/CfPAkzAdPwnzwpMsHt6dH+0d5QMb49dl0sfbrufHmc/7mc/O9567Pe3/jufLmc/bmc5dLyM+/V9yePFfffK69+Vx/87nx5nP+5nPzveeuDzi6P97/+7Tr58qbz9mbz+1vPlfffK69+Vx/87nL35ffPvgs2/Vz/uZz873nrg/pfOO58uZz9uZz+5vPXf6+THuso7lfr6Prcx7feK6/+dx48zl/87n53nPXRwW+8Vx58Vy9/vl1e/O5/c3nrn9f2mO9z3693q+PB3zjuf7mc+PN5/zN5+Z7z43tzeeuf198O18VN//Pg//vb774pFgKZU+h1BRKS6H0FMpIoXgKZWZQrj/Z/zglZe17ytr3lLXvKWvfU9a+p6x9T1n7nrL2PWXtz5S1P1PW/kxZ+zNl7c+UtT9T1v5MWfszZe3PlLU/U9b+k08VP48pORjLwew5mJqDaTmYnoMZORjPweTsAiVnFyg5u0DJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u4Dl7AKWswtYzi5gObuA5ewClrMLWM4uYDm7gOXsApazC+w5u8CeswvsObvAnrML7Dm7wJ6zC+w5u8CeswvsObvAnrML1JxdoObsAjVnF6g5u0DN2QVqzi5Qc3aBmrML1JxdoObsAi1nF2g5u0DL2QVazi7QcnaBlrMLtJxdoOXsAi1nF2g5u0DP2QV6zi7Qc3aBnrML9JxdoOfsAj1nF+g5u0DP2QV6zi4wcnaBnPOBJeeAYMk5IVhyjgiWnDOCJeeQYMk5JVhyjgmWnHOCJeegYMk5KVhyjgqWnLOCJeewYMk5LVhyjguWnPOCJefAYMk5MVhyjgyWnDODJefQYMk5NVhyjg2WnHODJefgYMk5OVhyjg6WnLODlnN20HLODlrO2UHLOTtoW83BtBxMz8GMHIznYHJ2gZyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODlrO2UHLOTtoOWcHLefsoOWcHbScs4OWc3bQcs4OWs7ZQcs5O2g5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODtoHTtu19uh+aOO3GwJ/vyLwA4ftvkH5wOm05o8rYtvvN8T+h2IplD2FUlMoLYXyt4Pm15Pj3Sc/cGrgG7/XHzg08B1KS6H0FErKrvaBAwNttn+/uG/tCWVmUD5wXOA7lJJCsRTKB9b+LCelP6HUFEpLofQUykiheAplZkzODxwS+A4l5a+zmfLX2Uz56+wDBwS+Q0n56+wDxwO+QxkpFE+hZKz9fdtSKCWFYimUPYVSUygthdJTKCOF4imUlLVfUtZ+SVn7JWXtl5S1X1LWfklZ+yVl7ZeUtV9S1n5JWfuWsvYtZe1bytq3lLVvKWvfUta+pax9Q6/94w3QP9d1Z62OB6T1//Sm/l+GtwfDvfz5S0vxX6VLv7XMmJ0+TuYzyXyu/7T5SaHCJmRsQjubUGUTamxCnU2IbZ8ubBt1YdupjW2nNrad2th2amPbqY1tpza2ndqAO/XJGAmM+/vpb411+3b/GzvJhPaNTaiwCRmb0M4mVNmEGptQZxMabEJsO/XOtlNXtp26su3UlW2nrmw7dWXbqSvbTl3ZduoK3KlPhicwJp7RtgRGSWBYAmNPYNQERktg9ARGwjrv9393y7Y9mqDLVuySYimU+z/3YvXX7tsvXyD0mfH/MrYUSspPf9QPUPo8Kd4vKS2F0lMoI4XiKZRPrJdeflHGFcW3FEpJoVgKZU+h1BRKS6H0FMpIoXgK5QNrv5T6+OJSL/+GmVsKpaRQLIWyp1BqCqWlUHoKZaRQPrD2y7CT8vuJt98oM4PypNX685g9498WT3qgP49pOZieg5kpmA+cCPwWpuRgLAeTsG7G9eHacT42xouXrnXzf7+0Wvvzl/q5V8yt/u+3t7NvvMod16dwFcSnqvj1KpYwL7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe3ymWlu9JEw0Yd/ghAInGJxwe287g8PV90tChRManNDhhLtrum2PF1Jt80uCwwkTTagbnFDghLu/rc0eX9rsmtDhhLs/6b4/Tl30ZleEtsEJ8O9Su72mz5fMrY1LgsMJE03oG5xQ4ASDE3Y4ocIJDU7ocMIH13TvlwSHE+6v6XPnG5eEcXtN7/MFocAJBifcXdP9PLnat3lJqHBCgxM6nDDghNtr+tdl3GW7JEw0wTc4ocAJBifscEKFExqc0OGE8UHC5Zp2hxPur+nHSbpul4R5e02fr0OfEQqcYHDC7Tn96t+is8IJDU7ocMKAExxOgL85eXKg9GOI8uS0Wun7eW63txcfuZS6PTa/Uku5gjw5rfh3lOonZbz6FOhztw2VZ2edZOxN2n6Xtq/S9k3avkvbD2l7l7afyvYmPWtNetaa9Kw16Vlr0rPWpGetSc9ak561Jj1rjWXWPoR2lvF5CiVPxA9eD1aenXqTsd+l7au0fZO279L2Q9repe2nsn3dpO2lZ22VnrVVetZW6VlbpWdtlZ61VXrWVulZW6VnbWOZtacQy/g8hVgm4inEMuROIZa5dQqxjKJTiGW6nEIsA+MUYpkBpxDLtv4Q6mw7dU9e9q8uZi7PEiU/q5T8i/3qcrHyLCvxo9+lYXxKO59Sz1b682XY5VlW4meVnE9p0in5xqeUvi/9+b7n8iwg8rNKO59S5VNqfEqdT2nwKTmf0qRTmhufUvbu/eJe8PIsCvSzSjufUuVTanxKnU9p8Ck5n9KkU3p2xz/Q6c+FAMupEDoZoVOje6HzrJfgZ50GoRPfy7iSnQz8lpMROu2ETpXQiWx/siraZnGIa17FfYhr3sR9iIu2WYS55k3cYa55E3eYa97EHeZV1lzzJu4w12yzCHPZCSraZhHmsjNUtM0izGVnqGibRZjLzlDRNoswl52h4DaLIAw4AdtmEYSJJoDbLIJQ4ASDE7BtFkGocEKDEzqcgG2zCILDCRNNALdZBKHACdg2iyB0OAF7J+NBALdZBAH+XQK3WQTB4YSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yzi4yxsm0UQCpxgcAK2zSIIFU5ocEKHEwacgG2zCMJEE8BtFkEocILBCTucUOGEBid0OAHbZhEEhxOwbRZxCALbZhGEAicYnIBtswhChRManNDhhAEnOJwAf3OCbrPY94Q2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPZ/lS3hHzwARHOB4e9bmYp7HUzS2Gvm1kK+yptr5tZCnvdzFLY62aWwl43sxT2uvngw144Hxz20rNWOB8c9tKzVjgfHPbSs1Y4Hxz20rNWOB8c9lT54EOIKx8cQrqZpbDXzSyFvW5mKeyrtL1uZinsdTNLYa+bWQp73cxS2Otmlg574Xxw2EvPWuF8cNhLz1rhfHDYS89a4Xxw2EvPWuF8cNhLz1qufHAIUeWDQ4gqHxxCVPngEGKZW6cQVT44hKjywSFElQ8OIap8cAhR5YMPIa58cAglL/tXAcpQIssHhxLZkcQ4rkWWDw4lsnxwKJHlg0OJLB8cSmT54FAiyweHElk++FBiyweHElk+OJTI8sGhRJYPDqXKp0SWDw4lsnxwKJHlg0OJLB8cSmT54EOJLR8cSmT54FAiyweHElk+OJQqnxJZPjiUyPLBoUSWDw4lsnxwKJHlg1eUiSwfvJzI8sHLiSwfvJz48nd0+eDlRJYPXk58L+Po8sHLiSwfvJzI8sHLqRI6se1P/s/dHue6PXSqvbDxcwOfW/31pfbOp+P+j6uKT1XxssmaF1lzkzXfZc2rrHmTNe+y5rITtMiO0CI7Q012hprsDDXZGWqyM9RkZ6jJzlCDzdCTMOCE2zOpPU7q1FYvCRNN2Dc4ocAJBifc3tv8sXiq75eECic0OKHDCXfXdNvGv1/aNr8kOJww0YS6wQkFTrj729rs8aXNrgkdTrj7k+7746hbb3ZFaBucAP8utdtrup6/S21cEhxOmGhC3+CEAicYnLDDCRVOaHBChxM+uKZ7vyQ4nHB/TZ8737gkjNtr+ty9nxEKnGBwwt013c88RN/mJaHCCQ1O6HDCgBNur+n5uPy5l+2SMNEE3+CEAicYnLDDCRVOaHBChxPGBwmXa9odTri/ph8nWrpdEubtNX2+Dn1GKHCCwQm35/Srf4vOCic0OKHDCQNOcDgB/ubkydHpjyGaJ7RZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNojlZm0VzsjaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZhL30rBVuswh76Vkr3GbRXLnNIuylZ61wm0Vz5TaL5mRtFiFE1WYRQlRtFiFE1WYRQixz6xSiarNoTtZm0ZyszaI5WZtFc7I2i+ZkbRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc742i+VE1maxnMjaLJYT2W3xy4mszWI5kbVZLCe+l3F0bRbLiazNYjmRtVksp0roRLY/9SbaZnGIa17FfYhr3sR9iIu2WYS55k3cYa55E3eYa97EHeZV1lzzJu4w12yzCHPZCSraZhHmsjNUtM0izGVnqGibRZjLzlDRNoswl52h4DaLIAw4AdtmEYSJJoDbLIJQ4ASDE7BtFkGocEKDEzqcgG2zCILDCRNNALdZBKHACdg2iyB0OAF7J+NBALdZBAH+XQK3WQTB4YSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yzi4yxsm0UQCpxgcAK2zSIIFU5ocEKHEwacgG2zCMJEE8BtFkEocILBCTucUOGEBid0OAHbZhEEhxOwbRZxCALbZhGEAicYnIBtswhChRManNDhhAEnOJwAf3OCbrMYNaHN4oAIt1mEve4N22Gve8N22OvesB32Vdpe94btsNe9YTvsdW/YDnvdG7bDXrfN4rAXbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWuE2i7CnarM4hLjaLEJI94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gve8P2YS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a7naLEKIqs0ihKjaLEKIqs0ihFjm1ilE1WYRQlRtFiFE1WYRQlRtFiFE1WZxCHG1WYRQ8rJ/dd1/KJG1WYQS2QV6cVyLrM0ilMjaLEKJrM0ilMjaLEKJrM0ilMjaLEKJrM3iUGJrswglsjaLUCJrswglsjaLUKp8SmRtFqFE1mYRSmRtFqFE1mYRSmRtFocSW5tFKJG1WYQSWZtFKJG1WYRS5VMia7MIJbI2i1Aia7MIJbI2i1Aia7NYUSayNovlRNZmsZzI2iyWE9lt8cuJrM1iOZG1WSwnvpdxdG0Wy4mszWI5kbVZLKdK6ES2P3lJyAcfEOF8cNjrZpbCXjezFPa6maWwr9L2upmlsNfNLIW9bmYp7HUzS2Gvmw8+7IXzwWEvPWuF88FhLz1rhfPBYS89a4XzwWEvPWuF88FhT5UPPoS48sEhpJtZCnvdzFLY62aWwr5K2+tmlsJeN7MU9rqZpbDXzSyFvW5m6bAXzgeHvfSsFc4Hh730rBXOB4e99KwVzgeHvfSsFc4Hh730rOXKB4cQVT44hKjywSFElQ8OIZa5dQpR5YNDiCofHEJU+eAQosoHhxBVPvgQ4soHh1Dysn8VoAwlsnxwKJEdSYzjWmT54FAiyweHElk+OJTI8sGhRJYPDiWyfHAokeWDDyW2fHAokeWDQ4ksHxxKZPngUKp8SmT54FAiyweHElk+OJTI8sGhRJYPPpTY8sGhRJYPDiWyfHAokeWDQ6nyKZHlg0OJLB8cSmT54FAiyweHElk+eEWZyPLBy4ksH7ycyPLBy4kvf0eXD15OZPng5cT3Mo4uH7ycyPLBy4ksH7ycKqET2f409yf54FbH47nWx58hHzwwfvg4mc8k83kStf5BocImZGxCO5tQZRNqbEKdTYhtny5sG3Vh26mNbac2tp3a2HZqY9upjW2nNrad2oA79ckYCYz7++kHT5+G0CQT2jc2ocImZGxCO5tQZRNqbEKdTWiwCbHt1DvbTl3ZdurKtlNXtp26su3UlW2nrmw7dWXbqStwpz4ZnsCYeEbbEhglgWEJjD2BURMYLYHRExgJ67zf/919dWg/KJZCuf9z/8YHeX1m/L+MLYWS8tMf9QOUP5+cD0pLofQUykiheArlE+vlzydv4+PsLYVSUiiWQtlTKDWF0lIoPYUyUiieQvnA2n9xlDSOjmwplJJCsRTKnkKpKZSWQukplJFC+cDaf3FIOCgzg/LsGPnHMXvGvy3KVnMwLQfTczAzBfOBE4HfwpQcjOVgEtZNuz5cO87Hxnjx0rVuj7O+1V4c9fVzr5hb/d9vb2ffeJXbrk/hKohPVfHrVSxhXmTNTdZ8lzWvsuZN1rzLmstO0CI7QovsDDXZGWqyM9RkZ6jJzlCTnaEmO0MNNkNPwoATbs+k9vhMtbZ6SZhowr7BCQVOMDjh9t7mj8VTfb8kVDihwQkdTri7ptv2eCHVNr8kOJww0YS6wQkFTrj729rs8aXNrgkdTrj7k+7749RFb3ZFaBucAP8utdtr+nzJ3Nq4JDicMNGEvsEJBU4wOGGHEyqc0OCEDid8cE33fklwOOH+mj53vnFJGLfX9Ll7PyMUOMHghLtrup8nV/s2LwkVTmhwQocTBpxwe03P9iCU7ZIw0QTf4IQCJxicsMMJFU5ocEKHE8YHCZdr2h1OuL+mHyfpul0S5u01fb4OfUYocILBCbfn9Kt/i84KJzQ4ocMJA05wOAH+5uTJgdJPIcb25LTaX15OuT02v1JLuYKU5OuVP3fb0LIv0vYmbb9L21dp+yZt36Xth7S9S9tPZXuTnrUmPWtNetaa9Kw16Vlr0rPWpGetSc9ak561xjJrH0I7y/g8hZIn4ueuB1v2Jm2/S9tXafsmbd+l7Ye0vUvbT2X7uknbS8/aKj1rq/SsrdKztkrP2io9a6v0rK3Ss7ZKz9rGMmtPIZbxeQqxTMRTiGXInUIsc+sUYhlFpxDLdDmFWAbGKcQyA04hlm39IdTZduqevOxfXMy8lBqfElc79TquVei+S8P4lHY+pexG+D9fhr2UBp+S8ylNOiXf+JTS96U/3ve8lIxPaedTqnxKjU+p8ykNPiXnU5p0SnPjU8revf98L/hSMj6lnU+p8ik1PqXOpzT4lJxPadIpPbvjH+j0x0KAL6dC6GSETo3uhc6zXoKfdRqETnwv40p2MvBbTkbotBM6VUInsv2pmGabRYhLXsUd4pI3cYe4ZpvFMpe8iXuZS97Evcwlb+Je5lXWXPIm7mUu2WaxzGUnqGabxTKXnaGabRbLXHaGarZZLHPZGarZZrHMZWcots1iEQacAG2zWISJJmDbLBahwAkGJ0DbLBahwgkNTuhwArTNYhEcTphoArbNYhEKnABts1iEDidA72QMArbNYhHg3yVsm8UiOJww0QRsm8UiFDjB4IQdTqhwQoMTOpwAbbNYBIcToG0W6+MsaJvFIhQ4weAEaJvFIlQ4ocEJHU4YcAK0zWIRJpqAbbNYhAInGJywwwkVTmhwQocToG0Wi+BwArTNYh2CgLZZLEKBEwxOgLZZLEKFExqc0OGEASc4nAB/c4Jus7CS0GZxQITbLMJe94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gv22Zx2Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2FO1WRxCXG0WIaR7w3bY696wHfa6N2yHfZW2171hO+x1b9gOe90btsNe94btsNe9YfuwF26zCHvpWSvcZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561XG0WIUTVZhFCVG0WIUTVZhFCLHPrFKJqswghqjaLEKJqswghqjaLEKJqsziEuNosQih52b+67j+UyNosQonsAr04rkXWZhFKZG0WoUTWZhFKZG0WoUTWZhFKZG0WoUTWZnEosbVZhBJZm0UokbVZhBJZm0UoVT4lsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WawoE1mbxXIia7NYTmRtFsuJ7Lb45UTWZrGcyNoslhPfyzi6NovlRNZmsZzI2iyWUyV0YtufPCMf7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0PtjZ8sHOlg926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7Gz5YGfLBztbPtjZ8sHOlg92tnyws+WDnS0f7Gz5YGfLBztbPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YCfMBzthPtgJ88FOmA92wnywE+aDnTAf7IT5YCfMBzthPtgJ88HOlw/e+z93e5zr9tCp9sLGzw18bvXXl9obn44f4q4qPlXFyyZrXmTNTdZ8lzWvsuZN1rzLmstO0CI7QovsDDXZGWqyM9RkZ6jJzlCTnaEmO0MNNkNPwoATbs+k9jipU1u9JEw0Yd/ghAInGJxwe2/zx+Kpvl8SKpzQ4IQOJ9xd020b/35p2/yS4HDCRBPqBicUOOHub2uzx5c2uyZ0OOHuT7rvj6NuvdkVoW1wAvy71G6v6Xr+LrVxSXA4YaIJfYMTCpxgcMIOJ1Q4ocEJHU744Jru/ZLgcML9NX3ufOOSMG6v6XP3fkYocILBCXfXdD/zEH2bl4QKJzQ4ocMJA064vabn4/LnXrZLwkQTfIMTCpxgcMIOJ1Q4ocEJHU4YHyRcrml3OOH+mn6caOl2SZi31/T5OvQZocAJBifcntOv/i06K5zQ4IQOJww4weEE+JuTJ0enP4aoPaHNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqF25zaJ25TaL2pXbLGpXbrOoXbnNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqJ2szaJ2sjaL2pXbLGpXbrOoXbnNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqF25zSLspWetcJtF2EvPWuE2i9qV2yzCXnrWCrdZ1K7cZlE7WZtFCFG1WYQQVZtFCFG1WYQQy9w6hajaLGona7OonazNonayNovaydosaidrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2unaLGqna7Oona7Nona6Nova6dosaqdrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2unaLGqna7Oona7Nona6Nova6dosaqdrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2vnaLJYTWZvFciJrs1hOZLfFLyeyNovlRNZmsZz4XsbRtVksJ7I2i+VE1maxnCqhE9n+1HbRNotDXPMq7kNc8ybuQ1y0zSLMNW/iDnPNm7jDXPMm7jCvsuaaN3GHuWabRZjLTlDRNoswl52hom0WYS47Q0XbLMJcdoaKtlmEuewMBbdZBGHACdg2iyBMNAHcZhGEAicYnIBtswhChRManNDhBGybRRAcTphoArjNIggFTsC2WQShwwnYOxkPArjNIgjw7xK4zSIIDidMNAHcZhGEAicYnLDDCRVOaHBChxOwbRZBcDgB22YRH2dh2yyCUOAEgxOwbRZBqHBCgxM6nDDgBGybRRAmmgBuswhCgRMMTtjhhAonNDihwwnYNosgOJyAbbOIQxDYNosgFDjB4ARsm0UQKpzQ4IQOJww4weEE+JsTdJtFt4Q2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPb/jQz8sFTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh882fLBky0fPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwZMtHzzZ8sGTLR882fLBky0fPNnywZMtHzzZ8sGTLR882fLBky0fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPAnzwZMwHzwJ88GTMB88CfPBkzAfPAnzwZMwHzwJ88GTMB88CfPBky0fvG9Pj/aP8oCM8euz6WLt13Pjzef8zefme89dn/f+xnPlzefszecul5Cff6+4PXmuvvlce/O5/uZz483n/M3n5nvPXR9wdH+8//dp18+VN5+zN5/b33yuvvlce/O5/uZzl78vv33wWbbr5/zN5+Z7z10f0vnGc+XN5+zN5/Y3n7v8fZn2WEdzv15H1+c8vvFcf/O58eZz/uZz873nro8KfOO58uK5ev3z6/bmc/ubz13/vrTHep/9er1fHw/4xnP9zefGm8/5m8/N954b25vPXf+++Ha+Km7+nwf/39988UmxFMqeQqkplJZC6SmUkULxFMrMoFx/sv9xSsra95S17ylr31PWvqesfU9Z+56y9j1l7XvK2p8pa3+mrP2ZsvZnytqfKWt/pqz9mbL2Z8ranylrf6as/SefKn4eU3IwloPZczA1B9NyMD0HM3IwnoPJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u0DJ2QVKzi5QcnYBy9kFLGcXsJxdwHJ2AcvZBSxnF7CcXcBydgHL2QUsZxfYc3aBPWcX2HN2gT1nF9hzdoE9ZxfYc3aBPWcX2HN2gT1nF6g5u0DN2QVqzi5Qc3aBmrML1JxdoObsAjVnF6g5u0DN2QVazi7QcnaBlrMLtJxdoOXsAi1nF2g5u0DL2QVazi7QcnaBnrML9JxdoOfsAj1nF+g5u0DP2QV6zi7Qc3aBnrML9JxdYOTsAjnnA0vOAcGSc0Kw5BwRLDlnBEvOIcGSc0qw5BwTLDnnBEvOQcGSc1Kw5BwVLDlnBUvOYcGSc1qw5BwXLDnnBUvOgcGSc2Kw5BwZLDlnBkvOocGSc2qw5BwbLDnnBkvOwcGSc3Kw5BwdLDlnBy3n7KDlnB20nLODlnN20Laag2k5mJ6DGTkYz8Hk7AI5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODlrO2UHLOTtoOWcHLefsoOWcHbScs4OWc3bQcs4OWs7ZQcs5O2g5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20D5y2a+3R/dDGbzcE/n5F4AcO232D8oHTac0fV8S232+I/Q/FUih7CqWmUFoK5W8Hza8nx7tPfuDUwDd+rz9waOA7lJZC6SmUlF3tAwcG2mz/fnHf2hPKzKB84LjAdyglhWIplA+s/VlOSn9CqSmUlkLpKZSRQvEUysyYnB84JPAdSspfZzPlr7OZ8tfZBw4IfIeS8tfZB44HfIcyUiieQslY+/u2pVBKCsVSKHsKpaZQWgqlp1BGCsVTKClrv6Ss/ZKy9kvK2i8pa7+krP2SsvZLytovKWu/pKz9krL2LWXtW8rat5S1bylr31LWvqWsfUtZ+wZf+6P9c1131up4QFr/T2/q/2V4ezDcy5+/tBT/Vbr0W8uM2enjZD6TzOf6T5ufFCpsQsYmtLMJVTahxibU2YTY9unCtlEXtp3a2HZqY9upjW2nNrad2th2amPbqQ24U5+MkcC4v5/+1li3b/e/sZNMaN/YhAqbkLEJ7WxClU2osQl1NqHBJsS2U+9sO3Vl26kr205d2XbqyrZTV7adurLt1JVtp67AnfpkeAJj4hltS2CUBIYlMPYERk1gtARGT2AkrPN+/3e3bNujCbpsxS4plkK5/3MvVn/tvv3yBUKfGf8vY0uhpPz0R/0Apc+T4v2S0lIoPYUyUiieQvnEeunlF2VcUXxLoZQUiqVQ9hRKTaG0FEpPoYwUiqdQPrD2S6mPLy718m+YuaVQSgrFUih7CqWmUFoKpadQRgrlA2u/DDspv594+40yMyhPWq0/j9kz/m3xpAf685iWg+k5mJmC+cCJwG9hSg7GcjAJ62ZcH64d52NjvHjpWjf/90urtT9/qZ97xdzq/357O/vGq9xxfQpXQXyqil+vYgnzImtusua7rHmVNW+y5l3WXHaCFtkRWmRnqMnOUJOdoSY7Q012hprsDDXZGWqwGXoSBpxweya1x2eqtdVLwkQT9g1OKHCCwQm397YzOFx9vyRUOKHBCR1OuLum2/Z4IdU2vyQ4nDDRhLrBCQVOuPvb2uzxpc2uCR1OuPuT7vvj1EVvdkVoG5wA/y6122v6fMnc2rgkOJww0YS+wQkFTjA4YYcTKpzQ4IQOJ3xwTfd+SXA44f6aPne+cUkYt9f0Pl8QCpxgcMLdNd3Pk6t9m5eECic0OKHDCQNOuL2mf13GXbZLwkQTfIMTCpxgcMIOJ1Q4ocEJHU4YHyRcrml3OOH+mn6cpOt2SZi31/T5OvQZocAJBifcntOv/i06K5zQ4IQOJww4weEE+JuTJwdKP4bwJ6fVSt/Pc7u9vfjIpdTtsfmVWsoV5Mlpxb+jVD8p49WnQJ+7bcifnXWSsTdp+13avkrbN2n7Lm0/pO1d2n4q25v0rDXpWWvSs9akZ61Jz1qTnrUmPWtNetaa9Kw1lln7ENpZxucplDwRP3g9mD879SZjv0vbV2n7Jm3fpe2HtL1L209l+7pJ20vP2io9a6v0rK3Ss7ZKz9oqPWur9Kyt0rO2Ss/axjJrTyGW8XkKsUzEU4hlyJ1CLHPrFGIZRacQy3Q5hVgGxinEMgNOIZZt/SHU2XbqnrzsX13M7M8SJT+rlPyL/epyMX+WlfjR79IwPqWdT6lnK/35Mmx/lpX4WSXnU5p0Sr7xKaXvS3++79mfBUR+VmnnU6p8So1PqfMpDT4l51OadEpz41PK3r1f3Avuz6JAP6u08ylVPqXGp9T5lAafkvMpTTqlZ3f8A53+XAiwnAqhkxE6NboXOs96CX7WaRA68b2MK9nJwG85GaHTTuhUCZ3I9qdZRdssDnHNq7gPcc2buA9x0TaLMNe8iTvMNW/iDnPNm7jDvMqaa97EHeaabRZhLjtBRdsswlx2hoq2WYS57AwVbbMIc9kZKtpmEeayMxTcZhGEASdg2yyCMNEEcJtFEAqcYHACts0iCBVOaHBChxOwbRZBcDhhogngNosgFDgB22YRhA4nYO9kPAjgNosgwL9L4DaLIDicMNEEcJtFEAqcYHDCDidUOKHBCR1OwLZZBMHhBGybRXychW2zCEKBEwxOwLZZBKHCCQ1O6HDCgBOwbRZBmGgCuM0iCAVOMDhhhxMqnNDghA4nYNssguBwArbNIg5BYNssglDgBIMTsG0WQahwQoMTOpww4ASHE+BvTsBtFmXb8W0WAdFts1j2sjdsL3vZG7aXvewN28u+StvL3rC97GVv2F72sjdsL3vZG7aXvWybRdjrtlkse+lZq9tmseylZ61um8Wyl561um0Wy1561uq2WSx7pjaLEKJqs1hCsjdsL3vZG7aXvewN28u+StvL3rC97GVv2F72sjdsL3vZG7aXvewN22Gv22ax7KVnrW6bxbKXnrW6bRbLXnrW6rZZLHvpWavbZrHspWctVZvFEmJqs1hCTG0WS4ipzWIJscytU4ipzWIJMbVZLCGmNoslxNRmsYSY2ixCiKrNYgklL/sX1/0vJa42i6XEdYHeOq7F1WaxlLjaLJYSV5vFUuJqs1hKXG0WS4mrzWIpcbVZhBJZm8VS4mqzWEpcbRZLiavNYilVPiWuNoulxNVmsZS42iyWElebxVLiarMIJbI2i6XE1WaxlLjaLJYSV5vFUqp8SlxtFkuJq81iKXG1WSwlrjaLpcTVZvEVZeJqs/hy4mqz+HLiarP4cuK6Lf7LiavN4suJq83iy4nvZRxbm8WXE1ebxZcTV5vFl1MldCLbn8qWkA8+IML54LDXzSyFvW5mKex1M0thX6XtdTNLYa+bWQp73cxS2OtmlsJeNx982Avng8NeetYK54PDXnrWCueDw1561grng8NeetYK54PDnioffAhx5YNDSDezFPa6maWw180shX2VttfNLIW9bmYp7HUzS2Gvm1kKe93M0mEvnA8Oe+lZK5wPDnvpWSucDw576VkrnA8Oe+lZK5wPDnvpWcuVDw4hqnxwCFHlg0OIKh8cQixz6xSiygeHEFU+OISo8sEhRJUPDiGqfPAhxJUPDqHkZf8qQBlKZPngUCI7khjHtcjywaFElg8OJbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwffCix5YNDiSwfHEpk+eBQIssHh1LlUyLLB4cSWT44lMjywaFElg8OJbJ88IoykeWDlxNZPng5keWDlxNf/o4uH7ycyPLBy4nvZRxdPng5keWDlxNZPng5VUIntv3J/7nb41y3h061FzZ+buBzq7++1N75dNz/cVXxqSpeNlnzImtusua7rHmVNW+y5l3WXHaCFtkRWmRnqMnOUJOdoSY7Q012hprsDDXZGWqwGXoSBpxweya1x0md2uolYaIJ+wYnFDjB4ITbe5s/Fk/1/ZJQ4YQGJ3Q44e6abtv490vb5pcEhxMmmlA3OKHACXd/W5s9vrTZNaHDCXd/0n1/HHXrza4IbYMT4N+ldntN1/N3qY1LgsMJE03oG5xQ4ASDE3Y4ocIJDU7ocMIH13TvlwSHE+6v6XPnG5eEcXtNn7v3M0KBEwxOuLum+5mH6Nu8JFQ4ocEJHU4YcMLtNT0flz/3sl0SJprgG5xQ4ASDE3Y4ocIJDU7ocML4IOFyTbvDCffX9ONES7dLwry9ps/Xoc8IBU4wOOH2nH71b9FZ4YQGJ3Q4YcAJDifA35w8OTr9MYR5QpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhTlZm4U5WZuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym0XYS89a4TaLsJeetcJtFubKbRZhLz1rhdsszJXbLMzJ2ixCiKrNIoSo2ixCiKrNIoRY5tYpRNVmYU7WZmFO1mZhTtZmYU7WZmFO1mZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhztdmsZzI2iyWE1mbxXIiuy1+OZG1WSwnsjaL5cT3Mo6uzWI5kbVZLCeyNovlVAmdyPanvYm2WRzimldxH+KaN3Ef4qJtFmGueRN3mGvexB3mmjdxh3mVNde8iTvMNdsswlx2goq2WYS57AwVbbMIc9kZKtpmEeayM1S0zSLMZWcouM0iCANOwLZZBGGiCeA2iyAUOMHgBGybRRAqnNDghA4nYNssguBwwkQTwG0WQShwArbNIggdTsDeyXgQwG0WQYB/l8BtFkFwOGGiCeA2iyAUOMHghB1OqHBCgxM6nIBtswiCwwnYNov4OAvbZhGEAicYnIBtswhChRManNDhhAEnYNssgjDRBHCbRRAKnGBwwg4nVDihwQkdTsC2WQTB4QRsm0UcgsC2WQShwAkGJ2DbLIJQ4YQGJ3Q4YcAJDifA35yg2yxqTWizOCDCbRZhr3vDdtjr3rAd9ro3bId9lbbXvWE77HVv2A573Ru2w173hu2w122zOOyF2yzCXnrWCrdZhL30rBVuswh76Vkr3GYR9tKzVrjNIuyp2iwOIa42ixDSvWE77HVv2A573Ru2w75K2+vesB32ujdsh73uDdthr3vDdtjr3rB92Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWq42ixCiarMIIao2ixCiarMIIZa5dQpRtVmEEFWbRQhRtVmEEFWbRQhRtVkcQlxtFiGUvOxfXfcfSmRtFqFEdoFeHNcia7MIJbI2i1Aia7MIJbI2i1Aia7MIJbI2i1Aia7M4lNjaLEKJrM0ilMjaLEKJrM0ilCqfElmbRSiRtVmEElmbRSiRtVmEElmbxaHE1mYRSmRtFqFE1mYRSmRtFqFU+ZTI2ixCiazNIpTI2ixCiazNIpTI2ixWlImszWI5kbVZLCeyNovlRHZb/HIia7NYTmRtFsuJ72UcXZvFciJrs1hOZG0Wy6kSOpHtT60k5IMPiHA+OOx1M0thr5tZCnvdzFLYV2l73cxS2OtmlsJeN7MU9rqZpbDXzQcf9sL54LCXnrXC+eCwl561wvngsJeetcL54LCXnrXC+eCwp8oHH0Jc+eAQ0s0shb1uZinsdTNLYV+l7XUzS2Gvm1kKe93MUtjrZpbCXjezdNgL54PDXnrWCueDw1561grng8NeetYK54PDXnrWCueDw1561nLlg0OIKh8cQlT54BCiygeHEMvcOoWo8sEhRJUPDiGqfHAIUeWDQ4gqH3wIceWDQyh52b8KUIYSWT44lMiOJMZxLbJ8cCiR5YNDiSwfHEpk+eBQIssHhxJZPjiUyPLBhxJbPjiUyPLBoUSWDw4lsnxwKFU+JbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwfvKJMZPng5USWD15OZPng5cSXv6PLBy8nsnzwcuJ7GUeXD15OZPng5USWD15OldCJbH/q+5N8cKvj8Vzr48+QDx4YP3yczGeS+TyJWv+gUGETMjahnU2osgk1NqHOJsS2Txe2jbqw7dTGtlMb205tbDu1se3UxrZTG9tObcCd+mSMBMb9/fSDp09DaJIJ7RubUGETMjahnU2osgk1NqHOJjTYhNh26p1tp65sO3Vl26kr205d2XbqyrZTV7adurLt1BW4U58MT2BMPKNtCYySwLAExp7AqAmMlsDoCYyEdd7v/+6+OrQfFEuh3P+5f+ODvD4z/l/GlkJJ+emP+gHKn0/OB6WlUHoKZaRQPIXyifXy55O38XH2lkIpKRRLoewplJpCaSmUnkIZKRRPoXxg7b84ShpHR7YUSkmhWAplT6HUFEpLofQUykihfGDtvzgkHJSZQXl2jPzjmD3j3xZlqzmYloPpOZiZgvnAicBvYUoOxnIwCeumXR+uHedjY7x46Vq3x1nfai+O+vq5V8yt/u+3t7NvvMpt16dwFcSnqvj1KpYwL7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe3ymWlu9JEw0Yd/ghAInGJxwe2/zx+Kpvl8SKpzQ4IQOJ9xd0217vJBqm18SHE6YaELd4IQCJ9z9bW32+NJm14QOJ9z9Sff9ceqiN7sitA1OgH+X2u01fb5kbm1cEhxOmGhC3+CEAicYnLDDCRVOaHBChxM+uKZ7vyQ4nHB/TZ8737gkjNtr+ty9nxEKnGBwwt013c+Tq32bl4QKJzQ4ocMJA064vaZnexDKdkmYaIJvcEKBEwxO2OGECic0OKHDCeODhMs17Q4n3F/Tj5N03S4J8/aaPl+HPiMUOMHghNtz+tW/RWeFExqc0OGEASc4nAB/c/LkQOnHEOPJabW/vJxye2x+pZZyBSnJ1yt/8Lah8eysk4y9Sdvv0vZV2r5J23dp+yFt79L2U9nepGetSc9ak561Jj1rTXrWmvSsNelZa9Kz1qRnrbHM2ofQzjI+T6HkifjB68HGs1NvMva7tH2Vtm/S9l3afkjbu7T9VLavm7S99Kyt0rO2Ss/aKj1rq/SsrdKztkrP2io9a6v0rG0ss/YUYhmfpxDLRDyFWIbcKcQyt04hllF0CrFMl1OIZWCcQiwz4BRi2dYfQp1tp+7Jy/7VxczjWaLkZ5XI2qnHs6zEj36XhvEp7XxK2Y3wLy7DHs+yEj+r5HxKk07JNz6l9H3pz/c9j2cBkZ9V2vmUKp9S41PqfEqDT8n5lCad0tz4lLJ37xf3go9nUaCfVdr5lCqfUuNT6nxKg0/J+ZQmndKzO/6BTn8uBFhOhdDJCJ0a3QudZ70EP+s0CJ34XsaV7GTgt5yM0GkndKqETmT7k5tom8UhrnkV9yGueRP3IS7aZhHmmjdxh7nmTdxhrnkTd5hXWXPNm7jDXLPNIsxlJ6hom0WYy85Q0TaLMJedoaJtFmEuO0NF2yzCXHaGgtssgjDgBGybRRAmmgBuswhCgRMMTsC2WQShwgkNTuhwArbNIggOJ0w0AdxmEYQCJ2DbLILQ4QTsnYwHAdxmEQT4dwncZhEEhxMmmgBuswhCgRMMTtjhhAonNDihwwnYNosgOJyAbbOIj7OwbRZBKHCCwQnYNosgVDihwQkdThhwArbNIggTTQC3WQShwAkGJ+xwQoUTGpzQ4QRsm0UQHE7AtlnEIQhsm0UQCpxgcAK2zSIIFU5ocEKHEwac4HAC/M0Jus1iloQ2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPb/uQZ+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBzpYPdrZ8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WBnywc7Wz7Y2fLBzpYPdrZ8sLPlg50tH+xs+WBnywc7Wz7Y2fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7YT7YCfPBTpgPdsJ8sBPmg50wH+yE+WAnzAc7YT7YCfPBTpgPdrp8sG39n7s9znV76FR7YePnBj63+utL7e8/HQ9xVxWfquJlkzUvsuYma77LmldZ8yZr3mXNZSdokR2hRXaGmuwMNdkZarIz1GRnqMnOUJOdoQaboSdhwAm3Z1J7nNSprV4SJpqwb3BCgRMMTri9t/lj8VTfLwkVTmhwQocT7q7pto1/v7RtfklwOGGiCXWDEwqccPe3tdnjS5tdEzqccPcn3ffHUbfe7IrQNjgB/l1qt9d0PX+X2rgkOJww0YS+wQkFTjA4YYcTKpzQ4IQOJ3xwTfd+SXA44f6aPne+cUkYt9f0uXs/IxQ4weCEu2u6n3mIvs1LQoUTGpzQ4YQBJ9xe0/Nx+XMv2yVhogm+wQkFTjA4YYcTKpzQ4IQOJ4wPEi7XtDuccH9NP060dLskzNtr+nwd+oxQ4ASDE27P6Vf/Fp0VTmhwQocTBpzgcAL8zcmTo9MfQ5SOb7MIiG6bxbKXvWF72cvesL3sZW/YXvZV2l72hu1lL3vD9rKXvWF72cvesL3sZdsswl63zWLZS89a3TaLZS89a3XbLJa99KzVbbNY9tKzVrfNYtkztVmEEFWbxRKSvWF72cvesL3sZW/YXvZV2l72hu1lL3vD9rKXvWF72cvesL3sZW/YDnvdNotlLz1rddsslr30rNVts1j20rNWt81i2UvPWt02i2UvPWup2iyWEFObxRJiarNYQkxtFkuIZW6dQo1NiKnNYgkxtVksIaY2iyXE1GYRQlRtFksoedm/uO5/KTU+Ja4L9NZxLa42i6XE1WaxlLjaLJYSV5vFUuJqs1hKXG0WS4mrzSKUyNoslhJXm8VS4mqzWEpcbRZLqfIpNT4lrjaLpcTVZrGUuNoslhJXm0UokbVZLCWuNoulxNVmsZS42iyWUuVTanxKXG0WS4mrzWIpcbVZLCWuNouvKBNXm8WXE1ebxZcTV5vFl1Oje6HD1mbx5cTVZvHlxPcyjq3N4suJq83iy4mrzeLLqRI6ke1Ptou2WRzimldxH+KaN3Ef4qJtFmGueRN3mGvexB3mmjdxh3mVNW+y5pptFmEuO0FF2yzCXHaGirZZhLnsDBVtswhz2Rkq2mYR5rIzFNxmEYQBJ2DbLIIw0QRwm0UQCpxgcAK2zSIIFU5ocEKHE7BtFkFwOGGiCeA2iyAUOOHub+ufWxSC0OEE7J2MBwHcZhEE+HcJ3GYRBIcTJpoAbrMIQoETDE7Y4YQKJzQ4ocMJ2DaLIDicgG2ziI+zsG0WQShwgsEJ2DaLIFQ4ocEJHU4YcAK2zSIIE00At1kEocAJBifscEKFExqc0OEEbJtFEBxOwLZZxCEIbJtFEAqcYHACts0iCBVOaHBChxMGnOBwAvzNCbrNYreENosDItxmEfa6N2yHve4N22Gve8N22Fdp+yZtr3vDdtjr3rAd9ro3bIe9bpvFYS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYU/VZnEIcbVZhJDuDdthr3vDdtjr3rAd9lXanuVa0/fsdW/YDnvdG7bDXveG7bDXvWH7sBduswh76Vkr3GYR9tKzVrjNIuylZ61wm0XYS89a4TaLsJeetVxtFiFE1WYRQlRtFiFE1WYRQixz6xSiarMIIao2ixCiarMIIao2ixCiarM4hLjaLEIoedm/uu4/lMjaLEKJ7AK9OK5F1mYRSmRtFqFE1mYRSmRtFqFE1mYRSmRtFqFE1mZxKLG1WYQSWZtFKJG1WYQSWZtFKFU+JbI2i1Aia7MIJbI2i1Aia7MIJbI2i0OJrc0ilMjaLEKJrM0ilMjaLEKp8imRtVmEElmbRSiRtVmEElmbRSiRtVmsKBNZm8VyImuzWE5kbRbLiey2+OVE1maxnMjaLJYT38s4ujaL5UTWZrGcyNosllMldGLbn2ZGPnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54MnWz54suWDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eLLlgydbPniy5YMnWz54suWDJ1s+eLLlgydbPniy5YMnWz54suWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ2E+eBLmgydhPngS5oMnYT54EuaDJ2E+eBLmgydhPngS5oMnYT540uWD29Oj/aM8IGP8+my6WPv13HjzOX/zufnec9fnvb/xXHnzOXvzucsl5OffK25PnqtvPtfefK6/+dx48zl/87n53nPXBxzdH+//fdr1c+XN5+zN5/Y3n6tvPtfefK6/+dzl78tvH3yW7fo5f/O5+d5z14d0vvFcefM5e/O5/c3nLn9fpj3W0dyv19H1OY9vPNfffG68+Zy/+dx877nrowLfeK68eK5e//y6vfnc/uZz178v7bHeZ79e79fHA77xXH/zufHmc/7mc/O958b25nPXvy++na+Km//nwf/3N198UiyFsqdQagqlpVB6CmWkUDyFMjMo15/sf5ySsvY9Ze17ytr3lLXvKWvfU9a+p6x9T1n7nrL2Z8ra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j6h4RMMjOh4x8Ahw/0YgJh4B7t+IsxTg/o1AFDzC8Ahw/0YgGh7R8YiBRzgeMfEI/Mcs8P6NaRn9GzeKcv9G6AvfBB76wjeBh77wTeCh37T1hW8CD33hm8BDX/gm8NAXvgk89IX7N276yv0boa+9dZX7N0Jfe+sq92+EvvbWVe7fCH3travcvxH6XP0bNyOy/o0wEr4JPPSFbwIPfeGbwEO/aesL3wQe+sI3gYe+8E3goS98E3joC98EftNX7t8Ife2tq9y/EfraW1e5fyP0tbeucv9G6GtvXeX+jdDX3rpk/RthxNW/EUZc/RthxNW/EUYsG+xpxNW/EUZc/RthxNW/EUZc/RthxNW/cTMi698Io+S3/203QTix9W+EE9uFfnHKi61/I5zY+jfCia1/I5zY+jfCia1/I5zY+jfCia1/4+ZE178RTmz9G+HE1r8RTmz9G+HUCJ3Y+jfCia1/I5zY+jfCia1/I5zY+jduTnT9G+HE1r8RTmz9G+HE1r8RTo3Qia1/I5zY+jfCia1/I5zY+jfCia1/Y2ej2Po3thRb/8aWYuvf2FJs99pvKbb+jS3F1r+xpQg/ruPr39hSbP0bW4qtf2NLNUYpujm1UtLHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vOjSx4sufby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008eLLn286NLHiy59vOjSx4sufbzo0seLLn286NLHiy59vOjSx4sufbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwY08eLMX28GNPHizF9vBjTx4sxfbwY08eLMX28GNPHizF9vBjTx4swfbz8r6s91O24+zR7ozMfo3wd7fml9snv1G/mU9Z8yZqXQ1e96KqbrnrVVW+66l1Xfeiq6+7SortMi+42Nd1tarrb1HS3qeluU9Pdpqa7TQ22TZ8IxyMub6d+P+PTejtHLDiiHnhEwSMMj7g85eb9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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":3,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"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","debug_symbols":"7d3RjiS3eYbhe9ljIShW/WSxfCtBECi2HAgwJMOSAwSG7z2jeKp3ZLHdI/LTN+yt92xtd8+yH9dU/y9np/m3T3/45r/++t//+e13f/z+h0+/+/e/ffrT97//+sdvv//u5T/97dPyb2v9///2hz9//d1P/8UPP379lx8//S6n/atP33z3h5c/Hcvfv/r0x2//9M2n320l//0/vvrpSUfHk7a19aQa+fVJNbeetPU8KXqelHueVHqetPc8qfY86eh4Uiw9T0o9T+q5IqLnioieKyJ6rojouSKi54qInisieq6I3HNF5J4rIvdcEbnnisg9V0TuuSJyzxWRe66I3HNF5J4rovRcEaXniig9V0TpuSJKzxVReq6I0nNFlJ4rovRcEaXnith7roi954rYe66IveeK2HuuiL3nith7roi954rYe66IveeKqD1XRO25ImrPFVF7rojac0XUniui9lwRteeKqD1XRO25Io6eK+LouSKOnivi6Lkijp4r4ui5Io6eK+LouSKOnivi6Lki0rJ0PSt1PWvtetbW9azoelbuelbpetbe9aza9ayuayN1XRup69pIXddG6ro2Ute1kbqujdR1baSuayN1XRup69pYu66NtevaWLuujbXr2li7ro2169pYu66NtevaWLuujbXr2ti6ro2t69ro2tRMXbuaqWtbM3Xta6aujc3UtbOZurY2U9feZura3Exdu5upa3szde1vpq4NztS1w5m6tjhT1x5n6trkTF27nKlrmzN17XOmro3O1LXTmbq2OlPXXmfq2uxM7YAvaXl91l7rz5711S8eGy/3ntcHR9qP26NfxtzGo4+8ptdHH7nm26PX7ThXtE23ophuRXm6FZXpVrRPt6I63YqO2VbU3qj60BWl6VY03T37mO6efUx3zz6mu2cf092zj+nu2cd09+xjtnv2usx2z16X2e7Z6zLbPXtdZrtnr8ts9+x1me2evS6z3bPXZbZ79rrMds9el+nu2cn83Z/z8frgvKfP61nTuZ6YbD3mqzrX9VzPm6/8Zj11svUcc61nXSZbT5psPetk69kmW4/g/pM+r6cuD9bz8mOe1we/bBK/+crlXE+ebD1lsvXsk62nTraeY671bMtk60nm9ZR6rqeW1nrWydazTbaemGw9ebL1lMnWs0+2HvP9+SX5Xh/88lbVWs8x13pimWw9abL1rJOt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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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u32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu30Za7cvY+32Zazdvoy125cXqFM5Y+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Fa7evYO32FazdvoK121cWqFO5YO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVrt69g7fYVrN2+grXbV7B2+wrWbl/B2u0rWLt9BWu3r2Dt9hWs3b6CtdtXsHb7CtZuX8Ha7StYu30Fa7evYO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVrt69g7fYVrN2+grXbV7B2+wrWbl/B2u0rWLt9BWu3r2Dt9hWs3b6CtdtXsHb7CtZuX8Ha7StYu30Fa7evYO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVr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+iJmlFrJSB0dG66o1EpG6sNh4etPfrCDYu7ls9Kw/n13gzCtee4LnqoPp38r1z8c561dfyCvP5LXn8jrF/L6M3n9hbz+Sl4/ef8N5P03kvffSN5/I3n/jeT9dzg8Wbt+8v4byftvJO+/kbz/RvL+m8j7byLvv4m8/yby/juckatdP3n/TeT9N5H330TefxN5/xXy/ivk/VfI+6+Q99/h/FXt+sn7r5D3XyHvv0Lef4W8/2by/pvJ+28m77+ZvP8OZ3tq10/efzN5/83k/TeT999M3n8Lef8t5P23kPffQt5/h3Mjtesn77+FvP8W8v5byPtvIe+/lbz/VvL+W8n7byXvv8OZhNr1k/ffSt5/K3n/reT9t5L330befxt5/23k/beR99/hvDvt+sn7byPvv428/zby/tvI+28n77+dvP928v7byfvvcJaadv3k/beT999O3n87ef/t1P03Lwt1/13rp+6/a/3U/Xetn7r/rvVT99+1fur+u9ZP3X/X+qn771o/df9d6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6wfvv73Xx4/uy6v6wfvvYf3g/fewfvD+e1g/eP89rB+8/x7WD95/D+sH77+H9WP33770stUfavtSPzj/6rh+7P57XD92/z2uH7v/9vj073f9L7/Wj91/j+vH7r+99+3Ty5K+np/g/Kvj+rH773H90P13rTnv9Yclfa0fuv8e1h+w+Vcn6ofuvyfqh+6/J+qH7r8n6ofuvyfqh+6/a80x7vWXF/VD998T9UP33xP1g/ffWPtWf5L6tX7w/pu2+7dxkdi/1I/NvzpRP3j/Pawfu/+u/Sk9Pr3WunytH7v/HteP3X9DyNv5E2LOX+vH7r/H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XXx6P74mjvmaNOZrZMzX5DFfU8Z8TR3zNW3M1/QhX5OWMV8z5hRIY06BNOYUSGNOgTTmFEhjToE05hRIY06BNOYUkDGngIw5BVQewM9tWyoq/2bn78WnD4E0WeVxffWiBLGojFhUQSyqIhbVEIvq1xb1+2tUVhhOfE0Y8zVxzNekMV+jcdYd/6aprDCc+Joy5mvqmK9pY75mCBcwl2XM14QxXxPHfE0a8zVjToEy5hQoY06BMuYUKGNOgTLmFKhjToE65hSoY06BOuYUqGNOgTrmFKhjToE65hSoY06BOuYUaGNOgTbmFGhjToE25hRoY06BNuYUaGNOgTbmFGhjToE25hToY06BPuYU6GNOgT7mFOhjToE+5hToY06BPuYU6GNOgT7kFCjLMuZrwpiviWO+Jo35GhnzNXnM15QxX1PHfE0b8zVjToEw5hQIY06BMOYUCGNOgTDmFAhjToEw5hQIY06BMOYUCGNOgTjmFIhjToE45hSIY06BOOYUiGNOgTjmFIhjToE45hSIY06BNOYUSGNOgTTmFEhjToE05hRIY06BNOYUSGNOgTTmFBjzHsEy5j2CZcx7BMuY9wiWMe8RLDLmFJAxp4CMOQVkzCkgY04BGXMK5DGnQB5zCuQxp0AecwqMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjnl2sI55drCOeXawjnl2sC4y5mvymK8pY76mjvmaNuZrxpwCY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54d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+VeZnH+VyflXmZx/lRfu/pvJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V4Wcf1XI+VeFnH9VyPlXZeHuv4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcn5V5Wcf1XJ+VeVnH9VF+7+W8n5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXjZx/1cj5V42cf9XI+Vdt4e6/jZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyflXnZx/1cn5V52cf9UX7v7byflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VdrodwN+Feh7AK4W/BaKHcPXgvlbsJrodxdeC2Uuw2vhXL34bVQ7ka8FsreiclRWKsA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rczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7Iytws7YKuyMrcLO2CrsjK2ykHfiws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztiq7Iytys7YquyMrcrO2KoLeSeu7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Gzthq7Iytxs7YauyMrbaQd+LGzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2OrsjK3Oztjq7Iytzs7Y6gt5J+7sjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uSMrbiQM7ZWAdydeBXA3YlXAdydeBXA3YlXAdydeBXA3YlXAdydeBXA3YlXAeydmJyxtQpg78TkjK1VAHsnJmdsrQLYOzE5Y2sVwN6JyRlbqwD2TkzO2FoFsHdicsbWKoC9E5MztlYB7J2YnLG1CmDvxOSMrVUAeycmZ2ytX8HeickZW+tXsHdicsbW+hXsnZicsbV+BXsnJmdsrV/B3onJGVurAPZOTM7YWgWwd2JyxtYqgL0TkzO2VgHsnZicsbUKYO/E5IytVQB7JyZnbK0C2DsxOWNrFcDeickZW6sA9k5MzthaBbB3YnLG1iqAvROTM7ZWAeydmJyxtQpg78TkjK1VAHsnJmdsrQLYOzE5Y2sVwN6JyRlbqwD2TkzO2FoFsHdicsbWKoC9E5MztlYB7J2YnLG1CmDvxOSMrVUAeycmZ2ytAtg7MTljaxXA3onJGVurAPZOTM7YWgWwd2JyxtYqgL0TkzO2VgHsnZicsbUKYO/E5IytVQB5Jw7sjK3AztgK7IytwM7YWstjF0DeiQM7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2IjtjK7IztiI7YyuyM7biQt6JIztjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjbhKUv8/dks7wRA94EzAqBPoZzbQ0CpbwRAn0JnBECfQmcEQJ9CZwRAzwMnBGDzhc4IgO4DJZTfny0pvhEA3QfOCICeB84IEHYB0J34jADoTnxGAHQnPiMAuhOfEQDdiU8IwOYLnRHA3omx+UJnBLB3Ymy+0BkB7J0Ymy90RgB7J8bmC50RML4Tv71d+PWzrfZHHa0F2eso7Wc3Im+gEd0qN9iSG23JTaxydwnCLyHzSyj8Eiq/hMYvgTZNbBIqbULYJdB2/V0CbSffJWB351aXx4f7cRjp209e+v7Z9iwXu5Ory8Xu+t+Tq/uwR8VOE7dag51SbrUGO/3cag12qrrTmoad1m61BjsF3moNdrq81ZqZUquyNeLWvLPG0/BbazwNv7XG0/BbazwNv7XG0/A7a7qn4bfWeBp+a42n4bfWeBp+a424Ne+s8TT81hpPw2+t8TT81hpPw2+t8TT8xpq0eBp+a42n4bfWeBp+a42n4bfWiFvzzhpPw2+t8TT81hpPw2+t8TT81hpPw++sCZ6G31rjafitNZ6G31rjafitNeLWvLPG0/BbazwNv7XG0/BbazwNv7XG0/A7a6LRXHNMikzRaK45Y43RDnVM9kvRaIc6Y43RDnXGGqMd6oQ1yej9mjPWGL1fc8Yao7nmmHSUktFcc8YacWveWWP0fs0Za4ym4TPWGE3DZ6wxmobPWGM0DZ+wRoym4TPWGE3DZ6zxNPzWGk/Db62Riaz5xk8OrchD4fot+6fDq0/HnB8Ca3hj5EzZ+VYjZ0ratxo5Uy6/1ciZUrySkbs5M+V4bXPyTEle3ZyZsry6OTOleXVzZsrz6uaIm/PeHE/pH8yxmrx7efzk0Gv6w5wfDdXZavJWN9Jq8v6WkTFuAiW/MdJqStc2EvydOkRGWk3/6kZanRTUjbQ6VagbKW6kjpFWp5XvGXl8Bxf8nU9ERhqdbNbaHn92jctzzT+dbMDff0VkpNHJ5ntGnmg24O8CIzLS6GSjb6TRyUbfSKOTjb6R4kbqGGl0stE30uhk800jjyebqd5Wd6uRViebEDZvQmx/f7KZ6k14dxo51XvzLjPyRLOZ6i17txppdbJRN9LqZKNupLiROkZanWzUjbQ62agbaXWy+Z6Rx5PNVO8pvNVIs3+zaWU3sh8YWfv2k5f9s6G13cip3oF4q5Fm/2ajbaTZyaaEzcgqf/+mxVRvY7zVSHEjj408kSOnetPjrUaanWy0jTQ72WgbaXay0TbS7N9sdI2Uqd5neauRZv9m8y0jD29ayFTvyrzVSJ9sYmh/PmmxmyNuzntzfAL5YI7VqWK9cbXVHPPfvmEgU72N81YjrU4V3zLyTIazOlVoGznVe0FvNdLqVKFupNWpQt1Iq1OFupHiRuoYaXVa+Z6RxzcMpnpX6q1G+mSz/rtNr+fnqd6tqm6OTyDvzYlmp4rStppb+Ps3DKLZqULbSLNTxXeMPJHhpno/8K1GihupY6TZqULbSLNThbaRZqcKbSPNTiDaRpqdVr5l5PENg6ney32rkT7ZKBnpk42SkT7ZKBkpbqSOkT7ZKBnpk42SkT7ZrEb+ufC9m+PTygdzfAJ5b85U7zd/+5N3uSay/y4XO6H3DXfY+tNP/rlc7BytLlfmkXviThL4W73V5WInR3W52PlOXS52YlOXi53BtOWCv2v6e3KPZzPwt0ery50oVZ2RO1GqOiNXbMmdKVWdkAueqto+APb090cE8Lcfq8sFT1XfkXsmZoCnKmW54O/7VZcLnqq05YKnKm254KlKW65MJPc4ZoC/LVZd7kSp6ozciVLVGbkzpaoTcmdKVcdysd812hd5/OS+5PL3RwTsN4Lqy4VOVd+TeyJmYL9dU1+u2JILnar05UKnKn250KlKXy50qvqm3BMxAzpVqcvFfs+hvtyJUtUZuTOlqhNyZ0pVJ+QKjdzy5wC4S+BJSm8l8KSftxLAE01/1NHXQv7+rIn9TjZ9ueCJ5jtyT+RV7Peb6csFTzTacsETjbZc8ESjLVdsyQVPP9+Se5xXsd9hpS93olR1Ru5EqeqM3JlS1aHcjP1uJX25M6WqE3KJUlV/OcNm7DcEnZMg0BKC7BKe1nRf/9K1+GCgtqeaYwhPcrHTj7pc7PTzLbm1bU+7h3jwk4/vUGTst+fcaw12qrrVGuwEdqc12O+sudca7GR3qzXYKfBWa7DT5a3WiFvzzpqJEq62NZ6G31rjafitNZ6G31rjafidNdjvWrnXGk/Db63xNPzWGk/Db60Rt+adNZ6G31rjafitNZ6G31rjafitNZ6G31mD/X6Oe63xNPzWGk/Db63xNPzWGnFr3lljNNdkeTwpkeWdNUZzzQlrsLnwF1qTH68IyKW+scZohzpjjdEOdcYaox3qjDVG79ecscbo/Zoz1hjNNcdvWM/YLP17rTF6v+aENdiM/nutMZqGz1hjNA2fscZoGj5jjbg176wxmobPWGM0DZ+xxtPwW2s8Db+1xtPwO2uw363wTWu+8ZNrfSzx1j9ekfq0YIj9HoZ7rZkpDStbM1MaVrZG3Jp31syUhpWtmSkNK1szUxr+mTW9vLFmpjSsbM1MaVjXGvB3YlxmzRNuI+U31hhNw2esMZqGz1hjNA2fsUbcmnfWGE3DZ6wxmobPWGM0DZ9gZYG/c+RWa4ym4RPWgL/LRMmaXa6JhLvLxU6tMT4+3FPqB3LD0uRR9apg/3R9/nXGzqIXCBZrgrFz4wWCsdPgBYKxM94FgrGT2wWCsfOYvmDw96tcIBg7Z10g2FrSAn/LygWCxZpga0kL/F0rFwi2lrTA37dygWBjSauAv3PlAsHGklYBf+/KBYKNJa2yiDXBxpJWAX+vywWCjSWtAv4OlgsEW0ta4O9LuUCwtaQF/m6TCwRbS1rg7yG5QLC1pAX+zpALBFtLWuDv97hAsLWkBf4ujgsEW0ta4O/NuECwtaQF/o6LCwRbS1rg76O4QLC1pAX+7ogLBFtLWuDvebhAsLWkBf5OhgsEW0ta4O9PuECwtaSVrCUt8PdeXCDYWtJK1pKWWEta4G8huUCwtaQF/saQCwSLNcHWkhb4OzsuEGwtaYG/X+MCwdaSFvi7MC4QbC1pgb+34gLB1pIW+DsmLhBsLWmBvw/iAsHWkhb4uxsuEGwtaYG/Z+ECwdaSFvg7ES4QbC1pgb+/4ALB1pIW+LsGLhBsLWmBvxfgAsHWkhY4w/8CwdaSFjhv/wLB1pIWOBv/AsHWkhY4x/4CwdaSFjhz/gLB1pIWOB/+AsHWkpY1Rnyxxogv1hjxxRojvlhjxBdrjPhijRFfrDHiizVGfLHGiC/WGPHFGiO+WGPEF2uM+GKNEV+sMeKLNUZ8scaIr9YY8dUaI75aY8RXa4z4uog1wcaSVrXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRHfrDHimzVGfLPGiG/WGPFtEWuCjSWtZo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxbSaCeK/x8eH650/e5U7Uhc/IneiE7q09PtzrG7kTnc9n5E50Op+RO9HZfEbuRDPwCbkzEaXPyJ2p756QO1PfPSF3otn3jFyxJddWqpqJIn1GLm2q2iXQJqVdAnb6SXX7PZK+aAzi4JznCwRjJ6ALBGNnoAsEY6egCwSLNcHYSegCwdhZ6ALB2GnoAsHY2ekCwdaSFjjn+QLB1pIWOOf5AsHWkhY45/kCwdaSFjjn+QLB1pIWOOf5AsHGklYH5zxfINhY0urgnOcLBBtLWn0Ra4KNJa0Oznm+QLCxpNXBOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0irWkBU7yvkCwtaRVrCWtItYEW0ta4MT2CwRbS1rg1PYLBFtLWuDk9gsEW0ta4PT2CwRbS1rgBPcLBFtLWuAU9wsEW0ta4NT3CwRbS1rWGPHdGiO+W2PEd2uM+G6NEd+tMeK7NUZ8t8aI79YY8d0aI75bY8R3a4z4bo0R360x4rs1Rny3xojv1hjx3RojvltjxHdjjPi0GGPEr4JtJa1VsK2ktQq2lbRWwWJNsK2ktQq2lbRWwbaS1irYVtJaBVtLWsYY8atga0nLGCN+FWwtaRljxK+CrSUtY4z4VbC1pGWMEb8Ktpa0jDHiV8HWkpYxRvwq2FrSMsaIXwVbS1rGGPGrYGtJyxgjfhVsLWkZY8Svgq0lLWOM+FWwtaRljBG/CraWtIwx4lfB1pKWMUb8Ktha0jLGiF8FW0taxhjxq2BrScsYI34VbC1pGWPEr4KtJS1jjPhVsLWkZYwRvwq2lrSMMeJXwdaSljFG/CrYWtIyxohfBVtLWsYY8atga0nLGCN+FWwtaRljxK+CrSUtY4z4VbC1pGWMEb8Ktpa0jDHiV8HWkpYxRvwq2FrSMsaIXwVbS1rGGPGrYGtJyxgjfhVsLWkZY8Svgq0lLWOM+FWwtaRljBG/CraWtIwx4lfB1pKWMUb8Ktha0jLGiF8FW0taxhjxq2BrScsYI34VbC1pGWPEr4KtJS1jjPhVsLWkZYwRvwo2lrSCNUZ8sMaID9YY8cEaI36VY02wsaQVrDHigzVGfLDGiA/WGPHBGiM+WGPEB2uM+GCNER+sMeKDNUZ8sMaID9YY8cEaIz5YY8QHa4z4YI0RH6wx4oM1RnywxogP1hjxwRojPlhjxAdrjPhgjREfrDHigzVGfLDGiA/WGPHBGiM+WGPEB2uM+GCNER+sMeKDNUZ8sMaID9YY8cEaIz5YY8QHa4z4YI0RH6wx4oM1RnywxogP1hjxwRojPlhjxAdrjPhgjREfrDHigzVGfLDGiA8zEcR7jY8P1z9/8iZ3Jn74GbkTndC9bR/u9Y3cic7nM3InOp3PyJ3obD4jd6IZ+IzciSbgM3Jn6rvHcmeiSZ+RO9Hse0buRJPvGbm2UtVMFOkzcmlT1S6BNintErDTT5bHaN1Lb0eDeH6Usd5BevNLh51+1OVipx9tueCEZ3W52OlHXS52+lGXi51+1OWKLbnY6UddLnZSUpdrK1WBE53V5dpKVeA0Z3W5tlIVOMlZXa6tVAVOcVaXaytVgROc1eXaSlXg9GZ1uaZSVQQnN6vLNZWqIji1WV2uqVQVF7El11SqiuC0ZnW5plJVBCc1q8u1larAKc3qcm2lKnBCs7pcW6kKnM6sLtdWqgInM6vLtZWqwKnM6nJtpSpwIrO6XFupCpzGrC7XVqoCJzGry7WVqsApzOpybaUqcAKzulxbqQqcvqwu11aqAicvq8u1larAqcvqcm2lKnDisrpcW6kKnLasLtdWqgInLavLtZWqwCnL6nJtpSpwwrK6XFupCpyurC7XVqoCJyury7WVqsCpyupybaUqcKKyulxbqQqcpqwu11aqAicpq8u1laqyrVQFTsnWlgtOyVaXaytVFVupCpyBri5XbMm1larAGejqcm2lKnAGurpcW6kKnIGuLtdWqgJnoKvLtZWqwBno6nJtpSpwXrq6XFupyhZbPdpiq0dbbPVoi60ebbHVoy22erTFVo+22OrRFls92mKrR1ts9WiLrR5tsdWjLbZ6tMVWj7bY6tEWWz3aYqtHW2z1aIutHm2x1aMttnqyxVZPttjqyRZbPdliq6dFbMk1laqSLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1tsdbHFVhdbbHWxxVYXW2x1WcSWXFOpSmyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWbCUfcaHx+u6Y3ciRrRCbkzAYt7a48P9/pG7kRH1Rm5Ex1VZ+SKLbkTDYBn5E40AJ6RO1PfPSF3pr57Qu5EA+AJuTMBi8/ItZWqZgIWn5FLm6p2CcIvATv91NgfElqsR2P40suj6hCeqi75STB2/rlAMHYCukAwdga6QDB2CtIXDI4YvkAwdhK6QDB2FrpAMHYaukCwWBNsLWmB44YvEGwtaYEjhy8QbC1pgWOHLxBsLWmBo4cvEGwtaYHjhy8QbC1pgSOILxBsLWmBY4gvEGwsaWVwFPEFgo0lrQyOI75AsLGklRexJthY0srgWOILBBtLWhkcTXyBYGtJCxxPfIFga0kLHFF8gWBrSQscU3yBYGtJCxxVfIFga0kLHFd8gWBrSQscWXyBYGtJCxxbfIFga0kLHF18gWBrSQscX3yBYGtJCxxhfIFga0kLHGN8gWBrSQscZXyBYGtJCxxnfIFga0kLHGl8gWBrSQsca3yBYGtJCxxtfIFga0kLHG98gWBrSQsccXyBYGtJCxxzfIFga0kLHHV8gWBrSQscd3yBYGtJCxx5fIFga0krizXB1pJWtpa0wEneFwi2lrSytaRVrCUtcF77BYKtJS1wZvsFgsWaYGtJC5zcfoFga0kLnN5+gWBrSQuc4H6BYGtJC5zifoFga0kLnPp+gWBrScsaIz5bY8Rna4z4bI0Rn60x4rM1Rny2xojP1hjx2RojPltjxGdrjPhsjRGfrTHiszVGfLbGiM/WGPHZGiM+W2PEZ2uM+GyNEZ+tMeKzNUZ8tsaIz9YY8cUaI75YY8QXa4z4Yo0RXxaxJthY0irWGPHFGiO+WGPEF2uM+GKNEV+sMeKLNUZ8scaIL9YY8cUaI75YY8QXa4z4Yo0RX6wx4os1Rnyxxogv1hjxxRojvlhjxJeZCOLrpx8frn/+5F3uRF34hNyZ2NK9tceHe30jd6Lz+YzciU7nM3InOpvPyJ1oBj4jd6IJ+IzcmfruCbkz9d0TcieafU/InYkkfUaurVQ1E0X6jFzaVLVLEH4J2Omn5br9HuVyNIhL3AZxSXn/dO1PgrHzzwWCsRPQBYKxM9AFgrFTkL5gcM7zBYKxk9AFgrGz0AWCsdPQBYLFmmBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGNJq4Jzni8QbCxpVXDO8wWCjSWtuog1wcaSVgXnPF8g2FjSquCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWuCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWuCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWtFa0gIneV8g2FrSitaSVrKWtMB57RcItpa0wJntFwgWa4KtJS1wcvsFgq0lLXB6+wWCrSUtcIL7BYKtJS1wivsFgq0lLXDq+wWCrSUta4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjxzRojvlljxDdrjPhmjRHfFrEm2FjSatYY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R32YiiPcaHx+uf/7kXe5EXfiM3IlO6N7a9uH6Ru5E5/MZuROdzmfkTnQ2n5E70Qx8Qu5MROkzcmfquyfkztR3T8idaPY9I1dsybWVqmaiSJ+RS5uqdgm0SWmXgJ1++vaTwxJiOJrE8/bpLK9/68Axz/p6sfOPvl7sAKSvFzsB6esVY3qxM5C+XuwQpK8XOwXp68WOTPp6jeUrcLizvl5j+Qoc7ayv11i+Agc76+s1lq/Asc76eo3lK3Cos75eW/mqgyOd9fXaylcdHOisr9dWvuqLGNNrK191cJizvl5b+aqDo5z19RrLV+AgZ329xvIVOMZZX6+xfAUOcdbXayxfgSOc9fUay1fgAGd9vcbyFTi+WV+vsXwFDm/W12ssX4Gjm/X1GstX4OBmfb3G8hU4tllfr7F8BQ5t1tdrLF+BI5v19RrLV+DAZn29xvIVOK5ZX6+xfAUOa9bXayxfgaOa9fUay1fgoGZ9vcbyFTimWV+vsXwFDmnW12ssX4EjmvX1GstX4IBmfb3G8hU4nllfr7F8BQ5n1tdrLF+Bo5n19RrLV+BgZn29xvJVMZavwLnb+nqN5atiLF8VMabXWL4CR6vr6zWWr8Dh6vp6jeUrcLy6vl5j+QocsK6v11i+Akes6+s1lq/AIev6eo3lK3Aku75eY/nKGL+9G+O3d2P89m6M396N8du7MX57N8Zv78b47d0Yv70b47d3Y/z2bozf3o3x27sxfns3xm/vxvjt3Ri/vdvit8syFd/78M3pq96Z+u8ZvTOdz4dv+Vz1znQ+n9E70/l8Ru9M5/MZvTPNv2f0zjT/ntA7Ff/5jN6p+u8JvTPNv2f0zjT/ntErxvQay1fE/OddA29m2jVA56C18LIXEmM8+MV7/7N3wdBB6ALB2KTmKwRDR6ErBENnoSsEQ4ehKwSLNcHQcegKwdB56ArB0OHpCsHWkhY2svkCwdjM5isEW0ta2NTmKwRbS1rY3OYrBFtLWtjk5isEW0ta2OzmKwRbS1rY9OYrBFtLWtj85isEW0ta2ATnKwRbS1rYDOcrBFtLWtgU5ysEW0ta2BznKwRbS1rYJOcrBFtLWtgs5ysEW0ta2DTnKwRbS1rYPOcrBFtLWthE5ysEW0ta2EznKwRbS1rYVOcrBFtLWthc5ysEW0ta2GTnKwRbS1rYbOcrBFtLWth05ysEW0ta2HznKwRbS1rYhOcrBFtLWtiM5ysEW0ta2JTnKwRbS1rYnOcrBFtLWtik5ysEW0ta2KznKwRbS1rYtOcrBFtLWti85ysEW0ta2MTnKwRbS1rYzOcrBFtLWtjU5ysEW0ta3VrS6saSVsAme18h2FjSWn+KNcFTtaUsD3p7lneCp2pLJwRj45C/LTg/+KK51DeCpzq0zgie6tA6I3iq8fCMYLEmeKrx8IzgqfpwCeX3p0uKbwRP1YfPCJ5qPDwjeKrx8ITguXDLZwRPlbTOCJ4qaZ0RPFXSOiNYrAmeKmmdEWwtac2FWz4jmDhp7SKI09MmAh2LHEvdRbTl4FfvxO1UdCyyvmDwRPQ9wTFuhUh+Ixg8EekLFmuCwRORvmDwRKQvGDwR6QsGT0TfFJzzo5Aa3ggGT0/qgtGxyPqCp0paZwTPlbROCJ4raZ0QLNYEz5W0TggGT1oppKdC0oHgdRZ63ItZQ/NTJevtgF0yeNa6QjJ42rpCMnjeukAyOh75CsngmesKyeCp6wrJ4LnrCsliTzJ49rpCsr30hQ5LvkKyvfSFDky+QDI6MvkKyfbSFzo2+QrJ9tIXOjr5Csn20hc6PvkKyfbSFzpC+QrJ9tIXOkb5Csn20hc6SvkKyfbSFzpO+QrJ9tIXOlL5Csn20hc6VvkKyfbSFzpa+QrJ9tIXOl75Csn20hc6YvkKyfbSFzpm+QrJ9tIXOmr5Csn20hc6bvkKyfbSFzqQ93uSe31g4nr982fvgqfqymcET3Va9/ZATPX+BjGFjmvVFhzRca36gqc6p88InmpGPiN4qgn5jOC5+vAJwXP14ROCp5qNzwieajI+I9hY0oqLtaSFzpj+JHgXQZyedhHgiUiK7IXUevCrdwwgiugsaH3BYk0weCL6nuBjWktEZ0HrCwZPRPqCwRORvmDwRKQuGJ0FrS8YPD3pC54qaR3DSyI6C1pfsFgTPFfSOiF4rqR1QvBcSeuE4LmS1gnBTEmryeu7GOjc6HMimBLRWxHgKSfH/aZYTuXv321A5zvrC5aZBJ8I7uh8Z33B4ClHXzB4ytEXDJ5y9AWDpxx1weh8528KPs6x6HxnfcFTJa0zgqdKWmcEizXBcyWtE4LnSlonBDMlLXnzzAQ6r/mcCKZE9E4EOlM5t7wVUvrRg1Mty/L44TmXp0rKk2T0nHOBZPSkc4Fk9KxzgWSxJxk971wgGT3xXCAZPfNcIBk9IV0gGT1P6UtGZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+ur20le3l77QydlXSLaXvrq99NXtpS90RvoVks2lr4TOSb9Csrn0ldBZ6VdINpe+0iL2JJtLXwmdmX6FZHPpK6Fz06+QbC99obPTr5BsL32hc9mvkGwvfaGz2a+QbC99ofPZr5BsL32hM9qvkGwvfaFz2q+QbC99obPar5BsL32h89qvkGwvfaEz26+QbC99oXPbr5BsL32hc96vkGwvfcEz5C+QbC99wXPkL5BsL33Bs+QvkGwvfcHz5C+QbC99wTPlL5BsL33Bc+UvkGwvfcGz5S+QbC99wfPlL5BsL33B8+gvkGwvfdlj3Sd7rPtkj3Wf7LHukz3WfbLHuk/2WPfJHus+2WPdJ3us+2SPdZ/sse6TPdZ9sse6T/ZY98ke6z7ZY90ne6z7ZI91n+yx7pM91n2yx7pP9lj3yR7rPtlj3Sd7rPtkj3Wf7LHukz3WfbLHuk/2WPfJHus+2WPdJ3us+2SPdZ/sse6TPdZ9sse6T/ZY98ke6z7ZY90ne6z7ZI91n+yx7pM91n2yx7pP9lj3yR7rPtlj3Sd7rHuxx7oXe6x7sce6F3use1nEnmRz6Uvsse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rPttj3Wd7rPtsj3Wf7bHu8yL2JJtLX9ke6z7bY91ne6z7bI91n+2x7rM91n22x7rP9lj32R7rPttj3Wd7rPtsj3Wf7bHusz3WfbbHus/2WPfZHus+22PdZ3us+2yPdZ/tse6zPdZ9nouC3mv8/ele//zZu+CpuvIZwVOd1r21h+Be3wie6qw+I3iqk/qM4KnO6TOCp5qRzwieakI+IXguHvYZwXP14ROCp5qNzwieajI+I1isCbaWtJgZ2LsI4vS0iwBPRDUtWyFNjn71foFrf3/8Fzju9aiOzqm+QDI6p/oKyeC56ArJ4MnoCsng2egKyWJPMng+ukIyeEK6QjJ4nrpCsr30hc6pvkAyOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn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urI9opfMX6W6KD2il8xfpbqePKKXzF+luhQ8opfMX6W6ijuil8xfpboAO6KXzF+lunY6opfMX6W67Dmil8xfpbpiOaKXzF+lutg4opfMX6W6Tjiil8xfpbrEN6KXzF+lujo3opfMX6W6sDail8tflVTXxEb0cvmrkupy1oheLn9VHkaml8tflVQXkUb0cvmrkur6z4heMn+V6tLNiF4yf5XqqsuIXjJ/leqCyYheMn+V6lrHiF4yf5XqMsWIXjJ/leoKw4heMn+V6uLAiF4yf5WquX9EL5m/StWuP6KXzF+lasAf0Uvmr1K11I/oJfNXqZrkR/SS+atUbe8jesn8FVl/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj620+y/vaTrL/9JOtvP8n628+Hkenl8lcnWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e1nqn7v58d+vL9871+++W8+yL4f7S2x2c/naP0//c6P8vrM+6OXD3j2t+/c+vs771++c7H9n68tdlxMP5Mb0fR/Of1U3e+a/m+nn8mpavq/nX4m367p/3b6mVKMpv/b6ZumTzz9TAlX0//t9DP9PkXT/+30M/12SdP/7fS162OevnZ9aaffXt+4fH7fz+mnukOk6f92+tr1MU9fuz7m6WvXl3b69Wf658X0TdMnnr52fczT166Pefra9TFPX7s+5ulr15d2+uX1kct58Te9qW5iavq/nb52fczT166Pefra9TFP3zR94ulr18c8fe36mKevXR/z9LXrY56+dn3E0091n13T/+30tetjnr52fczT166Pefqm6RNPX7s+5ulr18c8fe36mKevXR/z9LXrI55+166Pefra9TFPX7s+5ulr18c8fdP0iaevXR/z9LXrY56+dn3M09euj3n62vXxTr8+tOtjnr52fczT166Pefra9TFP3zR94ulr18c8fe36mKevXR/x9Dfl/bXT354zeE9/Oz2n//U2R92U95mnr7zPPH3lfebpm6ZPPH3lfebpK+8zT195n3n6+tse5unrb3uIp79r18c8fe360k7/6zXGumvXxzx97fqYp2+aPvH0tetLO/2vF9nqrl0f8/S162OevnZ9zNPXro94+od2fczT164v7fS//03voV0f8/S162Oevmn6xNPXro95+tr1MU9fuz7m6WvXxzx97fqIp2/a9TFPX7s+5ulr18c8fe36mKdvmj7x9LXrY56+dn3M09euj3n62vUxT1+7PuLpF+36mKevXR/z9LXrY56+dn3M0zdNn3j62vUxT1+7Pubpa9fHPH3t+pinr10f8fRP7fqYp69dH/P0tetjnr52fczTN02fePra9TFPX7s+5ulr18c8fe36mKevXR/x9Kvy/oTp+17QqErl8WdkmlH4GSnhxp+Rcmj8GSktxp+RMl38GSl5hZ9R099CxJ+R/mIh/oy0Z4g/I+0ZFs/o+1W1ZppR+BlpzxB/RtozxJ+R9gyLZ/T94k/TniH+jLRnCD+jrj1D/BlpzxB/RtozxJ+R9gyLZ/T974K6aUbhZ6Q9Q/wZac8Qf0baM8SfkfYM8WekPUP0GbWH9gzxZ6Q9Q/wZac8Qf0baM8SfkWlG4WekPUP8GWnPEH9G2jPEn5H2DPFnpD1D+Blt2jPEn5H2DPFnpD1D/BlpzxB/RqYZhZ+R9gzxZ6Q9Q/wZac8Qf0baM8SfkfYM4We0a88Qf0baM8SfkfYM8WekPUP8GZlmFH5G2jPEn5H2DPFnpD1D/BlpzxB/RtozhJ/RoT1D/BlpzxB/RsY7I9e2xuf/RySdSBJnDWeSxInAmSSxb3cmSeyufUkasQd2JknsVJ1JEv/eypkk8W+XnEmaSDqRVMYZIvm1S7mZMo4XSWUcL5LKOF4klXGGSH7tJm1FGceLpDKOF0llHC+SyjheJE0knUgq4zj9brEo43iRVMbxIqmM40VSGceJ5KmM40VSGceLpDKOF0llHC+SJpJOJJVxvEgq43iRVMbxIqmM40VSGceJZFXG8SKpjONFUhnHi6QyjhdJE0knkso4XiSVcbxIKuN4kVTG8SKpjONEsinjeJFUxvEiqYzjRVIZx4ukiaQTSWUcL5LKOF4klXG8SCrjeJFUxnEi2ZVxvEgq43iRVMbxIqmM40Uytp9s5fXFvZfzC8heX8UAvV4UA/TYps9dbmxn5i43tn1yltsfsT2Ou9zYRuRXcn/3M/8ZDN7ful7Aie0tFsOJbRcWwzHBuYYTe3G5GE4i7+gPJ5HT9IeTyJfOi2/Xn/kHZCLHuxTklshLrwVJ69K9QdI6em+QtO7fG6QJpA9I2lThDZI2gXiDpE0r3iCVbJxAKtn4gAx+6RwIpJKNE0glGyeQSjZOIE0gfUAq2TiBVLJxAqlk4wRSycYJpJKND8jgt5WBQCrZOIFUsnECqWTjBNIE0gekko0TSCUbJ5BKNk4glWycQCrZ+IAMfjEbCKQJpMdF3R78oi4QSD02Lv9ytQe/XYoDMvjpUiCQWqM5gdQazQmk1mhOIE0gv4M8t/Ofrz2P/QKkfKQTSK3RnEBqjeYEUsnGCaSSjQ/I4AdLgUAq2TiBVLJxAqlk4wTSBNIHpJKNE0glGyeQvMnmF59jO8q7rfM4P3jU/oGSN9u4o+RNN94ogx8rhULJm3DcUfJmHHeUvCnHHaUJ5QjKVt4ou12g5E067ih5s447SqUdN5RKO24olXa8UAY/WwqFUmnnlyjtsV2gVNpxQ6m044bShHIApe3nG+VRLlAq7bihVNpxQ6m044ZSaccNpdKOF8rgB0yhUCrtXP8L2eBHSRfDUSK5gWOCcw1HqeEGjnLADRw5+xs4mQ7afr+Tluqg7Te5//M/lkwXbUf0JnKmQ3oTmc0hvYn845BeI9ObyOUN6U1k3Ib0JvJiQ3qZ7NX/6CXzV5munA7pJfNXmW6GDukl81eZLnAO6SXzV5nuWQ7pJfNXma5DDukl81eZbi0O6SXzV5kuFw7pJfNXme4ADukl81eZruoN6SXzV5lu1A3pJfNXmS6+Dekl81eZ7qcN6SXzV5mukQ3pJfNXmW57Dekl81eZLmUN6SXzV5nuTg3pJfNXRuavjMxfZTp3NqSXzF8Zmb8yMn+V6TjckF4yf5Xp1NqQXjJ/lelw2ZBeMn+V6QzYkF4yf5XpqNaQXjJ/lelE1ZBeMn+V6eDTkF4yf5XpfNKQXjJ/lekY0ZBeMn+V6bTPkF4yf5XpTM6QXjJ/lengzJBeMn+V6XTLkF4yf5XpCMqQXjJ/lemcyJBeMn+V6TDHkF4yf5XpxMWQXjJ/lelYxJBeMn+V6ezCkF4yf5XpgMGQXjJ/lekUwJBeMn+VqVR/SC+Zv8pUZj+kl8xfZaqcH9JL5q8yFcMP6SXzV1T17f+jl8tfbWT97RtZf/tG1t++kfW3P9WQ6eXyVxtZf/tG1t++kfW3b2T97Vumfu/td7ehWn9/jv3L1xbb//naYscVSd7Lft4kTSSdSPLeDPQmyXtg0Jsk7zVCb5K8Z8a9SfJeGXcmmamvfjFJ3hvj3iSVcbxIKuOMkGyvb1x6uSJpIulEUhnHi6QyjhdJZZwRkvWH5HlFUhnHi6QyjhPJTDcjFpNUxvEiqYzjRVIZZ4Rkef1usZxXv1vMdJtjMUllHC+SyjheJJVxvEgq43iRVMZxIpnpbstikso4XiSVcbxIKuN4kTSRdCKpjONFUhnHi6QyjhdJZRwvkso4TiQz3U5aTFIZx4ukMo4XSWUcL5Imkk4klXG8SCrjeJFUxvEiqYzjRVIZx4lkpvtli0kq43iRVMbxIqmM40XSRNKJpDKOF0llHC+SyjheJJVxvEgq4ziRzHRDcDFJZRwvkhaaZN1fcnvb6xeSz69+fXG9agYIfhfPX29sb+avN7aD8tcb2+f4643tRn6l93c/+UdaMoNf0VtNJ7ZrWE0n9rZzNZ3YG8zVdEx0bugk8pwT6CRyqPOy3PVn/iCZyPsuJpnIVS8mSevXvUkGv+CIRJI2B7iTpM0M7iRp84U7SRNJJ5K0ucWdpDKOF0llHC+SyjheJJVxfEjuwa+oIpFUxvEiqYzjRVIZx4ukiaQTSWUcL5LKOF4klXG8SCrjeJFUxnEiuSnjeJFUxvEiqYzjRVIZx4ukiaQTSbmgkX8t8/2u5B78/i4QyeC3TqOQ/P4vuPbgt06RSOrF8SKprZoXSW3VvEhqq+ZFUn5ygOS5nf987XnsVyTlJ51IBr91ikRSWzUvkso4XiSVcbxImkg6kVTG8SKpjONFUhnHi6QyjhdJZRwnksFvnSKR5M04v/gc2+O093f+aGTazvLJkjfl+LPkzTn+LE0s3VjyZh1/lrxpx58lb97xZ8mbeH7Fsr/s5bY9yhVL3szjzjL49VMslso9fiyVe/xYKvf4sTSxdGOp3PNblh/7uf8PS+UeP5bKPX4slXtu/u1I8Auni+kEv1q6mo7Sxh0d5Yc7OkoEd3RMdG7oZLrx9L1Bfw9+f9Nfb6YbTyN6M914GtGbyHOO6A1+F9JfbyJfOKQ3kdMb0pvIuw3pNTK9ZP4q1Q3NEb1k/irVDc0RvWT+KtNVzCG9ZP4q0+XKIb1k/irTdckhvWT+KtMFyCG9ZP4q0zXFIb1k/irTZcIhvWT+KtOVvyG9ZP4q08W8Ib1k/irT9bkhvWT+KtMltyG9XP7qyHQVbUgvl786Ml0YG9LL5a+Oh5Hp5fJXR6bLV0N6ufzVkemK1JBeMn+V6SLTkF4yf5XputGQXjJ/lelS0JBeMn+1kfmrjcxfZbpPNaSXzF/tZP5qJ/NXmW55Dekl81eZ7mIN6SXzV5luTA3pJfNXme41Dekl81eZbh8N6SXzV5nuCA3pJfNXmW7yDOkl81eZ7tsM6SXzV5luxQzpJfNXme6uDOkl81eZLpgM6SXzV8QXF35z+dn2f7622HFFUvflvEjqvpwXSd2XcyJJfGnBm6RuaHuR1A1tL5K6oe1F0kTSiaRuaHuRVMbxIqmMM0Kyvb5x6eWKpDKOF0llHCeSxBcbvEkq44yQrD8kzyuSyjheJJVxvEiaSDqRVMbxIqmM40VSGWeEZHn9brGcV79bzHSbYzFJZRwnkpnuiSwmqYzjRVIZx4ukMo4XSRNJJ5LKOF4klXG8SCrjeJFUxvEiqYzjRDLTTZ/FJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEhmuqu1mKQyjhdJZRwvkso4XiRNJJ1IKuN4kVTG8SKpjONFUhnHi6Qyjg9Jy3TbbjFJZRwvkso4XiSVcbxImkg6kVTG8SIZ208WsxfJs7cvJJ/cX19cjyu9sV2fu97gd/H89cZ2UP56Y/scf72x3civ9P7uJ/9AS6YFv6K3mk5s17CaTuxt52o6sTeYq+kkcpET6CTynP50gl8WnEjnN1nu+jN/kEzkfReTTOSqF5Ok9evuJE0knUjS5gB3krSZwZ0kbb5wJ0mbRdxJ0uYWb5LBr3sikVTG8SKpjONFUhnHi6SJpBNJZRwvkso4XiSVcbxIKuN4kVTGcSIZ/MIuEkllHC+SyjheJJVxvEiaSDqRVMbxIqmM40VSGceLpDKOF0llHCeSwa9rI5FUxvEiqYzjRVIZx4ukiaQTSWUcL5LKOE4kg9/fDUJy4E65Bb+/i0RSL84IyYFGgOC3TpFI6sXxIqmtmhdJbdW8SGqr5kQy+K3TICTP7fzna89jvyIpP+lFUls1L5LaqnmRNJF0IqmM40VSGceLpDKOF0llHC+SyjhOJIPfOkUiqYzjRVIZx4ukMo4XSRNJJ5LKOF4klXG8SCrjeJHkzTi/+BybvVFudpSfz1Ht33LnTURLuQe/o5qXO2/aWsudN5s5cf9gyZvO/FmaWLqx5E1o/ix5M5o/S96U5s9SOc2PpbKXF8sS/GYrFktlJD+Wyj1DLNtL4VaO8w+Wf/nqzV7Lx20rH5+6lk/ySkmryJvIe5N3/jePJfjFWc3of2akDBh/RsqW8WekzBp/RsrC4WeU6fZ22hkpu8efkXYC8Wek7UH8GZlmFH5G2jPEn5H2DPFnpD1D/BlpzxB/RtozhJ/Rrj1D/BlpzxB/RtozxJ+R9gzxZ2SaUfgZac8Qf0baM8SfkfYM8WekPUP8GWnPEH5Gh/YM8WekPUP8GWnPEH9G2jPEn5FpRuFnpD1D/BlpzxB/RspHS2c0cIOsmPJR/BnJ162d0fd7QE8GmlH4GcnXxZ+RfF38Gen3R/FnpN8fxZ+R8tHSGQ10mpaifBR/Rvr9UfwZ6fdH8WekPUP8GZlmFH5G2jPEn5H2DPFnpD1D/BlpzxB/RtozhJ/RqT1D/Blpz+A/o9985+3xbuPets827s9m4lObBoQpadeAMCXTlACmpH0DwpS0cUCYknYOCFPS1mHxlLb6ntJ+Xk1JeweAKVVtHhCmpN0DwpS0e0CYknYPCFMyTQlgSto9LJ7SyLW+qt0DwpS0e0CYknYPCFPS7gFgSk27B4QpafeAMCXtHv6LU/rgrm3CGu4m7gPcn78re3Nv2xfuz9++2fsnzWFX5JX5V5FXjncnv+9vHFauuCuZr+GurL2Gu9LzEu5deXgNdyXcNdyVWf25l/LCUbcr7sqsa7ibuC/hrsS6hrvy6hruyqtruCuvruGuvLqC+/lQXl3DXXl1DXfl1TXclVfXcDdxH+D+/Lnw+s7nVr9wH/pN3/lQYl1FXpl1FXml1lXklVtXkVdyXUR+U3ZdRV7pdRV55ddV5JVgV5E3kV9EXhl2FXll2FXklWFXkVeGXUVeGXYR+V0ZdhV5ZdhV5JVhV5FXhl1F3kR+EXll2FXklWFXkVeGXUVeGXYVeWXYReQPZdhV5JVhV5FXhl1FXhl2FXkT+UXklWFXkVeGXUVeGXYVeWXYVeSVYReRN2XYVeSVYVeRV4ZdRV4ZdhV5E/lF5JVhV5FXhl1FXhl2FXll2FXklWEXkS/KsKvIK8OuIq8Mu4q8Muwq8ibyi8grw64irwy7irwy7CryyrCryCvDLiJ/KsOuIq8Mu4q8Muwq8sqwq8ibyC8irwy7irwy7CryyrCryCvDriKvDLuIfFWGXUVeGXYVeWXYVeSVYVeRN5FfRF4ZdhV5ZdhV5JVhV5FXhl1FXhl2EfmmDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7CLyXRl2FXll2FXklWFXkVeGXUXeRH4ReWXYVeSVYVeRV4ZdRV4ZdhV5Zdg15OtDGXYVeWXYVeSVYVeRV4ZdRd5EfhF5ZdhV5JVhV5FXhl1FXhl2FXll2EXkN2XYVeSVYVeRV4ZdRV4ZdhV5E/lF5JVhV5FXhl1FXhl2FXll2FXklWEXkd+VYVeRV4ZdRV4ZdhV5ZdhV5E3kF5FXhl1FXhl2FXll2FXklWFXkVeGXUT+UIZdRV4ZdhV5ZdhV5JVhV5E3kV9EXhl2FXll2FXklWFXkVeGXUVeGXYReVOGXUVeGXYVeWXYVeSVYVeRN5FfRF4ZdhV5ZdhV5JVhV5FXhl1FXhl2EfmiDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7P/6HD90TuXMOzrKgnd0lNfu6ChT3dEx0bmho2xyR0f54Y6OPP4dHfnwOzryyjd0qrzyHZ1EXrm39vriXq/0JnK/Q3oT+dkhvUamN5HnHNKbyEUO6U3kC4f0JnJ6Q3oTebcRvS2RGxvSS+avGpm/amT+qhmZXjJ/1cj8VSPzV43MXzUyf9XJ/FUn81edzF91Mn/VjUwvmb/qZP6qk/mrTuavOpe/ag8uf9UeXP6qZbpQP6SXy1+1h5Hp5fJXLdPl8SG9XP6qZbqyPaSXzF9luig9pJfMX2W6njykl8xfZboUPKSXzF9luoo7pJfMX2W6ADukl8xfZbp2OqSXzF9luuw5pJfMX2W6Yjmkl8xfZbrYOKSXzF9luk44pJfMX2W6xDekl8xfZbo6N6SXzF9lurA2pJfMX2W6Jjakl8xfZbqcNaSXzF9luhI1pJfMX2W6iDSkl8xfZbr+M6SXzF9lunQzpJfMX2W66jKkl8xfZbpgMqSXzF9lutYxpJfMX2W6TDGkl8xfZbrCMKSXzF9lujgwpJfMX2Vq7h/SS+avMrXrD+kl81eZGvCH9JL5q0wt9UN6yfxVpib5Ib1k/ipT2/uQXjJ/Rdbf3sj62xtZf3sj629vZP3tjay/vZH1tzey/vZG1t/eyPrbG1l/eyPrb29k/e2NrL+9kfW3N7L+9kbW397I+tsbWX97I+tvb2T97Y2sv72R9bc3sv72Rtbf3sj62xtZf3sj62/vZP3tnay/vZP1t3ey/vb+MDK9XP6qk/W3d7L+9k7W397J+ts7WX97J+tv72T97Z2sv72T9bd3sv72nqnf+/mpH+9Pvfcv3/s3n2Oz9lK4leP8+RzV/vadW39/5/3Ldy62//O1xY6rGSXyDFlnlKlHPe2MEnmztDNK5CfTziiRB047I9OMws8oUdZIO6NE++e0M0q0M087I+0Z4s9Ie4a1M2qvj1x6uZhRpnsiaWekPUP8GWnPEH9G2jOsnVH9mdF5NSPTjMLPSHuG+DPSniH+jLRniD8j7Rniz0h7hrUzKq+/Cyrn1d8FZbqrlXZG2jPEn5H2DPFnpD1D/BmZZhR+RtozxJ+R9gzxZ6Q9Q/wZac8Qf0baM4SfUab7kmlnpD1D/BlpzxB/RtozxJ+RaUbhZ6Q9Q/wZac8Qf0baM8SfkfYM8WekPUP4GWW6s5x2RtozxJ+R9gzxZ6Q9Q/wZmWYUfkbaM8SfkfYM8WekPUP8GWnPEH9G2jOEn1HVniH+jLRniD8j7Rniz0h7hvgzMs0o/Iy0Z4g/I+0Z4s9Ie4bwM2q8+ci5rbHxphhvkrxZw5skbyLwJmki6USS1117k+T1wN4keZ2qN0ne31t5k+T97ZIzya6M40VSGWeE5ECXclfG8SKpjONF0kTSiaQyzgjJgW7SrozjRVIZx4ukMo4XSWUcF5L/898tkk4klXFcfrf4/O9WxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJHclHG8SCrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJHclXG8SCrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJE8lHG8SCrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJG02H7yqC8J3frjC8leX80AvR5XemO7Pn+9RqY3toPy1xvb5/jrje1GfqX3dz/5e3t/63750zy2w1hNJ7ZrWEynxN52rqYTe4O5mk4iFzmBTiLPOYGOsdL5TZa7/swfJBN538UkE7nqxSRp/bo7SVpv706SNgd4kzxpM4M7Sdp84U6SNou4k6TNLe4kTSSdSCrjeJFUxvEiqYzjRVIZx4ukMo4TyeCXuZFIKuN4kVTG8SKpjONF0kTSiaQyjhdJZRwvkso4XiSVcbxIKuM4kQx+XRuJpDKOF0llHC+SckEj/1rm613JJ0m5ICeSwW+dRiE58C+4gt86RSKpF8eLpLZqXiRNJJ1IaqvmRVJ+coDkuZ3/fO157Fck5Se9SGqr5kVSWzUfklvwW6dIJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJHkzzi8+x//0ery/87n9fI66fbAMfu0UiyVvzvFnyZt0/FnyZh1/liaWbix5844/S97E8yuWzd7fuR9XLHkzjz9L3tTjz1K5x41l8AuoWCyVe/xYKvf4sVTu+SXL53/LFUsTSzeWyj1+LJV7rv/tyBb8wulqOsomd3SUNm7oBL8uupqOEsEdHXn8OzqZbjx9b9Dfgt/f9Neb6cbTiN5MN55G9CbynEN6E7nIIb2JfOGIXkvk9Ib0JvJuQ3oz3dAc0Uvmr1Ld0BzRS+avUt3QHNFL5q8yXcUc0kvmrzJdrhzSS+avMl2XHNJL5q8yXYAc0kvmrzJdUxzSS+avMl0mHNJL5q8yXfkb0kvmrzJdzBvSS+avMl2fG9JL5q8yXXIb0kvmrzJdRRvSS+avMl0YG9JL5q8yXesa0kvmrzJdvhrSS+avMl2RGtJL5q8yXWQa0kvmrzJdNxrSS+avMl0KGtJL5q+akekl81eZ7lMN6SXzV43MXzUyf5XplteQXjJ/leku1pBeMn+V6cbUkF4yf5XpXtOQXjJ/len20ZBeLn+1Z7ojNKSXy1/tmW7yDOnl8lf7w8j0cvmrPdOtmCG9XP5qz3R3ZUgvmb/KdMFkSC+ZvyK+uPCby8/2OhJQ7LgiqftyXiR1X86LpO7LeZHUfTkvkrqh7USS+MqCN0nd0PYiqRvaXiR1Q9uLpImkE0llnBGS7fWNSy9XJJVxvEgq43iRVMbxIqmMM0Ky/pA8L0gSX4LwJqmM40VSGceLpDKOF0kTSSeSyjgjJMvrY5Tz6neLmW5zLCapjONFUhnHi6QyjhPJTDdQFpNUxvEiqYzjRVIZx4ukiaQTSWUcL5LKOF4klXG8SCrjeJFUxnEimekO0WKSyjheJJVxvEgq43iRNJF0IqmM40VSGceLpDKOF0llHC+SyjhOJDPdAltMUhnHi6QyjhdJZRwvkiaSTiSVcbxIKuN4kVTG8SKpjONFUhnHiWSme3yLSSrjeJFUxvEiqYzjRTK2n9z31xf34+hfSPb6agbo9aoZIPhdPH+9sb2Zv97YDspdb/C7eP56Y7uRX+n93U/+kZbM4Ff0VtOJ7RpW0zHRuaETe4O5mk4iFzmBTiLPOYFOIoc6L8tdf+YPkom871qSwa8hIpGk9evuJGm9vTtJ2hzgTtJE0okkbb5wJ0mbRdxJ0uYWd5LKOF4klXF8SB7BL5IikVTG8SKpjONFUhnHi6SJpBNJZRwvkso4XiSVcbxIKuN4kVTGcSIZ/CowEkllHC+SyjheJJVxvEiaSDqRVMbxIqmM40Qy+P3dICQH7koewe/vIpHUi+PzL7iO4LdOkUjqxfEiqa2aF0lt1bxIaqvmRDL4rdMgJM/t/Odrz2O/Iik/6UVSWzUvktqqeZE0kXQiqYzjRVIZx4ukMo4XSWUcL5LKOE4kg986RSKpjONFUhnHiyRvxvnF59geZX9/53P7+Rx1+2RpYunGkjfn+LPkTTr+LHmzjj9L3rTjz5I377izDH75NAzLZu/v3I8rlryZx58lb+rxZ6nc48fSxNKNpXKPH0vlHj+Wyj2/ZPn8b7liqdzjx1K5x41l8GuoS1h+0FGSuaOjbHJHR2njjo6Jzg0dJYI7OvL4d3Qy3Xj63qB/BL+/6a83042nAb3Bb1n6603kOYf0JnKRQ3oT+cIhvUamN5F3G9Kb6YbmiF4yf5XqhuaIXjJ/leqG5oheMn+V6SrmkF4yf5XpcuWQXjJ/lem65JBeMn+V6QLkkF4yf5XpmuKQXjJ/leky4ZBeMn+V6crfkF4yf5XpYt6QXjJ/len63JBeLn9lmS65Denl8leW6SrakF4uf2UPI9PL5a8s07WuIb1c/soyXb4a0kvmrzJdkRrSS+avMl1kGtJL5q8yXTca0kvmrzJdChrSS+avNjJ/tZH5q0z3qYb0kvmrncxf7WT+KtMtryG9ZP4q012sIb1k/irTjakhvWT+KtO9piG9ZP4q0+2jIb1k/irTHaEhvWT+KtNNniG9ZP4q032bIb1k/irTrZghvWT+KtPdlSG9ZP4q0wWTIb1k/or44sJvLj/b60hAseOKpO7LOZEkvrbgTVL35bxI6r6cF0nd0PYiaSLpRFI3tL1I6oa2F0nd0PYiqYzjRVIZZ4Rke33j0ssFSeLLCt4klXG8SCrjeJFUxhkhWX9InlckTSSdSCrjeJFUxvEiqYzjRVIZx4ukMs4IyfL63WI5r363mOk2x2KSyjheJJVxvEgq43iRNJF0IqmM40VSGceLpDKOF0llHC+SyjhOJDPdx1lMUhnHi6QyjhdJZRwvkiaSTiSVcbxIKuN4kVTG8SKpjONFUhnHiWSmG1WLSSrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrj+JAsme7ELSapjONFUhnHi6QyjhdJE0knkso4XiSVcbxIKuM4kQx+F2+z1+foW2tfSDq3CJTgN/TWsont+dayie3i1rIxsblkE9tprWUT2zutZRPbDa1lE3uHu5ZN7K3sUjbB7xmuZcPqi7836pTgdxLXsmH1xSNsTGwu2bD64u8tICX4Xce1bFh98QgbVl88wobVFw+wCX6Hci0bVl888HuG4Pct17Jh9cUjbExsLtmw+uIRNqy+eIQNqy8eYcPqi0fYsPriATbB74euZSNffM1GvviajXzxNRsTm0s28sXXbOSLr9nIF1+zkS++ZiNffMkm+I3ctWzki6/ZyBdfs5EvvmZjYnPJRr74mo188TUb+eJrNvLF12zkiy/ZBL+rupaNfPE1G/niazbyxddsTGwu2cgXX7ORL75mI198zUa++JqNfPElm9h3D1t7/xlwe3LyZDPw7+5iXzJczMbE5pJNaH+zmE1of7OYTWh/s5hNaH+zmE1of7OWTew7fIvZhN77LWYjX3zNhtUXD/zb+dj37BazYfXFI2xYffEIG1ZfPPBvoGPfhVvMhtUXD7CJfbttMRtWXzzChtUXj7Bh9cUDv2eIfQNtMRtWXzzChtUXj7Bh9cUjbFh98QgbVl/8nc0Z+97XYjasvniEDasvHmEjX3zNxsTmko188TUb+eJrNvLF12zki6/ZyBdfsol9t2wxG/niazbyxdds5Iuv2ZjYXLKRL75mI198zUa++JqNfPE1G/niSzax75YtZiNffM1GvviajXzxNRsTm0s28sXXbOSLr9nIF1+zkS++ZiNffMkm9t2yxWzki6/Z2H+dje+/jjsXXInyVnDCK6jwChq8go6uYMGNIW8FG7yCHV7BAa8A/k222G/y938De1rsN3lEQew3eURB7Dd5REHsN/n7v7E7S+w3eURB7Dd5REHsN3lEQew3eURB7Dd5REHsN3lgV1Fiv8kjCmK/ySMKYr/JIwpiv8kDCs7Yb/KIgthv8oiC2G/yiILYb/KIgthv8ogC+Df5hH+TT/g3+YR/k0/4N7nCv8kV/k2u8G9yhX+TF/TUeyuAf5Mr/Jtc4d/kCv8mV/g3ucG/yQ3+TW7wb3KDf5MXdGR7K4B/kxv8m9zg3+QG/yY3+De5w7/JHf5N7vBvcod/k316VrfXh9q30zwVDPyNl08b6lIFDV5BB1dQffo/lyrY4BXs8AoOeAUGr6DAK0B/k+sj9pv8/S9m6yP2mzyiIPabPKBgi/0mjyiI/SZ//2vNusV+k0cUxH6TRxTEfpNHFMR+k0cUxH6TRxTEfpO/7yrqFvtNHlEQ+00eULDHfpNHFMR+k0cUxH6TRxTEfpNHFMR+k0cUxH6TRxTEfpNHFMC/yTv8m7zDv8kH/Jt8wL/JB/ybfMC/yT4dUksVwL/JB/ybfMC/yQf8m3zAv8kG/yYb/Jts8G+ywb/JPh1SSxXAv8kG/yYb/Jts8G+ywb/JBf5NLvBvcoF/kwv8m+zTIbVUAfyb7NJf9LDyUvDoD08FA3/j5dJftFSBS3/RWgUbvIIdXsEBr8DgFRR4BSe8ggqvAP5NPmO/yQN/MVtjv8kjCmK/ySMKYr/JIwpiv8kDf63p0l+0VkHsN3lEQew3eURB7Dd5REHsN3lEQew3eWBX0WK/ySMKYr/JIwpiv8kjCmK/ySMKYr/JIwpiv8kjCmK/ySMKYr/JIwpiv8kjCuDf5A7/Jnf4N7nDv8kd/k3u8G9yh3+TO/yb3OHf5A7/Jnf0N7k90N/k9kB/k9sD/U1uD/Q3uT3Q3+T2QH+T2wP9TW4P9De5PdDf5PaAf5M3+Dd5g3+TN/g3eYN/k106pNYqgH+TN/g3ecN9k7dH7f/PRVtF3evr8/etf3z++vOf7P/2P3nRzjDyn9z+9X9y/zf/yX2z/2f/e8nWM5X885/s3f4Y8M9/sP/L/+DfK6VG/oPbv/0P7v/2P3j82/+g/dv/oMNPva2fx3vu7fzyf3Hndv7zxeex/6//K/q/H+qM+KFqxA/VIn6oPvdDvf+LPIppxv6Ltv/Wf9H+3/ovOv5b/0X23/ovKv+t/6Lzv/VfVP9b/0Xtv/Vf9F/P+//zR+uv770/2s9Xt+3nY9kj5scKncxrre+vPf7+EFjoYD4iIHQuHxFg6AJCp/IRAaFD+YiA0Jl8REDoNfmIgNBb8gEBJfSSfEQA+ktc0F/igv4Su5RiLBWA/hIX9Je4oL/EsUtJRgSgv8SxK0lGBKC/xLELSUYEoL/EsetIRgSgv8TARRj/CMDtpvq/AoJXMNz+ov3/CsD9i5l/BIT+KTQiAPfvZf4RgPvnMv8IAP5rmf8rIPQ7MPCb7tjdCwMCYlcvjAgInQdGBIR+iUcEhH6JRwSEfolHBIR+iUcEhH6JRwSEfolHBKC/xLEbFwYExC5cGBHw33+JLzcN//trt62/7Oi2Pz786Ocf3CwoXHCXcOBLMHwJBV/CiS+h4ktocST8fKge70Mdj//68ZVt+/nnLpt9/A3nZh8fa4v5sUKfSRkZd+grKSMCDF1A6BspIwJCny0bERD6atmIgNBHy0YEhL5ZNiBge6ALCH2xbEQA+ku8ob/ELtUFSwWgv8Qb+ku8ob/EG/pLvKG/xDv6S7yjv8Q7+ku8o7/EO/pLvKO/xDv6S7yjv8Q7+ku8o7/EB/pLfMS+IP31r5OPI/Q7MCIg9E+h73+ZeRyhfwqNCAj9U2hAgIX+KTQiIHQeGBEQOg+MCAj9Dnz/k6LDQr8DIwJC54ERAaHzwIiA0C/xiIDQL/GIgNAv8YCAEvolHhEQ+iUeERD6JR4RgP4Su7SXLBWA/hKX//5L/Js/Zny0nz86e3z8Od/nH52Vii+h4Uvo8BLOB76EDV/Cji/hiC3hnfGfErY/JPzlO/f3d358dO+39iHXuOQWLrmxHcIff5Z+9X+PsR3CkITYDmFIQmyHMCKhxnYIQxJiO4QhCbEdwpCE2A5h5N/6uDQNLZYQ+yUfkhDodf75UIHe258P5fKC9tc1in0v+5cPtZX36YpiFx+qB/xQLu09v/pQzn+p4tLes1TAji7gQBdg6AIKuoATXUBFF9DQBXRwAR39Je7oL3FHf4k7+kvs0tuzVAD6S9zRX+KO/hJ39Je4g7/E9gB/ie0B/hLbA/wltgf4S2wP8JfYHuAvsT3AX2J7gL/E9gB/ie2B/hJv6C/xhv4Sb+gv8Yb+Evt0C60UgP4Sb+gv8Yb+Em/oL/GG/hLv6C/xjv4S7+gv8Y7+Evt0C60UgP4S7+gv8Y7+Eu/oL/GO/hIf6C/xgf4SH+gv8YH+Evu0O60UgP4SH+gv8YH+Eh/oL/GB/hIb+kts6C+xob/Ehv4S+/RrrRSA/hIb+kts6C+xob/Ehv4SF/SXuKC/xAX9JS7oL7FPv9ZKAegvcUF/iQv6S1zQX+KC/hKf6C/xif4Sn+gv8Yn+Evt0ZK0UgP4Sn+gv8Yn+Ep/oL/GJ/hJX9Je4or/EFf0lrugvsU9v1UoB6C9xRX+JK/pLXNFf4or+EqN3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x1ZB79gq6B1bBb1jq6B3bJUH+Etc0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq0TvWPrRO/YOtE7tk70jq3zAf4Sn+gdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rF1ondsnegdWyd6x9aJ3rFV0Tu2KnrHVkXv2KroHVv1Af4SV/SOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOroXdsNfSOrYbesdXQO7baA/wlbugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWR+/Y6ugdWx29Y6ujd2z1B/hL3NE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6t5ycFf4r/55PCKwB/jJ+fFPw1fn5S8Of4+UnB3+PnJwV/kJ+fFPxFfn5S8Cf5+Unh32T0uq2nAvg3Gb1w66kA/k1Gr9x6KoB/k9FLt54K4N9k9NqtpwL4Nxm9eOupAP5NRq/eeiqAf5PRy7eeCuDfZPT6racC+DcZvYDrqQD+TUav4HoqgH+T0Uu4ngrg32T0Gq6nAvg3Gb2I66kA/k1Gr+J6KoB/k9HLuJ4fD/5NRq/jen48+DcZvZDr+fHg32T0Sq7nx4N/k9FLuZ4fD/5NRq/leiqAf5PRi7meCuDfZPRqrqcC+DcZvZzrqQD+TUav53oqgH+T0Qu6ngrg32T0iq6nAvg3Gb2k66kA/k1Gr+l6KoB/k9GLup4K4N9k9KqupwL4Nxm9rOupAP5NRq/reiqAf5PRC7ueCuDfZPTKrqcC+DcZvbTrqQD+TUav7XoqgH+T0Yu7ngrg32T06q6nAvg3Gb2866kA/k1Gr+96KoB/k9ELvJ4K4N9k9AqvpwL4Nxm9xOupAP5NRq/xeipAf5M3+B6vDb7Ha4Pv8drge7yenw9eAfqbvMH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV4bfI/XBt/jtcH3eG3wPV47fI/XDt/jtcP3eO3wPV77A/1N3uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsdrh+/x2uF7vHb4Hq8dvsfrgO/xOuB7vA74Hq8DvsfreKC/yQd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4HfA9Xgd8j9cB3+N1wPd4GXyPl8H3eBl8j5fB93jZA/1NNvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B6vAt/jVeB7vAp8j1eB7/EqD/Q3ucD3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eJ3yP1wnf43XC93id8D1e5wP9TT7he7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77Hq8L3eFX4Hq8K3+NV4Xu86gP9Ta7wPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Pv8WrwPV4Nvserwfd4tQf6m9zge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerw7f49Xhe7w6fI9Xh+/x6g/0N7nD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6ug9XvsDvcfrqQD8TX4qAH+TnwrA3+SnAvA3+akA/E1+KgB/k58KwN/kpwLwN/mpAP5NRu/xeiqAf5PRe7yeCuDfZPQer6cC+DcZvcfrqQD+TUbv8XoqgH+T0Xu8ngrg32T0Hq+nAvg3Gb3H66kA/k1G7/F6KoB/k9F7vJ4K4N9k9B6v538H/JuM3uP1/O+Af5PRe7ye/x3wbzJ6j9fzvwP+TUbv8Xr+d8C/yeg9Xk8F8G8yeo/XUwH8m4ze4/VUAP8mo/d4PRXAv8noPV5PBfBvMnqP11MB/JuM3uP1VAD/JqP3eD0VwL/J6D1eTwXwbzJ6j9dTAfybjN7j9VQA/yaj93g9FcC/yeg9Xk8F8G8yeo/XUwH8m4ze4/VUAP8mo/d4PRXAv8noPV5PBfBvMnqP11MB/JuM3uP1VAD/JqP3eD0VwL/J6D1eTwXwbzJ6j9dTAfybjN7j9VQA/yaj93g9FcC/yeg9Xk8F8G8yeo/XUwH8m4ze4/VUAP8mo/d4PRXAv8noPV5PBfBvMnqP11MB+pu8wfd4bfA9Xht8j9cG3+P1/HzwCtDf5A2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Hu8Nvgerw2+x2uD7/Ha4Xu8dvgerx2+x2uH7/HaH+hv8g7f47XD93jt8D1eO3yP1w7f47XD93jt8D1eO3yP1w7f47XD93jt8D1eO3yP1w7f47XD93jt8D1eO3yP1w7f47XD93jt8D1eO3yP1w7f47XD93jt8D1eO3yP1x67Q6rY/s/XFrtUEPo9GFIQ+mdRKe2l4KxXCkL/LBpSEPpn0ZCC0D+LhhSEzgcjCmL3Fw0pCP0enNv5z9eex36lIPR7MKQgdD4YUmDwCkK/yUMKQr/JQwpCv8lDCkK/yUMKQr/JIwpi9xcNKYB/k2P3Fw0pgH+TY/cXDSmAf5Nj9xcNKYB/k2P3Fw0p+O+/yZebxP/9ta321+dobbOfz3G2f7mjXNB2tFbvRqZ3J9N7oOr90GAJNJQEGs4EGmoCDS2BBlhf8aOhwnqFDw2w7/+HBtg3/UND7He61cfri/t3X9Lf3/nRf762/aE39pvurzf2+/87vc5/F1Jj+4q1bGL7lbVsYvugtWxi+6ulbFps37aWTWw/uJZNbJ+5lk0m/+rNxsTmko188TUb+eJrNvLF12zki6/ZyBdfsunyxdds5Iuv2cgXX7ORL75mY2JzyUa++JqNfPE1G/niazbyxdds5Iuv2BwP+eJrNvLF12zki6/ZyBdfszGxuWQjX3zNRr74mo188TUb+eJrNvLFl2w2+eJrNvLF12zki6/ZyBdfszGxuWQjX3zNRr74mo188TUb+eJrNvLFl2x2Un8z0D957KT+ZogN6Ts10BV47KTv1BAb0ndqiA3pOzXC5iDd3wyxId3fDLEh9TcDfUnHQepvhtiY2FyyId3fDLEh9cVDbEh98RAbUl88xIbUF4+wMVJfPMSG1BcPsZEvvmYjX3zNxhKx+cV33tppL4XP/5afr97+9tV7KS+BdbsimclFryWZyXOvJZnJoa8lmcnPO5H8oJPJ0bvTKZk8vT+dTK7en04mX+9PJ5Oz96djonNDR379jg6rB+/n6ztvvR5/0Pl3CbuwenB/kqwe/Fck9/0t0MoVSVa/7k4y+M0eJJKsOcCfJGtm8CfJmi/8SZpIOpFkzS2/Izmw0w1+UwqJJGnGeX62169j98fnZ/7XGSf4fS0kkqQZ53ckR16c4LfGkEiSZpwJJEkzzgSSpBlnAkkTSSeSpBlnAknSjPNLkgMZJ9U1vLUkWTPOtr3hbHtzyDipLu0tJZnqLt80kiMvTqorfmtJsmYcf5KsGcefpImkE0nWjONPkjXj+JNkzTi/IzmQcVLdQVxLkvb3OO38Idm/kKz9/Z0fP1+7tfZBMtWNxbUkaX+P406SNuOc25tkNYcNRqprj2tJmkh+JzniJ1NdklxLkjbjuJOkzTjuJGkzjjtJ2t/jOJO0VPcy15Kk/T3Or0h+32BYqluca0kq4+xb+/NvMD7omOjc0FEWuaPDmi+ee6z3Z97Lf749sFTXPteSZM0XvyI55OVY84U7yVR3R9eSZM0X/iRZ84U/SdZ84U/SRNKJJGtu+R3Jge1Bqlusa0kq4zz/T/e4yNKpbrf601EWuaGz0+aLs70/c9sctgc7bb5wJ0mbL35DcsTLpbpAvJakiaQTSdp84U6SNl+4k6TNF+4kabOIO0na3PIrkgPbg1S3v9eSVMbxIqmM40VSGceLpImkE0llHC+SyjheJJVxniT//BfiH3SUW+7oKIvc0El1Q/3yO3/opUgBH3pje/X+7kts/eM7/wd6Yztqf72WR+/IZin45XB/vbE9pL/e2E7PX29s7+avN7Ybc9cb/J717/QOJLXgF6r99SbyV0N6E/mrIb1GpjeTvxrRG9xftZ882A+HvBD8wrK/3uD+6jd6h/xGcH/lrTf4TWF/vcH9lbve4P7KXW9wf+Wu1xLpHfAbwS/S+utN5K+G9CbyV0N6M/mrEb2Z/NWA3tj3TPvDXt+5P8rpkBdiXx2doDe0v/qd3hG/EfuC5wS9RqY3tL+aoDe0v5qgN7S/mqA3tL/6pd4RvxHaX/nrjX1LcYLeRP5qSG8mfzWiN5O/GtFrMHrPP/PghwYcz3StAccHXWsI7m3663P05wdxyJ6x775N0Bvc2/xG74h3jX1DbYLe4N7GXW9wb+OuN7i3cddrZHqD+6Bf6R3wrrHvZE3Qm8hfDelN5K+G9GbyV9/1ltj3mybozeSvRvQC+av+90xbYl8hGtRgoTVs9qPh49/5/v1/d21/Fau2j8+8b9un3tg+yF9vbB/0K721vf9Aftu/fOeBnUWJfaFnMZvY/motm9hebCmb2HdxFrOJ7fHWsontB9eyie0z17Ixsblkk8jrurORL75mI198zUa++JqNfPElm9j3XBazkS++ZiNffM1GvviajYnNJRv54ms28sXXbOSLr9nIF1+zkS++ZBP7BshiNvLF12zki6/ZyBdfszGxuWRD6m+Kvf6OotglG1J/M8Imdu/8RDbldYSgnPWKDek7NcSG9J0aYkP6Tg2xId3fDLEh3d8MsSH1NwO33Uvsrv7FbEj3NyNsYt8AWMyG1BcPsSH1xUNsSH3xEBsTm0s2pL54iA2pLx5iI198zUa++JqNfPElm9i3G37J5hffudbXv/2tf9xl/fw3ibHvPCxmk8kXe7PJ5Iu92ZjYXLLJ5Iu92WTyxd5sMvnif8emn1dsMvlibzaZfLEzm+A3N6ax+ejqOMoVG1JfPMSG1BcPsSH1xUNsTGwu2ZD64iE2pL54iA2pLx7p2wp+02QtG1JfPMIm+K0UJzYfeim87ofe2P51319f3I+jf9G7PZq9PvVTwc9X1z/+Fx3blc5QbHSKYzvIGYpj+8IZimO7vRmKY3u4GYpjO7MJioPfb5mhOLbjmqGYznMFv+IyQ7HRKabzXMFvucxQTOe5gt9zmaGYzXOdwW+6zFDM5rnO4HddZihm81znw+gUs3muM/jdmBmK2TzXGfzGywzFdJ4r+D2WGYrpPFfw2ykzFNN5ruB3TmYopvNcwW+SzFBM57mC3w+ZoZjOcwW/9TFDMZ3nCn6XY4ZiOs8V/IbGDMV0niv4vYsZiuk8V/DbFDMU03mu4HckZiim81zBbz7MUEznuYLfZ5ihmM5zHXSeK/hljRmK6TzXQee5jM5zBb90MkMxnecKfpVkhmKjU0znuYLfBZmhmM5zBb/hMUMxnecKfm9jhmI6zxX8NsYMxXSeK/gdixmK6TxX8JsTMxTTea7g9yFmKKbzXMFvOcxQTOe5gt9dmKGYznMFv5EwQzGd5wp+z2CGYjrPFfz2wAzFdJ4r+J2AGYrpPFfwTv8Ziuk8V/D+/RmK6TxX8K78GYrpPFfwXvsZiuk8V/AO+hmK6TwXXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDX+l66CtdD32l66GvdD309WF0itk8V6Xroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Pf6HroG10PfaProW90PfTtYXSK2TxXo+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76lqmjvNf99cX1z+/8oTfRazykN9HP6d7a64t7vdKb6Kf0kN5EP6OH9Cb6CT2kN1EmHtGbqbF6SG+m93dEb6b3d0Rvoiw8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zpvhVyim81zO2+FXKKbzXM4b4lcopvNczlviVyim81zOm+JXKKbzXM6b5VcopvNcdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPth76dGProb8rJvNcd8VknuuumMxz3RVnOsVknuuumMxz3RWTea67YjLPdVdM57nYeujviuk8F1sP/V0xnedi66G/K6bzXGw99HfFdJ6LrYf+rpjOc7H10N8V03kuth76u2I6z8XWQ39XTOe52Hro74rpPBdbD/1dMZ3nYuuhvyum81xsPfR3xXSei62H/q6YznOx9dDfFdN5LrYe+rtiOs/F1kN/V0znudh66O+K6TwXWw/9XTGd52Lrob8rpvNcbD30d8V0nouth/6umM5zsfXQ3xXTeS62Hvq7YjrPxdZDf1dM57nYeujviuk8F1sP/V0xnedi66G/K6bzXGw99HfFdJ6LrYf+rpjOc7H10N8V03kuth76u2I6z8XWQ39XTOe52Hro74rpPBdbD/1dMZ3nYuuhvyum81xsPfR3xXSei62H/q6YznOx9dDfFdN5LrYe+rtiOs/F1kN/V0znudh66O+K6TwXWw/9XTGd52Lrob8rpvNcbD30d8V0nouth/6umM1zHXQ99AddD/1B10N/0PXQ3/XQKWbzXAddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH5E6ykc7Hy9uf//kL72RGsqn9AZap0d/vni0d3oDrdJTegOt0VN6A63QU3oDZeIpvYES8ZTeSPvvhN5IbdVTegNl4Sm9gZLwlF4yfxWppXpKL6y/etEA65leNPj2QSU/svaoo3+XzMvjMe6HSu9+73z7IHu9vn2QuV7nDdL2en37IHu9vn2QvV7fPshebybT69sH2ev17Zns9ZL5K+eN0fZ6yfyV87Zoe71k/sp5U7S9XjJ/5bwl2l4vmb9y3hBtr5fMXzlvh7bXy+WvTufN0PZ6ufzV6bwV2l4vl786b5lML5e/Op23Qdvr5fJXp/MmaHu9ZP7KeQu0vV4yf+W8AdpeL5m/ct7+bK+XzF85b36210vmr5y3PtvrJfNXzhuf7fWS+Svnbc/2esn8lfOmZ3u9ZP7KecuzvV4yf+W84dleL5m/ct7ubK+XzF85b3a210vmr5y3OtvrJfNXzhud7fWS+Svnbc72esn8lfMmZ3u9ZP7KeYuzvV4yf+W8wdleL5m/ct7ebK+XzF85b26210vmr5y3NtvrJfNXzhub7fWS+Svnbc32esn8lfOmZnu9ZP6qkPkr5z3c5nqd93Db6yXzV5XMXznvWbfXm8n0kvkr5z3r9nrJ/JXznnV7vWT+ynnPur1eMn/lvGfdXi+Zv3Les26vl8xfOe9kt9dL5q/I+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72RNbfnsj62xNZf3si629Pt0yml8tfJbL+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2ZrL89k/W3Z7L+9kzW355vmUwvl7/KZP3tmay/PZP1t2ey/vZM1t+eyfrbM1l/eybrb89k/e2ZrL89k/W3Z7L+9kzW357J+tszWX97Jutvz2T97Zmsvz2T9bdnsv72TNbfnsn62zNZf3sm62/PZP3tmay/PZP1t2ey/vZM1t+eyfrbM1l/eybrb89k/e2ZrL89k/W3Z7L+9kzW357J+tszWX97Jutvz2T97Zmsvz2T9bdnsv72TNbfnsn62zNZf3sm62/PkfquRzsfL27pnd5A+9GM3kh9yKP3x4tHe6c30Ho1pTfQejWlN5PpDZQHp/QGyoNTeiPtvzN6I+2/M3oD5cEZvZH6kKf0kvmrSH3IU3ph/dWLhhxAg28f1M7x0NDP9l0uv436eOrjeHnqWl4V+3ZCKxT79kIrFPt2QysU+/ZDCxQ7bzBeodi3J1qh2LcrWqHYty9aoTjTKabzXM7bjFcopvNczhuNVyim81zOW41XKKbzXM6bjVcopvNcztuNVyim81zOG45XKKbzXM5bjlcoZvNcxXnT8QrFbJ6rOG87XqGYzXOVW6ZTzOa5ivPW4xWK2TxXcd58vEIxnedy3n68QjGd53LegLxCMZ3nct6CvEIxnedy3oS8QjGd53LehrxCMZ3nct6IvEIxnedy3oq8QjGd53LejLxCMZ3nct6OvEIxnedy3pC8QjGd53LekrxCMZ3nct6UvEIxnedy3pa8QjGd53LemLxCMZ3nct6avEIxnedy3py8QjGd53LenrxCMZ3nct6gvEIxnedy3qK8QjGd53LepLxCMZ3nct6mvEIxnedy3qi8QjGd5yqZTjGd5yp0nst5V/gKxXSeq9B5rkrnuZx3wq9QTOe5nPfCr1Cc6RTTeS7n7fArFNN5LucN8SsU03ku5y3xKxTTeS7nTfErFNN5LufN8isU03kuuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dBXuh76StdDX+l66CtdD329ZTrFbJ6r0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10NfI3WU31/9eHH7+ye/6A20G8/ojdRdPXp/vHi0d3oDrdJTegOt0VN6A63QU3oDZeIpvYES8ZTeSPvvjN5I+++M3kBZeEZvpKbqKb1k/ipSS/WUXlh/9aIhB9Dg2wf10p6/SqV+l8zz+UzmOZWvV7fxqti3E1qh2LcXWqHYtxtaodi3H1qg2HmP9ArFvj3RCsW+XdEKxb590QrFmU4xnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGb52rOe6RXKGbzXM15j/QKxWyeq90ynWI2z9Wc90ivUMzmuZrzHukViuk8l/Me6RWK6TyX8x7pFYrpPJfzHukViuk8l/Me6RWK6TyX8x7pFYrpPJfzHukViuk8l/Me6RWK6TyX8x7pFYrpPNdJ57mcd4WvUEznuU46z5XoPJfzTvgViuk8l/Ne+BWKM51iOs/lvB1+hWI6z+W8IX6FYjrP5bwlfoViOs/lvCl+hWI6z+W8WX6FYjrPRddD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtP10He6HvpO10Pf6Xro+y3TKWbzXJ2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66HukjvLRzseL298/+UVvoN14Sm+gdXr0/nxxe6c30Co9pTfQGj2lN9AKPaU3UCae0RupsXpKb6T9d0ZvpP13Rm+gLDylN5PpJfNXkVqqp/TC+qsXDbCe6UWDbx80nj/5uB3n8V00L89Xl/zmF895jfQCwb6d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43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eJ3yP1wnf43XC93id8D1e5wP9nXzC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wXf43XB93hd8D1eF3yP1/VAfydf8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf42XwPV4G3+Nl8D1eBt/jZQ/0d7LB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBl8j5fB93gZfI+Xwfd4GXyPl8H3eBX4Hq8C3+NV4Hu8CnyPV3mgv5MLfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xge7wKfI9Xge/xKvA9XgW+x6vA93gV+B6vAt/jVeB7vAp8j1eB7/Eq8D1eBb7Hq8D3eBX4Hq8C3+NV4Hu8CnyPV4Hv8SrwPV4FvserwPd4FfgerwLf41Xhe7wqfI9Xhe/xqvA9XvWB/k6u8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eF7/Gq8D1eFb7Hq8L3eFX4Hq8K3+NV4Xu8KnyPV4Xv8arwPV4Vvserwvd4Vfgerwrf41Xhe7wqfI9Xhe/xqvA9XhW+x6vC93hV+B6vCt/jVeF7vCp8j1eD7/Fq8D1eDb7Hq8H3eLUH+ju5wfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4Nvserwfd4Nfgerwbf49Xge7wafI9Xg+/xavA9Xg2+x6vB93g1+B6vBt/j1eB7vBp8j1eD7/Fq8D1eDb7Hq8H3eDX4Hq8G3+PV4Hu8GnyPV4Pv8WrwPV4dvserw/d4dfgerw7f49Uf6O/kDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93h1+B6vDt/j1eF7vDp8j1eH7/Hq8D1eHb7Hq8P3eHX4Hq8O3+PV4Xu8OnyPV4fv8erwPV4dvserw/d4dfgerw7f49Xhe7w6fI9Xh+/x6vA9Xh2+x6vD93gN+B6vAd/jNeB7vAZ8j9d4oL+TB3yP14Dv8RrwPV4DvsdrwPd4DfgerwHf4zXge7wGfI/XgO/xGvA9XgO+x2vA93gN+B6vAd/jNeB7vAZ8j9eA7/Ea8D1eA77Ha8D3eA34Hq8B3+M14Hu8BnyP14Dv8RrwPV4DvsdrwPd4DfgerwHf4zXge7wGfI/XgO/xGvA9XgO+x2vA93gN+B6vAd/jNeB7vAZ8j9eA7/Ea8D1eA77Ha8D3eA34Hq8B3+M14Hu8BnyP14Dv8RrwPV4DvsdrwPd4DfgerwHf4zXge7wGfI/XgO/xGvA9XgO+x2vA93gN+B6vAd/jNeB7vAZ8j9eA7/Ea8D1eA77Ha8D3eA34Hq8B3+M14Hu8BnyP14Dv8RrwPV4DvsdrwPd4DfgerwHf4zXge7wGfI/XgO/xGvA9XgO+x2vA93gN+B6vAd/jNeB7vAZ8j9eA7/Ea8D1eA77Ha8D3eA34Hq+B3uN1PtB7vJ4KwN/JTwXg7+SnAvB38lMB+Dv5qQD8nfxUAP5OfioAfyc/FYC/k58K4N/J6D1eTwXw72T0Hq+nAvh3MnqP11MB/DsZvcfrqQD+nYze4/VUAP9ORu/xeiqAfyej93g9FcC/k9F7vJ4K4N/J6D1eTwXw72T0Hq+nAvh3MnqP1/O/Af9ORu/xev434N/J6D1ez/8G/DsZvcfr+d+Afyej93g9/xvw72T0Hq+nAvh3MnqP11MB/DsZvcfrqQD+nYze4/VUAP9ORu/xeiqAfyej93g9FcC/k9F7vJ4K4N/J6D1eTwXw72T0Hq+nAvh3MnqP11MB/DsZvcfrqQD+nYze4/VUAP9ORu/xeiqAfyej93g9FcC/k9F7vJ4K4N/J6D1eTwXw72T0Hq+nAvh3MnqP11MB/DsZvcfrqQD+nYze4/VUAP9ORu/xeiqAfyej93g9FcC/k9F7vJ4K4N/J6D1eTwXw72T0Hq+nAvh3MnqP11MB/DsZvcfrqQD+nYze4/VUAP9ORu/xeiqAfyej93g9FaC/kw/4Hq8DvsfrgO/xOuB7vJ6fD14B+jv5gO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vA74Hq8DvsfrgO/xOuB7vE74Hq8TvsfrhO/xOuF7vM4H+jv5hO/xOuF7vE74Hq8TvsfrhO/xOuF7vE74Hq8TvsfrhO/xOuF7vE74Hq8TvsfrhO/xOuF7vE74Hq8TvsfrhO/xOuF7vE74Hq8TvsfrhO/xOuF7vE74Hq8TvsfrjN0hVez852uLfVQQ+n0wpSD0s6iU/lJQ2ycFoZ9FUwpCP4umFIR+Fk0pCJ0PZhTE7i+aUhD6fVCP+s/X1uv8pCD0+2BKQeh8MKXA4BWEfidPKQj9Tp5SEPqdPKUg9Dt5SkHod/KMgtj9RVMK4N/JsfuLphTAv5Nj9xdNKYB/J8fuL5pSAP9Ojt1fNKXg77+TP24S/+fX9jZen6P3w74/R+3/5Y5yQ9vRXr0Hmd6TTO+FqvdNgyXQUBJoqAk0tAQaegINsL7iW0OD9QpvGmDf/28aYN/pbxpiv6d7e7y+ePzsS8bXd36M76/tf+iN/U731xv7/f87vc6/F9Ji+4q9bGL7lb1sYvugvWxi+6utbHps37aXTWw/uJdNbJ+5l00m/+rNxsTmIxv54s9s5Is/s5Ev/sxGvvgzG/nij2yGfPFnNvLFn9nIF39mI1/8mY2JzUc28sWf2cgXf2YjX/yZjXzxZzbyxZ/YXA/54s9s5Is/s5Ev/sxGvvgzGxObj2zkiz+zkS/+zEa++DMb+eLPbOSLP7I55Is/s5Ev/sxGvvgzG/niz2xMbD6ykS/+zEa++DMb+eLPbOSLP7ORL/7I5iT1NxP9k9dJ6m+m2JC+pya6Aq+T9D01xYb0PTXFhvQ9NcPmIt3fTLEh3d9MsSH1NxN9Sc//r9h8ZGNi85EN6f5mig2pL55iQ+qLp9iQ+uIpNqS+eIaNkfriKTakvniKjXzxZzbyxZ/ZWCI2v/jOR6/2Uvj8r3x/9fFvX32W8hLYjk8kM7novSQzee69JDM59L0kM/l5J5JvdDI5enc6JZOn96eTydX708nk6/3pZHL2/nRMdG7oyK/f0WH14KO+vvMx2vUHnf8uYRdWD+5PktWD/4rkeX4JtPKJJKtfdycZ/GYPEknWHOBPkjUz+JNkzRf+JE0knUiy5pbfkZzY6Qa/KYVEkjTjPD/b68ex5+P9M//XGSf4fS0kkqQZ53ckZ944wW+NIZEkzTgLSJJmnAUkSTPOApImkk4kSTPOApKkGeeXJCcyTqpreHtJsmac4/iCc5zdIeOkurS3lWSqu3zLSM68cVJd8dtLkjXj+JNkzTj+JE0knUiyZhx/kqwZx58ka8b5HcmJjJPqDuJekrQ/x+n1m+T4gWQbX9/58f21R+9vJFPdWNxLkvbnOO4kaTNOPb5INnPYYKS69riXpInkzyRn/GSqS5J7SdJmHHeStBnHnSRtxnEnSftzHGeSlupe5l6StD/H+RXJnzcYluoW516Syjjn0f/8HYw3OiY6N3SURe7osOaL5x7r6zOf5X+/PbBU1z73kmTNF78iOeXlWPOFO8lUd0f3kmTNF/4kWfOFP0nWfOFP0kTSiSRrbvkdyYntQapbrHtJKuM8/0/3+pClU91u9aejLHJD56TNF7V/feZ+OGwPTtp84U6SNl/8huSMl0t1gXgvSRNJJ5K0+cKdJG2+cCdJmy/cSdJmEXeStLnlVyQntgepbn/vJamM40VSGceLpDKOF0kTSSeSyjheJJVxvEgq4zxJ/vkX4m90lFvu6CiL3NBJdUP943d+00uRAt70xvbq46svsY+37/y/0BvbUfvrtTx6ZzZLwS+H++uN7SH99cZ2ev56Y3s3f72x3Zi73uD3rH+ndyKpBb9Q7a83kb+a0pvIX03pNTK9mfzVjN7g/qp/58FxOeSF4BeW/fUG91e/0TvlN4L7K2+9wW8K++sN7q/c9Qb3V+56g/srd72WSO+E3wh+kdZfbyJ/NaU3kb+a0pvJX83ozeSvJvTGvmc6Hvb6zuNRqkNeiH11dIHe0P7qd3pn/EbsC54L9BqZ3tD+aoHe0P5qgd7Q/mqB3tD+6pd6Z/xGaH/lrzf2LcUFehP5qym9mfzVjN5M/mpGr8HorX/mwTcNOJ7pswYcH/RZQ3BvM16fYzw/iEP2jH33bYHe4N7mN3pnvGvsG2oL9Ab3Nu56g3sbd73BvY27XiPTG9wH/UrvhHeNfSdrgd5E/mpKbyJ/NaU3k7/6WW+Jfb9pgd5M/mpGL5C/Gv+eaUvsK0STGiy0hsO+Nbz9ne+//7vr56tYtb995vM43vXG9kH+emP7oF/pbf3rF+SP84fvPLGzKLEv9GxmE9tf7WUT24ttZRP7Ls5mNrE93l42sf3gXjaxfeZeNiY2H9kk8rrubOSLP7ORL/7MRr74Mxv54o9sYt9z2cxGvvgzG/niz2zkiz+zMbH5yEa++DMb+eLPbOSLP7ORL/7MRr74I5vYN0A2s5Ev/sxGvvgzG/niz2xMbD6yIfU3xV6/R1HsIxtSfzPDJnbv/EI25XWEoNT2iQ3pe2qKDel7aooN6Xtqig3p/maKDen+ZooNqb+ZuO1eYnf1b2ZDur+ZYRP7BsBmNqS+eIoNqS+eYkPqi6fYmNh8ZEPqi6fYkPriKTbyxZ/ZyBd/ZiNf/JFN7NsNv2Tzi+/c2utvf9sfd1nf/yYx9p2HzWwy+WJvNpl8sTcbE5uPbDL5Ym82mXyxN5tMvvi/YzPqJzaZfLE3m0y+2JlN8Jsby9i8dXVc5RMbUl88xYbUF0+xIfXFU2xMbD6yIfXFU2xIffEUG1JfPNO3FfymyV42pL54hk3wWylObN70UnjdN72x/et5vr54XNf4Qe/x6Pb61E8F31/d/vgXHduVrlBsdIpjO8gVimP7whWKY7u9FYpje7gVimM7swWKg99vWaE4tuNaoZjOcwW/4rJCsdEppvNcwW+5rFBM57mC33NZoZjNc9XgN11WKGbzXDX4XZcVitk8V30YnWI2z1WD341ZoZjNc9XgN15WKKbzXMHvsaxQTOe5gt9OWaGYznMFv3OyQjGd5wp+k2SFYjrPFfx+yArFdJ4r+K2PFYrpPFfwuxwrFNN5ruA3NFYopvNcwe9drFBM57mC36ZYoZjOcwW/I7FCMZ3nCn7zYYViOs8V/D7DCsV0nuui81zBL2usUEznuS46z2V0niv4pZMViuk8V/CrJCsUG51iOs8V/C7ICsV0niv4DY8Viuk8V/B7GysU03mu4LcxViim81zB71isUEznuYLfnFihmM5zBb8PsUIxnecKfsthhWI6zxX87sIKxXSeK/iNhBWK6TxX8HsGKxTTea7gtwdWKKbzXMHvBKxQTOe5gnf6r1BM57mC9++vUEznuYJ35a9QTOe5gvfar1BM57mCd9CvUEznueh66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99o+uhb3Q99I2uh77R9dC3h9EpZvNcja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32n66HvdD30na6HvtP10PeH0Slm81ydroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peuh7po7y0c7XF7c/v/Ob3kRv4ym9iZ7To/fXF4/2SW+ip/SU3kTP6Cm9iZ7QU3oTZeIZvZkaq6f0Znr/zujN9P6d0ZsoC0/pNTK9ZP4qU0v1lF5Yf/WmAdYzvWmI7YOu9vVPycbDJZkH75FeoTi2F1qhOLYbWqE4th9aodjoFMf2RCsUx3ZFKxTH9kUrFMd2USsU03mu4D3SKxTTea7gPdIrFNN5ruA90isU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3CMt0RzcJa3QHL0He4nm4E5piebgXmmJ5uDOaolmI9RM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RzOfDWvQe7CWa+XxYi96DvUQznw9rDyPUzOfDWvQe7CWa+XxYi96DvUQzoQ+L3oO9RDOhD4veg71EM6EPi96DvUQzoQ+L3oO9RDOhD4veg71EM6EPi96DvUQzoQ+L3oO9RDOhD4vej/w7zRNthC16O7K/4uidub9U/HMzTovemLtAcarn9ZTiVE/rKcVGpzhVYp5SnOt9PKM41/t4RnGqrDylOFVSnlEcvfN6gWI6zxW98/pO8ZsKYB/1psJCqzgex5eK41GOH/71lS/Npffv730e74pje6MVimN7o18qbn18fe/zh+/9+XO80Ynto3bTie25dtOJ7c820wnepb2bTmzft5tObI+4m05s77mbjonODZ1U/tedjrzyHR155Ts68sp3dOSVb+gE71PfTUde+Y6OvPIdHXnlOzomOjd05JXv6Mgr39GRV76jI698R0de+YZO8M773XTkle/oyCvf0ZFXvqNjonNDR175jo688h0deeU7OvLKd3TklW/oBL9LsJuOvPIdHXnlOzryynd0THRu6Mgr39GRV76jI698R0de+Y6OvPINneC3I3bTkVe+oyOvfEdHXvmOjonODR155Ts68sp3dOSV7+jIK9/RkVf+TKcHv++xm4688h0deeU7OvLKd3RMdG7oyCvf0ZFXvqMjr3xHR175jo688g2d4DdYdtORV76jI698R0de+Y6Oic4NHXnlOzryynd05JXv6Mgr39GRV76hE/xOzm468sp3dOSV7+jIK9/RMdG5oSOvfEdHXvmOjrzyHR155Ts68so3dILfJ9tNR175jo688h0deeU7OiY6N3Tkle/oyCvf0ZFXvqMjr3xHR175hk7wu3K76cgr39GRV76jI698R8dE54aOvPIdHXnlOzryynd05JXv6Mgr39DR3b5bOvLKd3Tkle/oyCvf0THRuaEjr3xHR175jo688h0deeUbOrzXxYq9vnOxj3Ro3+hT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FYpjO64Viuk8V/ArLisUG51iOs8V/JbLCsV0niv4PZcVitk8Vw1+02WFYjbPVYPfdVmhmM1z1YfRKWbzXDX43ZgVitk8Vw1+42WFYjrPFfweywrFdJ4r+O2UFYrpPFfwOycrFNN5ruA3SVYopvNcwe+HrFBM57mC3/pYoZjOcwW/y7FCMZ3nCn5DY4ViOs8V/N7FCsV0niv4bYoViuk8V/A7EisU03mu4DcfViim81zB7zOsUEznuS46zxX8ssYKxXSe66LzXEbnuYJfOlmhmM5zBb9KskKx0Smm81zB74KsUEznuYLf8FihmM5zBb+3sUIxnecKfhtjhWI6zxX8jsUKxXSeK/jNiRWK6TxX8PsQKxTTea7gtxxWKKbzXMHvLqxQTOe5gt9IWKGYznMFv2ewQjGd5wp+e2CFYjrPFfxOwArFdJ4reKf/CsV0nit4//4KxXSeK3hX/grFdJ4reK/9CsV0nit4B/0KxXSei66HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dA3uh76RtdD3+h66BtdD317GJ1iNs/V6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10He6HvpO10Pf6XroO10PfX8YnWI2z9Xpeug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7X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k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//SLrb7/I+tsvsv72i6y//XoYmV4uf3WR9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tRtbfbmT97UbW325k/e32MDK9XP7KyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dMvVdj3a+vrhdn/Qmeh/N6M3Uhzx6f33xaJ/0JnpeTelN9Lya0mtkehPlwSm9ifLglN5M798ZvZnevzN6E+XBGb2Z+pCn9JL5q0x9yFN6Yf3VmwZLoCG2D2rneGnoZ/sulz9GfX3q43j71LW8K47thFYoju2FViiO7YZWKI7thxYoDt5gvEJxbE+0QnFsV7RCcWxftEKx0Smm81zB24xXKKbzXMEbjVcopvNcwVuNVyim81zBm41XKKbzXMHbjVcopvNcwRuOVyim81zBW45XKGbzXCV40/EKxWyeqwRvO16hmM1zlYfRKWbzXCV46/EKxWyeqwRvPl6hmM5zBW8/XqGY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E7S/XjJ/FbwF2l8vmb8K3gDtr5fMXwVvf/bXS+avgjc/++sl81fBW5/99ZL5q+CNz/56yfxV8LZnf71k/ip407O/XjJ/Fbzl2V8vmb8K3vDsr5fMXwVvd/bXS+avgjc7++sl81fBW5399ZL5q+CNzv56yfxV8DZnf71k/ip4k7O/XjJ/FbzF2V8vmb8K3uDsr5fMXwVvb/bXS+avgjc3++sl81fBW5v99ZL5q+CNzf56yfxV8LZmf71k/ip4U7O/XjJ/Vcj8VfAebne9wXu4/fWS+atK5q+C96z76zUyvWT+KnjPur9eMn8VvGfdXy+Zvwres+6vl8xfBe9Z99dL5q+C96z76yXzV8E72f31kvkrsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//SLrb7/I+tsvsv72i6y//XoYmV4uf3WR9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tRtbfbmT97UbW325k/e32MDK9XP7KyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrb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do/Y/9g9Yv9j94j9j90j9j92j9j/2D1i/2P3iP2P3SP2P3aP2P/YPWL/Y/eI44/dI44/do84/tg94vhj94jjj90jjj92jzj+2D3i+GP3iOOP3SOOP3WPaJJfpM5be/5L+/Hbv/QPvyXXJL8aveK65k6v697pdbVOr2vp9LrWTq9r6/S69k6v6+jzuqZO7/dTp/f7qdP7/dTp/X7q9H4/dXq/nzq930+d3u+nTu/3U6f3+7nT+/3c6f1+7vR+P3d6v587vd/Pnd7v507v93On9/u50/v93On9/t7p/f7e6f3+3un9/t7p/f7e6f3+3un9/t7p/f7e6f3+3un9/t7p/b51er9vnd7vW6f3+9bp/b51er9vnd7vW6f3+9bp/b51er9vnd7vl07v90un9/ul0/v90un9fun0fr90er9fOr3fL53e75dO7/dLp/f7tdP7/drp/X7t9H6/dnq/Xzu936+d3u/XTu/3a6f3+7XT+/3a6f1+6/R+v3V6v986vd9vnd7vt07v91un9/ut0/v91un9fuv0fr91er/fO73f753e7/dO7/d7p/f7vdP7/d7p/X7v9H6/d3q/3zu93++d3u+PTu/3R6f3+6PT+/3R6f3+6PR+f3R6vz86vd8fnd7vj07v90ef9/ul09/XLp3+vnbp9Pe1S6e/r11ufd7vl05/X7t0+vvapdPf1y6d/r526fT3tUunv69dOv197dLp72uXTn9fu3T6+9ql09/XLp3+vnbp9Pe1S6e/r106/X3t0unva5dOf1+7dPr72qXT39cunf6+dun097VLp7+vXTr9fe3S6e9rl05/X7t0+vvapdPf1y6d/r526fT3tUunv69dOv197dLp72uXTn9fu3T6+9ql09/XLp3+vnbp9Pe1S6e/r106/X3tevVp0P/66p9tQL89Xz19/ed75r/fgP6j995u6+Ott+X2/eo2/5vvPN+XxzvP9+Nla/vR/u6d9+P5zvOHd/768/712q8/qDeKXn3qNor+cUU72g6HohJFO9qsh6ISRTvaSoiiEkUbihZTtKNNxygqUbSjLdEoKlG0ow3bKCpRtKPt5CgqUZTOqJai243OaCRF99tD0WN5pyidUTVF6YyqKUpnVE3RhqIDKbp9K7q+U5TOqJqidEbVFKUzqqYonVE1RemMiik60RmNpOiyPxRdt3eK0hlVU5TOqJqi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"},{"name":"lookup_validity","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"consumer","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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J0P+nq7yDtadDPl7uso7WFY/Pv7Lfy7vMuj39HUG/Z6+zqDf09cZ9Hv6OoN+T19n0O/p6wz6PX2ZQd7BupNBv6evM2zQ0/IO1p0MG/S0vIN1J8MGPS3vYN3JsEFPyztYNzLIO1h3MmzQ0/IO1p0MG/S0b9DTvkFP63tk1xm+wZBqx8eijuOXL/gfhvA+fnza++dC6mv5lnv5nnv5Jffya+7lR+7lt9zL77mXP3Ivf6Zefs3dujV369bcrVtzt+436E+PLj9369bcrVtzt27N3bo1d+tG7taN3K0buVs3crfuN1hOjy4/d+tG7taN3K0buVs3crduy926LXfrttyt23K37jfITI8uP3frttyt23K3bsvdui136/bcrdtzt27P3bo9d+t+g7P06PJzt27P3bo9d+v23K3bc7fuyN26I3frjtytO3K37jeoSY8uP3frjtytO3K37sjduiN3687crTtzt+7M3bozd+t+g4H06PJzt+7M3bozd+vO3K07U7duHKlbN47UrRtH6taNI3XrxpG6deNI3bpxpG7dOFK3bhypWzeO3K1ruVvXcreu5W5dy9263+ATPbr83K1ruVvXcreu5W5dy926nrt1PXfreu7W9dyt+w3a0KPLz926nrt1PXfreu7W9dytm9umitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVO13DZVy21Ttdw2VcttU7Ujdeu23DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2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CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wvz1gfnvA/PaA+e0B89vjqLC8rP1VwPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN/eYH57g/ntDea3N5jf3o4Ky8vaXzWY395gfnuD+e0N5rc3mN/eYH57g/ntDea3N5jf3mB+e4P57Q3mtzeY395gfnuD+e0N5rc3mN/eYH57g/ntDea3N5jf3jbz2928/Pi0h9mvPv1KvNcO607ivfZYNxJvprjfSbzXPutO4r12WncS77XXupO44hLvtd+6k3ivHdedxLg912aq+53EuD3XZrL7ncS4PddmuvudxLg912bC+53EuD3XZsr7ncS4Pddm0vudxLg912ba+53EuD3XZuL7ncS4Pddm6vudxLg912by+53EuD3XZvr7ncS4PddmAvydxLg912YK/J3EuD3XZhL8ncS4PddmGvydxLg912Yi/J3EuD3XZir8ncS4PddmMvydxLg912Y6/J3EuD3XZkL8ncS4PddmSvydxLg912ZS/J3EuD3XZlr8ncS4PddmYvydxLg912Zq/J3EuD3XZnL8ncS4PddmevydxLg912aC/J3EuD3XZor8ncS4PddmkvydxLg912aa/J3EtD1X30yUv5OYtufqm6nydxLT9lz9qLjEtD1X30yXv5OYtufqmwnzdxLj9lybKfN3EuP2XJtJ83cS4/Zcm2nzdxLj9lybifN3EuP2XJup83cS4/Zcm8nzdxLj9lyb6fN3EuP2XJsJ9HcS4/Zcmyn0dxLj9lw4h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoR84h37gHPqBc+gHzqEfR8Ulpu25Bs6hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4hz6iXPoJ86hnziHfh4Vl5i255o4h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHftIcej9oDv2ZGLbnOhPD9lxnYtie60xccYlhe64zMWzPdSaG7bnOxLA915kYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2LanstwDr3hHHrDOfSGc+jtqLjEtD2X4Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nEPvOIfecQ694xx6xzn0flRcYtqey3EOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hLziHvuAc+oJz6AvOoS9HxSWm7bkKzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77iHPqKc+grzqGvOIe+HhWXmLbnqjiHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6wDn0gXPoA+fQB86hj6PiEtP2XIFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfcM59A3n0DecQ99wDn07Ki4xbc/VcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59S+3QvzLUDTLI74t6jI8Mrb/NIL/TuZFBfu9yI4P8buRGBvn9xXUGfUX9Rgb5PcAfZ+j1bQb5Vr+RQb6nb2SQ7+nhHxlGef/zIN/TNzLI9/SNDPI9fSODfE/fyCDf09cZ9FXmEe0jwyhvM8j3w40M6nOpNq8/Pl7PXfbbDOpz6U4G9bl0J4P6XLqRQV6nvZNB6/eH16q0Jv5rVV8+w8+ljPGxLDveL6tqLis0l9U0l9U1lzU0lzUll/X1dOa9ZZnmslxzWZpTfmhO+aE55YfmlB+aU35oTvmhOeWn5pSfmlN+ak75qTnlp+aUn5pTfmpO+ak55afmlJ+SU74fklO+H5JTvh+SU74fklO+H5JTvh+SU74fklO+H5JTvh+SU74fmlPeNKe8aU5505zypjnlTXPKm+aUN80pb5pT3jSnvGlOedec8q455V1zyrvmlHfNKe+aU941p7xrTnnXnPKuOeWL5pQvmlO+aE75ojnli+aUL5pTvmhO+aI55YvmlC+aU75qTvmqOeWr5pSvmlO+ak75qjnlq+aUr5pTvmpO+ao55UNzyofmlA/NKR+aUz40p3xoTvnQnPKhOeVDc8qH5pRvmlO+aU75pjnlm+aUb5pTvmlO+aY55ZvmlG+aU75pTvmuOeW75pTvmlNe8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvg7Nu69D8+7r0Lz7OjTvvo5DcsoPzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo1775OzbuvU/Pu69S8+zoPySk/Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uv8jtuc5uVzWfV4u6zQXNY3/CTa/FyWl/F2WVNyWd9xP/HOskxzWa65rKK5rKfnVjkullXG60vX4/Oz9WNBobagpragrragobagKbagx+8e/qcXZGoLcrUFFbUFqU3qqTap59dP6qivD/d3C+pqCxpqC5pSCyrHcagtyNQWpDWpzwVpTepzQVqT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qZffjtzLt9zL99zLL7mXX3MvP3IvP3frttyt23K3bsvduj136/bcrdtzt27P3bo9d+v23K3bc7duz926PXfr9tytO3K37sjduiN3647crTtyt+7I3bojd+uO3K07crfuyN26M3frztytO3O37szdujN3687crTtzt+7M3bozd+vO1K0bR+rWjSN168aRunXjSN26caRu3ThSt24cqVs3jtStG0fq1o0jd+ta7ta13K1ruVvXcrfu1wM2zy4/d+ta7ta13K1ruVvXcreu525dz926nrt1PXfrfj1W8+zyc7eu525dz926nrt1PXfrltytW3K3bsnduiV36349TPPs8nO3bsnduiV365bcrVtyt27N3bo1d+vW3K1bc7fu14tSzy4/d+vW3K1bc7duzd26NXfrhvTcv4IQI6Tn/vXy30+eaeO1/Nl//Zdyvh7sqw+O1Qffv+fz07s77Hj3oDalcfn/Im1K43r50tV8vXzpar5evnQ1Xy9fuppjvpbRjni7fOlqvly+NqVxvXzpX4ivl6+9MbpcvnbrTvtYfnu7fO3WvVy+duteLl+7dS+Xr926l8sXb92r5Wu37oXPHdqUxvXytVv3cvnarXu5fO3WvVy+duteLl+7dS+Xr926l8vXbt3L5Wu37uXyc7euNqVxvfzcratNaVwvP3fralMa18vP3bralMb18nO3rjalcb381K3btCmN6+Wnbt2mTWlcLz9167Yjdes2bUrjevmpW7dpUxrXy0/duk2b0rhcvjalcb383K2rTWlcLz9362pTGtfLz9262pTG9fJzt+7XYw5P/p3j7esxh2eXr/1Xpl8uX/uvTL9cfs29fO2/Mv3iD4M11/4r0y+XL/RXpq8sX+ivV19Z/ky9/KLduhd/mqoV7da9XL52614uX7t1L5ev3bqXyxdv3avla7fu1a8rRbt1L5ev3bqXy9du3avlV+3WvVy+duteLl+7dS+Xr926l8vXbt3L5Wu37uXyc7duzd26NXfr1tytG7lbN3K3buRu3cjdupG7dSN360bu1o3crRu5Wzdyt27L3botd+u23K3bcrfu1+tIzy4/d+u23K3bcrduy926LXfr/sTnOZfxWr61+NXyXw+W1Qfr6oOx+mBbffD9T5Z9/Mvy6sf7B8fqg3PxwZ94GzcetNUHffXBcvmg2dsH6+qDsfrgT96ccXy8OdPf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"}],"outputs":{"globals":{"notes":[{"fields":[{"kind":"integer","sign":false,"value":"00000000000000000000000000000000000000000000000000000000aad5fd6b"},{"kind":"string","value":"PublicKeyNote"}],"kind":"tuple"}],"storage":[{"fields":[{"name":"signing_public_key","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"signing_pub_key_x","type":{"kind":"field"}},{"name":"signing_pub_key_y","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::constructor_parameters"}}],"kind":"struct","path":"SchnorrAccount::constructor_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"SchnorrAccount::entrypoint_parameters"}}],"kind":"struct","path":"SchnorrAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::verify_private_authwit_abi"}]}},"file_map":{"100":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash\n};\n\nuse dep::std::aes128::aes128_encrypt;\nuse dep::std::println;\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogOutgoingBody {\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint,\n}\n\nimpl EncryptedLogOutgoingBody {\n pub fn new(\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint\n ) -> Self {\n Self { eph_sk, recipient, recipient_ivpk_app }\n }\n\n pub fn compute_ciphertext(self, ovsk_app: GrumpkinPrivateKey, eph_pk: GrumpkinPoint) -> [u8; 176] {\n // Again, we could compute `eph_pk` here, but we keep the interface more similar\n // and also make it easier to optimise it later as we just pass it along\n\n let mut buffer: [u8; 160] = [0; 160];\n\n let serialized_eph_sk: [Field; 2] = self.eph_sk.serialize();\n let serialized_eph_sk_high = serialized_eph_sk[0].to_be_bytes(32);\n let serialized_eph_sk_low = serialized_eph_sk[1].to_be_bytes(32);\n\n let address_bytes = self.recipient.to_field().to_be_bytes(32);\n let serialized_recipient_ivpk_app = self.recipient_ivpk_app.serialize();\n let serialized_recipient_ivpk_app_x = serialized_recipient_ivpk_app[0].to_be_bytes(32);\n let serialized_recipient_ivpk_app_y = serialized_recipient_ivpk_app[1].to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = serialized_eph_sk_high[i];\n buffer[i + 32] = serialized_eph_sk_low[i];\n buffer[i + 64] = address_bytes[i];\n buffer[i + 96] = serialized_recipient_ivpk_app_x[i];\n buffer[i + 128] = serialized_recipient_ivpk_app_y[i];\n }\n\n // We compute the symmetric key using poseidon.\n let full_key: [u8; 32] = poseidon2_hash(\n [\n ovsk_app.high, ovsk_app.low, eph_pk.x, eph_pk.y,\n GENERATOR_INDEX__SYMMETRIC_KEY as Field\n ]\n ).to_be_bytes(32).as_array();\n\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(buffer, iv, sym_key).as_array()\n }\n}\n\nmod test {\n use crate::encrypted_logs::outgoing_body::EncryptedLogOutgoingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash\n };\n\n use crate::context::PrivateContext;\n\n #[test]\n fn test_encrypted_log_outgoing_body() {\n let eph_sk = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb,\n 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe\n );\n let recipient_ivsk_app = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31,\n 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022\n );\n let sender_ovsk_app = GrumpkinPrivateKey::new(\n 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b,\n 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e\n );\n\n let eph_pk = eph_sk.derive_public_key();\n let recipient_ivpk_app = recipient_ivsk_app.derive_public_key();\n\n let recipient = AztecAddress::from_field(0xdeadbeef);\n\n let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app);\n\n let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk);\n\n let expected_outgoing_body_ciphertext = [\n 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 122, 191, 158, 69, 35, 255, 215, 171, 196, 45, 91, 184, 83, 80, 238, 201, 1, 233, 235, 159, 171, 130, 158, 64, 176, 165, 132, 30, 84, 81, 71, 195, 145, 47, 82, 247, 210, 192, 23, 4, 220, 90, 56, 109, 46, 105, 79, 251, 165, 141, 185, 233, 191, 118, 219, 153, 191, 162, 99, 238, 241, 249, 9, 74, 210, 241, 54, 28, 126, 226, 85, 235, 174, 75, 239, 207, 100, 184, 248, 194\n ];\n\n for i in 0..expected_outgoing_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_outgoing_body_ciphertext[i]);\n }\n assert_eq(expected_outgoing_body_ciphertext.len(), ciphertext.len());\n }\n}\n"},"101":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nuse dep::std::aes128::aes128_encrypt;\n\nstruct EncryptedLogHeader {\n address: AztecAddress,\n}\n\nimpl EncryptedLogHeader {\n fn new(address: AztecAddress) -> Self {\n EncryptedLogHeader { address }\n }\n\n fn compute_ciphertext(self, secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 48] {\n let full_key = point_to_symmetric_key(secret, point);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n\n let input: [u8; 32] = self.address.to_field().to_be_bytes(32).as_array();\n aes128_encrypt(input, iv, sym_key).as_array()\n }\n}\n\n#[test]\nfn test_encrypted_log_header() {\n let address = AztecAddress::from_field(0xdeadbeef);\n let header = EncryptedLogHeader::new(address);\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let ciphertext = header.compute_ciphertext(secret, point);\n\n let expected_header_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 23, 131, 32, 226, 26, 176, 43, 39, 239, 177, 177, 192, 85, 216, 17, 15, 18, 187, 35, 225, 135, 192, 63, 88, 29, 173, 232, 46, 72, 82, 187, 139\n ];\n\n assert_eq(ciphertext, expected_header_ciphertext);\n}\n"},"102":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr","source":"use crate::note::note_interface::NoteInterface;\nuse crate::event::event_interface::EventInterface;\nuse dep::protocol_types::{grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse dep::std::aes128::aes128_encrypt;\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogIncomingBody {\n plaintext: [u8; M]\n}\n\nimpl EncryptedLogIncomingBody {\n pub fn from_note(note: T, storage_slot: Field) -> Self where T: NoteInterface {\n let mut plaintext = note.to_be_bytes(storage_slot);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface {\n let mut plaintext = event.private_to_be_bytes(randomness);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn compute_ciphertext(self, eph_sk: GrumpkinPrivateKey, ivpk_app: GrumpkinPoint) -> [u8] {\n let full_key = point_to_symmetric_key(eph_sk, ivpk_app);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(self.plaintext, iv, sym_key)\n }\n}\n\nmod test {\n use crate::encrypted_logs::incoming_body::EncryptedLogIncomingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, traits::Serialize,\n abis::event_selector::EventSelector\n };\n\n use crate::{\n note::{note_header::NoteHeader, note_interface::NoteInterface},\n event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand,\n context::PrivateContext\n };\n\n struct AddressNote {\n address: AztecAddress,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n }\n\n global ADDRESS_NOTE_LEN: Field = 3;\n global ADDRESS_NOTE_BYTES_LEN = 32 * 3 + 64;\n\n impl NoteInterface for AddressNote {\n fn compute_note_content_hash(self) -> Field {1}\n\n fn get_note_type_id() -> Field {\n 1\n }\n\n fn get_header(self) -> NoteHeader { self.header}\n\n fn set_header(&mut self, header: NoteHeader) {self.header = header; }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n (1, 1)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {(1,1)}\n\n fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]}\n\n fn deserialize_content(fields: [Field; ADDRESS_NOTE_LEN]) -> Self {\n AddressNote { address: AztecAddress::from_field(fields[0]), owner: AztecAddress::from_field(fields[1]), randomness: fields[2], header: NoteHeader::empty() }\n }\n\n fn to_be_bytes(self, storage_slot: Field) -> [u8; ADDRESS_NOTE_BYTES_LEN] {\n let serialized_note = self.serialize_content();\n\n let mut buffer: [u8; ADDRESS_NOTE_BYTES_LEN] = [0; ADDRESS_NOTE_BYTES_LEN];\n\n let storage_slot_bytes = storage_slot.to_be_bytes(32);\n let note_type_id_bytes = AddressNote::get_note_type_id().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = storage_slot_bytes[i];\n buffer[32 + i] = note_type_id_bytes[i];\n }\n\n for i in 0..serialized_note.len() {\n let bytes = serialized_note[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n buffer\n }\n }\n\n impl AddressNote {\n pub fn new(address: AztecAddress, owner: AztecAddress, randomness: Field) -> Self {\n AddressNote { address, owner, randomness, header: NoteHeader::empty() }\n }\n }\n\n #[test]\n fn test_encrypted_note_log_incoming_body() {\n let note = AddressNote::new(\n AztecAddress::from_field(0x1),\n AztecAddress::from_field(0x2),\n 3\n );\n\n let storage_slot = 2;\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let body = EncryptedLogIncomingBody::from_note(note, storage_slot);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_note_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100\n ];\n\n assert_eq(expected_note_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_note_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_note_body_ciphertext[i]);\n }\n }\n\n struct TestEvent {\n value0: Field,\n value1: Field,\n value2: Field,\n }\n\n impl Serialize<3> for TestEvent {\n fn serialize(self) -> [Field; 3] {\n [self.value0, self.value1, self.value2]\n }\n }\n\n global TEST_EVENT_LEN: Field = 3;\n global TEST_EVENT_BYTES_LEN = 32 * 3 + 64;\n global TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS = 32 * 3 + 32;\n\n impl EventInterface for TestEvent {\n fn get_event_type_id() -> EventSelector {\n EventSelector::from_signature(\"TestEvent(Field,Field,Field)\")\n }\n\n fn private_to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN] = [0; TEST_EVENT_BYTES_LEN];\n\n let randomness_bytes = randomness.to_be_bytes(32);\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = randomness_bytes[i];\n buffer[32 + i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn to_be_bytes(self) -> [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] = [0; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS];\n\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[32 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n }\n\n #[test]\n fn test_encrypted_log_event_incoming_body() {\n let test_event = TestEvent { value0: 1, value1: 2, value2: 3 };\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let randomness = 2;\n\n let body = EncryptedLogIncomingBody::from_event(test_event, randomness);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_event_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160\n ];\n\n assert_eq(expected_event_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_event_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_event_body_ciphertext[i]);\n }\n }\n}\n"},"107":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/utils.nr","source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n constants::GENERATOR_INDEX__INNER_NOTE_HASH,\n hash::{\n pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash,\n compute_siloed_nullifier as compute_siloed_nullifier_from_preimage\n},\n utils::arr_copy_slice\n};\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n pedersen_hash(\n [header.storage_slot, note_hash],\n GENERATOR_INDEX__INNER_NOTE_HASH\n )\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let (_, inner_nullifier) = note_with_header.compute_note_hash_and_nullifier(context);\n\n compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier)\n}\n\nfn compute_note_hash_for_read_request_from_innter_and_nonce(\n inner_note_hash: Field,\n nonce: Field\n) -> Field {\n // TODO(#1386): This if-else can be nuked once we have nonces injected from public\n if (nonce == 0) {\n // If nonce is zero, that means we are reading a public note.\n inner_note_hash\n } else {\n compute_unique_note_hash(nonce, inner_note_hash)\n }\n}\n\npub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface {\n let inner_note_hash = compute_inner_note_hash(note);\n let nonce = note.get_header().nonce;\n\n compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n if (header.note_hash_counter != 0) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n inner_note_hash\n } else {\n // If a note is not transient, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the siloed_note_hash which has already been hashed with\n // nonce and then contract address. This hash will match the existing leaf in the note hash\n // tree, so the kernel can just perform a membership check directly on this hash/leaf.\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce);\n compute_siloed_note_hash(header.contract_address, unique_note_hash)\n // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is\n // \"siloed\" by contract address. When a note hash is computed solely for the purpose of\n // nullification, it is not strictly necessary to silo the note hash before computing\n // its nullifier. In other words, it is NOT NECESSARY for protocol security that a nullifier\n // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are\n // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be\n // used for nullifier computation, and this achieves the (arguably unnecessary) property that\n // nullifiers are computed from a note hash's fully-computed note hash tree leaf.\n }\n}\n\npub fn compute_note_hash_and_optionally_a_nullifier(\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n compute_nullifier: bool,\n serialized_note: [Field; S]\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n note.set_header(note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, note_header.nonce);\n let siloed_note_hash = compute_siloed_note_hash(note_header.contract_address, unique_note_hash);\n\n let inner_nullifier = if compute_nullifier {\n let (_, nullifier) = note.compute_note_hash_and_nullifier_without_context();\n nullifier\n } else {\n 0\n };\n // docs:start:compute_note_hash_and_optionally_a_nullifier_returns\n [inner_note_hash, unique_note_hash, siloed_note_hash, inner_nullifier]\n // docs:end:compute_note_hash_and_optionally_a_nullifier_returns\n}\n"},"108":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr","source":"use dep::protocol_types::grumpkin_point::GrumpkinPoint;\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note\n) -> NoteEmission where Note: NoteInterface {\n let contract_address = (*context).this_address();\n let note_hash_counter = context.side_effect_counter;\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n let serialized_note = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash,\n note_hash_counter\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n NoteEmission::new(*note)\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(\n context: &mut PrivateContext,\n note: Note\n) where Note: NoteInterface {\n let (note_hash, nullifier) = note.compute_note_hash_and_nullifier(context);\n\n let note_hash_counter = note.get_header().note_hash_counter;\n let note_hash_for_consumption = if (note_hash_counter == 0) {\n // Counter is zero, so we're nullifying a non-transient note and we don't populate the note_hash with real\n // value (if we did so the `notifyNullifiedNote` oracle would throw).\n 0\n } else {\n // A non-zero note hash counter implies that we're nullifying a transient note (i.e. one that has not yet been\n // persisted in the trees and is instead in the pending new note hashes array). In such a case we populate its\n // hash with real value to inform the kernel which note we're nullifyng so that it can find it and squash both\n // the note and the nullifier.\n note_hash\n };\n\n let nullifier_counter = context.side_effect_counter;\n assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0);\n\n context.push_new_nullifier(nullifier, note_hash_for_consumption)\n}\n"},"109":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_emission.nr","source":"/**\n * A note emission struct containing the information required for emitting a note.\n * The exact `emit` logic is passed in by the application code\n */\nstruct NoteEmission {\n note: Note\n}\n\nimpl NoteEmission {\n pub fn new(note: Note) -> Self {\n Self { note }\n }\n\n pub fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n\n pub fn discard(self) {}\n}\n\n/**\n * A struct wrapping note emission in `Option`.\n * This is the struct provided to application codes, which can be used to emit\n * only when a note was actually inserted.\n * It is fairly common to have cases where a function conditionally inserts,\n * and this allows us to keep the same API for emission in both cases (e.g. inserting \n * a change note in a token's transfer function only when there is \"change\" left).\n */\nstruct OuterNoteEmission {\n emission: Option>,\n}\n\nimpl OuterNoteEmission {\n pub fn new(emission: Option>) -> Self {\n Self { emission }\n }\n\n pub fn emit(self, _emit: fn[Env](NoteEmission) -> ()) {\n if self.emission.is_some() {\n _emit(self.emission.unwrap());\n }\n }\n\n pub fn discard(self) {}\n}\n"},"111":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr","source":"use dep::std::option::Option;\nuse crate::note::note_getter_options::{PropertySelector, Select, Sort, Comparator, NoteStatus};\nuse dep::protocol_types::traits::ToField;\nuse crate::note::note_interface::NoteInterface;\nuse crate::note::constants::MAX_NOTES_PER_PAGE;\n\n// docs:start:NoteViewerOptions\nstruct NoteViewerOptions {\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>,\n limit: u32,\n offset: u32,\n status: u8,\n}\n// docs:end:NoteViewerOptions\n\nimpl NoteViewerOptions {\n pub fn new() -> NoteViewerOptions where Note: NoteInterface {\n NoteViewerOptions {\n selects: BoundedVec::new(),\n sorts: BoundedVec::new(),\n limit: MAX_NOTES_PER_PAGE as u32,\n offset: 0,\n status: NoteStatus.ACTIVE\n }\n }\n\n // This method adds a `Select` criterion to the options.\n // It takes a field_index indicating which field to select,\n // a value representing the specific value to match in that field, and\n // a comparator (For possible values of comparators, please see the Comparator enum from note_getter_options)\n pub fn select(\n &mut self,\n property_selector: PropertySelector,\n value: T,\n comparator: Option\n ) -> Self where T: ToField {\n self.selects.push(\n Option::some(\n Select::new(\n property_selector,\n value.to_field(),\n comparator.unwrap_or(Comparator.EQ)\n )\n )\n );\n *self\n }\n\n pub fn sort(&mut self, property_selector: PropertySelector, order: u8) -> Self {\n self.sorts.push(Option::some(Sort::new(property_selector, order)));\n *self\n }\n\n pub fn set_limit(&mut self, limit: u32) -> Self {\n assert(limit <= MAX_NOTES_PER_PAGE as u32);\n // By requesting that the limit is a constant, we guarantee that it will be possible to loop over it, reducing\n // gate counts when a limit has been set. This isn't required in unconstrained code, but we still keep this\n // requirement here for API consistency.\n assert_constant(limit);\n self.limit = limit;\n *self\n }\n\n pub fn set_offset(&mut self, offset: u32) -> Self {\n self.offset = offset;\n *self\n }\n\n // This method sets the status value, which determines whether to retrieve active or nullified notes.\n pub fn set_status(&mut self, status: u8) -> Self {\n self.status = status;\n *self\n }\n}\n"},"112":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_getter.nr","source":"use dep::protocol_types::{constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTES_ORACLE_RETURN_LENGTH}};\nuse crate::context::PrivateContext;\nuse crate::note::{\n constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH},\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_request\n};\nuse crate::oracle;\n\nmod test;\n\nfn extract_property_value_from_selector(\n serialized_note: [Field; N],\n selector: PropertySelector\n) -> Field {\n // Selectors use PropertySelectors in order to locate note properties inside the serialized note. \n // This allows easier packing and custom (de)serialization schemas. A note property is located\n // inside the serialized note using the index inside the array, a byte offset and a length.\n let value = serialized_note[selector.index].to_be_bytes(32);\n let offset = selector.offset;\n let length = selector.length;\n let mut value_field = 0 as Field;\n let mut acc: Field = 1;\n for i in 0..32 {\n if i < length {\n value_field += value[31 + offset - i] as Field * acc;\n acc = acc * 256;\n }\n }\n value_field\n}\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note: Note\n) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address), \"Mismatch note header contract address.\");\n assert(header.storage_slot == storage_slot, \"Mismatch note header storage slot.\");\n}\n\nfn check_note_fields(serialized_note: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n let value_field = extract_property_value_from_selector(serialized_note, select.property_selector);\n\n // Values are computed ahead of time because circuits evaluate all branches\n let is_equal = value_field == select.value.to_field();\n let is_lt = value_field.lt(select.value.to_field());\n\n if (select.comparator == Comparator.EQ) {\n assert(is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(is_lt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(is_lt | is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!is_lt & !is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!is_lt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let field_0 = extract_property_value_from_selector(fields_0, sort.property_selector);\n let field_1 = extract_property_value_from_selector(fields_1, sort.property_selector);\n let eq = field_0 == field_1;\n let lt = field_0.lt(field_1);\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n\n context.push_note_hash_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n\n constrain_get_notes_internal(context, storage_slot, opt_notes, options)\n}\n\nfn constrain_get_notes_internal(\n context: &mut PrivateContext,\n storage_slot: Field,\n opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let mut returned_notes = BoundedVec::new();\n\n // The filter is applied first to avoid pushing note read requests for notes we're not interested in. Note that\n // while the filter function can technically mutate the contents of the notes (as opposed to simply removing some),\n // the private kernel will later validate that these note actually exist, so transformations would cause for that\n // check to fail.\n let filter_fn = options.filter;\n let filter_args = options.filter_args;\n let filtered_notes = filter_fn(opt_notes, filter_args);\n\n let mut prev_fields = [0; N];\n for i in 0..filtered_notes.len() {\n let opt_note = filtered_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_note_hash_read_request(note_hash_for_read_request);\n\n // The below code is used to collapse a sparse array into one where the values are guaranteed to be at the \n // front of the array. This is highly useful because the caller knows that the returned array won't have\n // more than option.limits notes, and can therefore loop over this limit value instead of the entire array,\n // resulting in a smaller circuit and faster proving times.\n // We write at returned_notes[num_notes] because num_notes is only advanced when we have a value in \n // filtered_notes.\n returned_notes.push(note);\n };\n }\n\n assert(returned_notes.len() <= options.limit, \"Got more notes than limit.\");\n assert(returned_notes.len() != 0, \"Cannot return zero notes\");\n\n returned_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n // This function simply performs some transformations from NoteGetterOptions into the types required by the oracle.\n\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> BoundedVec where Note: NoteInterface {\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n let notes_array = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let mut notes = BoundedVec::new();\n for i in 0..notes_array.len() {\n if notes_array[i].is_some() {\n notes.push(notes_array[i].unwrap_unchecked());\n }\n }\n\n notes\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [u8; N], [u8; N], [Field; N], [u8; N], [u8; N], [u8; N], [u8; N], [u8; N]) {\n let mut num_selects = 0;\n let mut select_by_indexes = [0; N];\n let mut select_by_offsets = [0; N];\n let mut select_by_lengths = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by_indexes[num_selects] = select.unwrap_unchecked().property_selector.index;\n select_by_offsets[num_selects] = select.unwrap_unchecked().property_selector.offset;\n select_by_lengths[num_selects] = select.unwrap_unchecked().property_selector.length;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by_indexes = [0; N];\n let mut sort_by_offsets = [0; N];\n let mut sort_by_lengths = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by_indexes[i] = sort.unwrap_unchecked().property_selector.index;\n sort_by_offsets[i] = sort.unwrap_unchecked().property_selector.offset;\n sort_by_lengths[i] = sort.unwrap_unchecked().property_selector.length;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (\n num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order\n )\n}\n"},"113":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_header.nr","source":"use dep::protocol_types::address::AztecAddress;\nuse dep::protocol_types::traits::{Empty, Eq, Serialize};\n\nstruct NoteHeader {\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)\n // Check the nonce to see whether a note is transient or not.\n note_hash_counter: u32, // a note_hash_counter of 0 means non-transient\n}\n\nimpl Empty for NoteHeader {\n fn empty() -> Self {\n NoteHeader { contract_address: AztecAddress::zero(), nonce: 0, storage_slot: 0, note_hash_counter: 0 }\n }\n}\n\nimpl Eq for NoteHeader {\n fn eq(self, other: Self) -> bool {\n (self.contract_address == other.contract_address) & \n (self.nonce == other.nonce) & \n (self.storage_slot == other.storage_slot)& \n (self.note_hash_counter == other.note_hash_counter)\n }\n}\n\nimpl NoteHeader {\n pub fn new(contract_address: AztecAddress, nonce: Field, storage_slot: Field) -> Self {\n NoteHeader { contract_address, nonce, storage_slot, note_hash_counter: 0 }\n }\n}\n\nimpl Serialize<4> for NoteHeader {\n fn serialize(self) -> [Field; 4] {\n [self.contract_address.to_field(), self.nonce, self.storage_slot, self.note_hash_counter as Field]\n }\n}\n"},"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"118":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/initializer.nr","source":"use dep::protocol_types::{\n address::AztecAddress, hash::{compute_siloed_nullifier, pedersen_hash},\n constants::GENERATOR_INDEX__CONSTRUCTOR, abis::function_selector::FunctionSelector\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext}, oracle::get_contract_instance::get_contract_instance,\n oracle::get_contract_instance::get_contract_instance_avm\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn assert_is_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_contract_initialization_nullifier(context.this_address());\n let header = context.get_header();\n header.prove_nullifier_inclusion(init_nullifier);\n}\n\nfn compute_contract_initialization_nullifier(address: AztecAddress) -> Field {\n compute_siloed_nullifier(\n address,\n compute_unsiloed_contract_initialization_nullifier(address)\n )\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let instance = get_contract_instance_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn compute_initialization_hash(init_selector: FunctionSelector, init_args_hash: Field) -> Field {\n pedersen_hash(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n"},"120":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr","source":"use dep::protocol_types::{\n abis::nullifier_leaf_preimage::{NullifierLeafPreimage, NULLIFIER_LEAF_PREIMAGE_LENGTH},\n constants::NULLIFIER_TREE_HEIGHT, hash::pedersen_hash, utils::arr_copy_slice\n};\n\n// INDEX_LENGTH + NULLIFIER_LEAF_PREIMAGE_LENGTH + NULLIFIER_TREE_HEIGHT\nglobal NULLIFIER_MEMBERSHIP_WITNESS: Field = 24;\n\nstruct NullifierMembershipWitness {\n index: Field,\n leaf_preimage: NullifierLeafPreimage,\n path: [Field; NULLIFIER_TREE_HEIGHT],\n}\n\nimpl NullifierMembershipWitness {\n pub fn deserialize(fields: [Field; NULLIFIER_MEMBERSHIP_WITNESS]) -> Self {\n let leaf_preimage_fields = arr_copy_slice(fields, [0; NULLIFIER_LEAF_PREIMAGE_LENGTH], 1);\n Self {\n index: fields[0],\n leaf_preimage: NullifierLeafPreimage::deserialize(leaf_preimage_fields),\n path: arr_copy_slice(\n fields,\n [0; NULLIFIER_TREE_HEIGHT],\n 1 + NULLIFIER_LEAF_PREIMAGE_LENGTH\n )\n }\n }\n}\n\n#[oracle(getLowNullifierMembershipWitness)]\nunconstrained fn get_low_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_low_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n\n#[oracle(getNullifierMembershipWitness)]\nunconstrained fn get_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"126":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr","source":"use dep::protocol_types::{\n grumpkin_point::GrumpkinPoint,\n abis::validation_requests::{KeyValidationRequest, key_validation_request::KEY_VALIDATION_REQUEST_LENGTH}\n};\n\n#[oracle(getKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field\n) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {}\n\nunconstrained fn get_key_validation_request_internal(npk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n let result = get_key_validation_request_oracle(npk_m_hash, key_index);\n KeyValidationRequest::deserialize(result)\n}\n\npub fn get_key_validation_request(pk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n get_key_validation_request_internal(pk_m_hash, key_index)\n}\n\n"},"130":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/unsafe_rand.nr","source":"#[oracle(getRandomField)]\nunconstrained fn rand_oracle() -> Field {}\n\n// Called `unsafe_rand` because we do not constrain in circuit that we are dealing with an actual random value.\n// Instead we just trust our PXE.\nunconstrained pub fn unsafe_rand() -> Field {\n rand_oracle()\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"133":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/keys.nr","source":"use crate::keys::PublicKeys;\nuse dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {}\n\nunconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] {\n get_public_keys_and_partial_address_oracle(address)\n}\n\nfn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle_wrapper(address);\n\n let keys = PublicKeys {\n npk_m: GrumpkinPoint::new(result[0], result[1]),\n ivpk_m: GrumpkinPoint::new(result[2], result[3]),\n ovpk_m: GrumpkinPoint::new(result[4], result[5]),\n tpk_m: GrumpkinPoint::new(result[6], result[7])\n };\n\n let partial_address = PartialAddress::from_field(result[8]);\n\n (keys, partial_address)\n}\n"},"135":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/notes.nr","source":"use crate::note::{note_header::NoteHeader, note_interface::NoteInterface};\n\nuse dep::protocol_types::{address::AztecAddress, utils::arr_copy_slice};\n\n#[oracle(notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field,\n _counter: u32\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_created_note_oracle(\n storage_slot,\n note_type_id,\n serialized_note,\n inner_note_hash,\n counter\n )\n}\n\n#[oracle(notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field, _counter: u32) -> Field {}\n\nunconstrained pub fn notify_nullified_note(\n nullifier: Field,\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash, counter)\n}\n\n#[oracle(getNotes)]\nunconstrained fn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by_indexes: [u8; N],\n _select_by_offsets: [u8; N],\n _select_by_lengths: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u8; N],\n _sort_by_indexes: [u8; N],\n _sort_by_offsets: [u8; N],\n _sort_by_lengths: [u8; N],\n _sort_order: [u8; N],\n _limit: u32,\n _offset: u32,\n _status: u8,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; N],\n select_by_offsets: [u8; N],\n select_by_lengths: [u8; N],\n select_values: [Field; N],\n select_comparators: [u8; N],\n sort_by_indexes: [u8; N],\n sort_by_offsets: [u8; N],\n sort_by_lengths: [u8; N],\n sort_order: [u8; N],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; M],\n select_by_offsets: [u8; M],\n select_by_lengths: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by_indexes: [u8; M],\n sort_by_offsets: [u8; M],\n sort_by_lengths: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i < num_notes {\n // lengths named as per typescript.\n let return_header_length: u32 = 2; // num_notes & contract_address.\n let extra_preimage_length: u32 = 2; // nonce & note_hash_counter.\n let read_offset: u32 = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let note_hash_counter = fields[read_offset + 1] as u32;\n let header = NoteHeader { contract_address, nonce, storage_slot, note_hash_counter };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n note.set_header(header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n// Only ever use this in private!\n#[oracle(checkNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\n// Only ever use this in private!\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"154":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header};\n\nuse crate::context::PrivateContext;\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange}\n};\n\nstruct SharedMutablePrivateGetter {\n context: &mut PrivateContext,\n // The contract address of the contract we want to read from\n other_contract_address: AztecAddress,\n // The storage slot where the SharedMutable is stored on the other contract\n storage_slot: Field,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numberic value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\n// We have this as a view-only interface to reading Shared Mutables in other contracts.\n// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date\nimpl SharedMutablePrivateGetter {\n pub fn new(\n context: &mut PrivateContext,\n other_contract_address: AztecAddress,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n assert(other_contract_address.to_field() != 0, \"Other contract address cannot be 0\");\n Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] }\n }\n\n pub fn get_value_in_private(self, header: Header) -> T where T: FromField {\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header);\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // If our context has the same header as the one we pass in via the parameter, we are trying to read the \"current\" value\n // and thus need to set the tx max block number below. If the context header is not the same as the one we pass in, this means\n // we are trying to read a historical value and thus have no constraint on the max block number that this transaction can be included in.\n if (self.context.historical_header.global_variables.block_number.eq(header.global_variables.block_number)) {\n self.context.set_tx_max_block_number(block_horizon);\n }\n\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n header: Header\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n self.other_contract_address\n );\n }\n\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"159":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash\n};\n\nuse crate::context::{PrivateContext, UnconstrainedContext};\nuse crate::note::{\n lifecycle::create_note, note_getter::{get_note, view_notes}, note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions, note_emission::NoteEmission\n};\nuse crate::oracle::notes::check_nullifier_exists;\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct PrivateImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:struct\n\nimpl Storage for PrivateImmutable {}\n\nimpl PrivateImmutable {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. \n // e.g. the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n}\n\nimpl PrivateImmutable {\n // docs:start:initialize\n pub fn initialize(\n self,\n note: &mut Note\n ) -> NoteEmission where Note: NoteInterface {\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_new_nullifier(nullifier, 0);\n\n create_note(self.context, self.storage_slot, note)\n }\n // docs:end:initialize\n\n // docs:start:get_note\n pub fn get_note(self) -> Note where Note: NoteInterface {\n let storage_slot = self.storage_slot;\n get_note(self.context, storage_slot)\n }\n // docs:end:get_note\n}\n\nimpl PrivateImmutable {\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // view_note does not actually use the context, but it calls oracles that are only available in private\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let mut options = NoteViewerOptions::new();\n view_notes(self.storage_slot, options.set_limit(1)).get(0)\n }\n // docs:end:view_note\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"187":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr","source":"global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3;\n\nuse crate::{\n abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::compute_siloed_nullifier,\n merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash}\n};\n\nstruct NullifierLeafPreimage {\n nullifier : Field,\n next_nullifier :Field,\n next_index : u32,\n}\n\nimpl Empty for NullifierLeafPreimage {\n fn empty() -> Self {\n Self {\n nullifier : 0,\n next_nullifier : 0,\n next_index : 0,\n }\n }\n}\n\nimpl Hash for NullifierLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash(self.serialize())\n }\n }\n}\n\nimpl LeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl IndexedTreeLeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn get_next_key(self) -> Field {\n self.next_nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl Readable for NullifierLeafPreimage {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n let siloed_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.nullifier, siloed_value, \"Value of the nullifier leaf does not match read request\");\n }\n}\n\nimpl NullifierLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.nullifier == 0) & (self.next_nullifier == 0) & (self.next_index == 0)\n }\n\n pub fn serialize(self) -> [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH] {\n [self.nullifier, self.next_nullifier, self.next_index as Field]\n }\n\n pub fn deserialize(fields: [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH]) -> Self {\n Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u32 }\n }\n}\n\nimpl Eq for NullifierLeafPreimage {\n fn eq(self, other: Self) -> bool {\n (self.nullifier == other.nullifier) &\n (self.next_nullifier == other.next_nullifier) &\n (self.next_index == other.next_index)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NullifierLeafPreimage::empty();\n let serialized = item.serialize();\n let deserialized = NullifierLeafPreimage::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"20":{"path":"std/embedded_curve_ops.nr","source":"use crate::ops::arith::{Add, Sub, Neg};\nuse crate::cmp::Eq;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct EmbeddedCurvePoint {\n x: Field,\n y: Field,\n is_infinite: bool\n}\n\nimpl EmbeddedCurvePoint {\n fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n fn neg(self) -> EmbeddedCurvePoint { \n EmbeddedCurvePoint {\n x: self.x,\n y: -self.y,\n is_infinite: self.is_infinite\n }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\n// Scalar represented as low and high limbs\nstruct EmbeddedCurveScalar {\n lo: Field,\n hi: Field,\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the \n// underlying proof system.\n#[foreign(multi_scalar_mul)]\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N]\n) -> [Field; 3]\n// docs:end:multi_scalar_mul\n{}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(\n scalar_low: Field,\n scalar_high: Field\n) -> [Field; 3]\n// docs:end:fixed_base_scalar_mul\n{\n let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false };\n let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high };\n multi_scalar_mul([g1], [scalar])\n}\n\n// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray\n// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format.\n// docs:start:embedded_curve_add\nfn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint\n) -> EmbeddedCurvePoint\n// docs:end:embedded_curve_add\n{\n let point_array = embedded_curve_add_array_return(point1, point2);\n let x = point_array[0];\n let y = point_array[1];\n EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"220":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr","source":"use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash};\nuse dep::std::cmp::Eq;\n\nglobal GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct GrumpkinPoint {\n x: Field,\n y: Field,\n}\n\nimpl Serialize for GrumpkinPoint {\n fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] {\n [self.x, self.y]\n }\n}\n\nimpl Deserialize for GrumpkinPoint {\n fn deserialize(serialized: [Field; GRUMPKIN_POINT_SERIALIZED_LEN]) -> Self {\n Self {\n x: serialized[0],\n y: serialized[1],\n }\n }\n}\n\nimpl Eq for GrumpkinPoint {\n fn eq(self, point: GrumpkinPoint) -> bool {\n (point.x == self.x) & (point.y == self.y)\n }\n}\n\nimpl Hash for GrumpkinPoint {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl GrumpkinPoint {\n pub fn new(x: Field, y: Field) -> Self {\n Self { x, y }\n }\n\n pub fn zero() -> Self {\n Self { x: 0, y: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.x == 0) & (self.y == 0)\n }\n\n // TODO(David): Would be quite careful here as (0,0) is not a point\n // on the curve. A boolean flag may be the better approach here,\n // would also cost less constraints. It seems like we don't need to \n // group arithmetic either. \n fn assert_is_zero(self) {\n assert(self.x == 0);\n assert(self.y == 0);\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 64] {\n let mut result = [0 as u8; 64];\n let x_bytes = self.x.to_be_bytes(32);\n let y_bytes = self.y.to_be_bytes(32);\n for i in 0..32 {\n result[i] = x_bytes[i];\n result[i + 32] = y_bytes[i];\n }\n result\n }\n}\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"225":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr","source":"use dep::std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul};\nuse crate::{grumpkin_point::GrumpkinPoint, traits::Empty};\n\nglobal GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN: Field = 2;\n\nstruct GrumpkinPrivateKey {\n high: Field,\n low: Field,\n}\n\nimpl Eq for GrumpkinPrivateKey {\n fn eq(self, key: GrumpkinPrivateKey) -> bool {\n (key.high == self.high) & (key.low == self.low)\n }\n}\n\nimpl Empty for GrumpkinPrivateKey {\n fn empty() -> Self {\n Self { high: 0, low: 0 }\n }\n}\n\nimpl GrumpkinPrivateKey {\n pub fn new(high: Field, low: Field) -> Self {\n GrumpkinPrivateKey { high, low }\n }\n\n pub fn zero() -> Self {\n Self { high: 0, low: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.high == 0) & (self.low == 0)\n }\n\n pub fn serialize(self) -> [Field; GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN] {\n [self.high, self.low]\n }\n\n pub fn derive_public_key(self) -> GrumpkinPoint {\n let public_key = fixed_base_scalar_mul(self.low, self.high);\n GrumpkinPoint { x: public_key[0], y: public_key[1] }\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"35":{"path":"std/option.nr","source":"use crate::hash::{Hash, Hasher};\nuse crate::cmp::{Ordering, Ord, Eq};\nuse crate::default::Default;\n\nstruct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some { self._value } else { default }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some { self } else { other }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some { self } else { default() }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some { Option::none() } else { self }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option where T: Eq {\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option where T: Ord {\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else {\n if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n"},"365":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr","source":"mod public_key_note;\n\n// Account contract that uses Schnorr signatures for authentication.\n// The signing key is stored in an immutable private note and should be different from the encryption/nullifying key.\ncontract SchnorrAccount {\n use dep::std;\n\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable};\n use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;\n use dep::authwit::{\n entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions,\n auth_witness::get_auth_witness, auth::{compute_authwit_nullifier, compute_outer_authwit_hash}\n };\n use dep::aztec::hash::compute_siloed_nullifier;\n use dep::aztec::oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness;\n\n use crate::public_key_note::{PublicKeyNote, PUBLIC_KEY_NOTE_LEN};\n\n #[aztec(storage)]\n struct Storage {\n // docs:start:storage\n signing_public_key: PrivateImmutable,\n // docs:end:storage\n }\n\n // Constructs the contract\n #[aztec(private)]\n #[aztec(initializer)]\n fn constructor(signing_pub_key_x: Field, signing_pub_key_y: Field) {\n let this = context.this_address();\n let header = context.get_header();\n let this_npk_m_hash = header.get_npk_m_hash(&mut context, this);\n // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we\n // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that\n // important.\n\n // docs:start:initialize\n let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash);\n storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this));\n // docs:end:initialize\n }\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts file\n #[aztec(private)]\n #[aztec(noinitcheck)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(noinitcheck)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n // docs:start:entrypoint\n // Load public key from storage\n let storage = Storage::init(context);\n // docs:start:get_note\n let public_key = storage.signing_public_key.get_note();\n // docs:end:get_note\n // Load auth witness\n let witness: [Field; 64] = get_auth_witness(outer_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n\n // Verify signature of the payload bytes\n let verification = std::schnorr::verify_signature_slice(\n public_key.x,\n public_key.y,\n signature,\n outer_hash.to_be_bytes(32)\n );\n assert(verification == true);\n // docs:end:entrypoint\n true\n }\n\n /**\n * @notice Helper function to check validity of private authwitnesses\n * @param consumer The address of the consumer of the message\n * @param message_hash The message hash of the message to check the validity\n * @return True if the message_hash can be consumed, false otherwise\n */\n unconstrained fn lookup_validity(consumer: AztecAddress, inner_hash: Field) -> pub bool {\n let public_key = storage.signing_public_key.view_note();\n\n let message_hash = compute_outer_authwit_hash(consumer, context.chain_id(), context.version(), inner_hash);\n\n let witness: [Field; 64] = get_auth_witness(message_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n let valid_in_private = std::schnorr::verify_signature_slice(\n public_key.x,\n public_key.y,\n signature,\n message_hash.to_be_bytes(32)\n );\n\n // Compute the nullifier and check if it is spent\n // This will BLINDLY TRUST the oracle, but the oracle is us, and\n // it is not as part of execution of the contract, so we are good.\n let nullifier = compute_authwit_nullifier(context.this_address(), inner_hash);\n let siloed_nullifier = compute_siloed_nullifier(consumer, nullifier);\n let lower_wit = get_low_nullifier_membership_witness(context.block_number(), siloed_nullifier);\n let is_spent = lower_wit.leaf_preimage.nullifier == siloed_nullifier;\n\n !is_spent & valid_in_private\n }\n}\n"},"366":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr","source":"use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext};\nuse dep::aztec::{\n note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app,\n protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}\n};\n\nglobal PUBLIC_KEY_NOTE_LEN: Field = 3;\n// PUBLIC_KEY_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)\nglobal PUBLIC_KEY_NOTE_BYTES_LEN: Field = 3 * 32 + 64;\n\n// Stores a public key composed of two fields\n// TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value?\n#[aztec(note)]\nstruct PublicKeyNote {\n x: Field,\n y: Field,\n // We store the npk_m_hash only to get the secret key to compute the nullifier\n npk_m_hash: Field,\n}\n\nimpl NoteInterface for PublicKeyNote {\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n}\n\nimpl PublicKeyNote {\n pub fn new(x: Field, y: Field, npk_m_hash: Field) -> Self {\n PublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() }\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"62":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_private_key::GrumpkinPrivateKey,\n grumpkin_point::GrumpkinPoint, utils::arr_copy_slice\n};\nuse dep::std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}};\n\n// TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since\n// point is not the only input of the function. Unify naming with TS once we have a better name.\npub fn point_to_symmetric_key(secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 32] {\n let shared_secret_fields = multi_scalar_mul(\n [EmbeddedCurvePoint { x: point.x, y: point.y, is_infinite: false }],\n [EmbeddedCurveScalar { lo: secret.low, hi: secret.high }]\n );\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly\n let shared_secret = GrumpkinPoint::new(shared_secret_fields[0], shared_secret_fields[1]);\n let mut shared_secret_bytes_with_separator = [0 as u8; 65];\n shared_secret_bytes_with_separator = arr_copy_slice(shared_secret.to_be_bytes(), shared_secret_bytes_with_separator, 0);\n shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY;\n sha256(shared_secret_bytes_with_separator)\n}\n\n#[test]\nfn check_point_to_symmetric_key() {\n // Value taken from \"derive shared secret\" test in encrypt_buffer.test.ts\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let key = point_to_symmetric_key(secret, point);\n // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1\n let expected_key = [\n 49, 167, 146, 222, 151, 129, 138, 184, 87, 210, 245, 249, 99, 100, 1, 59, 223, 180, 5, 99, 14, 7, 177, 236, 159, 203, 231, 72, 220, 180, 241, 23\n ];\n assert_eq(key, expected_key);\n}\n"},"63":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/getters.nr","source":"use dep::protocol_types::{\n header::Header, abis::validation_requests::KeyValidationRequest, address::AztecAddress,\n constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint,\n storage::map::derive_storage_slot_in_map\n};\nuse crate::{\n context::PrivateContext,\n oracle::{keys::get_public_keys_and_partial_address, key_validation_request::get_key_validation_request},\n keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}},\n state_vars::{shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter}\n};\n\nglobal DELAY = 5;\n\n// docs:start:key-getters\ntrait KeyGetters {\n fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;\n}\n\nimpl KeyGetters for Header {\n fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, NULLIFIER_INDEX, self)\n }\n\n fn get_ivpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, INCOMING_INDEX, self)\n }\n\n fn get_ovpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, OUTGOING_INDEX, self)\n }\n\n fn get_tpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, TAGGING_INDEX, self)\n }\n\n fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {\n get_master_key(context, address, NULLIFIER_INDEX, self).hash()\n }\n}\n// docs:end:key-getters\n\nfn get_master_key(\n context: &mut PrivateContext,\n address: AztecAddress,\n key_index: Field,\n header: Header\n) -> GrumpkinPoint {\n let key = fetch_key_from_registry(context, key_index, address, header);\n if key.is_zero() {\n // Keys were not registered in registry yet --> fetch key from PXE\n let keys = fetch_and_constrain_keys(address);\n // Return the corresponding to index\n keys.get_key_by_index(key_index)\n } else {\n // Keys were registered --> return the key\n key\n }\n}\n\nfn fetch_key_from_registry(\n context: &mut PrivateContext,\n key_index: Field,\n address: AztecAddress,\n header: Header\n) -> GrumpkinPoint {\n let x_coordinate_map_slot = key_index * 2 + 1;\n let y_coordinate_map_slot = x_coordinate_map_slot + 1;\n let x_coordinate_derived_slot = derive_storage_slot_in_map(x_coordinate_map_slot, address);\n let y_coordinate_derived_slot = derive_storage_slot_in_map(y_coordinate_map_slot, address);\n\n let x_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n x_coordinate_derived_slot\n );\n let y_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n y_coordinate_derived_slot\n );\n let x_coordinate = x_coordinate_registry.get_value_in_private(header);\n let y_coordinate = y_coordinate_registry.get_value_in_private(header);\n\n GrumpkinPoint::new(x_coordinate, y_coordinate)\n}\n\n// Passes only when keys were not rotated - is expected to be called only when keys were not registered yet\nfn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys {\n let (public_keys, partial_address) = get_public_keys_and_partial_address(address);\n\n let computed_address = AztecAddress::compute(public_keys.hash(), partial_address);\n\n assert(computed_address.eq(address));\n\n public_keys\n}\n\n// A helper function since requesting nsk_app is very common\n// TODO(#6543)\npub fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"86":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr","source":"use dep::protocol_types::address::AztecAddress;\n\nstruct UnconstrainedContext {\n block_number: u32,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UnconstrainedContext {\n fn new() -> Self {\n // We could call these oracles on the getters instead of at creation, which makes sense given that they might\n // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user\n // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not\n // available.\n let block_number = block_number_oracle();\n let contract_address = contract_address_oracle();\n let chain_id = chain_id_oracle();\n let version = version_oracle();\n Self { block_number, contract_address, version, chain_id }\n }\n\n fn block_number(self) -> u32 {\n self.block_number\n }\n\n fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n fn version(self) -> Field {\n self.version\n }\n\n fn chain_id(self) -> Field {\n self.chain_id\n }\n}\n\n#[oracle(getContractAddress)]\nunconstrained fn contract_address_oracle() -> AztecAddress {}\n\n#[oracle(getBlockNumber)]\nunconstrained fn block_number_oracle() -> u32 {}\n\n#[oracle(getChainId)]\nunconstrained fn chain_id_oracle() -> Field {}\n\n#[oracle(getVersion)]\nunconstrained fn version_oracle() -> Field {}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"98":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash\n};\n\nuse dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field};\n\nuse crate::oracle::unsafe_rand::unsafe_rand;\n\nuse crate::event::event_interface::EventInterface;\nuse crate::note::note_interface::NoteInterface;\n\nuse crate::encrypted_logs::{\n header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody,\n outgoing_body::EncryptedLogOutgoingBody\n};\n\npub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n event: Event\n) -> [u8; OB] where Event: EventInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; OB] = [0; OB];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = OB - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\npub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n note: Note\n) -> [u8; M] where Note: NoteInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; M] = [0; M];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = M - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\nfn fr_to_private_key(r: Field) -> GrumpkinPrivateKey {\n let r_bytes = r.to_be_bytes(32);\n\n let mut high_bytes = [0; 32];\n let mut low_bytes = [0; 32];\n\n for i in 0..16 {\n high_bytes[16 + i] = r_bytes[i];\n low_bytes[16 + i] = r_bytes[i + 16];\n }\n\n let low = bytes32_to_field(low_bytes);\n let high = bytes32_to_field(high_bytes);\n\n GrumpkinPrivateKey::new(high, low)\n}\n\nfn compute_ivpk_app(ivpk: GrumpkinPoint, contract_address: AztecAddress) -> GrumpkinPoint {\n // It is useless to compute this, it brings no value to derive fully.\n // Issue(#6955)\n ivpk\n /*\n // @todo Just setting infinite to false, but it should be checked.\n // for example user could define ivpk = infinity using the registry\n assert((ivpk.x != 0) & (ivpk.y != 0), \"ivpk is infinite\");\n\n let i = fr_to_private_key(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M]));\n let I = i.derive_public_key();\n\n let embed_I = EmbeddedCurvePoint { x: I.x, y: I.y, is_infinite: false };\n let embed_ivpk = EmbeddedCurvePoint { x: ivpk.x, y: ivpk.y, is_infinite: false };\n\n let embed_result = embedded_curve_add(embed_I, embed_ivpk);\n\n GrumpkinPoint::new(embed_result.x, embed_result.y)*/\n}\n"},"99":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr","source":"use crate::{\n context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},\n encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog\n};\nuse dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash,\n constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index\n};\n\nfn emit_with_keys(\n context: &mut PrivateContext,\n note: Note,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n let note_header = note.get_header();\n let note_hash_counter = note_header.note_hash_counter;\n let storage_slot = note_header.storage_slot;\n\n let note_exists_index = find_index(\n context.new_note_hashes.storage,\n |n: NoteHash| n.counter == note_hash_counter\n );\n assert(\n note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, \"Can only emit a note log for an existing note.\"\n );\n\n let contract_address: AztecAddress = context.this_address();\n let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());\n\n let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);\n\n context.emit_raw_note_log(note_hash_counter, encrypted_log);\n}\n\npub fn encode_and_encrypt_note(\n context: &mut PrivateContext,\n ov: AztecAddress,\n iv: AztecAddress\n) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n let header = context.get_header();\n let ovpk = header.get_ovpk_m(context, ov);\n let ivpk = header.get_ivpk_m(context, iv);\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n\npub fn encode_and_encrypt_note_with_keys(\n context: &mut PrivateContext,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json b/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json new file mode 100644 index 000000000000..b5b8d9f58ead --- /dev/null +++ b/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"SchnorrSingleKeyAccount","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/f0owmWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLrX/ent52x9uL03n3fp7ut73upv3x6fbUP++m58PL/vrcxue3u9towGi7kVFkVDLaymiW0SKjJqMuIyliK0XMUsQsRcxSxCxFzFLELEXMUsQsRcxSxCxFLFLEIkUsUsQiRSxSxCJFLFLEIkUsUsQiRTQpokkRTYpoUkSTIpoU0aSIJkU0KaJJEV2K6FJElyK6FNGliC5FdCmiSxFdiuhSxCpFrFLEKkWsUsQqRaxSxCpFrFLEKkWsUsSQIoYUMaSIIUUMKWJIEUOKGFLEkCKGFJHNhlahVdFqS6uZVgutGq06rVZaURuhNkJthNoItRFqI9RGqI1QG6E2Qm0UtVHURlEbRW0UtVHURlEbRW0QaIZEM0SaIdMMoWZINUOsGXLNEGyGZDNEmyHbDOFmSDdDvBnyzRBwhoQzRJwh4wwhZ0g5Q8wZcs4QdIakM0SdIesMYWdIO0PcGfLOEHiGxDNEniHzDKFnSD1D7BlyzxB8huQzRJ8h+wzhZ0g/Q/wZ8s8QgIYENESgIQMNIWhIQUMMGnLQEISGJDREoSELDWFoSENDHBry0BCIhkQ0RKIhEw2haEhFQywactEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRsoue5KJFLlrkokUuWuSiRS5a5KL13y56Pf3cvR92Dy/7293e28eP4+O/q77X4/nX298v139/Aw=="},{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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M27pBbf0ilt6wy29w5Zecbtpxe2mFbebVtxueumtU8ql43bTittNK243rbjdtOJ204bbTRtuN2243bThdtNLb7xRLh23mzbcbtpwu2nD7aYNt5t23G7acbtpx+2mHbebXkr6Vy4dt5t23G7acbtpx+2mHbabpgW2m6YFtpumBbabpgW2m6YFtpumBbabpgW2m6YFtpumBbabpgW3mwbcbhpwu2nA7aYBt5teSlJVLh23mwbcbhpwu2nA7aYBt5tG3G4acbtpxO2mEbebXkr+Uy4dt5tG3G4acbtpxO2mEbebJtxumnC7acLtpgm3m17KiFMuHbebJtxumnC7acLtpgm3mwpuNxXcbiq43VRwu+mlNDHl0nG7qeB2U8HtpoLbTQW3m2bcbppxu2nG7aYZt5teyp1SLh23m2bcbppxu2nG7aYZt5vispASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LSXBZSILLQhJcFpLgspBkge2mgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSSWWUi911vpfXlRuuFuule64W66V7rhbrpXuuFuule64W66V7rhbrpTumUW0l7pdrtpX3rZSg+1PZVut5vulm63m+6Wbreb7pZut5v2+PA1TVGeSrfbTXdLt9tNe++3d47Lkp43R7vddLd0u910r3S7LKS13HwvPSzpqXSz3XS/dLPddL90s910v3Sz3XS/dLPddL90s910v3Sz3XQtN8Z76eW5dLPddL90s910t3S7LKS4xNq30pPUp9INd9O0HZfGZf0h4Kl0w910r3TD3XSvdLvdNCySbq8O4eHlt9LtdtPd0u120xDytsOE+OM1f5Rut5vulm63m+6WbrebhnrvpqGm37rpi5enVrf3/vHpv14cf+S256JzDFvV7e5KTP2fttjlLI215coUEFooW4dpdccWWX8p3YT2+HSScSnDSbn0hFu64JaecUsvuKVX3NIbbukdtvRLGU7KpeN209cMp+XXf7LslC0p3WqRVOPTm6cz31zOfHPcJ25xSUWCSyqShtszGm7P6Lg9o+P2jI47gXXcCcwuqWjoScZrlJBSDHgN+9F6c9w/0sDF8eTFcMvoNdx3gBY/f41qv/07DOvv29trQ6k/dV7aX2q8LVGoeUdnKGFboZLu6xnbrxWKsJUn2MrF7rciSby3i9KfvtCGj/dyv3+hS+qfv9BJ0q3m9Xf7h290qi+//rcm2pb7G4fWfppi+OBwnCmGjyTHmWJ4cB1niuGReJgpwXByGmeK4TF+nCmGDwjGmWL46GGcKeKmPJsyTaLN9TZ1pBL6nil1MyXci45leVXI0raqw8MzizEsX7d7mqyMYfc0KRzD7mnyPYbd00wOEHbHaWYSDLunmXYw7J5mjsKwe5oJDcNucbuvtNunyl2715/JNrsffn/9Yfc/LfRJ8dsW+vT3bQt9ovu2hT6lfdfC5JPXty30aerbFvqE9G0Lfer5toXiFn7XQp9Odi1cR8BbHfHhIevNQp9Ovm2hTyffttCnk29b6NPJdy0Un06+baFPJ9+20KeTb1vo08m3LRS38LsW+nSyb2HZ/kovtvZsoU8n37bQp5NvW+jTybct9OnkuxZmn06+baFPJ9+20KeTb1vo08m3LRS38LsWGp5OimzUYmll+WxhLLXcoBar5uVPZErOhocIZaWGs76yUsORXFmp4eT8RaUtPih9ZnIUwwFXWanhHKqs1HBcVFZqONUpKxUapfNkpD2l82Sk1rb8XfoLpfNkpD2l82SkPaUTZaTPSutEGWlH6UQZaUfpRBlpR+k8GanfcbR1ie1JqdAonScj7SmdJiPVkLd75GqM4UnpNBmpxrS9vKanS1yz5VtblJVOk5H2lFq+E0ZZ6TQZqfZw33t7lyel02SkXaXTZKS2pK3LtPB0R2xu02SkXaXTZKRdpbB3z+UGe/dctnyP0JeuJ2j99mt4f7iz4cftBC/qiGmj08f++AO3vBL4+UaQbPk+oy9Z2NO9jL5jYVvyrY4WkjxYGP/CQsv3KmlekmH5Eqa+XR7zQ2f6rDNvq7+ezGwvlZ8iDQcuPZGGs5aeSGEQaThh6Yk0HK6+JLIstxGoPETIXyINxzA9kZYDm5pIy5FKSWQxfTOYmshZEs9HkbMkno8iZ0k8H0UKg8hZEs9HkQSJp1i+YUxPJEHiKZZvAFMTaflGLz2RDInH8o1beiIZEo/lG7H0RDIkHsv3SumJZEg8lu9Q0hPJkHgs3xekJ5Ih8Vi+G0dPJEPisXwPjJ5IhsRj+X4UPZEMicfyHSN6IhkSj+V7OvREMiQey3dd6IlkSDyW74vQE8mQeCzfuaAnkiHxWL63QE/klYknBrk/6v7wDPhLkaHVsj0D3nr788H4cinRX7n0gFt6xC094ZYuuKVn3NILbukVt/SGWzpuN8243TTjdtOM200zbje9lDCsXDpuN8243TTjdtOM200zbjctuN204HbTgttNC243vRQZq1w6bjctuN204HbTgttNC243rbjdtOJ204rbTStuN70ULqpcOm43rbjdtOJ204rbTStuN2243bThdtOG200bbje9FEOpXDpuN2243bThdtOG200bbjftuN2043bTjttNO243vZQ2qFw6bjftuN2043bTjttNO2w3rQtsN60LbDetC2w3rQtsN60LbDetC2w3rQtsN60LbDetC2w3rQtuNw243TTgdtOA200Dbje9lJKmXDpuNw243TTgdtOA200DbjeNuN004nbTiNtNI243vZTApVw6bjeNuN004nbTiNtNI243TbjdNOF204TbTRNuN72U7qRcOm43TbjdNOF204TbTXFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSA2XhdRwWUgNl4XUcFlIbYHtpg2XhdRwWUgNl4XUcFlIDZeF1HBZSA2XhdQss5B6r7fS+/KidMPddK90w910r3TD3XSvdMPddK90w910r3TD3XSvdMPddKd0wyykvvSylR5qeyrdbjfdLd1uN90t3W433S3dbjft8eFrmqI8lW63m+6Wbreb9t5v7xyXJT1vjna76W7pdrvpbulmu+labr6XHpb0Z+l2WUj7pZvtpvulm+2m+6Wb7ab7pZvtpvulm+2m+6Wb7aZruTHeSy/PpZvtpvulm+2m+6Ub7qax9q30JPXP0u2ykNZyt+PSuEjsT6Ub7qZ7pRvupnul2+2mYZF0e3UIDy+/lW63m+6WbrebhpC3HSbEH6/5o3S73XS3dLvddLd0u9001Hs3DTX91k1fvDy1ur33j0//9eL4I7c9F51j2Kpud1di6j9tsdupR9pil+EUQ8nLZsv6O+NnW3K+nU7men+p/BRpNy8oirSbLBRFGs4geiKFQaThXPMlkWW5bcflITP/Emk4AemJNJyV9EQaTlV6Ig1nJDWRdjlbmiJnSTwfRc6SeD6KnCXxfBQpDCIZEo9dxpimSIbEY5dbpimSIfHYZaFpimRIPHb5apoiGRKPXWabpkiGxGOXA6cpkiHx2GXLaYpkSDx2eXWaIhkSj10GnqZIhsRjl6unKZIh8dhl9WmKZEg8dvl/miIZEo9dpqCmSIbEY5dTqCmSIfHYZR9qimRIPHZ5ipoiGRKPXUajpkiCxNPtch81RRIknm6XJakpcprEI7eHekt+EikMIqdJPJ9EXpl41lJvlcSl1R2RsjbxzZIe/yRc9EuZl8qlN9zSO2zplzIvlUsPuKVH3NITbumCW3rGLR23m75GXd1SxrJTtqR0q0VSjU9v3k9889e4KK03D2e+eTzzzdOZby5nvnk+883LmW9eT3xzuyCXPe51twty2S8d9gKMbhfksl+64JYOewFGtwty2S8d9gKMbhfksl867AUYYbn0DPOLWb3Ihv6RVpbn2g2PSLu1G56Rdms3fOS4W7vhM8fd2g0fOu7VbvnUcbd2w8eOu7UbPnfcrd3wweNu7cB9NRn+9963w4H1f7e//8lvVWn4m6Go0vB3SFGl4W+bokrDeVdRpeFkrKjScIZWVGk4bSuqNJzL9VSK4QSvqJIi+wjs0wg/AOLAtQtw7bAPJKy1wz6RsNYO+4DfWrvT2V9gyFdfHM/+0hfLfPahvpz4RMX67u3Ud+9nvntZTn33cOq7x1PfHfa5h7V2Aa4d9smHtXbYRx/W2mGffVhrh334ISwd+FeaS/9mXbt24KcfOvDTDx346YeO+/RDsPwHEWonc8Hy304oqmT49SMEhl8/QmD49SNEhl8/Qrz0LxTyBhCI+eFA5aXKVsMttLYW21N3iBG28gRbucBWnmErL7CVV9jKG2zlHbXytMBWDttDE2wPTbA99NInF3Urh+2hCbaHJtgemmB7aILtod9/Yu/H32D8evGPPwvYmVpXq24vjlHuL/6bn7zD9x/E+/H4yVZ8W3aKX8JyV9p+e+uf9URj9SRj9YixerKxeoqxeqqxepqxerqtevJirB5j+3M2tj9nY/tzNrY/Z2P7cza2P2dj+3M2tj9nY/tzMbY/F2P7czG2Pxdj+3Mxtj8XY/tzMbY/F2P7czG2Pxdj+3M1tj9XY/tzNbY/V2P7czW2P1dj+3M1tj9XY/tzNbY/V2P7czO2Pzdj+3Mztj83Y/tzM7Y/N2P7czO2Pzdj+3Mztj83Y/tzN7Y/d2P7cze2P3dj+3M3tj93Y/tzN7Y/d2P7cze2P3db+3NcbO3PcbG1P8fF1v4cF1v7c1xs7c9xsbU/x+Xq/Tlvf3a99LDz1jHdnjCL5U6CSHV58drewvbGD3cmxpdVpH77a6Eg6bcX/zSluinPpjQ35dmU7qY8mRIWN+XZlOCmPJsS3ZRnU5Kb8myKuCnPpmQ35dkUT7QvTPFE+8IUT7QvTPFE+2xK9ET7whRPtC9M8UT7whRPtC9METfl2RRPtC9M8UT7whRPtC9M8UT7whRPtM+mJE+0L0zxRPvCFE+0L0zxRPvCFHFTnk3xRPvCFE+0L0zxRPvCFE+0L0zxRPtsiniifWGKJ9oXpniifWGKJ9oXpoib8myKJ9oXpniifWGKJ9oXpniifWGKJ9pnU7In2hemeKJ9YYon2hemeKJ9YYq4Kc+mWE60qdz+gisvy2+m/KzdcvDMG2f7kfp9r91yPsxlq73t/WPM+YYIb/VOCC/y6t/t/ULAXpf7G/8ghL9YfLlx01O7//XeDyj680trvvmWas2fXxxy3KzIUnZevKS7b00eX/xzGS0nWl/Gw8toOYP7Mh5dxmJ5avBlPLyMluccX8bDy2h5MkNbRgn19sYS+s4yxiY3dbEV+eYyWp4lfRkPL6P4Ms6wjJbndV/Gw8to+uhCbudLZWk7yxhku3065PwoNJCs5LiDnBBeUI00qPF9O18Maa+evtwOLkN/vN7u1RVxoYSt+PLwzj/+sfwsvgMXr8GjH1d8uLj47Z3jmjA/Fx8lyfZqyT8+/dfL+636aLn6vL11lJJ+q/7Vppe2eU0e5rWQ6otX137bIttyf+PQfm1OGsj9KX0R9+WlL9l9eelLcV9e+lLdl5e+NPflpS/dfXnlS1vcl5e+mE6lA32ZKO/meptMUgl9z5e6+fL45Et5dTQRl3Y7mogh3t85huUvHJ8oSYM4Lu74xY5PlP5BHJ9orgBxfKKJBcTxiWYhEMcnmrIwHO8TzW8gjk80GYI47jPnAcfXH9o2xx+egfjh+E8XfY7UcFHcRQUXfd7TcNFnOA0XfS7TcNFnLQ0XfX76votp8ZlIw0WfczRc9NnlgIvrjLhV/fin4puLPrtouCjuooKLPrtouOizi4aLPrtouOizi4aLPrsouBh8dtFw0WcXDRd9djniYmlb1Y9/LLi56LOLhoviLiq46LOLhos+u2i46LOLhos+u2i46LOLgovRZxcNF3120XDR9Oxyh5FEaWX57GIsdaPRrrIf4CW/IAQpmh4xtMUKk1jTgV1brOlc/UWxLT6IfQaHpGg6/mqLNZ1StcWaDpPKYpPpzKct1nQ00xY7U4LaFTtTgmrbLQ2x9FdihUnsTAlqV+xUCWpP7FQJak/sVAlqT+xUCWpHrMyUoHq7neHEusT2LHamBLUrdqYEtSt2ogRVQ94wvTXG8CxWJhIb0/bympb0LHaiBLUvdqIEtS92ogS1L3aiBFV7uO/Gvcuz2IkS1K7YPFGCaku6E+IfyQmb2IkS1L7YiRLUvljTCar17QdX6bE8Vy/Q1ZvOOL3ef3TvLX7+h9b67Tf3Hu9lhPLqJ/cQ71dMxP74M/rL21ByvNXRc3u46iL1Xy6aDk9fcrFvt+L23HdcbEu+wW7a2nofXIx/5aLpVPYlF2u/HbuHZcm/2fhTqulM1lN5kJo+S83bv4Fc7y+VXzpNxzE9ncV0ElPUaTqEKeo0nb8UdZqOXl/SWZbbsFQeMuZNp5DotB3n9HTaDlx6Om1HIj2d8+ShzzrnyUMfddZ58tBnnfPkoc8658lDn3WS5CHbt7Ep6iTJQ7ZvS1PUSZKHbN9mpqiTJA/Zvm1MUSdJHrJ9G5iiTpI8ZPvmK0WdJHnI9i1PijpJ8pDtG40UdZLkIdu39yjqJMlDtm+qUdRJkods3/aiqJMkD9m+MUVRJ0kesn3riKJOjjwktm/uUNTJkYfE9u0Xijo58pAsQqKTIw+J7VsYFHVem4diirenx2Pu5bPO0GrZHsJvvT39cYJcfD+BdvUdufqLefza1Qfo6iN09Qm6eoGuPkNXX6Crh+61AbrXBuheG6F7bYTutRG610boXnsx0Vi7euheG6F7bYTutRG610boXpuge22C7rUJutcm6F57MftWu3roXpuge22C7rUJutcm6F4r0L1WoHutQPdage61F1NStauH7rUC3WsFutcKdK8V6F6boXtthu61GbrXZuheezF+U7t66F6boXtthu61GbrXZuheW6B7bYHutQW61xboXnsxRVG7euheW6B7bYHutQW61xboXluhe22F7rUVutdW6F57MaFPu3roXluhe22F7rUVutdW6F7boHttg+61DbrXNuheezH9Tbt66F7boHttg+61DbrXNuhe26F7bYfutR2613boXnsxWUy7euhe26F7bYfutR2613bkXpsX5F6bF+RemxfkXpsX5F6bF+RemxfkXpsX5F6boblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblR2TY3qvd6e+u+vKredK/drd50r92t3nSv3a3edK/drd50r92t3nSv3a3edK/drd5yr+1LL1v1obbn6i332t3qTXOj9qu33Gv3q7fca3t8+Nau/+Vz9ZZ77X71lntt73179bKk5x3TNDdqv3rLvXa/esO9dq0436sPS3qu3nCvPVC94V67W32xzI06UL3hXnugesO99kD1hnvtgeoN99q14hjv1ZcX1RvutQeqN9xrD1RvutfG2rfqk9Tn6k332rSdwsZFYn+u3nSv3aveMjfqQPWWe21YJN1eHUJcnqu33Gv3q7fca8OagbfqY87P1VvutfvVW+61+9Vb7rWh3nttqOm3Xvvqvdvt/CTKj0//9eK4vHrznuOt7L7+DnB/deq/nLHcx8c6YzkjhJKXzZkWdpzJ+Xbcmev9pfJLp+U0oajTMkNLVafphKKo03SWUdRpOvV8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dPXQvbZB99oO3Ws7dK/t0L22Q/fai1HD2tVD99oO3Ws7dK/t0L22I/fauCD32rgg99q4IPfauCD32rgg99q4IPfauCD32rgg99q4IPfauED32gDdawN0rw3QvTZA99qLuaXa1UP32gDdawN0rw3QvTZA99oI3WsjdK+N0L02Qvfai5mY2tVD99oI3WsjdK+N0L02QvfaBN1rE3SvTdC9NkH32ot5i9rVQ/faBN1rE3SvTdC9NkH3WoHutQLdawW61wp0r72Y5addPXSvFeheK9C9VqB7rUD32gzdazN0r83QvTZD99qLOXHa1UP32gzdazN0r83QvTZD99oC3WsLdK8t0L22QPfaixlk2tVD99oC3WsLdK8t0L22QPfaCt1rK3SvrdC9tkL32ov5VtrVQ/faCt1rK3SvheZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSC5kYlaG5UguZGJWhuVFqQe22C5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVLLNjeq93t66L6+qN91rd6s33Wt3qzfda3erN91rd6s33Wt3qzfda3erN91rd6u33Gv70stWfajtqXrT3Kj96i332v3qLffa/eot99oeH76163/5XL3lXrtfveVe23vfXr0s6XnHNM2N2q/ecq/dr95wr10rzvfqw5Keqzfca/ert8yNOlC94V57oHrDvfZA9YZ77YHqDffaA9Ub7rVrxTHeqy8vqjfcaw9Ub7jXHqjedK+NtW/Vr4f1z9Wb7rVpO4WNi8T+VL1lbtSB6k332t3qLffasEi6vTqEuDxXb7nX7ldvudeGkLc9J8Scn6u33Gv3q7fca/ert9xrQ7332lDTb7321Xu32/lJlB+f/uvFcXn15j3HW9k9t7sxMfVfzlju42OdsZwRQsnL5kwLO87kfDvuzPX+Uvmp0zIZS1Wn5dyhqdN0QlHUaTrL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raiTJA/ZBm8r6iTJQ7Zx24o6SfKQbci2ok6SPHQxWjumeKMtxdzLZ52h1bJBq1pvTzCvfjErW7n6i+HX2tUH6OojdPUJunqBrj5DV1+gq6/Q1UP32grdaxt0r23QvbZB99oG3WsvRg1rVw/daxt0r23QvbZB99oG3Ws7dK/t0L22Q/faDt1rL2bLalcP3Ws7dK/t0L22Q/faDtxr07IA99q1euBeu1YP3GvX6oF77Vo9cK9dqwfutWv1wL12rR64167VA/fatXroXhuge22A7rUButcG6F57MRNTu3roXhuge22A7rUButcG6F4boXtthO61EbrXRuheezFvUbt66F4boXtthO61EbrXRuhem6B7bYLutQm61yboXnsxy0+7euhem6B7bYLutQm61yboXivQvVage61A91qB7rUXc+K0q4futQLdawW61wp0rxXoXpuhe22G7rUZutdm6F57MYNMu3roXpuhe22G7rUZutdm6F5boHttge61BbrXFuheezHfSrt66F5boHttge61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrR+61AZobFaC5UQGaGxWguVFhQe61AZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRwTY3qvd6e+u+vKredK/drd50r92t3nSv3a3edK/drd50r92t3nSv3a3edK/drd5yr+1LL1v1oban6k1zo/art9xr96u33Gv3q7fca3t8+Nau/+Vz9ZZ77X71lntt73179bKk5x3TNDdqv3rLvXa/esO9dq0436sPS3qu3nCv3a/eMjfqQPWGe+2B6g332gPVG+61B6o33GsPVG+4164Vx3ivvryo3nCvPVC94V57oHrTvTbWvlWfpD5Xb7rXpu0UNi4S+1P1lrlRB6o33Wt3q7fca8Mi6fbqEOLyXL3lXrtfveVeG9YAv1Ufc36u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+2pg/eD9V8D7r4D3XwHvvwLefzN4/83g/TeD998M3n912FcD6wfvvxm8/2bw/pvB+28G778FvP8W8P5bwPtvAe+/OvyqgfWD998C3n8LeP8t4P23gPffCt5/K3j/reD9t4L3Xx2m1MD6wftvBe+/Fbz/VvD+W8H7Lzj/SsD5VwLOvxJw/pWA868EnH8l4PwrAedfCTj/SsD5VwLOvxJw/pWA868EnH8l4PwrAedfCTj/SsD5VwLOvxJw/lUG519lcP5VBudfZXD+VV6w+28G519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnXxVw/lUB518VcP5VAedflQW7/xZw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQXnX1Vw/lUF519VcP5VXbD7bwXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfNXD+VQPnXzVw/lUD51+1Bbv/NnD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VB+dfdXD+VQfnX3Vw/lVfsPtvB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+df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W4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjK6MztjI6YyujM7YyOmMrL+CdOKMztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2Cjpjq6Aztgo6Y6ugM7bKAt6JCzpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOrojO2Kjpjq6Iztio6Y6su4J24ojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YaOmOroTO2Gjpjq6EzttoC3okbOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6ujM7Y6OmOrozO2Ojpjqy/gnbijM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq4MztuICzthaBWB34lUAdideBWB34lUAdideBWB34lUAdideBWB34lUAdideBaB3YnDG1ioAvRODM7ZWAeidGJyxtQpA78TgjK1VAHonBmdsrQLQOzE4Y2sVgN6JwRlbqwD0TgzO2FoFoHdicMbWKgC9E4MztlYB6J0YnLG1fgR6JwZnbK0fgd6JwRlb60egd2Jwxtb6EeidGJyxtX4EeicGZ2ytAtA7MThjaxWA3onBGVurAPRODM7YWgWgd2JwxtYqAL0TgzO2VgHonRicsbUKQO/E4IytVQB6JwZnbK0C0DsxOGNrFYDeicEZW6sA9E4MzthaBaB3YnDG1ioAvRODM7ZWAeidGJyxtQpA78TgjK1VAHonBmdsrQLQOzE4Y2sVgN6JwRlbqwD0TgzO2FoFoHdicMbWKgC9E4MztlYB6J0YnLG1CkDvxOCMrVUAeicGZ2ytAtA7MThjaxWA3onBGVurAPRODM7YWgWgd2JwxtYqAL0TgzO2VgHgnTigM7YCOmMroDO2Ajpjay0PXQB4Jw7ojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YCuiMrYDO2ArojK2AztgK6IytgM7YiuiMrYjO2IrojK2IztiKC3gnjuiMrYjO2IrojK2IztiK6IytiM7YiuiMrYjO2IrojK2IztiK6IytiM7YiuiMrYjO2IrojK2IztiK6IytiM7YiuiMrYjO2IrojK2IztiK6IytiM7YirYJT1nir9dmeSfAdB84IsD0LpRzuwko9Y0A07vQEQGmd6EjAkzvQkcEmJ4HDgiwzRc6IsB0Hyih/HptSfGNANN94IgA0/PAEQGCLsB0Jz4iwHQnPiLAdCc+IsB0Jz4iwHQnPiDANl/oiAD0TmybL3REAHonts0XOiIAvRPb5gsdEYDeiW3zhY4IuL4Tvz0ufH5tq/1WR2tB7nWU9ncHkQNoREPlBi65kUtuQpV7lyD4EjK+hIIvoeJLaPgSYNPEJqHCJoS7BNiuf5cA28nvEmx351aX24v7fhjp2zsv/f7a9ijXdidXl2u7639Nru7DHtV2mhhqje2UMtQa2+lnqDW2U9VIa5rttDbUGtspcKg1ttPlUGtmSq3K1ohb884aT8NvrfE0/NYaT8NvrfE0/NYaT8PvrOmeht9a42n4rTWeht9a42n4rTXi1ryzxtPwW2s8Db+1xtPwW2s8Db+1xtPwG2vS4mn4rTWeht9a42n4rTWeht9aI27NO2s8Db+1xtPwW2s8Db+1xtPwW2s8Db+zJngafmuNp+G31ngafmuNp+G31ohb884aT8NvrfE0/NYaT8NvrfE0/NYaT8PvrImkuWafFJkiaa45Yg1ph9on+6VI2qGOWEPaoY5YQ9qhDliTSM9rjlhDel5zxBrSXLNPOkqJNNccsUbcmnfWkJ7XHLGGNA0fsYY0DR+xhjQNH7GGNA0fsEZI0/ARa0jT8BFrPA2/tcbT8FtrZCJrvvDOoRW5KVw/5f7q8OrVMeebwBreGDlTdh5q5ExJe6iRM+XyoUbOlOKVjLybM1OO1zYnz5Tk1c2ZKcurmzNTmlc3Z6Y8r26OuDnvzfGU/sEc1uTdy+2dQ6/pN3P+aqjOrMlb3UjW5P0lI2PcBEp+YyRrStc20vidOkBGsqZ/dSNZJwV1I1mnCnUjxY3UMZJ1WvmakfsnuMbvfAIyknSyWWu7/ewal8ea/3ayMX7/FZCRpJPN14w80GyM3wUGZCTpZKNvJOlko28k6WSjb6S4kTpGkk42+kaSTjZfNHJ/spnqtrqhRrJONiFs3oTYvj/ZTHUT3kgjp7o37zQjDzSbqW7ZG2ok62SjbiTrZKNupLiROkayTjbqRrJONupGsk42XzNyf7KZ6p7CoUbS/mbTyt3IvmNk7ds7L/fXhtbuRk51B+JQI2l/s9E2knayKWEzssr3Dy2muo1xqJHiRu4beSBHTnXT41AjaScbbSNpJxttI2knG20jaX+z0TVSprrPcqiRtL/ZfMnI3UMLmequzKFG+mQTQ/v9SYu7OeLmvDfHJ5AP5rBOFevB1VZzzN8+MJCpbuMcaiTrVPElI49kONapQtvIqe4FHWok61ShbiTrVKFuJOtUoW6kuJE6RrJOK18zcv/AYKq7Uoca6ZPN+r1Nr+fnqe5WVTfHJ5D35kTaqaK0reYWvn9gEGmnCm0jaaeKrxh5IMNNdT/wUCPFjdQxknaq0DaSdqrQNpJ2qtA2knYC0TaSdlr5kpH7BwZT3cs91EifbJSM9MlGyUifbJSMFDdSx0ifbJSM9MlGyUifbFYjf/+D77s5Pq18MMcnkPfmTHW/+dt3vsulyP53ubYTet9wh60/vPPfy7Wdo9XlyjxyD5wkGb/VW12u7eSoLtd2vlOXazuxqcu1ncG05Rq/a/prcvdnM+O3R6vLnShVHZE7Uao6Ile45M6Uqg7INZ6q2n0A7On7I4Lx24/V5RpPVV+ReyRmGE9VynKN3/erLtd4qtKWazxVacs1nqq05cpEcvdjhvHbYtXlTpSqjsidKFUdkTtTqjogd6ZUtS/X9l2jfZHbO/cll++PCLZvBNWXazpVfU3ugZhh+3ZNfbnCJdd0qtKXazpV6cs1nar05ZpOVV+UeyBmmE5V6nJt33OoL3eiVHVE7kyp6oDcmVLVAbkCI7f8PgDeJeAkpbcScNLPWwnGE02/1dHXQr4/a9q+k01frvFE8xW5B/Kq7fvN9OUaTzTaco0nGm25xhONtlzhkms8/XxJ7n5etX2Hlb7ciVLVEbkTpaojcmdKVbtys+27lfTlzpSqDsgFSlX95Qybbd8QdEyCmJYQ5C7h4c90X/+ja/HGQG0PNccQHuTaTj/qcm2nny/JrW172j3EnXfeP6HItm/PGWuN7VQ11BrbCWykNbbvrBlrje1kN9Qa2ylwqDW20+VQa8SteWfNRAlX2xpPw2+t8TT81hpPw2+t8TT8zhrbd62MtcbT8FtrPA2/tcbT8FtrxK15Z42n4bfWeBp+a42n4bfWeBp+a42n4XfW2L6fY6w1nobfWuNp+K01nobfWiNuzTtrSHNNltuTElneWUOaaw5YY5sLf6I1+XZFQC71jTWkHeqINaQd6og1pB3qiDWk5zVHrCE9rzliDWmu2b9hPdtm6Y+1hvS85oA1thn9Y60hTcNHrCFNw0esIU3DR6wRt+adNaRp+Ig1pGn4iDWeht9a42n4rTWeht9ZY/tuhS9a84V3rvX2R7z1tytSH/7A0PY9DGOtmSkNK1szUxpWtkbcmnfWzJSGla2ZKQ0rWzNTGv47a3p5Y81MaVjZmpnSsK41xu/EOM2aB9xGym+sIU3DR6whTcNHrCFNw0esEbfmnTWkafiINaRp+Ig1pGn4ACvL+J0jQ60hTcMHrDF+l4mSNXe5FAn3Ltd2ao3x9uKeUt+RG5Ymt6pXBfdX18d/zraz6AmChU2w7dx4gmDbafAEwbYz3gmCbSe3EwTbzmP6go3fr3KCYNs56wTBbEnL+C0rJwgWNsFsScv4XSsnCGZLWsbvWzlBMFnSKsbvXDlBMFnSKsbvXTlBMFnSKouwCSZLWsX4vS4nCCZLWsX4HSwnCGZLWsbvSzlBMFvSMn63yQmC2ZKW8XtIThDMlrSM3xlygmC2pGX8fo8TBLMlLeN3cZwgmC1pGb834wTBbEnL+B0XJwhmS1rG76M4QTBb0jJ+d8QJgtmSlvF7Hk4QzJa0jN/JcIJgtqRl/P6EEwSzJa3ElrSM33txgmC2pJXYkpawJS3jt5CcIJgtaRm/MeQEwcImmC1pGb+z4wTBbEnL+P0aJwhmS1rG78I4QTBb0jJ+b8UJgtmSlvE7Jk4QzJa0jN8HcYJgtqRl/O6GEwSzJS3j9yycIJgtaRm/E+EEwWxJy/j9BScIZktaxu8aOEEwW9Iyfi/ACYLZkpZxhv8JgtmSlnHe/gmC2ZKWcTb+CYLZkpZxjv0JgtmSlnHm/AmC2ZKWcT78CYLZkhYbI76wMeILGyO+sDHiCxsjvrAx4gsbI76wMeILGyO+sDHiCxsjvrAx4gsbI76wMeILGyO+sDHiCxsjvrAx4isbI76yMeIrGyO+sjHi6yJsgsmSVmVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8ZWPEVzZGfGVjxFc2RnxlY8RXNkZ8Y2PENzZGfGNjxDc2RnxbhE0wWdJqbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPjGxohvbIz4xsaIb2yM+MbGiG9sjPg2E0G813h7cf39ne9yJ+rCR+ROtEP31m4v7vWN3In25yNyJ9qdj8idaG8+IneiGfiA3JmI0kfkztR3D8idqe8ekDvR7HtErnDJ5UpVM1Gkj8iFTVV3CbBJ6S7BdvpJdft3JH3RGMSNc55PEGw7AZ0g2HYGOkGw7RR0gmBhE2w7CZ0g2HYWOkGw7TR0gmDb2ekEwWxJyzjn+QTBbEnLOOf5BMFsScs45/kEwWxJyzjn+QTBbEnLOOf5BMFkSasb5zyfIJgsaXXjnOcTBJMlrb4Im2CypNWNc55PEEyWtLpxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZKWcc7zCYLZkpZxzvMJgtmSlnHO8wmC2ZJWYUtaxkneJwhmS1qFLWkVYRPMlrSME9tPEMyWtIxT208QzJa0jJPbTxDMlrSM09tPEMyWtIwT3E8QzJa0jFPcTxDMlrSMU99PEMyWtNgY8Z2NEd/ZGPGdjRHf2RjxnY0R39kY8Z2NEd/ZGPGdjRHf2RjxnY0R39kY8Z2NEd/ZGPGdjRHf2RjxnY0R39kY8Z2MEZ8WMkb8Kpgraa2CuZLWKpgraa2ChU0wV9JaBXMlrVUwV9JaBXMlrVUwW9IiY8SvgtmSFhkjfhXMlrTIGPGrYLakRcaIXwWzJS0yRvwqmC1pkTHiV8FsSYuMEb8KZktaZIz4VTBb0iJjxK+C2ZIWGSN+FcyWtMgY8atgtqRFxohfBbMlLTJG/CqYLWmRMeJXwWxJi4wRvwpmS1pkjPhVMFvSImPEr4LZkhYZI34VzJa0yBjxq2C2pEXGiF8FsyUtMkb8KpgtaZEx4lfBbEmLjBG/CmZLWmSM+FUwW9IiY8SvgtmSFhkjfhXMlrTIGPGrYLakRcaIXwWzJS0yRvwqmC1pkTHiV8FsSYuMEb8KZktaZIz4VTBb0iJjxK+C2ZIWGSN+FcyWtMgY8atgtqRFxohfBbMlLTJG/CqYLWmRMeJXwWxJi4wRvwpmS1pkjPhVMFvSImPEr4LZkhYZI34VzJa0yBjxq2C2pEXGiF8FsyUtMkb8KpgsaQU2RnxgY8QHNkZ8YGPEr3LYBJMlrcDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPbIz4wMaID2yM+MDGiA9sjPjAxogPMxHEe423F9ff33mTOxM//IjciXbo3rYX9/pG7kT78xG5E+3OR+ROtDcfkTvRDHxE7kQT8BG5M/Xdfbkz0aSPyJ1o9j0id6LJ94hcrlQ1E0X6iFzYVHWXAJuU7hJsp58st9G6l972BvF8K2M9QXrzj852+lGXazv9aMs1TnhWl2s7/ajLtZ1+1OXaTj/qcoVLru30oy7XdlJSl8uVqowTndXlcqUq4zRndblcqco4yVldLleqMk5xVpfLlaqME5zV5XKlKuP0ZnW5VKkqGic3q8ulSlXROLVZXS5VqoqLcMmlSlXROK1ZXS5VqorGSc3qcrlSlXFKs7pcrlRlnNCsLpcrVRmnM6vL5UpVxsnM6nK5UpVxKrO6XK5UZZzIrC6XK1UZpzGry+VKVcZJzOpyuVKVcQqzulyuVGWcwKwulytVGacvq8vlSlXGycvqcrlSlXHqsrpcrlRlnLisLpcrVRmnLavL5UpVxknL6nK5UpVxyrK6XK5UZZywrC6XK1UZpyury+VKVcbJyupyuVKVcaqyulyuVGWcqKwulytVGacpq8vlSlXGScrqcrlSVeZKVcYp2dpyjVOy1eVyparClaqMM9DV5QqXXK5UZZyBri6XK1UZZ6Cry+VKVcYZ6OpyuVKVcQa6ulyuVGWcga4ulytVGeelq8vlSlVcbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWT1xs9cTFVk9cbPXExVZPi3DJpUpViYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OrCxVYXLra6cLHVhYutLotwyaVKVcLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6jITjrrXeHtxTW/kTtSIDsidCVjcW7u9uNc3cifaqo7InWirOiJXuORONAAekTvRAHhE7kx994DcmfruAbkTDYAH5M4ELD4ilytVzQQsPiIXNlXdJQi+BNvpp8Z+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4ZNMl74SH+s+8bHuEx/rPvGx7hMf6z7xse4TH+s+8bHuEx/rPvGx7hMf6z7xse4TH+s+8bHuEx/rPlli3d+LMpSP7kUZSjD3osRiUYZSwL0oQ336XpShTnovylCvuxdlqBttRVmic9+LsrijWyJc34uyuKNbokTfi7K4o1siLd+LsrijW6IV34uyuKNbIv7ei7K4o1ui5t6LsrijWyLP3ouyuKNborfei7K4o1sioN6LsrijW6KI3ouyuKNbInHei7K4o1uiWd6LOnlHv39QueqD6lUf1K76oH7RB51N77t/ULjqg+JVH5Su+iC56oOu2hnKVTtDuWpnKFftDOWqnaFetTPUq3aGetXOUK/aGepVO0O9ameoV+0M9aqdoV61M9SrdoZ21c7QrtoZ2lU7Q7tqZ2hX7Qztqp2hXbUztKt2hnbVztCu2hn6VTtDv2pn6FftDP2qnaFftTP0q3aGftXO0K/aGfpVO0O/aGcQlb8WjVW2D2r9tw/6u6faROUvOk8oK9osK9ksS2yWlW2WVWyWVW2W1WyW1U2WFWzu8sHmLh9s7vLB5i4fbO7yweYuH2zu8sHmLh9s7vLB5i4fbe7y0eYuH23u8tHmLh9t7vLR5i4fbe7y0eYuH23u8tHmLp9s7vLJ5i6fbO7yyeYun2zu8snmLp9s7vLJ5i6fbO7yyeYuLzZ3ebG5y4vNXV5s7vJic5cXm7u82NzlxeYuLzZ3ebG5y2ebu3y2uctnm7t8trnLZ5u7fLa5y2ebu3y2uctnm7t8trnLF5u7fLG5yxebu3yxucsXm7t8sbnLF5u7fLG5yxebu3yxuctXm7t8tbnLV5u7fLW5y1ebu3y1uctXm7t8tbnLV5u7fLW5yzebu3yzucs3m7t8s7nLN5u7fLO5yzebu3yzucs3m7t8s7nLd5u7fLe5y3ebu3y3uct3m7t8t7nLd5u7fLe5y3ebu3w3uctnm3/7mm3+7Wu2+bev2ebfvubF5C6fbf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/uabf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/uabf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/uabf7ta7b5t6/Z5t++lrORy8+v/toN4cv26rD+n7vk1zeEf+m961Jub13zcn+1xG++c0z59s4x9Ydbzbu8eufWt3eOO++8/uP+9dr139PrBT0bbe0LevWCGrpazRdUY0ENXUvnC6qxoIau9PMF1VhQ8QWda0ENXQ7sC6qxoIYuVvYF1VhQQ5dS+4JqLKihC719QTUW1E+KplrQuvhJEdKCtuW2oD2/WVA/KZpsQf2kaLIF9ZOiyRZUfEGBFrTeF7S8WVA/KZpsQf2kaLIF9ZOiyRbUT4omW1A/KZprQYOfFCEtaG63BS31zYL6SdFkC+onRZMtqJ8UTbag4gs614L6SdFkC+onRZMtqJ8UTbagflI02YL6SdFcCxr9pGiyBfWToskW1E+KJltQPymabEHFF3SuBfWToskW1E+KJltQPymabEH9pGiyBfWTorkWNPlJ0WQL6idFky2onxRNtqB+UjTZgoov6FwL6idFky2onxRNtqB+UjTZgvpJ0WQL6idFcy2o+EnRZAvqJ0WTLaifFE22oH5SNNmCii/oXAvqJ0WTLaifFE22oH5SNNmC+knRXAuafQ49YUFD2xY0i+aC7hOts8+hky2oz6GTLaj4gs61oD6HTragPodOtqA+h062oD6HTrag/sTCXAta/ImFyRbUT4omW1A/KUJa0P2LeIqfFE22oOILOteC+knRZAvqJ0VIC7p/zUfxk6LJFtRPiiZbUD8pmmtBq58UTbagflI02YL6SRHSgu4/9Vf9pGiyBRVf0LkW1E+KJltQPymabEH9pGiyBfWToskW1E+K5lrQ5idFky2onxRNtqB+UjTZgvpJ0WQLKr6gcy2onxRNtqB+UjTZgvpJ0WQL6idFky2onxTNtaDdT4omW1A/KZpsQf2kaLIF9ZOiyRZUfEHnWlA/KZpsQf2kaLIF9ZOiyRbUT4omW1A/KZpqQdviJ0WTLaifFE22oH5SNNmC+knRZAsqvqBzLaifFE22oH5SNNmC+knRZAvqJ0WTLaifFM21oMFPiiZbUJ9D9Rc0btDMdW1VL7PbJVq3IL6gcy2oz6GTLajPoZMtqM+hky2oz6GTLajPoXMtaPQ5dLIF9ScWJltQf2JhsgX1k6LJFlR8QYEWdPcinhb9pGiyBfWToskW1E+KJltQPylCWtDdaz5a9JOiuRY0+UnRZAvqJ0WTLaifFE22oH5SNNmCii8o0ILuP/WX/KRosgX1k6LJFtRPiiZbUD8pmmxB/aRorgUVPymabEH9pGiyBfWToskW1E+KJltQ8QWda0H9pGiyBfWToskW1E+KJltQPymabEH9pGiuBc1+UjTZgvpJ0WQL6idFky2onxRNtqDiCzrXgvpJ0WQL6idFky2onxRNtqB+UjTZgvpJ0VwLWvykaLIF9ZOiyRbUT4omW1A/KZpsQcUXdK4F9ZOiyRbUT4omW1A/KZpsQf2kaLIF9ZOiuRa0+knRZAvqJ0WTLaifFE22oD6HHltQXe509WlxiO0+0w2x3SevIbb7fDTC9uZTzBDbfdYYYrtPBENs9194h9gubvsI231KHWK7T6n6tu9fqNF8Sh1iu0+pQ2z3KXWE7d2nVH3b9zHy3afUIbb7lDrEdp9Sh9gubvsI231KHWK7T6n6tu8/OdB9Sh1iu0+pQ2z3KXWA7X3xKXWI7T6lDrHdp9QhtvuUOsR2cdtH2O5T6hDbfUodYrtPqUNs9yl1iO0+pY6wPfiUOsR2n1KH2O5T6hDbfUodYru47SNs9yl1iO0+pQ6x3afUIbb7lDrEdp9SR9gefUodYrtPqUNs9yl1iO0+pQ6xXdz2Ebb7lDrEdp9Sh9juU+oQ231KHWK7T6kjbE8+pQ6x3afUIbb7lDrEdp9Sh9gubvsI2+fK7aqMo57mStfK5syVgXXNkbmSqrI5c+VJZXPmSn3K5syVzZTNETfnvTlzncYrmzPXmbmyOZ6QP5jDm5B3MXpdeBPyvjmZNyEfMIc3IR8whzch7wKveuZNyAfMETfnvTm8CfmAObwJ+YA5vAn5gDm8CXn/14fMm5D3zSm8CfmAObwJ+YA5vAn5gDm8CfmAOeLmvDeHNyEfMIc3IR8whzchHzDHE/IHczwhvzenekL+YI4n5A/meEL+YI4n5A/miJvz3hxPyB/M8YT8wRxPyB/M8YT8wRxPyO/NaZ6QP5jjCfmDOZ6QP5jjCfmDOeLmvDfHE/IHczwhfzDHE/IHczwhfzDHE/J7cya761zZHE/IH8zxhPzBHE/IH8wRN+e9OZ6QP5jjCfmDOdZzToibOUsOe+Z84b1jSVvVpT08iZxevXPo2x/ZxCXegSOhLt9dpL2/GKyL+Vt7fZHWRbKe+3yR1kWynj99kdZFsp6DfZHWRRJfJPuLZH0u8EVaF8n6fOKLtC6S9V8SfJHWRbL+i4Yv0rpIfuJgf5HM38A8/yLtQV3WRfITB4BF8hMHgEXyEweARRJfpMGLtIduWRfJTxwAFslPHAAWyU8cABbJTxwAFslPHOwvkvnbtOdfpL2nhdZF8hMHgEXyEweARfITB4BFEl8k+4vkJw4Ai+QnDgCL5CcOAIvkJw4Ai+QnDvYXyfzN6L5I6yL5iQPAIvmJA8Ai+YkDwCKJL5L9RfITB4BF8hMHgEXyEweARfITB4BF8hMH+4skfuIAsEh+4gCwSH7iALBIfuIAsEjii2R/kfzEAWCR/MQBYJH8xAFgkfzEAWCR/MTB/iJlP3EAWCQ/cQBYJD9xAFgkP3EAWCTxRbK/SH7iALBIfuIAsEh+4gCwSH7iYH+RCu+clMtme1nC3iKlevM9SL4vUpT20vjbi3N9eOcYHoznnX0GG887zww2Xtz4Mcbzzh2DjeedJc40vudfLy5LfmM873ww2HjezD/YeN5fDscaX3l/DTzV+LAZX94Y75PrION9ch1kvE+ug4wXN36M8T65DjLeJ9czjG/bJUGtvTHeJ9dBxvvkOsh4n1zHGN98ch1kvE+ug4z3yXWQ8T65DjJe3PgxxvvkOsh4n1wHGe+T6yDjfXIdZLxPrmOM7z65DjLeJ9dBxvvkOsh4n1wHGS9u/BjjfXIdZLxProOM98l1kPE+uQ4y3ifXIcavDrvxY4z3yXWQ8T65DjLeJ9dBxosbP8Z4n1wHGe+T6yDjfXIdZLxProOM98l1jPHBJ9dBxvvkOsh4n1wHGe+T6yDjxY0fY7zn+GPGxyC3QmKre8bvEppC8Bw/yHjP8WOMj57jBxnvOX6Q8Z7jzzB+FyIRouf4QcaLGz/GeP8FapDx/gvUION9ch1kvE+uZxi/f1YTfXIdY3zyyXWQ8T65DjLeJ9dBxvvkOsh4cePHGO+T6yDjfXIdZLxProOM98l1kPE+uY4xXnxyHWS8T66DjPfJdZDxPrkOMl7c+DHG++Q6yHifXAcZ75PrION9ch1kvE+uY4zPPrkOMt4n10HG++Q6yHifXAcZL278GON9ch1kvE+ug4z3yXWQ8T65DjLeJ9cxxhefXAcZ75PrION9ch1kvE+ug4wXN36M8T65DjLeJ9dBxvPm+NDyVrX0HeMP8DgqbzJXt5I3a6tbyZue1a3kzcPqVopbecjKfntxWfIbK3kzq7qVvClU3UreX0TUreT9jeOLVu7CZapPO1pWNp921Kz0aUfNSp921Kz0aUfNSnErD1m5f17ZfNpRs9KnHTUrfdpRs9KnHTUrfdrRsrL7tKNmpU87alb6tKNmpU87alaKW6llpU87alb6tKNmpU87alb6tKNmpU87SlbGxacdNSt92lGz0qcdNSt92lGzUtxKLSt92lGz0qcdNSt92lGz0qcdNSt92tGyMvi0o2alTztqVvq0o2alTztqVopbqWWlTztqVvq0o2alTztqVvq0o2alTztaVkafdtSs9GlHzUqfdtSs5M2VS7ppXM/HZM/KXUpBjLy5Ut1K3lypbiVvrlS3kjdXaluZeHPl16zcBT7ExJsr1a3kzZXqVvKeoqtbKW7lMSv3/rQ+Jp921Kz0aUfNSp921Kz0aUfNSp92tKwUn3aOWbl/Xik+7ahZ6dOOmpU+7ahZKW6llpU+7ahZ6dOOmpU+7ahZ6dOOmpU+7WhZmX3aUbPSpx01K33aUbPSpx01K8Wt1LLSpx01K33aUbPSpx01K33aUbPSpx0tK4lvWFe30qcdNSt92lGz0qcdNSvFrdSy0qcdNSt92lGz0qcdNSt92lGz0qcdLSuJb61Xt9KnHTUrfdpRs9KnHTUrxa3UstKnHTUrfdpRs9KnHTUrfdrRspL3fvDQNndCl7Zn5T6lgPd+cH0raXOlvpXiVmpZSZsr9a2kzZVftHIf+MB7P7i+lbS5Ut9K2lN0dSt57wf/qpW7f1rPez+4vpU+7ahZ6dOOmpXiVmpZ6dOOmpU+7Ryzcv+8kvd+cH0rfdpRs9KnHSUrE+/94PpW+rSjZqVPO2pW+rSjZqW4lVpW+rSjZqVPO2pW+rSjZqVPO2pW+rSjZSXv/eD6Vvq0o2alTztqVvq0o2aluJVaVvq0o2alTztqVvq0o2alTztqVvq0o2Ul7/3g+lb6tKNmpU87alb6tKNmpbiVWlb6tKNmpU87alb6tKNmpU87alb6tKNlJe+t9fpW+rSjZqVPO2pW+rSjZqW4lVpW8ubKupTbW9fa96zcpRQk3vvB9a3kzZXaVvLeD65vJW+uVLeSN1d+zcrdPxdNvPeD61spbqWWlbyn6OpW8p6iq1vp046alT7tHLNyfwbnvR9c3Ure+8H1rfRpR81Kn3bUrPRpR81KcSu1rPRpR81Kn3bUrPRpR81Kn3bUrPRpR8tK3vvB9a30aUfNSp921Kz0aUfNSnErtaz0aUfNSp921Kz0aUfNSp921Kz0aUfLSt77wfWt9GlHzUqfdtSs9GlHzUpxK7Ws9GlHzUqfdtSs9GlHzUqfdtSs9GlHy8rm046alT7tqFnp046alT7tqFkpbqWWlT7tqFnp046alXPlyta39447751lM0d+r2MzZ7Ibv5XNmSv7KZszV5pTNmeufKZsjrg5782ZK0MpmzNXKlI2Z65TXWVz5jqnVTbHE/Jbc2SyW6K/Yk5bbub0/MYc3oR8wBzehHzAHN6EfMAcoTWn3s0pb8zhTcgHzOFNyAfM4U3IB8zhTcgHzOFNyPvmTHaz8FfMye1mTqlvzOFNyAfM4U3IB8zhTcgHzBE35705vAn5gDm8CfmAObwJ+YA5vAn5gDm8CXnfnMluo1U2xxPyB3M8IX8wxxPyB3PEzXlvjifkD+Z4Qv5gjifkD+Z4Qv5gjifk9+ZMdoOpsjmekD+Y4wn5gzmekD+YI27Oe3M8IX8wxxPyB3M8IX8wxxPyB3M8Ib83Z7K7WJXN8YT8wRxPyB/M8YT8wRxxc96b4wn5gzmekD+Y4wn5gzmekN+bY/xexaVtOI6w9Ad4x2tzer29utc3f31n/PbDEwTbziMnCBY2wbZzwwmCbWeBLwpe6162l8e+8+693fb03t/t6bbTwHB7bOeB4fbYPjMbbY/xW+6G2zNVntS3Z6r0qW/PVFn1a/Z8ZbB7X/XdSnErtaycKl+PtZI4uWtbSZzyta0kngi0rSSeHpStNH7DHJSVxFOJtpXEE4y2lT7tqFkpbqWWlT7tqFnp046alT7tqFnp046alT7taFlp/IY5KCt92lGz0qcdNSt92lGzUtxKLSt92lGz0qcdNSt92lGz0qcdNSt92tGy0vgtiVBW+rSjZqVPO2pW+rSjZqW4lVpW+rSjZqWHoUNW7l+Il41fiAdlpbedY1bu/mVsXrztqFnpbUfNSj9kU7PSD9nUrPRDNjUrPVcesrKE8uu1JcXXVhq/Rg7KSj9kU7PSD9nUrPRpR81KcSu1rPRpR81Kn3bUrPRpR81Kn3bUrPRpR8tK41cCQlnp046alczTzlcqSXF75/T4zkt5MJN53lE3U9xMPTOZZx51M5mnHnUzmecedTOZJx91M5lnny+ZmbdCUgmvzTR+3SOYmczzj7qZPgEpmukTkKKZ4mbqmekTkKKZPgH9hZntjZk+ASma6ROQopk+AR00s9/Hyf5mnDR+nSeYmT4BKZrpE5CimT4BKZopbqaemT4BKZrpE9B/fv/Xt9n4hafD7fEp5aM9Pnd8sif7JPHRHp8NPtrjaf+jPXNdx7t7p1ue7DreA4Lnuo73gOCpsuoRwVOlzyOCp8qTRwRPlRAPCJ7rWtsjgqdKcUcET5XLjghmS1pzXfl6RDBb0prr+tQjgtmS1lxXkR4RzJa05rrW84hgtqQ11xWZRwSzJa25rps8Ipgtac11deMRwWxJa65rEI8IZktac10peEQwW9Ka63q+I4LZktZcV90dEcyWtOa6Nu6IYLakNdcVbEcEsyWtua4zOyKYLWnNdTXYEcFsSWuua7aOCGZLWp0taXW2pNXZktZct7DtCy5z3ZV2RDBZ0ioLWdIqc91Zd0SwsAkmS1plrlvajggmS1plrhvPjghmS1pz3R52RDBb0prrJq4jgtmS1ly3Wh0RzJa05roh6ohgtqQ1121LRwSzJa25bi46Ipgtac11C9ARwWxJa67bdI4IZktac91Kc0QwW9Ka63aXI4LZktZct6QcEcyWtOa6beSIYLakNdetHUcEsyWtuW6/OCKYLWnNdYvEEcFsSWuu2xiOCGZLWnPdanBEMFvSmut2gCOC2ZLWXJT9I4LZktZcJPwjgtmS1ly0+iOC2ZLWXET5I4LZkhYbI76wMeILGyO+sDHiCxsjvrAx4gsbI76wMeILGyO+sDHiCxsjvsxFEP/idVStb5XEnddmudWRJb2xkvlWQWUrmW8g1LVyLp76WCuZbzZUtpL5FkRlK5lvPFe2UtxKLSuZbztXtpL5rnNlK33aUbPSp51jVrbbG+ee31jp046WlXPdaTDWSp921Kz0aeeYlfVuZXljpU87alaKW6llpU87alb6tKNmpU87alb6tHPMynz7xTGXN784znX7x1Ar57pXZKyVPu2oWenTjpqVPu2oWSlupZaVPu2oWenTjpqVPu2oWenTjpqVPu0oWVnnuttnrJU+7ahZ6dOOmpU+7ahZKW6llpU+7ahZ6dOOmpU+7ahZ6dOOmpU+7WhZOdf9WmOt9GlHzUqfdtSs9GlHzUpxK7Ws9GlHzUqfdtSs9GlHzUqfdtSs9GlHy8q57rgba6VPO2pW+rSjZqVPO2pWilupZaVPO2pW+rSjZqXxXFnT3Zv2wAd4A6GrN+N7fc0SqNbv3dMXbDyj6Qs2nqT0BRvPO/qCZSbBX9v/9zmb1fotfaPtMZ4eRttj/PxztD3GzzRH2zNVnlS3x/pdhKPtmSqrnjfYva/6buVUKXislVPl67FWilupZSVxyte2kngi0LaSeHrQtpJ40tC2kngqUbbS+h2fSFb6tKNmpU87alb6tKNmpbiVWlb6tKNmpU87alb6tKNmpU87alb6tKNlpfV7dpGs9GlHzUqfdtSs9GlHzUpxK7Ws9GlHzUqfdtSs9GlHzUqfdtSs9GlHy0rr93cjWenTjpqVPu2oWenTjpqV4lZqWenTjpqVPu2oWenTjpaV1q/3tWLl/lXo1fr1vkhWets5ZuU+RcD6RapIVnrbUbPSD9nUrPRDNi0rrV+kimSl58pDVpZQfr22pPjGSs+Valb6IZualeJWalnp046alT7tqFnp046alT7tqFnp046Slc36RapIVvq0o2alTztqVvq0o2alEFv5hUokye1oSFJ+OBtayoOZzPOOupnME4+6mcwzj7qZzFOPupnMc4+2mdYvVcUyk3n2+ZKZbdnMbP2NmczTj7qZzPOPupniZuqZ6ROQopk+Af3/7L1dmuNK0qO5o3lE0vxvP72N2fuoplJSZFdScp1jTDcY0Fd9oYokXjsfHTBFwB1hKgE5wlQC+h7mqCcwlYD8YEa/aBULphLQHEzbnnHS9pM4Gf2yVSyYSkCOME0w/WAqATnCVAJyhKkE5AhTCWgSZjmeMOt+AlMJyA9mrsuGV8NUAnKEqQTkCFMJyBGmCaYfTCWg/3NeTNKZr4KewaOU8haPcsdbPEoS7/AwXwU9g0du/y2eVP7989XgPdclzDOCjU1wKq86IziV+5wRnMpPzghO5RBnBKfyfBOCc12HOyM4lS+bEczmtHJdADsj2NgEszmtXFeezghmc1q5rg+dEczmtHJdxTkjmM1p5brWckYwm9PKdUXkjGA2p5XrusUZwWxOK9fVhTOC2ZxWrmsAZwSzOa1cV+rNCGZzWrmup5sRzOa0cl31NiOYzWk1NqfV2JxWZ3NauW4CnBHM5rQ6m9PqxiaYzWnlut1wRjCb08p1U+CMYDanlevWvRnBbE4r1w12M4LZnFau2+BmBLM5rVw3q80IZnNauW4pmxFM5rRGrhu/ZgSTOa2R6/asGcFkTmvcjE0wmdMauW50mhFM5rRGrpuRZgSzOa1cNwzNCGZzWrlu6pkRzOa0ct14MyOYzWnlujlmRjCb08p1A8uMYDanlesmkxnBbE4r140gM4LZnFaumzVmBLM5rVw3VMwIZnNauW56mBHM5rRy3ZgwI5jNaeW6eWBGMJvTytXgPyOYzWnl6s2fEczmtHJ1288IZnNaufrnZwSzOS22jvjB1hE/2DriB1tH/GDriB9sHfGDrSN+sHXED7aO+MHWET/YOuIHW0f8YOuIH2wd8YOtI36wdcQPto74wdYRP9g64gdbR/xg64gfbB3xg60jfrB1xA+2jvjB1hE/2DriB1tH/GDriB9sHfGDrSN+sHXED7aO+MHWET/YOuIHW0f8YOuIH2wd8YOtI36wdcQPto74wdYRP9g64gdbR/xg64gfuRrE78/9+vg+Pvz01sfzSfYPny22//pssePPKHN1k69Fmco7rEWZypWsRZnK76xFaULphTKVR1uLMpX7W4sy1QZvLcpUu8G1KJV2fFD2W677AS5E2R8/uIxyglJpxw2l0o4bSqUdN5QmlFMo2wtlPUGptOOGUmnHDaXSjhtKpR03lEo7Xihz3dFxIcry+Max1HaCUmnHDaXSjhtKpR03lCaUXiiVdtxQKu24oVTacUOptOOGUmnHC2Wue3LWolTacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8UKZ666qtSiVdtxQKu24oVTacUNpQumFUmnHDaXSjhtKpR03lEo7biiVdrxQ5rovbi1KpR03lEo7biiVdtxQmlB6oVTacUOptOOGUmnHDaXSjhfK6PfulV6eD1LHJ5SjPboERjtOBAd3f/6Cg3s0f8HGJji43/EXHNyVfCf4u/f/x57NO57gTmM1nuDuYTWe4PvPxXii3xe4Gk8qP+mPJ5X79MeTyqteF+zOn/qF0oTSC2Uqf70WJbFz90ZJ7PK9URInAm+UxOnBGWX0+zKRUBKnEm+UxAnGG6XSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOFMvqdtUgolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UEa/vxsJpdKOG0qlHTeUSjtuKE0ovVAq7bihVNpxQ6m044ZSaccNpdKOE8ot+vW+UVB+vgr9DkoovVDq2JlD+bFFYIt+kSoSSh07XiijX6SKhFJLNjeUWrK5oZSvnEJZt/rrs/XYT1CaUHqh1JLNDaWWbG4olXbcUCrtuKFU2vFCGf0iVSSUSjtuKJV23FAq7bihNKH0Qqm044aSOe188STd9sdqqNvxYzd0qz9gMucdd5jMiccdJnPm8YYZ/UJVLJjMuccdJnPycYfJnH2+gllvT5h1nMA0wfSDyZx/3GEqATnCVAJyhKkE5AhTCcgPZvRLVkPCbPUEphKQI0wlIEeYSkCTMMczTpbbSZyMftkqFkwlIEeYSkCOMJWAHGEqATnCVALyg1mUgOZgFnv6zGIncTLXhcCrYSoBOcJUAnKEaYLpB1MJyBGmEpAjTCWg72GWkxUc88XR/jCVgPxgMl9KPdE/xHwp9QwepZS3eJQ73uIx4XmHR9ngLR65/bd4Uvn30R/L3DFOKl1yXcU8IziVD54QnOta4xnBqdznjOBUfnJGcCqHOCPY2ASncnEzglP5shnBbE4r1zWwM4LZnFauK1VnBLM5rVzXk84IZnNaua76nBHM5rRyXZs5I5jNaeW6gnJGMJvTynWd44xgNqeV62rEGcFsTivXNYMzgtmcVq4r+2YEszmtXNffzQgmc1r7jcxp7Tcyp7XfyJzWnut2xBnBxiaYzGntNzKntee6S3JGMJnT2nPdyzghONftiTOC2ZxWrpsIZwSzOa1ct/rNCGZzWrluyJsRzOa0ct02NyOYzWnlurltRjCb08p1C9qMYDanletGsRnBbE4r1+1cM4LZnFauW65mBLM5rVy3Rc0IZnNauW5dmhHM5rRy3V40I5jNaeW6BWhGMJvTynWbzoxgNqeV61aaGcFsTivX7S4zgtmcVq5bUmYEszmtXLeNzAhmc1q5bu2YEczmtHLdfjEjmM1p5bpFYkYwm9PKdRvDjGA2p5XrVoMZwWxOK9ftADOC2ZxWrpb9GcFsTitXE/6MYDanlautfkYwm9PK1Sg/I5jNabF1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRv7N1xO9sHfE7W0f8ztYRf7B1xB9sHfEHW0f8wdYRf9yMTTCZ0zrYOuIPto74g60j/mDriD/YOuIPto74I1eD+P25b8+P7+PDT299PJ9k//DZYvuvzxY7TlCmOuHXokzlHdaiTOVK1qJM5XfWokzlpJaizNUuvxZlKve3FmWqDd5alKl2g2tRmlB6oVTamUPZHz+4jHKCUmnHDaXSjhtKpR03lEo7cyjbC2X9M8pcNzysRam044ZSaccNpdKOG0oTSi+USjtzKMvjG8dST75xzHX7x1qUSjtuKJV23FAq7XihzHXLylqUSjtuKJV23FAq7bihNKH0Qqm044ZSaccNpdKOG0qlHTeUSjteKHPddLQWpdKOG0qlHTeUSjtuKE0ovVAq7bihVNpxQ6m044ZSaccNpdKOF8pct42tRam044ZSaccNpdKOG0oTSi+USjtuKJV23FAq7bihVNpxQ6m044Uy141/a1Eq7bihVNpxQ6m044YyuK88tuPHg3xCOdqjS2C040RwcPfnLzi4R/MXHNxJuQuOfu+ev+DgruQ7wd+9/yd6NqPf0rcaT3D3sBqPCc87PMF3mqvxpPKT/nhSuU9/PKm86nXB7vypXyhTueClKKPftoiEkti5e6MkdvneKIkTgTdKE0ovlMRJwxslcSrxRkmcYLxRKu24oVTacUJp0W88RUKptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOFMvqtw0golXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UEa/vxsJpQnl1N8gfrze16Jf74uEUsfOHMqPfxlr0S9SBUIZ/SJVJJRasrmh1JLNDaWWbG4oTShnUNat/vpsPfYTlPKVbii1ZHNDqSWbG0qlHTeUSjteKKNfpIqEUmnHDaXSjhtKpR03lCaUXiiVdtxQKu24oWROO988yd6eRPZ+e31633/AZM477jCZE483zOjXqWLBZE497jCZc487TObk4w7TBHMOpvUXzO03mP/76XE8/OuoP56i//Epnl/HtWE/fu6PGTGHKpQZMac1lBkpBsafkdJl/BkptIafUfTLdjWj+4wUsePPSMk9/oy0EIg/I9OMws9Ie4a5Jzlu9vjJx89P/wZTCwFHmErujjAVsR1hKgv7wYx+ZzIWTKVLR5iKgZMwj/qEaeUEpvKaI0wTTD+YSkCOMJWAHGEqATnCVAJyhKkE9D3Mnxp/wsx1i/pqmEpAjjCVgP7PmyY25vvcZ/CY8LzDo9zxFo+SxFs8ygZv8cjtv8WTyr+P/viWe4yTcqtcN6nPCE7lg2cEp/KqM4JTuc8ZwcYmOJVDnBGcyvPNCE7l4mYEp/JlM4LJnFbJdYvzjGAyp1Vy3Yg8I5jMaZWbsQkmc1ol1029M4LJnFbJdevtjGA2p5XrBtkZwWxOK9dtrDOC2ZxWrptNZwSzOa1ct4TOCGZzWrlu3JwRzOa0ct1eOSOYzWntbE5rZ3Naua5NnRHM5rR2Nqe1szmtXJfMzghmc1q5LmydEczmtHJdfjojmM1p5bpIdEYwm9PKdSnnjGA2p5XrgssZwWxOK9dlkTOC2ZxWrosXZwSzOa1clxjOCGZzWrkuBJwRzOa0cl2tNyOYzWnluqJuRjCb08p11duMYDanlevKtBnBbE4r12VeM4LZnFaua6ZmBLM5rVwXIM0IZnNaua7mmRHM5rRyXRozI5jNaeW6JWVGMJvTynXbyIxgNqeV69aOGcFsTivX7RczgtmcVq5bJGYEszmtXLcxzAhmc1q5bjWYEczmtHLdDjAjmM1p5WrZnxHM5rRyNeHPCGZzWrna6mcEszmtXI3yM4LZnBZbR3xh64gvbB3xha0jvrB1xBe2jvjC1hFf2DriC1tHfGHriK9sHfE1V4P4l9dR9fF8kv3DZ4vtvz5b7DhBmeqEX4uS+QZCZ5TMtxU6o2S+2dAZJfMtiM4omW8890WZq7d+LUrm286dUTLfde6MUmnHDaUJ5RTK/vjB943oCUqlHTeUSjtuKJV23FAq7cyhbC+U9QSl0o4Xylx3R6xFqbTjhlJpxw2l0o4bShPKKZTl8Y1jqSffOOa6/WMtSqUdN5RKO24olXbcUCrteKHMdX/LWpRKO24olXbcUCrtuKE0ofRCqbTjhlJpxw2l0o4bSqUdN5RKO14oc92htBal0o4bSqUdN5RKO24oTSi9UCrtuKFU2nFDqbTjhlJpxw2l0o4Xylz3mK1FqbTjhlJpxw2l0o4bShNKL5RKO24olXbcUCrtuKFU2nFDqbTjhTLXXYJrUSrtuKFU2nFDGdxXbvX1IPu+f0A50SUQ/d49f8HBPZq/4OBOyl9wcL/jLjj6vXv+goN7B3/BwU94f8HBt47+go1NMJvTin7v3peCP1evRL93z19wLqc1ITiX0/osOPq9e18K/ly+EP3ePX/BuZzWhOBcTmtCsLEJzuW0JgTnclqft5bR793zF5zLaU0IzuW0PguOfu+ev+BcTmtCcC6nNSE4l9OaEGxsgnM5rQnBbE4r+r17/oLZnFb0e/e8Bbfo9+75CyZzWu1G5rRa9JsV/QUbm2Ayp9Wi3yXoL5jMabXo9/L5C2ZzWtHvuPMXzOa0ot8X5y+YzWlFv3vNXzCb04p+j5m/YDanFf1OMH/BbE4r+v1a/oLZnFb0u6r8BbM5rej3PvkLDn0OjzFef8W57dsHvaM9fiF+tONEb+hj+AK9oU9hf72xr325QG/oM/gCvaGP4C/1fvdX56M/3uZjnLzNY9+JspxO6MN9OZ3QO5fldEIvaJbTyeQi/elk8pz+dDI51Ot6ZM4f+kky9iUgUCQzueq1JHn9ujdJXm/vTdJE0okkb2bwJsmbL7xJ8mYRb5K8ucWbpDKOE8nYV39AkVTG8SKpjONFUhnHi6SJpBNJZRwvkso4XiSVcbxIKuN4kVTGcSIZ+8IPKJLKOF4klXG8SCrjeJE0kXQiqYzjRVIZx4ukMo4XSWUcL5LKOE4kY18fBEVSGceLpDKOF0llHC+SJpJOJJVxvEgq43iRVMbxIqmM40VSGceJZOyLu6BIKuN4kVTG8SKpjONFUi5ohuTn615b7CuqkEjGvhkpDsnPDVOxr1yCIqkTx4ukiaQTSW3VvEhqq+ZFUn5yhmTd6q/P1mM/ISk/6UVSWzUfkj321WFQJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEjGvrQPiqQyjhdJZRwvkso4XiRNJJ1IEmecLx5k354o9+0or+fo40+fLuXx4badcCdOREu5E+enpdyJ09ZS7sTZzIn7k2Xsiz7BWBLnM3eWxAnNnSVxRnNnaWLpxlI5zY+lspcfS+WpOZbjadX3W/+N5T/a26S6zxiJu/KUP/d9f/Kw8mfuqe53RuKunLaGuzLdGu7Kf2u4m7gv4a5cuYa7MugF3D9/H0J8Y/la7sqra7grry7hznwn+zfc96M/JXb7wH0rz6cudsJdeXUNd+VVf+6+fUud+SZ5mBmZZhR+RsrM8WekfB1/Rsri8Wek3B5/Rsr44WdUtA+IPyPtDuLPSHuG+DPSniH+jEwzCj8j7Rniz0h7hvgz0p4h/oy0Z4g/I+0Zws+oas8Qf0baM8SfkfYM8WekPUP8GZlmFH5G2jPEn5H2DPFnpD1D/BlpzxB/RtozhJ9R054h/oy0Z4g/I+0Z4s9Ie4b4MzLNKPyMlI/Wzujz/ee9KR+Fn1GXr1s8o493EfcuXxd/RvJ18WdkmlH4Gen7o/gz0vdH8WekfLR2RhP9v135KP6M9P1R+BkNfX8Uf0baM8SfkfYM8WekPUP8GZlmFH5G2jPEn5H2DPFnpD1D/BlpzxB/RtozRJ/RuGnPEH9G2jPEn5H2DPFnpD1D/BmZZhR+RtozXDCjL37yNl7PPLYfz3yzfzhRbSWyTVQ7jGwT1cYj20S1H4k70eeUNm1IEKakHQnClLQlQZiS9iQIUzJNCWBK2pUgTEn7D4QpaaeBMCXtKRCmpN3D6im1B+r9ttXfpvSH5/h4o/rYtafINlHtNJAm6tsGNHbtSpinrx0M8/RN0yeevnZGzNPXLop5+tpxMU9fuzPm6WsnRzz9Q/s75ulr18c8fe36mKevXR/z9E3TJ56+dn3M09euj3n62vUxT1+7Pubpa9dHPH3Tro95+tr1MU9fuz7m6WvXxzx90/SJp69dH/P0lfezTv/znbTDlPeJp1/k+dNO/+O9haPI8zNP3zR94unL8zNPX9/vM09f3+8zT195P+v0J7p9i/I+8fSrvt9nnr6+32eevnZ9zNPXro95+qbpE09fuz7m6WvXxzx97fqYp69dH/P0tesjnn7Tro95+tr1QU3/m5+8jcczb/vtx7d8ffsxf237uOevfR/3/E3zp56/dn7c89fWj3v+2vtxz1+bvxzzf01U27xkE+3a0K2d6H4rt+dER/kw0Ymb8bq2btkmqj0a0kSduxG6tmjM0zdNn3j62qAxT1/7M+bpa3vGPH3tzpinrz0b8fSHdnLM09f+jnn62vUxT1+7Pubpm6ZPPH3t+pinr10f8/S162OevnZ9zNPXro92+uOOS9Mnnr52fczT166Pefra9TFP3zR94ulr18c8fe36mKevvJ91+h9vuxu3TXmfefry/Gmn/+nWm/v0TdMnnr48P/P05fmZp6/v95mnr+/3maevvJ91+h87kMdtV95nnr6+32eevr7fZ56+dn3M0zdNn3j62vUxT1+7Pubpa9fHPH3t+pinr10f8fQP7fqYp69dH9T0v/jJE7dd3OevbR/3/LXv456/af7U89fOj3v+2vpxz197P+75a/OXY/6viWqbl2yipg3d4oneX6WPn7wd7cNEt/s4Hgq3w05mqr1bvplql4Y0U3t+2I7bh5/887P9ZPrapDFP3zT9pNO/P/PjB1s5mb62aMzT1w6NefraoDFPX/sz5ulr10Y8/aK9XNrpl/L4wW07mb42eMzT166Pefra9TFP3zR94ulr18c8fe36mKevXR/q9E++tyva32WbqHZyySZatWfLNlHtzrJNVPuwbBPVjivbRE0TTTZR7aKyTVT7pWwT1c5o9URff4+11U9/jzX1lx5VW6N8M9XeKN1MmzZH+Waq3VG+mWp7lG+m2h/lm6lppulmqh1Svplqi5Rvptoj5Zup9kj5Zqo9UrqZdu2R8s1Ue6R8M9UeKd9MtUfKN1PTTNPNVHukfDPVHinfTLVHyjdT7ZHyzVR7pHQzHdoj5Zup9kj5Zqo9Ur6Zao+Ub6ammaabqfZI+WaqPVK+mWqPlG+m2iPlm6n2SNlmeqegmaabqfZI+WaqPVK+mWqPlG+mppmmm6n2SPlmqj1Svplqj5Rvptoj5Zup9kjpZrppj5Rvptoj5Zup9kj5Zqo9Ur6ZmmaabqbaI+WbqfZI+WaqPVK+mWqPlG+m2iOlm+muPVK+mWqPlG+m2iPlm6n2SPlmapppuplqj5Rvptoj5Zup9kj5Zqo9Ur6Zao+UbqaH9kj5Zqo9Ur6Zao+Ub6baI+WbqWmm6WaqPVK+mWqPlG+m2iPlm6n2SPlmqj1Supma9kj5Zqo9Ur6Zao+Ub6baI+WbqWmm6WaqPVK+mWqPlG+m2iPlm6n2SPlmqj1SupkW7ZHyzVR7pHwz1R4p30y1R8o3U9NM081Ue6R8M9UeKd9MtUfKN1PtkfLNVHukdDOt2iPlm6n2SPlmqj1Svplqj5RvpqaZppup9kj5Zqo9Ur6Zao+Ub6baI+WbqfZI6WbatEfKN1PtkfLNVHukfDPVHinfTE0zTTdT7ZHyzVR7pHwz1R4p30y1R8o3U+2R0s20a4+Ub6baI+WbqfZI+WaqPVK+mZpmmm6m2iPlm6n2SPlmqj1Svplqj5RvptojpZvp0B4p30y1R8o3U+2R8s1Ue6R8MzXNNN1MtUfKN1PtkfLNVHukfDPVHinfTLVHyjbT/aY9Ur6Zao+Ub6baI+WbqfZI+WZqmmm6mWqPlG+m2iPlm6n2SPlmqj1Svplqj5Ruppv2SPlmqj1Svplqj5Rvptoj5ZupaabpZqo9Ur6Zao+Ub6baI+WbqfZI+WaqPVK6me7aI+WbqfZI+WaqPdLfnOmLu3Y9a7ibuC/hrp3JGu7aa6zhrt3DGu7aD6zhrgw/xf3Yy0Pi8RPIH7lPOfhDSXsVeeVhf/KHPZ76KPbhJ9et/vpsPfaTGSnfxp+RsnD8GZlmtHRGd8f2+MFWTmakjB1/Rsrj8Wek7B5/Rsr58WeknUD4GZm2B/FnpD3D4hmV5w9u28mMtGeIPyPtGeLPyDSj8DPSniH+jLRniD8j7RkunVE9467dwRru2gcs4V6U8ddwV25fw11ZfI57357cR//Afeo3YooS9iryJvLu5J1/h6IoN8efkXLz2hlNfB9SlJvjz0gZO/6MlMfDz6gqu8efkXJ+/BlpJ7B4Rp+/D6naHsSfkWlG4WekPUP8GWnPEH9G2jPEn5H2DPFnpD3DpTM6+x60aXewhrv2AWu4K+Ov4a7cvoa7ifsS7srXa7grM6/hrhy8hruy7RruyqtT3G0bD4l2fOoQnPotxq7Euoq8Musq8kqtq8grt64ibyK/iLyy6yrySq+ryCu/riKvBLuKvDLsIvJDGXYVeWXYVeSVYVeRV4ZdRd5EfhF5ZdhV5JVhV5FXhl1FXhl2FXll2DXkj5sy7CryyrCryCvDriKvDLuKvIn8IvLKsKvIK8OuIq8Mu4q8Muwq8sqwi8hvyrCryCvDriKvDLuKvDLsKvIm8ovIK8OuIq8Mu4q8Muwq8sqwq8grwy4ivyvDriKvDLuKvDLsKvLKsKvIm8gvIq8Mu4q8Muwq8sqwq8grw64irwy7iPyhDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7CLypgy7irwy7CryyrCryCvDriJvIr+IvDLsKvLKsKvIK8OuIq8Mu4q8Muwi8kUZdhV5ZdhV5JVhV5FXhl1F3kR+EXll2FXklWFXkVeGXUVeGXYVeWXYReSrMuwq8sqwq8grw64irwy7iryJ/CLyyrCryCvDriKvDLuKvDLsKvLKsIvIN2XYVeSVYVeRV4ZdRV4ZdhV5E/lF5JVhV5FXhl1FXhl2FXll2FXklWEXke/KsKvIK8OuIq8Mu4q8Muwq8ibyi8grw64irwy7irwy7CryyrCryCvDLiI/lGFXkVeGXUVeGXYVeWXYVeRN5BeRV4ZdRV4ZdhV5ZdhV5JVhV5FXhl1D3m7KsKvIK8OuIq8Mu4q8Muwq8ibyi8grw64irwy7irwy7CryyrCryCvDLiK/KcOuIq8Mu4q8Muwq8sqwq8ibyC8irwy7irwy7CryyrCryCvDriKvDLuI/K4Mu4q8Muwq8sqwq8grw/7vg7zomOi8oaMs+I6O8to7OspU7+go97yjo2zyhs6h/PCOjjz+Ozry4e/oyCu/o2Oi84ZOJq88ev/16THaid5M7ndGbyY/O6M3k0Od0ZvJc07otUwuckZvJl84ozeT05vRm8m7zeg1Mr1k/srI/JWR+Ssj81dG5q8Kmb8qZP6qkPmrQuavipHpJfNXhcxfFTJ/Vcj8VSHzV5XMX1Uyf1XJ/FUl81fVyPSS+atUN9TP6CXzV6luY5/RS+avUt08PqOXzF+lumV7Ri+Zv0p1o/SMXjJ/ler25Bm9ZP4q1U3BM3rJ/FWqW3Fn9JL5q1Q3wM7oJfNXqW47ndFL5q9S3ew5o5fMX6W6xXJGL5m/SnVj44xeMn+V6nbCGb1k/irVTXwzesn8Vapb52b0kvmrVDeszejl8lcl1W1iM3q5/FVJdXPWjF4uf1VuRqaXy1+VVDcizejl8lcl1e0/M3rJ/FWqm25m9JL5q1S3uszoJfNXqW4wmdFL5q9S3dYxo5fMX6W6mWJGL5m/SnULw4xeMn+V6saBGb1k/ipVc/+MXjJ/lapdf0Yvmb9K1YA/o5fMX6VqqZ/RS+avUjXJz+gl81ep2t5n9JL5K7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1t1ey/vZK1t9eyfrbK1l/e70ZmV4uf1XJ+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eU/V73x/79vz4Pj788G8eZN+P/pTY7fUcffzbn3wrj2feb6P8gGd/+sl9PH/y/uEnF9t/fbbYcTL9TG5E0/9y+qm63zX9b6efyalq+t9OP5Nv1/S/nX6mFKPpfzt90/SJp58p4Wr6304/0/cpmv6308/07ZKm/+30tetjnr52fWmn3x8/uPz8uT+nn+oeIk3/2+lr18c8fe36mKevXV/a6bfX9OvJ9E3TJ56+dn3M09euj3n62vUxT1+7Pubpa9eXdvrl8cilnvxOb6o7MTX9b6evXR/z9LXrY56+dn3M0zdNn3j62vUxT1+7Pubpa9fHPH3t+pinr10f8fRT3c+u6X87fe36mKevXR/z9LXrY56+afrE09euj3n62vUxT1+7Pubpa9fHPH3t+oinP7TrY56+dn3M09euj3n62vUxT980feLpa9fHPH3t+pinr10f8/S162OevnZ9vNNvN+36mKevXR/z9LXrY56+dn3M0zdNn3j62vUxT1+7Pubpa9dHPP1NeX/t9Lf7DJ7T36rn9D/ezdE25X3m6SvvM09feZ95+qbpE09feZ95+sr7zNNX3meevn63h3n6+t0e4unv2vUxT1+7vrTT/3gbY9u162OevnZ9zNM3TZ94+tr1pZ3+xxvZ2q5dH/P0tetjnr52fczT166PePqHdn3M09euL+30P/9O76FdH/P0tetjnr5p+sTT166Pefra9TFPX7s+5ulr18c8fe36iKdv2vUxT1+7Pubpa9fHPH3t+pinb5o+8fS162OevnZ9zNPXro95+tr1MU9fuz7i6Rft+pinr10f8/S162OevnZ9zNM3TZ94+tr1MU9fuz7m6WvXxzx97fqYp69dH/H0q3Z9zNPXro95+tr1MU9fuz7m6ZumTzx97fqYp69dH/P0tetjnr52fczT166PePpNef+C6fveoNGUyuPPyDSj8DNSwo0/I+XQ+DNSWow/I2W6+DNS8go/o67fhYg/I/3GQvwZac8Qf0baMyye0edb1bppRuFnpD1D/BlpzxB/RtozLJ7R5xt/uvYM8WekPUP4GQ3tGeLPSHuG+DPSniH+jLRnWDyjz78XNEwzCj8j7Rniz0h7hvgz0p4h/oy0Z4g/I+0Zos+o37RniD8j7Rniz0h7hvgz0p4h/oxMMwo/I+0Z4s9Ie4b4M9KeIf6MtGeIPyPtGcLPaNOeIf6MtGeIPyPtGeLPSHuG+DMyzSj8jLRniD8j7Rniz0h7hvgz0p4h/oy0Zwg/o117hvgz0p4h/oy0Z4g/I+0Z4s/INKPwM9KeIf6MtGeIPyPtGeLPSHuG+DPSniH8jA7tGeLPSHuG+DMy3hm5tjX2gzjFOJMkzhrOJIkTgTNJYt/uTJLYXfuSNGIP7EyS2Kk6kyT+3sqZJPG3S84kTSSdSCrjTJH82KXcTRnHi6QyjhdJZRwvkso4UyQ/dpP2oozjRVIZx4ukMo4XSWUcL5Imkk4klXGcvlssyjheJJVxvEgq43iRVMZxIlmVcbxIKuN4kVTG8SKpjONF0kTSiaQyjhdJZRwvkso4XiSVcbxIKuM4kWzKOF4klXG8SCrjeJFUxvEiaSLpRFIZx4ukMo4XSWUcL5LKOF4klXGcSHZlHC+SyjheJJVxvEgq43iRNJF0IqmM40VSGceLpDKOF0llHC+SyjhOJIcyjhdJZRwvkso4XiSVcbxIxvaTvTw+PEapH0CO9igGGO2kGGDENn3ucmM7M3e5se2Ts9xxi+1x3OXGNiJfyf3unX8PBs8f3U7gxPYWi+HEtguL4ZjgnMOJvbhcDCeRd/SHk8hp+sNJ5Euvi2/nz/wCmcjxLgW5JfLSa0HSunRvkLSO3hskrfv3BmkC6QOSNlV4g6RNIN4gadOKN0glGyeQSjY+IIPfdA4EUsnGCaSSjRNIJRsnkCaQPiCVbJxAKtk4gVSycQKpZOMEUsnGB2Twu5WBQCrZOIFUsnECqWTjBNIE0gekko0TSCUbJ5BKNk4glWycQCrZ+IAMfmM2EEgTSI8bdUfwG3WBQOqwcfnL1RH87lIckMGvLgUCqTWaE0it0ZxAao3mBNIE8jPIutVfn63HfgJSPtIJpNZoTiC1RnMCqWTjBFLJxgdk8AtLgUAq2TiBVLJxAqlk4wTSBNIHpJKNE0glGyeQvMnmi+fYjvJs6zzqDx5t/EDJm23cUfKmG2+UwS8rhULJm3DcUfJmHHeUvCnHHaUJ5QzKXp4oh52g5E067ih5s447SqUdN5RKO24olXa8UAa/thQKpdLOlyjttp2gVNpxQ6m044bShHICpe31ifIoJyiVdtxQKu24oVTacUOptOOGUmnHC2XwC0yhUCrtnP+FbPBLSRfDUSJ5A8cE5xyOUsMbOMoBb+DI2b+Bk+lC28/3pKW60PaT3P/8x5LpRtsZvYmc6ZTeRGZzSm8i/zil18j0JnJ5U3oTGbcpvYm82JReJnv1H71k/irTLadTesn8VaY7Q6f0kvmrTDdwTukl81eZ7rOc0kvmrzLdDjmll8xfZbprcUovmb/KdHPhlF4yf5XpHsApvWT+KtOtelN6yfxVpjvqpvSS+atMN75N6SXzV5nuT5vSS+avMt1GNqWXzF9luttrSi+Zv8p0U9aUXjJ/leneqSm9ZP7KyPyVkfmrTNedTekl81dG5q+MzF9luhxuSi+Zv8p01dqUXjJ/lenisim9ZP4q0zVgU3rJ/FWmS7Wm9JL5q0xXVE3pJfNXmS58mtJL5q8yXZ80pZfMX2W6jGhKL5m/ynS1z5ReMn+V6ZqcKb1k/irThTNTesn8VaarW6b0kvmrTJegTOkl81eZrhOZ0kvmrzJdzDGll8xfZbriYkovmb/KdFnElF4yf5Xp2oUpvWT+KtMFBlN6yfxVpqsApvSS+atMpfpTesn8VaYy+ym9ZP4qU+X8lF4yf5WpGH5KL5m/oqpv/49eLn+1kfW3b2T97RtZf/tG1t9+V0Oml8tfbWT97RtZf/tG1t++kfW3b5n6vbfv7obq4/kc+4fPFtt/fbbYcUaS92Y/b5Imkk4kee8M9CbJe8GgN0ne2wi9SfJeM+5NkveWcWeSmfrqF5PkvWPcm6QyjhdJZZwZkv3xg8soZyRNJJ1IKuN4kVTG8SKpjDNDsr1I1jOSyjheJJVxnEhmujNiMUllHC+SyjheJJVxZkiWx3eLpZ59t5jpbo7FJJVxvEgq43iRVMbxIqmM40VSGceJZKZ7WxaTVMbxIqmM40VSGceLpImkE0llHC+SyjheJJVxvEgq43iRVMZxIpnp7qTFJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEhmur9sMUllHC+SyjheJJVxvEiaSDqRVMbxIqmM40VSGceLpDKOF0llHCeSme4QXExSGceLpIUm2faH3NH39oHk/dOPD7ezZoDg9+L5643tzfz1xnZQ/npj+xx/vbHdyFd6v3vzz7RkBr9FbzWd2K5hNZ3Y287VdGJvMFfTMdF5QyeR57yATiKHel2WO3/mHyQTed/FJBO56sUkaf26N8ngNzgikaTNAe4kaTODO0nafOFO0kTSiSRtbnEnqYzjRVIZx4ukMo4XSWUcH5J78FtUkUgq43iRVMbxIqmM40XSRNKJpDKOF0llHC+SyjheJJVxvEgq4ziR3JRxvEgq43iRVMbxIqmM40XSRNKJpFzQzF/LfL5Xcg9+/y4QyeB3nUYh+fkvuPbgd50ikdSJ40VSWzUvktqqeZHUVs2LpPzkBMm61V+frcd+RlJ+0olk8LtOkUhqq+ZFUhnHi6QyjhdJE0knkso4XiSVcbxIKuN4kVTG8SKpjONEMvhdp0gkeTPOF8+x3ao9f/KPRqatlp8seVOOP0venOPP0sTSjSVv1vFnyZt2/Fny5h1/lryJ5yuW42Evt+1WzljyZh53lsFvP8Viqdzjx1K5x4+lco8fSxNLN5bKPd+y/LGf+79YKvf4sVTu8WOp3PPmb0eC33C6mE7wW0tX01HaeEdH+eEdHSWCd3RMdN7QyXTH0+cG/T34/Zv+ejPd8TSjN9MdTzN6E3nOGb3B74X015vIF07pTeT0pvQm8m5Teo1ML5m/SnWH5oxeMn+V6g7NGb1k/irTrZhTesn8VaabK6f0kvmrTLdLTukl81eZboCc0kvmrzLdpjill8xfZbqZcEovmb/KdMvflF4yf5XpxrwpvWT+KtPtc1N6yfxVppvcpvRy+asj061oU3q5/NWR6YaxKb1c/uq4GZleLn91ZLr5akovl786Mt0iNaWXzF9lupFpSi+Zv8p0u9GUXjJ/lemmoCm9ZP5qI/NXG5m/ynQ/1ZReMn+1k/mrncxfZbrLa0ovmb/KdC/WlF4yf5XpjqkpvWT+KtN9TVN6yfxVpruPpvSS+atM9whN6SXzV5nu5JnSS+avMt1vM6WXzF9luitmSi+Zv8p078qUXjJ/lekGkym9ZP6K+MaFb25+tv3XZ4sdZyR1v5wXSd0v50VS98s5kSS+acGbpO7Q9iKpO7S9SOoObS+SJpJOJHWHthdJZRwvkso4MyT74weXUc5IKuN4kVTGcSJJfGODN0llnBmS7UWynpFUxvEiqYzjRdJE0omkMo4XSWUcL5LKODMky+O7xVLPvlvMdDfHYpLKOE4kM90nspikMo4XSWUcL5LKOF4kTSSdSCrjeJFUxvEiqYzjRVIZx4ukMo4TyUx3+iwmqYzjRVIZx4ukMo4XSRNJJ5LKOF4klXG8SCrjeJFUxvEiqYzjRDLTvVqLSSrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrj+JC0THfbLSapjONFUhnHi6QyjhdJE0knkso4XiRj+8li9iBZR/9A8s798eF2nOmN7frc9Qa/F89fb2wH5a83ts/x1xvbjXyl97s3/0RLpgW/RW81ndiuYTWd2NvO1XRibzBX00nkIi+gk8hz+tMJfrPghXS+yXLnz/yDZCLvu5hkIle9mCStX3cnaSLpRJI2B7iTpM0M7iRp84U7Sdos4k6SNrd4kwx+uycSSWUcL5LKOF4klXG8SJpIOpFUxvEiqYzjRVIZx4ukMo4XSWUcJ5LBb9hFIqmM40VSGceLpDKOF0kTSSeSyjheJJVxvEgq43iRVMbxIqmM40Qy+O3aSCSVcbxIKuN4kVTG8SJpIulEUhnHi6QyjhPJ4PfvBiE5cU+5Bb9/F4mkTpwZkhONAMHvOkUiqRPHi6S2al4ktVXzIqmtmhPJ4HedBiFZt/rrs/XYz0jKT3qR1FbNi6S2al4kTSSdSCrjeJFUxvEiqYzjRVIZx4ukMo4TyeB3nSKRVMbxIqmM40VSGceLpImkE0llHC+SyjheJJVxvEjyZpwvnmOzJ8rNjvJ6jmb/lDtvIlrKPfg9qnm586attdx5s5kT9x8sedOZP0sTSzeWvAnNnyVvRvNnyZvS/Fkqp/mxVPbyYlmC39mKxVIZyY+lcs8Uy/5QuJWj/sbyD5/e7LF83Lby46lb+UleKWkVeRN5b/LOf/NYgt84qxn9Z0bKgPFnpGwZf0bKrPFnpCwcfkaZ7t5OOyNl9/gz0k4g/oy0PYg/I9OMws9Ie4b4M9KeIf6MtGeIPyPtGeLPSHuG8DPatWeIPyPtGeLPSHuG+DPSniH+jEwzCj8j7Rniz0h7hvgz0p4h/oy0Z4g/I+0Zws/o0J4h/oy0Z4g/I+0Z4s9Ie4b4MzLNKPyMtGeIPyPtGeLPSPlo6Ywm7iArpnwUf0bydWtn9Pk+oDsDzSj8jOTr4s9Ivi7+jPT9UfwZ6fuj+DNSPlo6o4lO01KUj+LPSN8fxZ+Rvj+KPyPtGeLPyDSj8DPSniH+jLRniD8j7Rniz0h7hvgz0p4h/Iyq9gzxZ6Q9g/+MvvnJ2+3Zxr1tP9u4fzYTV20aEKakXQPClExTApiS9g0IU9LGAWFK2jkgTElbh8VT2tpzSns9m5L2DgBTato8IExJuweEKWn3gDAl7R4QpmSaEsCUtHtYPKWZ2/qadg8IU9LuAWFK2j0gTEm7B4Apde0eEKak3QPClLR7+ItT+sFd24Q13E3cJ7jfvyt7cu/bB+73b9/s+aY57Iy8Mv8q8srx7uT3/YnDyhl3JfM13JW113BXel7CfSgPr+GuhLuGuzKrP/dSHjjadsZdmXUNdxP3JdyVWNdwV15dw115dQ135dU13JVXV3CvN+XVNdyVV9dwV15dw115dQ13E/cJ7vf3wuMn16194D71TV+9KbGuIq/Muoq8Uusq8sqtq8gruS4ivym7riKv9LqKvPLrKvJKsKvIm8gvIq8Mu4q8Muwq8sqwq8grw64irwy7iPyuDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7CLyhzLsKvLKsKvIK8OuIq8Mu4q8ifwi8sqwq8grw64irwy7irwy7CryyrCLyJsy7CryyrCryCvDriKvDLuKvIn8IvLKsKvIK8OuIq8Mu4q8Muwq8sqwi8gXZdhV5JVhV5FXhl1FXhl2FXkT+UXklWFXkVeGXUVeGXYVeWXYVeSVYReRr8qwq8grw64irwy7irwy7CryJvKLyCvDriKvDLuKvDLsKvLKsKvIK8MuIt+UYVeRV4ZdRV4ZdhV5ZdhV5E3kF5FXhl1FXhl2FXll2FXklWFXkVeGXUS+K8OuIq8Mu4q8Muwq8sqwq8ibyC8irwy7irwy7CryyrCryCvDriKvDLuI/FCGXUVeGXYVeWXYVeSVYVeRN5FfRF4ZdhV5ZdhV5JVhV5FXhl1FXhl2Dfl2U4ZdRV4ZdhV5ZdhV5JVhV5E3kV9EXhl2FXll2FXklWFXkVeGXUVeGXYR+U0ZdhV5ZdhV5JVhV5FXhl1F3kR+EXll2FXklWFXkVeGXUVeGXYVeWXYReR3ZdhV5JVhV5FXhl1FXhl2FXkT+UXklWFXkVeGXUVeGXYVeWXYVeSVYReRP5RhV5FXhl1FXhl2FXll2FXkTeQXkVeGXUVeGXYVeWXYVeSVYVeRV4ZdRN6UYVeRV4ZdRV4ZdhV5ZdhV5E3kF5FXhl1FXhl2FXll2FXklWFXkVeGXUS+KMOuIq8Mu4q8Muwq8sqwq8ibyC8irwy7irwy7CryyrCryCvDriKvDPs/z/GiU5Uz39FRFnxHR3ntHR1lqnd0THTe0FE2eUdH+eEdHXn8d3Tkw9/RkVd+Q6fJK7+jk8grj94fHx7tTG8i9zulN5GfndJrZHoTec4pvYlc5JTeRL5wSm8ipzelN5F3m9HbE7mxKb1k/qqT+atO5q+6kekl81edzF91Mn/VyfxVJ/NXg8xfDTJ/Ncj81SDzV8PI9JL5q0HmrwaZvxpk/mpw+at+4/JX/cblr3qmG+qn9HL5q34zMr1c/qpnunl8Si+Xv+qZbtme0kvmrzLdKD2ll8xfZbo9eUovmb/KdFPwlF4yf5XpVtwpvWT+KtMNsFN6yfxVpttOp/SS+atMN3tO6SXzV5lusZzSS+avMt3YOKWXzF9lup1wSi+Zv8p0E9+UXjJ/lenWuSm9ZP4q0w1rU3rJ/FWm28Sm9JL5q0w3Z03pJfNXmW6JmtJL5q8y3Yg0pZfMX2W6/WdKL5m/ynTTzZReMn+V6VaXKb1k/irTDSZTesn8VabbOqb0kvmrTDdTTOkl81eZbmGY0kvmrzLdODCll8xfZWrun9JL5q8ytetP6SXzV5ka8Kf0kvmrTC31U3rJ/FWmJvkpvWT+KlPb+5ReMn9F1t/eyfrbO1l/eyfrb+9k/e2drL+9k/W3d7L+9k7W397J+ts7WX97J+tv72T97Z2sv72T9bd3sv72Ttbf3sn62ztZf3sn62/vZP3tnay/vZP1t3ey/vZO1t/eyfrbO1l/eyfrbx9k/e2DrL99kPW3D7L+9nEzMr1c/mqQ9bcPsv72QdbfPsj62wdZf/sg628fZP3tg6y/fZD1tw+y/vaRqd/7/tS351Pv48PP/uY5NusPhVs56us5mv3pJ/fx/Mn7h59cbP/12WLH2YwSeYasM8rUo552Rom8WdoZJfKTaWeUyAOnnZFpRuFnlChrpJ1Rov1z2hkl2pmnnZH2DPFnpD3D2hn1xyOXUU5mlOk+kbQz0p4h/oy0Z4g/I+0Z1s6ovWZUz2ZkmlH4GWnPEH9G2jPEn5H2DPFnpD1D/Blpz7B2RuXxe0Glnv1eUKZ7tdLOSHuG+DPSniH+jLRniD8j04zCz0h7hvgz0p4h/oy0Z4g/I+0Z4s9Ie4bwM8p0v2TaGWnPEH9G2jPEn5H2DPFnZJpR+BlpzxB/RtozxJ+R9gzxZ6Q9Q/wZac8QfkaZ7llOOyPtGeLPSHuG+DPSniH+jEwzCj8j7Rniz0h7hvgz0p4h/oy0Z4g/I+0Zws+oac8Qf0baM8SfkfYM8WekPUP8GZlmFH5G2jPEn5H2DPFnpD1D+Bl13nzk3NbYeVOMN0nerOFNkjcReJM0kXQiyeuuvUnyemBvkrxO1Zsk7/dW3iR5v11yJjmUcbxIKuPMkJzoUh7KOF4klXG8SJpIOpFUxpkhOdFNOpRxvEgq43iRVMbxIqmM40LyP/+2SDqRVMZx+W7x/m8r43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEhuyjheJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEjuyjheJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEgeyjheJJVxvEgq43iRVMbxImki6URSGceLpDKOF0llHC+SyjheJJVxnEhabD95tIeEYeP2geRoj2aA0Y4zvbFdn79eI9Mb20H5643tc/z1xnYjX+n97s0/+vNHj9O3eWyHsZpObNewmE6Jve1cTSf2BnM1nUQu8gI6iTznBXSMlc43We78mX+QTOR9F5NM5KoXk6T16+4kab29O0naHOBNstJmBneStPnCnSRtFnEnSZtb3EmaSDqRVMbxIqmM40VSGceLpDKOF0llHCeSwW/mRiKpjONFUhnHi6QyjhdJE0knkso4XiSVcbxIKuN4kVTG8SKpjONEMvjt2kgklXG8SCrjeJGUC5r5a5mP90reScoFOZEMftdpFJITf8EV/K5TJJI6cbxIaqvmRdJE0omktmpeJOUnJ0jWrf76bD32M5Lyk14ktVXzIqmtmg/JLfhdp0gklXG8SCrjeJFUxvEiaSLpRFIZx4ukMo4XSWUcL5LKOF4keTPOF8/xn16P50+u2+s52vaDZfDbTrFY8uYcf5a8ScefJW/W8WdpYunGkjfv+LPkTTxfsez2/MnjOGPJm3n8WfKmHn+Wyj1uLIPfgIrFUrnHj6Vyjx9L5Z4vWd7/lTOWJpZuLJV7/Fgq95z/7cgW/IbT1XSUTd7RUdp4Qyf47aKr6SgRvKMjj/+OTqY7nj436G/B79/015vpjqcZvZnueJrRm8hzTulN5CKn9CbyhTN6LZHTm9KbyLtN6c10h+aMXjJ/leoOzRm9ZP4q1R2aM3rJ/FWmWzGn9JL5q0w3V07pJfNXmW6XnNJL5q8y3QA5pZfMX2W6TXFKL5m/ynQz4ZReMn+V6Za/Kb1k/irTjXlTesn8Vabb56b0kvmrTDe5Tekl81eZbkWb0kvmrzLdMDall8xfZbqta0ovmb/KdPPVlF4yf5XpFqkpvWT+KtONTFN6yfxVptuNpvSS+atMNwVN6SXzV93I9JL5q0z3U03pJfNXncxfdTJ/lekurym9ZP4q071YU3rJ/FWmO6am9JL5q0z3NU3pJfNXme4+mtLL5a/2TPcITenl8ld7pjt5pvRy+av9ZmR6ufzVnumumCm9XP5qz3TvypReMn+V6QaTKb1k/or4xoVvbn62xyUBxY4zkrpfzouk7pfzIqn75bxI6n45L5K6Q9uJJPEtC94kdYe2F0ndoe1FUndoe5E0kXQiqYwzQ7I/fnAZ5YykMo4XSWUcL5LKOF4klXFmSLYXyXpCkvgmCG+SyjheJJVxvEgq43iRNJF0IqmMM0OyPB6j1LPvFjPdzbGYpDKOF0llHC+SyjhOJDPdgbKYpDKOF0llHC+SyjheJE0knUgq43iRVMbxIqmM40VSGceLpDKOE8lM9xAtJqmM40VSGceLpDKOF0kTSSeSyjheJJVxvEgq43iRVMbxIqmM40Qy011gi0kq43iRVMbxIqmM40XSRNKJpDKOF0llHC+SyjheJJVxvEgq4ziRzHQf32KSyjheJJVxvEgq43iRjO0n9/3x4XEc4wPJ0R7NAKOdNQMEvxfPX29sb+avN7aDctcb/F48f72x3chXer9788+0ZAa/RW81ndiuYTUdE503dGJvMFfTSeQiL6CTyHNeQCeRQ70uy50/8w+SibzvWpLBb0NEIknr191J0np7d5K0OcCdpImkE0nafOFOkjaLuJOkzS3uJJVxvEgq4/iQPILfSIpEUhnHi6QyjhdJZRwvkiaSTiSVcbxIKuN4kVTG8SKpjONFUhnHiWTwW4GRSCrjeJFUxvEiqYzjRdJE0omkMo4XSWUcJ5LB798NQnLiXskj+P27SCR14vj8BdcR/K5TJJI6cbxIaqvmRVJbNS+S2qo5kQx+12kQknWrvz5bj/2MpPykF0lt1bxIaqvmRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJEMftcpEkllHC+SyjheJHkzzhfPsd3K/vzJdXs9R9t+sjSxdGPJm3P8WfImHX+WvFnHnyVv2vFnyZt33FkGv/k0DMtuz588jjOWvJnHnyVv6vFnqdzjx9LE0o2lco8fS+UeP5bKPV+yvP8rZyyVe/xYKve4sQx+G+oSlj/oKMm8o6Ns8o6O0sY7OiY6b+goEbyjI4//jk6mO54+N+gfwe/f9Neb6Y6nCb3B77L015vIc07pTeQip/Qm8oVTeo1MbyLvNqU30x2aM3rJ/FWqOzRn9JL5q1R3aM7oJfNXmW7FnNJL5q8y3Vw5pZfMX2W6XXJKL5m/ynQD5JReMn+V6TbFKb1k/irTzYRTesn8VaZb/qb0kvmrTDfmTekl81eZbp+b0svlryzTTW5Tern8lWW6FW1KL5e/spuR6eXyV5bptq4pvVz+yjLdfDWll8xfZbpFakovmb/KdCPTlF4yf5XpdqMpvWT+KtNNQVN6yfzVRuavNjJ/lel+qim9ZP5qJ/NXO5m/ynSX15ReMn+V6V6sKb1k/irTHVNTesn8Vab7mqb0kvmrTHcfTekl81eZ7hGa0kvmrzLdyTOll8xfZbrfZkovmb/KdFfMlF4yf5Xp3pUpvWT+KtMNJlN6yfwV8Y0L39z8bI9LAoodZyR1v5wTSeLbFrxJ6n45L5K6X86LpO7Q9iJpIulEUndoe5HUHdpeJHWHthdJZRwvkso4MyT74weXUU5IEt+s4E1SGceLpDKOF0llnBmS7UWynpE0kXQiqYzjRVIZx4ukMo4XSWUcL5LKODMky+O7xVLPvlvMdDfHYpLKOF4klXG8SCrjeJE0kXQiqYzjRVIZx4ukMo4XSWUcL5LKOE4kM92Ps5ikMo4XSWUcL5LKOF4kTSSdSCrjeJFUxvEiqYzjRVIZx4ukMo4TyUx3VC0mqYzjRVIZx4ukMo4XSRNJJ5LKOF4klXG8SCrjeJFUxvEiqYzjQ7JkuiduMUllHC+SyjheJJVxvEiaSDqRVMbxIqmM40VSGceJZPB78TZ7PMfYev9A0rlFoAS/Q28tm9ieby2b2C5uLRsTm1M2sZ3WWjaxvdNaNrHd0Fo2sXe4a9nE3souZRP8PsO1bFh98edGnRL8nsS1bFh98QwbE5tTNqy++HMLSAl+r+NaNqy+eIYNqy+eYcPqiyfYBL+Hci0bVl888T1D8Pst17Jh9cUzbExsTtmw+uIZNqy+eIYNqy+eYcPqi2fYsPriCTbB7w9dy0a++JyNfPE5G/niczYmNqds5IvP2cgXn7ORLz5nI198zka++JRN8Dty17KRLz5nI198zka++JyNic0pG/niczbyxeds5IvP2cgXn7ORLz5lE/xe1bVs5IvP2cgXn7ORLz5nY2Jzyka++JyNfPE5G/niczbyxeds5ItP2cS+97D3568B9zsnTzYTf3cX+ybDxWxMbE7ZhPY3i9mE9jeL2YT2N4vZhPY3i9mE9jdr2cS+h28xm9B7v8Vs5IvP2bD64om/nY99n91iNqy+eIYNqy+eYcPqiyf+Bjr2vXCL2bD64gk2se9uW8yG1RfPsGH1xTNsWH3xxPcMse9AW8yG1RfPsGH1xTNsWH3xDBtWXzzDhtUXf2ZTY9/3tZgNqy+eYcPqi2fYyBefszGxOWUjX3zORr74nI188Tkb+eJzNvLFp2xi31u2mI188Tkb+eJzNvLF52xMbE7ZyBefs5EvPmcjX3zORr74nI188Smb2PeWLWYjX3zORr74nI188TkbE5tTNvLF52zki8/ZyBefs5EvPmcjX3zKJva9ZYvZyBefs7G/zsb3r+PqgluivBVUeAUNXkGHVzDQFSy4Y8hbwQavYIdXcMArgD+TLfaZ/PlvYKvFPpNnFMQ+k2cUxD6TZxTEPpM//41dLbHP5BkFsc/kGQWxz+QZBbHP5BkFsc/kGQWxz+SJXUWJfSbPKIh9Js8oiH0mzyiIfSZPKKixz+QZBbHP5BkFsc/kGQWxz+QZBbHP5BkF8GdyhT+TK/yZXOHP5Ap/Jjf4M7nBn8kN/kxu8Gfygp56bwXwZ3KDP5Mb/Jnc4M/kBn8md/gzucOfyR3+TO7wZ/KCjmxvBfBncoc/kzv8mdzhz+QOfyYP+DN5wJ/JA/5MHvBnsk/P6vZ4qH2r5qlg4ne8fNpQlyro8AoGuILm0/+5VMEGr2CHV3DAKzB4BQVeAfqZ3G6xz+TPvzHbbrHP5BkFsc/kCQVb7DN5RkHsM/nzb2u2LfaZPKMg9pk8oyD2mTyjIPaZPKMg9pk8oyD2mfx5V9G22GfyjILYZ/KEgj32mTyjIPaZPKMg9pk8oyD2mTyjIPaZPKMg9pk8oyD2mTyjAP5M3uHP5B3+TD7gz+QD/kw+4M/kA/5M9umQWqoA/kw+4M/kA/5MPuDP5AP+TDb4M9ngz2SDP5MN/kz26ZBaqgD+TDb4M9ngz2SDP5MN/kwu8GdygT+TC/yZXODPZJ8OqaUK4M9kl/6im5WHgtu4eSqY+B0vl/6ipQpc+ovWKtjgFezwCg54BQavoMArqPAKGrwC+DO5xj6TJ35jtsU+k2cUxD6TZxTEPpNnFMQ+kyd+W9Olv2itgthn8oyC2GfyjILYZ/KMgthn8oyC2GfyxK6ixz6TZxTEPpNnFMQ+k2cUxD6TZxTEPpNnFMQ+k2cUxD6TZxTEPpNnFMQ+k2cUwJ/JA/5MHvBn8oA/kwf8mTzgz+QBfyYP+DN5wJ/JA/5MHuhncr+hn8n9hn4m9xv6mdxv6Gdyv6Gfyf2Gfib3G/qZ3G/oZ3K/oZ/J/QZ/Jm/wZ/IGfyZv8GfyBn8mu3RIrVUAfyZv8Gfyhnsml5v9PydlFW1vj8cf2/jx+O35Pxz/8H94Us0w8T/c/un/cP8H/8N6jP9n/3O91j2P/PofjmG/jfb5vxv/7H/35yqpif/d9g//d/s//N8d//B/Z//wf+fwottGPZ7z7vXD/5HVrf76cD32//v/cP77TDXgM7WAz9QDPtO49pke/45HDc3Uv7P9pX9n/0v/zvGX/h37S/9O+Uv/Tv1L/077S/9O/0v/zl8P9f/5zfTHz95v/fXpvj2fym4hnyp0+G6tPT97/PHdb6Gj98Tzhw7eE89v4M8fOnRPPH/oyD3x/KED98Tzh16BTzx/6AX45+cvodffE88Pfv4W8PO3gJ+/LlUXK58f/Pwt4OdvAT9/Y9eMTDw/+Pkbu2Jk4vnBz9/Y9SITzw9+/sauFpl4fvDzF7jS4r/Pj1sy9f8/f/AqhXdfmP/3+XF/8eW/zx/6/TPx/Li/9PLf58f9lZf/Pj/uL7z89/lDv/8/f3cduzzh8/PHrk6YeP7Q/n/i+UOfvxPPH/r8nXj+0OfvxPOHPn8nnj/0+Tvx/KHP34nnBz9/YxclfH7+2DUJE8//98/f053C/35228bDgG777YcD/fEbNAtKErwVHPAKDF5BgVdQ4RU0eAU9joLnM41wz3Tc/vpFKdv2+vuUzX78LuZmr6faQj5V6AtNJmYd+jqTiec38OcPfZXJxPOHvlxs4vlDXy028fyhLxabeP7Q14p9fv7tBv78oa8Um3h+8PN3Az9/XYoFVj4/+Pm7gZ+/G/j5u4Gfvxv4+buDn787+Pm7g5+/O/j5u4Ofvzv4+buDn787+Pm7g5+/O/j5e4Cfv0fs65w//YbxcYR+/088f+j3z8ffsDyO0O+fiecP/f75/PwW+v0z8fyh/f/E84f2/xPPH/r9//E3hA4L/f6feP7Q/n/i+UP7/4nnD33+Tjx/6PN34vlDn7+fn7+EPn8nnj/0+Tvx/KHP34nnBz9/XRpGVj4/+Plb/v75+81vJd766zfIbj9+M+/Hb5CVBq+gwysY6ArqDV7BBq9gh1dwxFbwjPN3BdtvCv7wk8fzJ99+NN73/lJrVGoLldrYvuC33yw/+b/F2L5gRkFsXzCjILYvmFDQYvuCGQWxfcGMgti+YEZBbF8w8Xc6Lk1AaxXEPr9nFAQ6k5/PFOiUfT6Ty7k5HjdB7HvZPzzTVp7XRhT78zONeM/k0q7z1TP5/u6JS7vOyuffwZ//AH9+A3/+Av78Ffz5G/jzd/DnH9jPP8DP3wF+/g7w83eAn78uvTornx/8/B3g5+8AP38H+Pk7sM9fu2Gfv3bDPn/thn3+2g37/LUb9vlrN+zz127Y56/dsM9fu2Gfv3YDP3838PN3Az9/N/DzdwM/f326fxY+P/j5u4Gfvxv4+buBn78b+Pm7g5+/O/j5u4Ofvzv4+evT/bPw+cHP3x38/N3Bz98d/Pzdwc/fA/z8PcDP3wP8/D3Az1+f7qWFzw9+/h7g5+8Bfv4e4OfvAX7+Gvj5a+Dnr4GfvwZ+/vp0Xy18fvDz18DPXwM/fw38/DXw87eAn78F/Pwt4OdvAT9/fbqvFj4/+PlbwM/fAn7+FvDzt4CfvxX8/K3g528FP38r+Pnr01+18PnBz98Kfv5W8PO3gp+/Ffz8beDnbwM/fxv4+dvAz1+fTqmFzw9+/jbw87eBn78N/Pxt4OcveP+VgfdfGXj/lYH3Xxl4/5WB918ZeP+VgfdfGXj/lYH3Xxl4/5WB918ZeP+VgfdfGXj/lYH3Xxl4/5WB918ZeP+VgfdfFfD+qwLef1XA+68KeP9VuWGfvwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/quD9VxW8/6qC919V8P6resM+fyt4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/1cD7rxp4/1UD779q4P1X7YZ9/jbw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4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2q+QzOe+one2XyGZz31F722/QjKf+4re836FZD73Fb5D/gLJfO4rfI/8BZL53Ff4LvkLJPO5r/B98hdI5nNf4TvlL5DM577C98pfIJnPfYXvlr9AMp/7Ct8vf4FkPvcVvo/+Asl87ouv6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o3vq574+u6N76ue+Prureb8Ummc1/G13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd94Wv677wdd0Xvq77wtd1X27GJ5nOfRW+rvvC13Vf+LruC1/XfeHrui98XfeFr+u+8HXdF76u+8LXdV/4uu4LX9d94eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33JVcL+mj7r0+P9vvPfglOdSrPCE71th69PwSPdiI41bt6RnCqN/WM4FTv6RnBqTLyjOBUCXlCcK4+7BnBuc7hCcGpsvGM4FTJeEawsQlmc1rIHdgvEcDu6SUiuCNqx+35IN0+/af3n+LaXx//T3Hcn6N69J7qCyRH76m+QnJwX3SF5ODO6ArJwb3RFZKNT3Jwf3SF5OAO6QrJwf3UFZL5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F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh62+vZP3tlay/vZL1t1ey/vb6yGR6ufxVJetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/ew3V7/1824+vLz/GD9/8N2/kOM7+JbHn7/fRx//6nR/l9Z6Pxyhv8PKfvnMfX9/5+OE7l3z8+7UlnxfTj+RGNP1fTj9U97um/9vpR3Kqmv5vpx/Jt2v6v51+pBSj6f92+lnTJ55+pISr6f92+pF+n6Lp/3b6kX67pOn/dvra9TFPX7u+sNPvr29c3r/v+/RD3UOk6f92+tr1MU9fuz7m6WvXF3b67Xv69WL6WdMnnr52fczT166Pefra9TFPX7s+5ulr1xd2+uX1lku9+ExvqDsxNf3fTl+7Pubpa9fHPH3t+pinnzV94ulr18c8fe36mKevXR/z9LXrY56+dn3E0w91P7um/9vpa9fHPH3t+pinr10f8/Szpk88fe36mKevXR/z9LXrY56+dn3M09euj3j6Q7s+5ulr18c8fe36mKevXR/z9LOmTzx97fqYp69dH/P0tetjnr52fczT166Pd/rtoV0f8/S162OevnZ9zNPXro95+lnTJ56+dn3M09euj3n62vURTz8p7++dfnrO4Gv6qVpO/8e7OVpS3meevvI+8/SV95mnnzV94ukr7zNPX3mfefrK+8zT12d7mKevz/YQT//Qro95+tr1hZ3+j7cxtkO7Pubpa9fHPP2s6RNPX7u+sNP/8Ua2dmjXxzx97fqYp69dH/P0tesjnv6pXR/z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l/M7J1YopvNczu+HWKGYznM5v8thhWI6z+X83oUViuk8l/M7ElYopvNczu8zWKGYznM5v3tghWI6z+X8noAViuk8l/NO/xWK6TyX8/79FYrpPJfzrvwViuk8l/Ne+xWK6TyX8w76FYrpPBddD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhb3Q99I2uh77R9dA3uh769sh0itk8V6ProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6XroO10Pfafroe90PfT9kekUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30PVJH+WjH64vbf7/zm95Ap/GU3kDP6dH764tHu9Ib6Ck9pTfQM3pKb6An9JTeQJl4Rm+kxuopvZHO3xm9kc7fGb2BsvCU3kyml8xfRWqpntIL66/eNMB6pjcNvn3Q2b7+KeXxMEnmznukVyj27YVWKPbthlYo9u2HVijOdIp9e6IVin27ohWKffuiFYp9u6gViuk8l/Me6RWK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QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77S9dBXuh76StdDX+l66Osj0ylm81yVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvoaqaP8+dWvL27//c5vegOdxjN6I3VXj95fXzzald5AT+kpvYGe0VN6Az2hp/QGysRTegMl4im9kc7fGb2Rzt8ZvYGy8IzeSE3VU3rJ/FWkluopvbD+6k1DDqDBtw/qpX39Uyr1p2Sej69kns/y/dVtvCv27YRWKPbthVYo9u2GVij27YcWKHbeI71CsW9PtEKxb1e0QrFvX7RCcaZTTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1DM5rma8x7pFYrZPFdz3iO9QjGb52qPTKeYzXM15z3SKxSzea7mvEd6hWI6z+W8R3qFYjrP5bxHeoViOs/lvEd6hWI6z+W8R3qFYjrP5bxHeoViOs/lvEd6hWI6z+W8R3qFYjrP5bxHeoViOs910Hku513hKxTTea6DznOddJ7LeSf8CsV0nst5L/wKxZlOMZ3nct4Ov0Ixnedy3hC/QjGd53LeEr9CMZ3nct4Uv0Ixnedy3iy/QjGd56LroW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/peug7XQ99p+uh73Q99P2R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uJdoJvRh3lu+l2gm9GHeG8SXaCb0Yd7byZdoJvRh3pvPl2gm9GHeW9WXaCb0Yd4b25doJvRh3tvgl2gm9GHem+aXaCb0Yd5b7JdoJvRh3hvyl2gm9GGEffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+SdinfxL26Z+EffonYZ/++ciEmvl82EnYp38S9umfhH36J2Gf/knYp38S9umfhH36J2Gf/knYp38S9umfhH36J2Gf/knYp38S9umfhH36p6c+/bd35cgpvb0rR17m7V1ll+/KkR94e1eOTuy3d+XoTH17V45Ovbd35ehc+n5XnhrA396Vy2e7pxbtt3fl8tnuqYn67V25fLZ7anN+e1cun+2eGpHf3pXLZ7unVuG3d+Xy2e6pmfftXbl8tntqt317Vy6f7Z4aYt/elctnu6eW1bd35fLZ7qmp9O1duXy2e2r7fHtXLp/tnhoz397V4mf72yvV216p3fZK/bZXGne90uqGwLdXSre90nHbK523vVK+7ZVue0bU254R9bZnRL3tGVFve0a0254R7bZnRLvtGdFue0a0254R7bZnRLvtGdFue0a0254R7bZnRL/tGdFve0b0254R/bZnRL/tGdFve0b0254R/bZnRL/tGdFve0aM254R47ZnxLjtGTFue0aM254R47ZnxLjtGTFue0aM254R465nRDb5i9Sj5a9X6uM/r/SXn5LLJn81uuJ9HU7f1+n0fWWn76s4fV/V6ftqTt9Xd/q+hs/3lZw+75PT531y+rxPTp/3yenzPjl93ienz/vk9HmfnD7vk9Pn/eH0eX84fd4fTp/3h9Pn/eH0eX84fd4fTp/3h9Pn/eH0eX84fd6fTp/3p9Pn/en0eX86fd6fTp/3p9Pn/en0eX86fd6fTp/3p9PnfXb6vM9On/fZ6fM+O33eZ6fP++z0eZ+dPu+z0+d9dvq8z06f98Xp8744fd4Xp8/74vR5X5w+74vT531x+rwvTp/3xenzvjh93lenz/vq9HlfnT7vq9PnfXX6vK9On/fV6fO+On3eV6fP++r0ed+cPu+b0+d9c/q8b06f983p8745fd43p8/75vR535w+75vT5313+rzvTp/33enzvjt93nenz/vu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vtF7PLq9PvVTwe+vbn/8i47tSlcoNjrFsR3kCsWxfeEKxbHd3grFsT3cCsWxndkCxcHvt6xQHNtxrVBM57mCX3FZodjoFNN5ruC3XFYopvNcwe+5rFDM5rlq8JsuKxSzea4a/K7LCsVsnqs+jE4xm+eqwe/GrFDM5rlq8BsvKxTTea7g91hWKKbzXMFvp6xQTOe5gt85WaGYznMFv0myQjGd5wp+P2SFYjrPFfzWxwrFdJ4r+F2OFYrpPFfwGxorFNN5ruD3LlYopvNcwW9TrFBM57mC35FYoZjOcwW/+bBCMZ3nCn6fYYViOs910Xmu4Jc1Viim81wXnecyOs8V/NLJCsV0niv4VZIVio1OMZ3nCn4XZIViOs8V/IbHCsV0niv4vY0Viuk8V/DbGCsU03mu4HcsViim81zBb06sUEznuYLfh1ihmM5zBb/lsEIxnecKfndhhWI6zxX8RsIKxXSeK/g9gxWK6TxX8NsDKxTTea7gdwJWKKbzXME7/VcopvNcwfv3Vyim81zBu/JXKKbzXMF77VcopvNcwTvoVyim81x0PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtH10De6HvpG10Pf6Hro28PoFLN5rkbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0/XQd7oe+k7XQ9/peuj7w+gUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf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81fBe9b99ZL5q+A96/56yfxV8J51f71k/ip4z7q/XjJ/Fbxn3V8vmb8K3snur5fMX5H1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0XWX/7RdbffpH1t19k/e3Xw8j0cvmri6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrbzey/nYj6283sv52I+tvt4eR6eXyV0bW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97Zap73q08/XF7fqkN9H7aEZvpj7k0fvri0f7pDfR82pKb6Ln1ZReI9ObKA9O6U2UB6f0Znr/zujN9P6d0ZsoD87ozdSHPKWXzF9l6kOe0gvrr940WAINsX1QO8dLQz/bd7n8MerrUx/H26eu5V1xbCe0QnFsL7RCcWw3tEJxbD+0QHHwBuMVimN7ohWKY7uiFYpj+6IVio1OMZ3nCt5mvEIxnecK3mi8QjGd5wrearxCMZ3nCt5svEIxnecK3m68QjGd5wrecLxCMZ3nCt5yvEIxm+cqwZuOVyhm81wleNvxCsVsnqs8jE4xm+cqwVuPVyhm81wlePPxCsV0nit4+/EKxXSeK3gD8grFdJ4reAvyCsV0nit4E/IKxXSeK3gb8grFdJ4reCPyCsV0nit4K/IKxXSeK3gz8grFdJ4reDvyCsV0nit4Q/IKxXSeK3hL8grFdJ4reFPyCsV0nit4W/IKxXSeK3hj8grFdJ4reGvyCsV0nit4c/IKxXSeK3h78grFdJ4reIPyCsV0nit4i/IKxXSeK3iT8grFdJ4reJvyCsV0nit4o/IKxXSeqxidYjrPVeg8V/Cu8BWK6TxXofNclc5zBe+EX6GYznMF74VfodjoFNN5ruDt8CsU03mu4A3xKxTTea7gLfErFNN5ruBN8SsU03mu4M3yKxTTeS66HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Fe6HvpK10Nf6XroK10PfX0YnWI2z1XpeugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa+ZOsqfX/364vbnd37Tm+htPKM3U3f16P31xaN90pvoKT2lN9Ezekpvoif0lN5EmXhKb6JEPKU30/t3Rm+m9++M3kRZeEZvpqbqKb1k/ipTS/WUXlh/9abBEmiI7YN6aV//lEr9Lpnb+ZXM7Sq/v7qNd8WxndAKxbG90ArFsd3QCsWx/dACxcF7pFcoju2JViiO7YpWKI7ti1YoNjrFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsVsnqsF75FeoZjNc7XgPdIrFLN5rvYwOsVsnqsF75FeoZjNc7XgPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea6TznMF7wpfoZjOc510nuui81zBO+FXKKbzXMF74VcoNjrFdJ4reDv8CsV0nit4Q/wKxXSeK3hL/ArFdJ4reFP8CsV0nit4s/wKxXSei66HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10Pfafroe90PfSdroe+0/XQ94fRKWbzXJ2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66HumjvLRztcXtz+/85veRG/jKb2JntOj968vbp/0JnpKT+lN9Iye0pvoCT2lN1EmntGbqbF6Sm+m9++M3kzv3xm9ibLwlF4j00vmrzK1VE/phfVXbxpgPdObhtg+aHx95+NxnMd30bx8fXWxD//wgtdILxAc2wktEBzbCi0QHNsLLRBsbIJju6EFgmPboQWCY/uhBYJjm6cFgtmcVvDy6AWC2ZxW8OroBYLZnFbw4ugFgtmcVvDa6AWC2ZxW8NLoBYLJnNYIXhm9QDCZ0xrBC6MXCCZzWuNhbILJnNYIXha9QDCZ0xrBq6IXCGZzWsGLohcIZnNawWuiFwhmc1rBS6IXCGZzWsErohcIZnNawQuiFwhmc1rB66EXCGZzWsHLoRcIZnNawauhFwhmc1rBi6EXCGZzWsFroRcIZnNawUuhFwhmc1rBK6EXCGZzWsELoRcIZnNaweugFwhmc1rBy6AXCGZzWsGroBcIZnNawYugFwhmc1rBa6AXCGZzWsFLoBcIZnNawSug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3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wfd4XfA9Xhd8j9cF3+N1PdDfyRd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4GXyPl8H3eBl8j5fB93jZA/2dbPA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9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vtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uh73Q99J2uh77T9dB3uh76/jA6xWyeq9P10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfc/UUT7a+fri9vfv/KY30dt4Sm+i5/To/fXFo33Sm+gpPaU30TN6Sm+iJ/SU3kSZeEZvpsbqKb2Z3r8zejO9f2f0JsrCU3qNTC+Zv8rUUj2lF9ZfvWmA9UxvGmL7oKt9/VOy8XBJ5sF7pFcoju2FViiO7YZWKI7th1YoNjrFsT3RCsWxXdEKxbF90QrFsV3UCsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFbJ5rBO+RXqGYzXON4D3SKxSzea7xMDrFbJ5rBO+RXqGYzXON4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5rkrnuYJ3ha9QTOe5Kp3nqkanmM5zBW+FX6GYznMFb4ZfoZjOcwVvh1+hmM5zBW+IX6GYznMFb4lfoZjOcwVvil+hmM5zBW+WX6GYznPR9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/YeuivB1sP/VMxmed6KibzXE/FZJ7rqdjoFJN5rqdiMs/1VEzmuZ6KyTzXUzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiNs910PXQH3Q99AddD/1B10P/1EOnmM1zHXQ99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/ZOooH+18fXH7+3f+1pupoXxKb6Ln9OhfXzzaJ72JntJTehM9o6f0JnpCT+lNlImn9CZKxFN6M71/J/Rmaque0psoC0/pTZSEp/SS+atMLdVTemH91ZsGWM/0piG2Dyr2ytqjjv5TMi+vj/FcKn36dxfbB/nrje2D3PUGb5D21xvbB/nrje2D/PXG9kH+eo1Mb2wf5K83tmfy10vmr4I3RvvrJfNXwdui/fWS+avgTdH+esn8VfCWaH+9ZP4qeEO0v14yfxW8HdpfL5e/OoM3Q/vr5fJXZ/BWaH+9XP7qfBiZXi5/dQZvg/bXy+WvzuBN0P56yfxV8BZof71k/ip4A7S/XjJ/Fbz92V8vmb8K3vzsr5fMXwVvffbXS+avgjc+++sl81fB25799ZL5q+BNz/56yfxV8JZnf71k/ip4w7O/XjJ/Fbzd2V8vmb8K3uzsr5fMXwVvdfbXS+avgjc6++sl81fB25z99ZL5q+BNzv56yfxV8BZnf71k/ip4g7O/XjJ/Fby92V8vmb8K3tzsr5fMXwVvbfbXS+avgjc2++sl81fB25r99ZL5q+BNzf56yfxVIfNXwXu43fUG7+H210vmryqZvwres+6v18j0kvmr4D3r/nrJ/FXwnnV/vWT+KnjPur9eMn8VvGfdXy+Zvwres+6vl8xfBe9k99dL5q/I+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72i6y//SLrb7/I+tsvsv7262Fkern81UXW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bcbWX+7kfW3G1l/u5H1t9vDyPRy+Ssj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tv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pvNcwfv3Vyim81zBu/JXKKbzXMF77VcopvNcwTvoVyim81x0PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtH10De6HvpG10Pf6Hro28PoFLN5rkbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0/XQd7oe+k7XQ9/peuj7w+gUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30PVNH+Wjn64vbn9/5TW+i13hKb6Kf06P31xeP9klvop/SU3oT/Yye0pvoJ/SU3kSZeEZvpsbqKb2Z3t8ZvZne3xm9ibLwlF4j00vmrzK1VE/phfVXbxpgPdObhtg+6Gpff5RsPFySefAe6RWKY3uhFYpju6EVimP7oRWKjU5xbE+0QnFsV7RCcWxftEJxbBe1QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxm+cawXukVyhm81wjeI/0CsVsnms8jE4xm+cawXukVyhm81wjeI/0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WX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX+7kfW3G1l/u5H1txtZf7s9jEwvl78ysv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj62+3TH3Xo52vL27XJ72J3qMZvZn6kEfvry8e7ZPeRD+vpvQm+nk1pdfI9CbKg1N6E+XBKb2Z3t8ZvZne3xm9ifLgjN5MfchTesn8VaY+5Cm9sP7qTYMl0BDbB7VzvDT0s/2Uyx+jvj71cbx96lreFcd2QisUx/ZCKxTHdkMrFMf2QwsUB28wXqE4tidaoTi2K1qhOLYvWqHY6BTTea7gbcYrFNN5ruCNxisU03mu4K3GKxTTea7gzcYrFNN5ruDtxisU03mu4A3HKxTTea7gLccrFLN5rhK86XiFYjbPVYK3Ha9QzOa5ysPoFLN5rhK89XiFYjbPVYI3H69QTOe5grcfr1BM57mCNyCvUEznuYK3IK9QTOe5gjchr1BM57mCtyGvUEznuYI3Iq9QTOe5grcir1BM57mCNyOvUEznuYK3I69QTOe5gjckr1BM57mCtySvUEznuYI3Ja9QTOe5grclr1BM57mCNyavUEznuYK3Jq9QTOe5gjcnr1BM57mCtyevUEznuYI3KK9QTOe5grcor1BM57mCNymvUEznuYK3Ka9QTOe5gjcqr1BM57mK0Smm81yFznMF7wpfoZjOcxU6z1XpPFfwTvgViuk8V/Be+BWKjU4xnecK3g6/QjGd5wreEL9CMZ3nCt4Sv0IxnecK3hS/QjGd5wreLL9CMZ3nouuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLX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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::entrypoint_parameters"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::verify_private_authwit_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"368":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr","source":"use dep::authwit::auth_witness;\nuse dep::aztec::{protocol_types::{address::PartialAddress, grumpkin_point::GrumpkinPoint}, keys::PublicKeys};\n\nstruct AuthWitness {\n keys: PublicKeys,\n signature: [u8; 64],\n partial_address: PartialAddress,\n}\n\nimpl AuthWitness {\n fn deserialize(values: [Field; 73]) -> Self {\n let mut signature = [0; 64];\n for i in 0..64 {\n signature[i] = values[i + 8] as u8;\n }\n Self {\n keys: PublicKeys {\n npk_m: GrumpkinPoint::new(values[0], values[1]),\n ivpk_m: GrumpkinPoint::new(values[2], values[3]),\n ovpk_m: GrumpkinPoint::new(values[4], values[5]),\n tpk_m: GrumpkinPoint::new(values[6], values[7])\n },\n signature,\n partial_address: PartialAddress::from_field(values[72])\n }\n }\n}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> AuthWitness {\n let witness: [Field; 73] = auth_witness::get_auth_witness(message_hash);\n AuthWitness::deserialize(witness)\n}\n"},"369":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr","source":"mod util;\nmod auth_oracle;\n\ncontract SchnorrSingleKeyAccount {\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext};\n\n use dep::authwit::{entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions};\n\n use crate::{util::recover_address, auth_oracle::get_auth_witness};\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n let witness = get_auth_witness(outer_hash);\n assert(recover_address(outer_hash, witness).eq(context.this_address()));\n true\n }\n}\n"},"370":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr","source":"use dep::std::{schnorr::verify_signature_slice};\nuse dep::aztec::prelude::AztecAddress;\nuse crate::auth_oracle::AuthWitness;\n\npub fn recover_address(message_hash: Field, witness: AuthWitness) -> AztecAddress {\n let message_bytes = message_hash.to_be_bytes(32);\n // In a single key account contract we re-used ivpk_m as signing key\n let verification = verify_signature_slice(\n witness.keys.ivpk_m.x,\n witness.keys.ivpk_m.y,\n witness.signature,\n message_bytes\n );\n assert(verification == true);\n\n AztecAddress::compute(witness.keys.hash(), witness.partial_address)\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/accounts/src/ecdsa/artifact.ts b/yarn-project/accounts/src/ecdsa/artifact.ts index 54ec3212dd0e..a38c97a094f1 100644 --- a/yarn-project/accounts/src/ecdsa/artifact.ts +++ b/yarn-project/accounts/src/ecdsa/artifact.ts @@ -1,5 +1,5 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import EcdsaAccountContractJson from '../artifacts/EcdsaAccount.json' assert { type: 'json' }; +import EcdsaAccountContractJson from '../../artifacts/EcdsaAccount.json' assert { type: 'json' }; export const EcdsaAccountContractArtifact = loadContractArtifact(EcdsaAccountContractJson as NoirCompiledContract); diff --git a/yarn-project/accounts/src/schnorr/artifact.ts b/yarn-project/accounts/src/schnorr/artifact.ts index f7cac3337f74..88c1c5d1e4e4 100644 --- a/yarn-project/accounts/src/schnorr/artifact.ts +++ b/yarn-project/accounts/src/schnorr/artifact.ts @@ -1,5 +1,5 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import SchnorrAccountContractJson from '../artifacts/SchnorrAccount.json' assert { type: 'json' }; +import SchnorrAccountContractJson from '../../artifacts/SchnorrAccount.json' assert { type: 'json' }; export const SchnorrAccountContractArtifact = loadContractArtifact(SchnorrAccountContractJson as NoirCompiledContract); diff --git a/yarn-project/accounts/src/single_key/artifact.ts b/yarn-project/accounts/src/single_key/artifact.ts index 55a819dc5704..f48ee9a14e8e 100644 --- a/yarn-project/accounts/src/single_key/artifact.ts +++ b/yarn-project/accounts/src/single_key/artifact.ts @@ -1,6 +1,6 @@ import { type NoirCompiledContract, loadContractArtifact } from '@aztec/aztec.js'; -import SchnorrSingleKeyAccountContractJson from '../artifacts/SchnorrSingleKeyAccount.json' assert { type: 'json' }; +import SchnorrSingleKeyAccountContractJson from '../../artifacts/SchnorrSingleKeyAccount.json' assert { type: 'json' }; export const SchnorrSingleKeyAccountContractArtifact = loadContractArtifact( SchnorrSingleKeyAccountContractJson as NoirCompiledContract, diff --git a/yarn-project/accounts/tsconfig.json b/yarn-project/accounts/tsconfig.json index 0b48acf92f77..62dae97b8603 100644 --- a/yarn-project/accounts/tsconfig.json +++ b/yarn-project/accounts/tsconfig.json @@ -28,5 +28,5 @@ "path": "../types" } ], - "include": ["src", "src/**/*.json"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 4e1eb36c75d7..a4fcecef5f71 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -53,7 +53,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { type AztecKVStore } from '@aztec/kv-store'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; import { initStoreForRollup, openTmpStore } from '@aztec/kv-store/utils'; -import { SHA256Trunc, StandardTree } from '@aztec/merkle-tree'; +import { SHA256Trunc, StandardTree, UnbalancedTree } from '@aztec/merkle-tree'; import { AztecKVTxPool, type P2P, createP2PClient } from '@aztec/p2p'; import { getCanonicalClassRegisterer } from '@aztec/protocol-contracts/class-registerer'; import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; @@ -550,26 +550,16 @@ export class AztecNodeService implements AztecNode { true, ); - const l2toL1SubtreeRoots = l2toL1Subtrees.map(t => Fr.fromBuffer(t.getRoot(true))); - const treeHeight = block.header.contentCommitment.txTreeHeight.toNumber(); - // NOTE: This padding only works assuming that an 'empty' out hash is H(0,0) - const paddedl2toL1SubtreeRoots = padArrayEnd( - l2toL1SubtreeRoots, - Fr.fromBuffer(sha256Trunc(Buffer.alloc(64))), - 2 ** treeHeight, - ); + let l2toL1SubtreeRoots = l2toL1Subtrees.map(t => Fr.fromBuffer(t.getRoot(true))); + if (l2toL1SubtreeRoots.length < 2) { + l2toL1SubtreeRoots = padArrayEnd(l2toL1SubtreeRoots, Fr.fromBuffer(sha256Trunc(Buffer.alloc(64))), 2); + } + const maxTreeHeight = Math.ceil(Math.log2(l2toL1SubtreeRoots.length)); // The root of this tree is the out_hash calculated in Noir => we truncate to match Noir's SHA - const outHashTree = new StandardTree( - openTmpStore(true), - new SHA256Trunc(), - 'temp_outhash_sibling_path', - treeHeight, - 0n, - Fr, - ); - await outHashTree.appendLeaves(paddedl2toL1SubtreeRoots); + const outHashTree = new UnbalancedTree(new SHA256Trunc(), 'temp_outhash_sibling_path', maxTreeHeight, Fr); + await outHashTree.appendLeaves(l2toL1SubtreeRoots); - const pathOfTxInOutHashTree = await outHashTree.getSiblingPath(BigInt(indexOfMsgTx), true); + const pathOfTxInOutHashTree = await outHashTree.getSiblingPath(l2toL1SubtreeRoots[indexOfMsgTx].toBigInt()); // Append subtree path to out hash tree path const mergedPath = subtreePathOfL2ToL1Message.toBufferArray().concat(pathOfTxInOutHashTree.toBufferArray()); // Append binary index of subtree path to binary index of out hash tree path @@ -704,10 +694,11 @@ export class AztecNodeService implements AztecNode { * * @param contract - Address of the contract to query. * @param slot - Slot to query. + * @param blockNumber - The block number at which to get the data or 'latest'. * @returns Storage value at the given contract slot. */ - public async getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise { - const committedDb = await this.#getWorldState('latest'); + public async getPublicStorageAt(contract: AztecAddress, slot: Fr, blockNumber: L2BlockNumber): Promise { + const committedDb = await this.#getWorldState(blockNumber); const leafSlot = computePublicDataTreeLeafSlot(contract, slot); const lowLeafResult = await committedDb.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt()); diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 4e3d71e4d8f2..38cf7e986bce 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -99,6 +99,7 @@ export { EncryptedLogHeader, EncryptedNoteLogIncomingBody, EncryptedLogOutgoingBody, + EventType, ExtendedNote, FunctionCall, GrumpkinPrivateKey, diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 247b509fbafb..43b6753efcec 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,6 +1,7 @@ import { type AuthWitness, type EventMetadata, + type EventType, type ExtendedNote, type GetUnencryptedLogsResponse, type IncomingNotesFilter, @@ -182,11 +183,15 @@ export abstract class BaseWallet implements Wallet { return this.pxe.getPXEInfo(); } getEvents( + type: EventType, + eventMetadata: EventMetadata, from: number, limit: number, - eventMetadata: EventMetadata, - ivpk: Point = this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, - ): Promise { - return this.pxe.getEvents(from, limit, eventMetadata, ivpk); + vpks: Point[] = [ + this.getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, + this.getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey, + ], + ) { + return this.pxe.getEvents(type, eventMetadata, from, limit, vpks); } } diff --git a/yarn-project/aztec/CHANGELOG.md b/yarn-project/aztec/CHANGELOG.md index 3e6001e44b15..58f934bc1ad6 100644 --- a/yarn-project/aztec/CHANGELOG.md +++ b/yarn-project/aztec/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [0.45.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.44.0...aztec-package-v0.45.0) (2024-07-02) + + +### Bug Fixes + +* Devnet deployment issues ([#7197](https://github.com/AztecProtocol/aztec-packages/issues/7197)) ([9cf4904](https://github.com/AztecProtocol/aztec-packages/commit/9cf49048eefd1f02d22c6b4a8db100b863f39f84)) + +## [0.44.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.43.0...aztec-package-v0.44.0) (2024-06-26) + + +### Features + +* Add OpenTelemetry to node ([#7102](https://github.com/AztecProtocol/aztec-packages/issues/7102)) ([6bf2b72](https://github.com/AztecProtocol/aztec-packages/commit/6bf2b7269fddb5bd7fe4c567710146b4969d2845)) +* Devnet deployments ([#7024](https://github.com/AztecProtocol/aztec-packages/issues/7024)) ([fa70876](https://github.com/AztecProtocol/aztec-packages/commit/fa70876a17b981e6ffa4bece390186b1231ba4fe)) +* Track spans ([#7129](https://github.com/AztecProtocol/aztec-packages/issues/7129)) ([924c3f8](https://github.com/AztecProtocol/aztec-packages/commit/924c3f8809b30d16e81eed5e467aa79ee7074f77)) + ## [0.43.0](https://github.com/AztecProtocol/aztec-packages/compare/aztec-package-v0.42.0...aztec-package-v0.43.0) (2024-06-18) diff --git a/yarn-project/aztec/package.json b/yarn-project/aztec/package.json index 989cf37a0391..e6dead0b6908 100644 --- a/yarn-project/aztec/package.json +++ b/yarn-project/aztec/package.json @@ -1,6 +1,6 @@ { "name": "@aztec/aztec", - "version": "0.43.0", + "version": "0.45.0", "type": "module", "exports": { ".": "./dest/index.js" diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 20725c32103d..d446d334c89e 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -193,7 +193,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "ETHEREUM_HOST", - "value": "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" + "value": "https://aztec-dev-mainnet-fork.aztec.network:8545/${var.API_KEY}" }, { "name": "DATA_DIRECTORY", diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 53987df2e8cb..f821a8266c97 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -3,16 +3,17 @@ import { AztecAddress, ContractStorageRead, ContractStorageUpdateRequest, + FunctionSelector, Gas, GlobalVariables, Header, L2ToL1Message, LogHash, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, @@ -168,6 +169,7 @@ describe('AVM WitGen, proof generation and verification', () => { 'get_fee_per_l2_gas', 'get_fee_per_da_gas', 'get_transaction_fee', + 'get_function_selector', 'get_chain_id', 'get_version', 'get_block_number', @@ -201,9 +203,10 @@ const proveAndVerifyAvmTestContract = async ( assertionErrString?: string, ) => { const startSideEffectCounter = 0; + const functionSelector = FunctionSelector.random(); const globals = GlobalVariables.empty(); globals.timestamp = TIMESTAMP; - const environment = initExecutionEnvironment({ calldata, globals }); + const environment = initExecutionEnvironment({ functionSelector, calldata, globals }); const contractsDb = mock(); const contractInstance = new SerializableContractInstance({ @@ -285,12 +288,12 @@ const proveAndVerifyAvmTestContract = async ( // TODO: pub somewhere more usable - copied from abstract phase manager const getPublicInputs = (result: PublicExecutionResult): PublicCircuitPublicInputs => { return PublicCircuitPublicInputs.from({ - callContext: result.execution.callContext, + callContext: result.executionRequest.callContext, proverAddress: AztecAddress.ZERO, - argsHash: computeVarArgsHash(result.execution.args), - newNoteHashes: padArrayEnd(result.newNoteHashes, NoteHash.empty(), MAX_NEW_NOTE_HASHES_PER_CALL), - newNullifiers: padArrayEnd(result.newNullifiers, Nullifier.empty(), MAX_NEW_NULLIFIERS_PER_CALL), - newL2ToL1Msgs: padArrayEnd(result.newL2ToL1Messages, L2ToL1Message.empty(), MAX_NEW_L2_TO_L1_MSGS_PER_CALL), + argsHash: computeVarArgsHash(result.executionRequest.args), + noteHashes: padArrayEnd(result.noteHashes, NoteHash.empty(), MAX_NOTE_HASHES_PER_CALL), + nullifiers: padArrayEnd(result.nullifiers, Nullifier.empty(), MAX_NULLIFIERS_PER_CALL), + l2ToL1Msgs: padArrayEnd(result.l2ToL1Messages, L2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_CALL), startSideEffectCounter: result.startSideEffectCounter, endSideEffectCounter: result.endSideEffectCounter, returnsHash: computeVarArgsHash(result.returnValues), diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index c3b28317377c..7c97fcede72c 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -1,6 +1,6 @@ import { type AvmCircuitInputs } from '@aztec/circuits.js'; import { sha256 } from '@aztec/foundation/crypto'; -import { type LogFn } from '@aztec/foundation/log'; +import { type LogFn, currentLevel as currentLogLevel } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; @@ -12,6 +12,10 @@ export const VK_FILENAME = 'vk'; export const VK_FIELDS_FILENAME = 'vk_fields.json'; export const PROOF_FILENAME = 'proof'; export const PROOF_FIELDS_FILENAME = 'proof_fields.json'; +export const AVM_BYTECODE_FILENAME = 'avm_bytecode.bin'; +export const AVM_CALLDATA_FILENAME = 'avm_calldata.bin'; +export const AVM_PUBLIC_INPUTS_FILENAME = 'avm_public_inputs.bin'; +export const AVM_HINTS_FILENAME = 'avm_hints.bin'; export enum BB_RESULT { SUCCESS, @@ -276,10 +280,10 @@ export async function generateAvmProof( } // Paths for the inputs - const bytecodePath = join(workingDirectory, 'avm_bytecode.bin'); - const calldataPath = join(workingDirectory, 'avm_calldata.bin'); - const publicInputsPath = join(workingDirectory, 'avm_public_inputs.bin'); - const avmHintsPath = join(workingDirectory, 'avm_hints.bin'); + const bytecodePath = join(workingDirectory, AVM_BYTECODE_FILENAME); + const calldataPath = join(workingDirectory, AVM_CALLDATA_FILENAME); + const publicInputsPath = join(workingDirectory, AVM_PUBLIC_INPUTS_FILENAME); + const avmHintsPath = join(workingDirectory, AVM_HINTS_FILENAME); // The proof is written to e.g. /workingDirectory/proof const outputPath = workingDirectory; @@ -335,6 +339,7 @@ export async function generateAvmProof( avmHintsPath, '-o', outputPath, + currentLogLevel == 'debug' ? '-d' : 'verbose' ? '-v' : '', ]; const timer = new Timer(); const logFunction = (message: string) => { diff --git a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts index ea93f78fe77f..ecfad7d8ed1a 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts +++ b/yarn-project/bb-prover/src/prover/bb_native_proof_creator.ts @@ -76,9 +76,7 @@ export class BBNativeProofCreator implements ProofCreator { public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; - return Promise.resolve( - publicInputs.newNoteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value)), - ); + return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } public async createProofInit( diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 7eed17fbe139..00c9d0e8b8a7 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -632,7 +632,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes); const logFunction = (message: string) => { - logger.debug(`BB out - ${message}`); + logger.verbose(`BB out - ${message}`); }; const result = await verificationFunction( @@ -647,7 +647,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { throw new Error(errorMessage); } - logger.debug(`Successfully verified proof from key in ${result.durationMs} ms`); + logger.info(`Successfully verified proof from key in ${result.durationMs} ms`); }; await runInDirectory(this.config.bbWorkingDirectory, operation); diff --git a/yarn-project/bb-prover/src/verifier/bb_verifier.ts b/yarn-project/bb-prover/src/verifier/bb_verifier.ts index ed0985c1dce3..e5c12ce088e6 100644 --- a/yarn-project/bb-prover/src/verifier/bb_verifier.ts +++ b/yarn-project/bb-prover/src/verifier/bb_verifier.ts @@ -129,9 +129,10 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { } async verifyProof(tx: Tx): Promise { - const { proof, enqueuedPublicFunctionCalls } = tx; - const expectedCircuit: ClientProtocolArtifact = - enqueuedPublicFunctionCalls.length > 0 ? 'PrivateKernelTailToPublicArtifact' : 'PrivateKernelTailArtifact'; + const { proof, data } = tx; + const expectedCircuit: ClientProtocolArtifact = data.forPublic + ? 'PrivateKernelTailToPublicArtifact' + : 'PrivateKernelTailArtifact'; try { await this.verifyProofForCircuit(expectedCircuit, proof); diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 98d8b51ecab8..c0e63aa43d34 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -48,39 +48,52 @@ export class Body { /** * Computes the transactions effects hash for the L2 block - * This hash is also computed in the `AvailabilityOracle` and the `Circuit`. + * This hash is also computed in the `AvailabilityOracle`. * @returns The txs effects hash. */ getTxsEffectsHash() { + // Adapted from proving-state.ts -> findMergeLevel and unbalanced_tree.ts + // Calculates the tree upwards layer by layer until we reach the root + // The L1 calculation instead computes the tree from right to left (slightly cheaper gas) + // TODO: A more thorough investigation of which method is cheaper, then use that method everywhere const computeRoot = (leaves: Buffer[]): Buffer => { - const layers: Buffer[][] = [leaves]; - let activeLayer = 0; - - while (layers[activeLayer].length > 1) { - const layer: Buffer[] = []; - const layerLength = layers[activeLayer].length; - - for (let i = 0; i < layerLength; i += 2) { - const left = layers[activeLayer][i]; - const right = layers[activeLayer][i + 1]; - - layer.push(sha256Trunc(Buffer.concat([left, right]))); + const depth = Math.ceil(Math.log2(leaves.length)); + let [layerWidth, nodeToShift] = + leaves.length & 1 ? [leaves.length - 1, leaves[leaves.length - 1]] : [leaves.length, Buffer.alloc(0)]; + // Allocate this layer's leaves and init the next layer up + let thisLayer = leaves.slice(0, layerWidth); + let nextLayer = []; + for (let i = 0; i < depth; i++) { + for (let j = 0; j < layerWidth; j += 2) { + // Store the hash of each pair one layer up + nextLayer[j / 2] = sha256Trunc(Buffer.concat([thisLayer[j], thisLayer[j + 1]])); } - - layers.push(layer); - activeLayer++; + layerWidth /= 2; + if (layerWidth & 1) { + if (nodeToShift.length) { + // If the next layer has odd length, and we have a node that needs to be shifted up, add it here + nextLayer.push(nodeToShift); + layerWidth += 1; + nodeToShift = Buffer.alloc(0); + } else { + // If we don't have a node waiting to be shifted, store the next layer's final node to be shifted + layerWidth -= 1; + nodeToShift = nextLayer[layerWidth]; + } + } + // reset the layers + thisLayer = nextLayer; + nextLayer = []; } - - return layers[layers.length - 1][0]; + // return the root + return thisLayer[0]; }; const emptyTxEffectHash = TxEffect.empty().hash(); - const leaves: Buffer[] = padArrayEnd( - this.txEffects.map(txEffect => txEffect.hash()), - emptyTxEffectHash, - this.numberOfTxsIncludingPadded, - ); - + let leaves: Buffer[] = this.txEffects.map(txEffect => txEffect.hash()); + if (leaves.length < 2) { + leaves = padArrayEnd(leaves, emptyTxEffectHash, 2); + } return computeRoot(leaves); } @@ -114,20 +127,7 @@ export class Body { return 2; } - // Note that the following could be implemented in a more simple way as "2 ** Math.ceil(Math.log2(numTxEffects));" - // but we want to keep the same logic as in Solidity and there we don't have the math functions. - let v = numTxEffects; - - // The following rounds numTxEffects up to the next power of 2 (works only for 4 bytes value!) - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - - return v; + return numTxEffects; } static random( diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 0890b0c6904b..a79a28ece159 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -291,9 +291,10 @@ export interface AztecNode { * * @param contract - Address of the contract to query. * @param slot - Slot to query. + * @param blockNumber - The block number at which to get the data or 'latest'. * @returns Storage value at the given contract slot. */ - getPublicStorageAt(contract: AztecAddress, slot: Fr): Promise; + getPublicStorageAt(contract: AztecAddress, slot: Fr, blockNumber: L2BlockNumber): Promise; /** * Returns the currently committed block header. diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 6092eda27800..b4e6e6eda2e9 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -381,14 +381,21 @@ export interface PXE { isContractPubliclyDeployed(address: AztecAddress): Promise; /** - * Returns the events of a specified type. + * Returns the events of a specified type given search parameters. + * @param type - The type of the event to search for—Encrypted, or Unencrypted. + * @param eventMetadata - Identifier of the event. This should be the class generated from the contract. e.g. Contract.events.Event * @param from - The block number to search from. * @param limit - The amount of blocks to search. - * @param eventMetadata - Identifier of the event. This should be the class generated from the contract. e.g. Contract.events.Event - * @param ivpk - The incoming viewing public key that corresponds to the incoming viewing secret key that can decrypt the log. + * @param vpks - (Used for encrypted logs only) The viewing (incoming and outgoing) public keys that correspond to the viewing secret keys that can decrypt the log. * @returns - The deserialized events. */ - getEvents(from: number, limit: number, eventMetadata: EventMetadata, ivpk: Point): Promise; + getEvents( + type: EventType, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[], + ): Promise; } // docs:end:pxe-interface @@ -401,6 +408,14 @@ export interface EventMetadata { fieldNames: string[]; } +/** + * This is used in getting events via the filter + */ +export enum EventType { + Encrypted = 'Encrypted', + Unencrypted = 'Unencrypted', +} + /** * Provides basic information about the running PXE. */ diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index 99df4ebcfa58..a15d73e021e9 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -3,7 +3,7 @@ import { CallRequest, GasSettings, LogHash, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, Nullifier, PartialPrivateTailPublicInputsForPublic, @@ -58,7 +58,7 @@ export const mockTx = ( ); } - const isForPublic = totalPublicCallRequests > 0; + const isForPublic = totalPublicCallRequests > 0 || publicTeardownCallRequest.isEmpty() === false; const data = PrivateKernelTailCircuitPublicInputs.empty(); const firstNullifier = new Nullifier(new Fr(seed + 1), 0, Fr.ZERO); const noteEncryptedLogs = EncryptedNoteTxL2Logs.empty(); // Mock seems to have no new notes => no note logs @@ -78,11 +78,11 @@ export const mockTx = ( const revertibleBuilder = new PublicAccumulatedDataBuilder(); const nonRevertibleBuilder = new PublicAccumulatedDataBuilder(); - const nonRevertibleNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty); + const nonRevertibleNullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty); nonRevertibleNullifiers[0] = firstNullifier; data.forPublic.endNonRevertibleData = nonRevertibleBuilder - .withNewNullifiers(nonRevertibleNullifiers) + .withNullifiers(nonRevertibleNullifiers) .withPublicCallStack( makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => i < numberOfNonRevertiblePublicCallRequests @@ -154,7 +154,7 @@ export const mockTx = ( }); } } else { - data.forRollup!.end.newNullifiers[0] = firstNullifier.value; + data.forRollup!.end.nullifiers[0] = firstNullifier.value; data.forRollup!.end.noteEncryptedLogsHash = Fr.fromBuffer(noteEncryptedLogs.hash()); data.forRollup!.end.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash()); data.forRollup!.end.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash()); diff --git a/yarn-project/circuit-types/src/tx/processed_tx.ts b/yarn-project/circuit-types/src/tx/processed_tx.ts index d20983f261bf..bb96b7f5615b 100644 --- a/yarn-project/circuit-types/src/tx/processed_tx.ts +++ b/yarn-project/circuit-types/src/tx/processed_tx.ts @@ -234,9 +234,9 @@ export function toTxEffect(tx: ProcessedTx, gasFees: GasFees): TxEffect { return new TxEffect( tx.data.revertCode, tx.data.getTransactionFee(gasFees), - tx.data.end.newNoteHashes.filter(h => !h.isZero()), - tx.data.end.newNullifiers.filter(h => !h.isZero()), - tx.data.end.newL2ToL1Msgs.filter(h => !h.isZero()), + tx.data.end.noteHashes.filter(h => !h.isZero()), + tx.data.end.nullifiers.filter(h => !h.isZero()), + tx.data.end.l2ToL1Msgs.filter(h => !h.isZero()), tx.finalPublicDataUpdateRequests.map(t => new PublicDataWrite(t.leafSlot, t.newValue)).filter(h => !h.isEmpty()), tx.data.end.noteEncryptedLogPreimagesLength, tx.data.end.encryptedLogPreimagesLength, diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 8cb40f57d623..b71e99074d51 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -50,10 +50,11 @@ export class Tx { public readonly publicTeardownFunctionCall: PublicCallRequest, ) { const kernelPublicCallStackSize = data.numberOfPublicCallRequests(); - if (kernelPublicCallStackSize !== enqueuedPublicFunctionCalls.length) { + const totalPublicCalls = enqueuedPublicFunctionCalls.length + (publicTeardownFunctionCall.isEmpty() ? 0 : 1); + if (kernelPublicCallStackSize !== totalPublicCalls) { throw new Error( `Mismatch number of enqueued public function calls in kernel circuit public inputs (expected - ${kernelPublicCallStackSize}, got ${enqueuedPublicFunctionCalls.length})`, + ${kernelPublicCallStackSize}, got ${totalPublicCalls})`, ); } } diff --git a/yarn-project/circuit-types/src/tx_effect.ts b/yarn-project/circuit-types/src/tx_effect.ts index bf5fb9d5a31a..b707ae237074 100644 --- a/yarn-project/circuit-types/src/tx_effect.ts +++ b/yarn-project/circuit-types/src/tx_effect.ts @@ -7,9 +7,9 @@ import { } from '@aztec/circuit-types'; import { Fr, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, RevertCode, } from '@aztec/circuits.js'; @@ -58,8 +58,8 @@ export class TxEffect { ) { // TODO(#4638): Clean this up once we have isDefault() everywhere --> then we don't have to deal with 2 different // functions (isZero and isEmpty) - if (noteHashes.length > MAX_NEW_NOTE_HASHES_PER_TX) { - throw new Error(`Too many note hashes: ${noteHashes.length}, max: ${MAX_NEW_NOTE_HASHES_PER_TX}`); + if (noteHashes.length > MAX_NOTE_HASHES_PER_TX) { + throw new Error(`Too many note hashes: ${noteHashes.length}, max: ${MAX_NOTE_HASHES_PER_TX}`); } noteHashes.forEach(h => { if (h.isZero()) { @@ -67,8 +67,8 @@ export class TxEffect { } }); - if (nullifiers.length > MAX_NEW_NULLIFIERS_PER_TX) { - throw new Error(`Too many nullifiers: ${nullifiers.length}, max: ${MAX_NEW_NULLIFIERS_PER_TX}`); + if (nullifiers.length > MAX_NULLIFIERS_PER_TX) { + throw new Error(`Too many nullifiers: ${nullifiers.length}, max: ${MAX_NULLIFIERS_PER_TX}`); } nullifiers.forEach(h => { if (h.isZero()) { @@ -76,8 +76,8 @@ export class TxEffect { } }); - if (l2ToL1Msgs.length > MAX_NEW_L2_TO_L1_MSGS_PER_TX) { - throw new Error(`Too many L2 to L1 messages: ${l2ToL1Msgs.length}, max: ${MAX_NEW_L2_TO_L1_MSGS_PER_TX}`); + if (l2ToL1Msgs.length > MAX_L2_TO_L1_MSGS_PER_TX) { + throw new Error(`Too many L2 to L1 messages: ${l2ToL1Msgs.length}, max: ${MAX_L2_TO_L1_MSGS_PER_TX}`); } l2ToL1Msgs.forEach(h => { if (h.isZero()) { @@ -146,18 +146,9 @@ export class TxEffect { hash() { const padBuffer = (buf: Buffer, length: number) => Buffer.concat([buf, Buffer.alloc(length - buf.length)]); - const noteHashesBuffer = padBuffer( - serializeToBuffer(this.noteHashes), - Fr.SIZE_IN_BYTES * MAX_NEW_NOTE_HASHES_PER_TX, - ); - const nullifiersBuffer = padBuffer( - serializeToBuffer(this.nullifiers), - Fr.SIZE_IN_BYTES * MAX_NEW_NULLIFIERS_PER_TX, - ); - const l2ToL1MsgsBuffer = padBuffer( - serializeToBuffer(this.l2ToL1Msgs), - Fr.SIZE_IN_BYTES * MAX_NEW_L2_TO_L1_MSGS_PER_TX, - ); + const noteHashesBuffer = padBuffer(serializeToBuffer(this.noteHashes), Fr.SIZE_IN_BYTES * MAX_NOTE_HASHES_PER_TX); + const nullifiersBuffer = padBuffer(serializeToBuffer(this.nullifiers), Fr.SIZE_IN_BYTES * MAX_NULLIFIERS_PER_TX); + const l2ToL1MsgsBuffer = padBuffer(serializeToBuffer(this.l2ToL1Msgs), Fr.SIZE_IN_BYTES * MAX_L2_TO_L1_MSGS_PER_TX); const publicDataWritesBuffer = padBuffer( serializeToBuffer(this.publicDataWrites), PublicDataWrite.SIZE_IN_BYTES * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, @@ -197,9 +188,9 @@ export class TxEffect { return new TxEffect( RevertCode.random(), Fr.random(), - makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, Fr.random), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.random), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.random), + makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.random), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.random), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.random), makeTuple(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataWrite.random), new Fr(noteEncryptedLogs.getKernelLength()), new Fr(encryptedLogs.getKernelLength()), diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index f226f6d2e169..c8bb1f971cdc 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -1,33 +1,33 @@ /* eslint-disable */ // GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants export const ARGS_LENGTH = 16; -export const MAX_NEW_NOTE_HASHES_PER_CALL = 16; -export const MAX_NEW_NULLIFIERS_PER_CALL = 16; +export const MAX_NOTE_HASHES_PER_CALL = 16; +export const MAX_NULLIFIERS_PER_CALL = 16; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL = 4; export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL = 16; -export const MAX_NEW_L2_TO_L1_MSGS_PER_CALL = 2; +export const MAX_L2_TO_L1_MSGS_PER_CALL = 2; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL = 32; export const MAX_PUBLIC_DATA_READS_PER_CALL = 32; -export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; -export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 32; -export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 32; +export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 16; +export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 16; +export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 16; export const MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL = 16; export const MAX_KEY_VALIDATION_REQUESTS_PER_CALL = 16; export const MAX_NOTE_ENCRYPTED_LOGS_PER_CALL = 16; 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_NOTE_HASHES_PER_TX = 64; +export const MAX_NULLIFIERS_PER_TX = 64; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; export const MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX = 32; export const MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 63; export const PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 1; export const MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX = 64; export const MAX_PUBLIC_DATA_READS_PER_TX = 64; -export const MAX_NEW_L2_TO_L1_MSGS_PER_TX = 8; -export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; -export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 128; -export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 128; +export const MAX_L2_TO_L1_MSGS_PER_TX = 8; +export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 64; +export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 64; +export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 64; export const MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX = 64; export const MAX_KEY_VALIDATION_REQUESTS_PER_TX = 64; export const MAX_NOTE_ENCRYPTED_LOGS_PER_TX = 64; @@ -133,22 +133,22 @@ export const TX_CONTEXT_LENGTH = 9; export const TX_REQUEST_LENGTH = 13; export const TOTAL_FEES_LENGTH = 1; export const HEADER_LENGTH = 23; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 457; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 578; -export const PRIVATE_CALL_STACK_ITEM_LENGTH = 460; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 393; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 482; +export const PRIVATE_CALL_STACK_ITEM_LENGTH = 396; export const PUBLIC_CONTEXT_INPUTS_LENGTH = 41; export const AGGREGATION_OBJECT_LENGTH = 16; export const SCOPED_READ_REQUEST_LEN = 3; export const PUBLIC_DATA_READ_LENGTH = 2; -export const VALIDATION_REQUESTS_LENGTH = 1602; +export const VALIDATION_REQUESTS_LENGTH = 1026; export const PUBLIC_DATA_UPDATE_REQUEST_LENGTH = 3; export const COMBINED_ACCUMULATED_DATA_LENGTH = 333; export const COMBINED_CONSTANT_DATA_LENGTH = 40; export const CALL_REQUEST_LENGTH = 7; export const PRIVATE_ACCUMULATED_DATA_LENGTH = 1152; -export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2803; +export const PRIVATE_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 2227; export const PUBLIC_ACCUMULATED_DATA_LENGTH = 983; -export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3834; +export const PUBLIC_KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 3258; export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 383; export const CONSTANT_ROLLUP_DATA_LENGTH = 14; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 31; @@ -167,6 +167,32 @@ export const NUM_BASE_PARITY_PER_ROOT_PARITY = 4; export const RECURSIVE_PROOF_LENGTH = 93; export const NESTED_RECURSIVE_PROOF_LENGTH = 109; export const VERIFICATION_KEY_LENGTH_IN_FIELDS = 114; +export const SENDER_SELECTOR = 0; +export const ADDRESS_SELECTOR = 1; +export const STORAGE_ADDRESS_SELECTOR = 1; +export const FUNCTION_SELECTOR_SELECTOR = 2; +export const START_GLOBAL_VARIABLES = 29; +export const CHAIN_ID_SELECTOR = 29; +export const VERSION_SELECTOR = 30; +export const BLOCK_NUMBER_SELECTOR = 31; +export const TIMESTAMP_SELECTOR = 32; +export const COINBASE_SELECTOR = 33; +export const UNUSED_FEE_RECIPIENT_SELECTOR = 34; +export const FEE_PER_DA_GAS_SELECTOR = 35; +export const FEE_PER_L2_GAS_SELECTOR = 36; +export const END_GLOBAL_VARIABLES = 37; +export const START_SIDE_EFFECT_COUNTER = 37; +export const TRANSACTION_FEE_SELECTOR = 40; +export const START_NOTE_HASH_EXISTS_WRITE_OFFSET = 0; +export const START_NULLIFIER_EXISTS_OFFSET = 16; +export const START_NULLIFIER_NON_EXISTS_OFFSET = 32; +export const START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET = 48; +export const START_SSTORE_WRITE_OFFSET = 64; +export const START_SLOAD_WRITE_OFFSET = 96; +export const START_EMIT_NOTE_HASH_WRITE_OFFSET = 128; +export const START_EMIT_NULLIFIER_WRITE_OFFSET = 144; +export const START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET = 160; +export const START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET = 162; export enum GeneratorIndex { NOTE_HASH = 1, NOTE_HASH_NONCE = 2, diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts index 26d871b060ee..9728ca03a034 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.test.ts @@ -3,7 +3,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type Tuple } from '@aztec/foundation/serialize'; -import { MAX_NEW_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX } from '../constants.gen.js'; +import { MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { siloNoteHash } from '../hash/index.js'; import { NoteHash, @@ -28,7 +28,7 @@ describe('buildNoteHashReadRequestHints', () => { settledLeafIndexes.includes(leafIndex) ? ({} as any) : undefined, }; let noteHashReadRequests: Tuple; - let noteHashes: Tuple; + let noteHashes: Tuple; let noteHashLeafIndexMap: Map = new Map(); let expectedHints: NoteHashReadRequestHints< typeof MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -89,7 +89,7 @@ describe('buildNoteHashReadRequestHints', () => { beforeEach(() => { noteHashReadRequests = makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); - noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => makeNoteHash(innerNoteHash(i))); + noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, i => makeNoteHash(innerNoteHash(i))); noteHashLeafIndexMap = new Map(); expectedHints = NoteHashReadRequestHintsBuilder.empty( MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -98,9 +98,9 @@ describe('buildNoteHashReadRequestHints', () => { numReadRequests = 0; numPendingReads = 0; numSettledReads = 0; - futureNoteHashes = new Array(MAX_NEW_NOTE_HASHES_PER_TX) + futureNoteHashes = new Array(MAX_NOTE_HASHES_PER_TX) .fill(null) - .map((_, i) => makeNoteHash(innerNoteHash(i + MAX_NEW_NOTE_HASHES_PER_TX))); + .map((_, i) => makeNoteHash(innerNoteHash(i + MAX_NOTE_HASHES_PER_TX))); }); it('builds empty hints', async () => { diff --git a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts index c065e0d422d5..60661223a9d1 100644 --- a/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_note_hash_read_request_hints.ts @@ -1,7 +1,7 @@ import { type Tuple } from '@aztec/foundation/serialize'; import { - type MAX_NEW_NOTE_HASHES_PER_TX, + type MAX_NOTE_HASHES_PER_TX, type MAX_NOTE_HASH_READ_REQUESTS_PER_TX, type NOTE_HASH_TREE_HEIGHT, } from '../constants.gen.js'; @@ -29,7 +29,7 @@ export async function buildNoteHashReadRequestHints>; }, noteHashReadRequests: Tuple, - noteHashes: Tuple, + noteHashes: Tuple, noteHashLeafIndexMap: Map, sizePending: PENDING, sizeSettled: SETTLED, diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts index 7c5834fe945a..beb031fb2592 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.test.ts @@ -3,7 +3,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; -import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; +import { MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { siloNullifier } from '../hash/index.js'; import { Nullifier, @@ -19,7 +19,7 @@ describe('buildNullifierNonExistentReadRequestHints', () => { getLowNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; const nonExistentReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); - let nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty); + let nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty); const innerNullifier = (index: number) => index + 1; @@ -36,8 +36,8 @@ describe('buildNullifierNonExistentReadRequestHints', () => { siloedValue: Fr; } - const populateNullifiers = (numNullifiers = MAX_NEW_NULLIFIERS_PER_TX) => { - nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => + const populateNullifiers = (numNullifiers = MAX_NULLIFIERS_PER_TX) => { + nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, i => i < numNullifiers ? makeNullifier(innerNullifier(i)) : Nullifier.empty(), ); }; @@ -77,7 +77,7 @@ describe('buildNullifierNonExistentReadRequestHints', () => { }); it('builds hints for half-full sorted nullifiers', async () => { - const numNonEmptyNullifiers = MAX_NEW_NULLIFIERS_PER_TX / 2; + const numNonEmptyNullifiers = MAX_NULLIFIERS_PER_TX / 2; populateNullifiers(numNonEmptyNullifiers); const hints = await buildHints(); @@ -103,7 +103,7 @@ describe('buildNullifierNonExistentReadRequestHints', () => { }); it('builds hints for read requests', async () => { - const numNonEmptyNullifiers = MAX_NEW_NULLIFIERS_PER_TX / 2; + const numNonEmptyNullifiers = MAX_NULLIFIERS_PER_TX / 2; expect(numNonEmptyNullifiers > 1).toBe(true); // Need at least 2 nullifiers to test a value in the middle. const sortedNullifiers = generateSortedNullifiers(numNonEmptyNullifiers + 3); @@ -118,7 +118,7 @@ describe('buildNullifierNonExistentReadRequestHints', () => { nullifiers = padArrayEnd( sortedNullifiers.map(n => makeNullifier(n.value)), Nullifier.empty(), - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, ); const hints = await buildHints(); diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts index b2393cf4bc4c..d217864333df 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_non_existent_read_request_hints.ts @@ -4,7 +4,7 @@ import { type Tuple } from '@aztec/foundation/serialize'; import { type IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, type MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, type NULLIFIER_TREE_HEIGHT, } from '../constants.gen.js'; @@ -26,8 +26,8 @@ interface SortedResult { } function sortNullifiersByValues( - nullifiers: Tuple, -): SortedResult { + nullifiers: Tuple, +): SortedResult { const numNullifiers = countAccumulatedItems(nullifiers); const sorted = nullifiers .slice(0, numNullifiers) @@ -43,9 +43,9 @@ function sortNullifiersByValues( sortedValues: padArrayEnd( sorted.map(s => s.nullifier), Nullifier.empty(), - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, ), - sortedIndexHints: padArrayEnd(sortedIndexHints, 0, MAX_NEW_NULLIFIERS_PER_TX), + sortedIndexHints: padArrayEnd(sortedIndexHints, 0, MAX_NULLIFIERS_PER_TX), }; } @@ -54,7 +54,7 @@ export async function buildNullifierNonExistentReadRequestHints( getLowNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierNonExistentReadRequests: Tuple, - pendingNullifiers: Tuple, + pendingNullifiers: Tuple, ) { const { sortedValues, sortedIndexHints } = sortNullifiersByValues(pendingNullifiers); diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts index 4e418633edc8..4561ed2ef42f 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.test.ts @@ -3,7 +3,7 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type Tuple } from '@aztec/foundation/serialize'; -import { MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; +import { MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX } from '../constants.gen.js'; import { Nullifier, type NullifierReadRequestHints, @@ -25,7 +25,7 @@ describe('buildNullifierReadRequestHints', () => { getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; let nullifierReadRequests: Tuple; - let nullifiers: Tuple; + let nullifiers: Tuple; let expectedHints: NullifierReadRequestHints< typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX @@ -93,7 +93,7 @@ describe('buildNullifierReadRequestHints', () => { beforeEach(() => { nullifierReadRequests = makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty); - nullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); + nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, i => makeNullifier(innerNullifier(i))); expectedHints = NullifierReadRequestHintsBuilder.empty( MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -101,9 +101,9 @@ describe('buildNullifierReadRequestHints', () => { numReadRequests = 0; numPendingReads = 0; numSettledReads = 0; - futureNullifiers = new Array(MAX_NEW_NULLIFIERS_PER_TX) + futureNullifiers = new Array(MAX_NULLIFIERS_PER_TX) .fill(null) - .map((_, i) => makeNullifier(innerNullifier(i + MAX_NEW_NULLIFIERS_PER_TX))); + .map((_, i) => makeNullifier(innerNullifier(i + MAX_NULLIFIERS_PER_TX))); }); it('builds empty hints', async () => { diff --git a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts index a7adfca91cf2..d9e9672045ef 100644 --- a/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_nullifier_read_request_hints.ts @@ -5,7 +5,7 @@ import { type Tuple } from '@aztec/foundation/serialize'; import { type IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { - type MAX_NEW_NULLIFIERS_PER_TX, + type MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, type NULLIFIER_TREE_HEIGHT, } from '../constants.gen.js'; @@ -39,7 +39,7 @@ export async function buildNullifierReadRequestHints; }, nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, sizePending: PENDING, sizeSettled: SETTLED, futureNullifiers: ScopedNullifier[], @@ -89,7 +89,7 @@ export function buildSiloedNullifierReadRequestHints; }, nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, sizePending: PENDING, sizeSettled: SETTLED, ) { @@ -105,7 +105,7 @@ export function buildSiloedNullifierReadRequestHints new Nullifier(n.value, n.counter, n.noteHash).scope(AztecAddress.ZERO), - ) as Tuple; + ) as Tuple; return buildNullifierReadRequestHints( oracle, diff --git a/yarn-project/circuits.js/src/scripts/constants.in.ts b/yarn-project/circuits.js/src/scripts/constants.in.ts index da2f6d4f2215..119eafb4fc87 100644 --- a/yarn-project/circuits.js/src/scripts/constants.in.ts +++ b/yarn-project/circuits.js/src/scripts/constants.in.ts @@ -5,6 +5,7 @@ import { fileURLToPath } from 'url'; const NOIR_CONSTANTS_FILE = '../../../../noir-projects/noir-protocol-circuits/crates/types/src/constants.nr'; const TS_CONSTANTS_FILE = '../constants.gen.ts'; const CPP_AZTEC_CONSTANTS_FILE = '../../../../barretenberg/cpp/src/barretenberg/vm/avm_trace/aztec_constants.hpp'; +const PIL_AZTEC_CONSTANTS_FILE = '../../../../barretenberg/cpp/pil/avm/constants_gen.pil'; const SOLIDITY_CONSTANTS_FILE = '../../../../l1-contracts/src/core/libraries/ConstantsGen.sol'; // Whitelist of constants that will be copied to aztec_constants.hpp. @@ -33,17 +34,80 @@ const CPP_CONSTANTS = [ 'MAX_PUBLIC_DATA_READS_PER_CALL', 'MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL', 'NOTE_HASH_LENGTH', - 'MAX_NEW_NOTE_HASHES_PER_CALL', + 'MAX_NOTE_HASHES_PER_CALL', 'NULLIFIER_LENGTH', - 'MAX_NEW_NULLIFIERS_PER_CALL', + 'MAX_NULLIFIERS_PER_CALL', 'L2_TO_L1_MESSAGE_LENGTH', - 'MAX_NEW_L2_TO_L1_MSGS_PER_CALL', + 'MAX_L2_TO_L1_MSGS_PER_CALL', 'LOG_HASH_LENGTH', 'MAX_UNENCRYPTED_LOGS_PER_CALL', 'HEADER_LENGTH', 'GLOBAL_VARIABLES_LENGTH', 'AZTEC_ADDRESS_LENGTH', - 'GAS_LENGTH', + 'START_NOTE_HASH_EXISTS_WRITE_OFFSET', + 'START_NULLIFIER_EXISTS_OFFSET', + 'START_NULLIFIER_NON_EXISTS_OFFSET', + 'START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET', + 'START_SSTORE_WRITE_OFFSET', + 'START_SLOAD_WRITE_OFFSET', + 'START_EMIT_NOTE_HASH_WRITE_OFFSET', + 'START_EMIT_NULLIFIER_WRITE_OFFSET', + 'START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET', + 'START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET', + 'SENDER_SELECTOR', + 'ADDRESS_SELECTOR', + 'STORAGE_ADDRESS_SELECTOR', + 'FUNCTION_SELECTOR_SELECTOR', + 'START_GLOBAL_VARIABLES', + 'CHAIN_ID_SELECTOR', + 'VERSION_SELECTOR', + 'BLOCK_NUMBER_SELECTOR', + 'TIMESTAMP_SELECTOR', + 'COINBASE_SELECTOR', + 'FEE_PER_DA_GAS_SELECTOR', + 'FEE_PER_L2_GAS_SELECTOR', + 'END_GLOBAL_VARIABLES', + 'START_SIDE_EFFECT_COUNTER', + 'TRANSACTION_FEE_SELECTOR', +]; + +const PIL_CONSTANTS = [ + 'MAX_NOTE_HASH_READ_REQUESTS_PER_CALL', + 'MAX_NULLIFIER_READ_REQUESTS_PER_CALL', + 'MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL', + 'MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL', + 'MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL', + 'MAX_PUBLIC_DATA_READS_PER_CALL', + 'MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL', + 'MAX_NOTE_HASHES_PER_CALL', + 'MAX_NULLIFIERS_PER_CALL', + 'MAX_L2_TO_L1_MSGS_PER_CALL', + 'MAX_UNENCRYPTED_LOGS_PER_CALL', + 'START_NOTE_HASH_EXISTS_WRITE_OFFSET', + 'START_NULLIFIER_EXISTS_OFFSET', + 'START_NULLIFIER_NON_EXISTS_OFFSET', + 'START_L1_TO_L2_MSG_EXISTS_WRITE_OFFSET', + 'START_SSTORE_WRITE_OFFSET', + 'START_SLOAD_WRITE_OFFSET', + 'START_EMIT_NOTE_HASH_WRITE_OFFSET', + 'START_EMIT_NULLIFIER_WRITE_OFFSET', + 'START_EMIT_L2_TO_L1_MSG_WRITE_OFFSET', + 'START_EMIT_UNENCRYPTED_LOG_WRITE_OFFSET', + 'SENDER_SELECTOR', + 'ADDRESS_SELECTOR', + 'STORAGE_ADDRESS_SELECTOR', + 'FUNCTION_SELECTOR_SELECTOR', + 'START_GLOBAL_VARIABLES', + 'CHAIN_ID_SELECTOR', + 'VERSION_SELECTOR', + 'BLOCK_NUMBER_SELECTOR', + 'TIMESTAMP_SELECTOR', + 'COINBASE_SELECTOR', + 'FEE_PER_DA_GAS_SELECTOR', + 'FEE_PER_L2_GAS_SELECTOR', + 'END_GLOBAL_VARIABLES', + 'START_SIDE_EFFECT_COUNTER', + 'TRANSACTION_FEE_SELECTOR', ]; /** @@ -91,6 +155,22 @@ function processConstantsCpp(constants: { [key: string]: string }): string { return code.join('\n'); } +/** + * Processes a collection of constants and generates code to export them as PIL constants. + * Required to ensure consistency between the constants used in pil and used in the vm witness generator. + * + * @param constants - An object containing key-value pairs representing constants. + * @returns A string containing code that exports the constants as cpp constants. + */ +function processConstantsPil(constants: { [key: string]: string }): string { + const code: string[] = []; + Object.entries(constants).forEach(([key, value]) => { + if (PIL_CONSTANTS.includes(key)) { + code.push(` pol ${key} = ${value};`); + } + }); + return code.join('\n'); +} /** * Processes an enum and generates code to export it as a TypeScript enum. * @@ -153,6 +233,18 @@ ${processConstantsCpp(constants)} fs.writeFileSync(targetPath, resultCpp); } +/** + * Generate the constants file in PIL. + */ +function generatePilConstants({ constants }: ParsedContent, targetPath: string) { + const resultPil: string = `// GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants in circuits.js +namespace constants(256); +${processConstantsPil(constants)} +\n`; + + fs.writeFileSync(targetPath, resultPil); +} + /** * Generate the constants file in Solidity. */ @@ -270,6 +362,10 @@ function main(): void { const cppTargetPath = join(__dirname, CPP_AZTEC_CONSTANTS_FILE); generateCppConstants(parsedContent, cppTargetPath); + // PIL + const pilTargetPath = join(__dirname, PIL_AZTEC_CONSTANTS_FILE); + generatePilConstants(parsedContent, pilTargetPath); + // Solidity const solidityTargetPath = join(__dirname, SOLIDITY_CONSTANTS_FILE); fs.mkdirSync(dirname(solidityTargetPath), { recursive: true }); 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 13c372ae95ed..72fe84f15cef 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<0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x157022d579f892f06461fb895cdf5550b24329e15e7a41df14f9dad582fa1bc5>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x059371f1444280bcc61a6cc118c825cf19ec48d99a1d83329c423173ffcd1ba5>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x029b1573da033e679c68a55e05987602c5e73419c4fdfdd6104e178a9a360834>`; 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 6689b80d3f24..676f8aca3577 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<0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x1eb5048b5bdcea5ba66519ecd1cbdb9e18fd957d52830b2bcb309f4ce9bcfbd3>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x23557986e5b094bee30a103a2966383adbe3dae3caf67daba63c9853ce2bb927>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x0b02f49b7283dacf553c5cfc0615c979fdd1cd146a1d4e71c78610345a711d22>`; 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 df58d2f111ea..4db396c18cd1 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,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x23a1d22e7bf37df7d68e8fcbfb7e016c060194b7915e3771e2dcd72cea26e427"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x022a2b82af83606ae5a8d4955ef6215e54025193356318aefbde3b5026952953"`; -exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x2c9346c79caabece80bfe330b9e45ed4dde78099e01a013da690485738a42af2>`; +exports[`PublicCallStackItem computes empty item hash 1`] = `Fr<0x211932b705c9a5dbbaf2433d2ee4b0a896ef9fb720a4efbe7c1e783747c36588>`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x272aa1a005b7839cdc8b72f50d2020529da11a5245f3c11481c29ce8b55e0da2>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x2d9862fe4fb3db6fe24996cbc3064346aa4551ccd41246c1ca6b002b8b0201fd>`; 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 5194415896aa..df8a677f2983 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 inputs hash 1`] = `Fr<0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125>`; +exports[`PublicCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x2e08158f3f0d9a94e3f17338aadc3733a15bf5d163f94cef1afd8a47b446d789>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x162be1c50854010ab8ab30efde30e9fb05c8d441c0d5942bb0eace875f584c64>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x17718899a1af9292f21e6cceab91915edf7dc356c0e7e7354340d25f91e935cf>`; diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index 907e41ad4f2a..6239bf2c951e 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -80,8 +80,14 @@ export class AvmExternalCallHint { * @param success whether the external call was successful (= did NOT revert). * @param returnData the data returned by the external call. * @param gasUsed gas used by the external call (not including the cost of the CALL opcode itself). + * @param endSideEffectCounter value of side effect counter at the end of the external call. */ - constructor(public readonly success: Fr, returnData: Fr[], public readonly gasUsed: Gas) { + constructor( + public readonly success: Fr, + returnData: Fr[], + public readonly gasUsed: Gas, + public readonly endSideEffectCounter: Fr, + ) { this.returnData = new Vector(returnData); } @@ -106,7 +112,12 @@ export class AvmExternalCallHint { * @returns whether all members are empty. */ isEmpty(): boolean { - return this.success.isZero() && this.returnData.items.length == 0 && this.gasUsed.isEmpty(); + return ( + this.success.isZero() && + this.returnData.items.length == 0 && + this.gasUsed.isEmpty() && + this.endSideEffectCounter.isZero() + ); } /** @@ -115,7 +126,12 @@ export class AvmExternalCallHint { * @returns A new AvmHint instance. */ static from(fields: FieldsOf): AvmExternalCallHint { - return new AvmExternalCallHint(fields.success, fields.returnData.items, fields.gasUsed); + return new AvmExternalCallHint( + fields.success, + fields.returnData.items, + fields.gasUsed, + fields.endSideEffectCounter, + ); } /** @@ -124,7 +140,7 @@ export class AvmExternalCallHint { * @returns An array of fields. */ static getFields(fields: FieldsOf) { - return [fields.success, fields.returnData, fields.gasUsed] as const; + return [fields.success, fields.returnData, fields.gasUsed, fields.endSideEffectCounter] as const; } /** @@ -134,7 +150,12 @@ export class AvmExternalCallHint { */ static fromBuffer(buff: Buffer | BufferReader): AvmExternalCallHint { const reader = BufferReader.asReader(buff); - return new AvmExternalCallHint(Fr.fromBuffer(reader), reader.readVector(Fr), reader.readObject(Gas)); + return new AvmExternalCallHint( + Fr.fromBuffer(reader), + reader.readVector(Fr), + reader.readObject(Gas), + Fr.fromBuffer(reader), + ); } /** diff --git a/yarn-project/circuits.js/src/structs/content_commitment.ts b/yarn-project/circuits.js/src/structs/content_commitment.ts index 6de8796aa5a3..92e0145bb0e7 100644 --- a/yarn-project/circuits.js/src/structs/content_commitment.ts +++ b/yarn-project/circuits.js/src/structs/content_commitment.ts @@ -6,7 +6,7 @@ import { CONTENT_COMMITMENT_LENGTH } from '../constants.gen.js'; export const NUM_BYTES_PER_SHA256 = 32; export class ContentCommitment { - constructor(public txTreeHeight: Fr, public txsEffectsHash: Buffer, public inHash: Buffer, public outHash: Buffer) { + constructor(public numTxs: Fr, public txsEffectsHash: Buffer, public inHash: Buffer, public outHash: Buffer) { if (txsEffectsHash.length !== NUM_BYTES_PER_SHA256) { throw new Error(`txsEffectsHash buffer must be ${NUM_BYTES_PER_SHA256} bytes`); } @@ -32,12 +32,12 @@ export class ContentCommitment { } toBuffer() { - return serializeToBuffer(this.txTreeHeight, this.txsEffectsHash, this.inHash, this.outHash); + return serializeToBuffer(this.numTxs, this.txsEffectsHash, this.inHash, this.outHash); } toFields(): Fr[] { const serialized = [ - this.txTreeHeight, + this.numTxs, Fr.fromBuffer(this.txsEffectsHash), Fr.fromBuffer(this.inHash), Fr.fromBuffer(this.outHash), @@ -80,7 +80,7 @@ export class ContentCommitment { isEmpty(): boolean { return ( - this.txTreeHeight.isZero() && + this.numTxs.isZero() && this.txsEffectsHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.inHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.outHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) diff --git a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts index b07195f0106e..b999251e5512 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combine_hints.ts @@ -6,7 +6,7 @@ import { inspect } from 'util'; import { MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; @@ -24,8 +24,8 @@ import { type PublicAccumulatedData } from './public_accumulated_data.js'; export class CombineHints { constructor( - public readonly sortedNoteHashes: Tuple, - public readonly sortedNoteHashesIndexes: Tuple, + public readonly sortedNoteHashes: Tuple, + public readonly sortedNoteHashesIndexes: Tuple, public readonly sortedUnencryptedLogsHashes: Tuple, public readonly sortedUnencryptedLogsHashesIndexes: Tuple, public readonly sortedPublicDataUpdateRequests: Tuple< @@ -64,8 +64,8 @@ export class CombineHints { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new CombineHints( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), - reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), + reader.readArray(MAX_NOTE_HASHES_PER_TX, NoteHash), + reader.readNumbers(MAX_NOTE_HASHES_PER_TX), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), @@ -83,14 +83,14 @@ export class CombineHints { nonRevertibleData: PublicAccumulatedData; }): CombineHints { const mergedNoteHashes = mergeAccumulatedData( - nonRevertibleData.newNoteHashes, - revertibleData.newNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, + nonRevertibleData.noteHashes, + revertibleData.noteHashes, + MAX_NOTE_HASHES_PER_TX, ); const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( mergedNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_TX, ); const unencryptedLogHashes = mergeAccumulatedData( diff --git a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts index 115052dd95b5..1adc6ae26c9e 100644 --- a/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/combined_accumulated_data.ts @@ -6,9 +6,9 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { inspect } from 'util'; import { - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, } from '../../constants.gen.js'; import { Gas } from '../gas.js'; @@ -22,15 +22,15 @@ export class CombinedAccumulatedData { /** * The new note hashes made in this transaction. */ - public newNoteHashes: Tuple, + public noteHashes: Tuple, /** * The new nullifiers made in this transaction. */ - public newNullifiers: Tuple, + public nullifiers: Tuple, /** * All the new L2 to L1 messages created in this transaction. */ - public newL2ToL1Msgs: Tuple, + public l2ToL1Msgs: Tuple, /** * Accumulated encrypted note logs hash from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. @@ -69,9 +69,9 @@ export class CombinedAccumulatedData { getSize() { return ( - arraySerializedSizeOfNonEmpty(this.newNoteHashes) + - arraySerializedSizeOfNonEmpty(this.newNullifiers) + - arraySerializedSizeOfNonEmpty(this.newL2ToL1Msgs) + + arraySerializedSizeOfNonEmpty(this.noteHashes) + + arraySerializedSizeOfNonEmpty(this.nullifiers) + + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + this.noteEncryptedLogsHash.size + this.encryptedLogsHash.size + this.unencryptedLogsHash.size + @@ -85,9 +85,9 @@ export class CombinedAccumulatedData { static getFields(fields: FieldsOf) { return [ - fields.newNoteHashes, - fields.newNullifiers, - fields.newL2ToL1Msgs, + fields.noteHashes, + fields.nullifiers, + fields.l2ToL1Msgs, fields.noteEncryptedLogsHash, fields.encryptedLogsHash, fields.unencryptedLogsHash, @@ -119,9 +119,9 @@ export class CombinedAccumulatedData { static fromBuffer(buffer: Buffer | BufferReader): CombinedAccumulatedData { const reader = BufferReader.asReader(buffer); return new CombinedAccumulatedData( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, Fr), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Fr), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), + reader.readArray(MAX_NOTE_HASHES_PER_TX, Fr), + reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, Fr), Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), @@ -144,9 +144,9 @@ export class CombinedAccumulatedData { static empty() { return new CombinedAccumulatedData( - makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, Fr.zero), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.zero), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), + makeTuple(MAX_NOTE_HASHES_PER_TX, Fr.zero), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.zero), Fr.zero(), Fr.zero(), Fr.zero(), @@ -160,15 +160,15 @@ export class CombinedAccumulatedData { [inspect.custom]() { return `CombinedAccumulatedData { - newNoteHashes: [${this.newNoteHashes + noteHashes: [${this.noteHashes .filter(x => !x.isZero()) .map(x => inspect(x)) .join(', ')}], - newNullifiers: [${this.newNullifiers + nullifiers: [${this.nullifiers .filter(x => !x.isZero()) .map(x => inspect(x)) .join(', ')}], - newL2ToL1Msgs: [${this.newL2ToL1Msgs + l2ToL1Msgs: [${this.l2ToL1Msgs .filter(x => !x.isZero()) .map(x => inspect(x)) .join(', ')}], 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 710c34fc68b6..e729c2accd9c 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 @@ -39,7 +39,7 @@ export class KernelCircuitPublicInputs { ) {} getNonEmptyNullifiers() { - return this.end.newNullifiers.filter(n => !n.isZero()); + return this.end.nullifiers.filter(n => !n.isZero()); } /** 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 87a4fd109610..7fd67916f4c0 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,10 +3,10 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -27,15 +27,15 @@ export class PrivateAccumulatedData { /** * The new note hashes made in this transaction. */ - public newNoteHashes: Tuple, + public noteHashes: Tuple, /** * The new nullifiers made in this transaction. */ - public newNullifiers: Tuple, + public nullifiers: Tuple, /** * All the new L2 to L1 messages created in this transaction. */ - public newL2ToL1Msgs: Tuple, + public l2ToL1Msgs: Tuple, /** * Accumulated encrypted note logs hashes from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. @@ -63,9 +63,9 @@ export class PrivateAccumulatedData { toBuffer() { return serializeToBuffer( - this.newNoteHashes, - this.newNullifiers, - this.newL2ToL1Msgs, + this.noteHashes, + this.nullifiers, + this.l2ToL1Msgs, this.noteEncryptedLogsHashes, this.encryptedLogsHashes, this.unencryptedLogsHashes, @@ -86,9 +86,9 @@ export class PrivateAccumulatedData { static fromBuffer(buffer: Buffer | BufferReader): PrivateAccumulatedData { const reader = BufferReader.asReader(buffer); return new PrivateAccumulatedData( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), + reader.readArray(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash), + reader.readArray(MAX_NULLIFIERS_PER_TX, ScopedNullifier), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedEncryptedLogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), @@ -108,9 +108,9 @@ export class PrivateAccumulatedData { static empty() { return new PrivateAccumulatedData( - makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier.empty), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), + makeTuple(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash.empty), + makeTuple(MAX_NULLIFIERS_PER_TX, ScopedNullifier.empty), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty), makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedEncryptedLogHash.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_init_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_init_circuit_private_inputs.ts index b2b83ece100b..52841aa52b46 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_init_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_init_circuit_private_inputs.ts @@ -1,14 +1,11 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_NEW_NOTE_HASHES_PER_CALL } from '../../constants.gen.js'; +import { MAX_NOTE_HASHES_PER_CALL } from '../../constants.gen.js'; import { TxRequest } from '../tx_request.js'; import { PrivateCallData } from './private_call_data.js'; export class PrivateKernelInitHints { - constructor( - public noteHashNullifierCounters: Tuple, - public firstRevertiblePrivateCallRequestIndex: number, - ) {} + constructor(public noteHashNullifierCounters: Tuple) {} toBuffer() { return serializeToBuffer(this.noteHashNullifierCounters); @@ -16,7 +13,7 @@ export class PrivateKernelInitHints { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new PrivateKernelInitHints(reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_CALL), reader.readNumber()); + return new PrivateKernelInitHints(reader.readNumbers(MAX_NOTE_HASHES_PER_CALL)); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_inner_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_inner_circuit_private_inputs.ts index 877263c6f4c8..c93964624f19 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_inner_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_inner_circuit_private_inputs.ts @@ -1,11 +1,11 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { MAX_NEW_NOTE_HASHES_PER_CALL } from '../../constants.gen.js'; +import { MAX_NOTE_HASHES_PER_CALL } from '../../constants.gen.js'; import { PrivateCallData } from './private_call_data.js'; import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelInnerHints { - constructor(public noteHashNullifierCounters: Tuple) {} + constructor(public noteHashNullifierCounters: Tuple) {} toBuffer() { return serializeToBuffer(this.noteHashNullifierCounters); @@ -13,7 +13,7 @@ export class PrivateKernelInnerHints { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); - return new PrivateKernelInnerHints(reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_CALL)); + return new PrivateKernelInnerHints(reader.readNumbers(MAX_NOTE_HASHES_PER_CALL)); } } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts index a35c33f9730b..13c3cc472327 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_reset_circuit_private_inputs.ts @@ -1,10 +1,6 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; -import { - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, -} from '../../constants.gen.js'; +import { MAX_NOTE_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX } from '../../constants.gen.js'; import { countAccumulatedItems } from '../../utils/index.js'; import { NoteLogHash } from '../log_hash.js'; import { ScopedNoteHash } from '../note_hash.js'; @@ -20,8 +16,8 @@ import { PrivateKernelData } from './private_kernel_data.js'; export class PrivateKernelResetOutputs { constructor( - public noteHashes: Tuple, - public nullifiers: Tuple, + public noteHashes: Tuple, + public nullifiers: Tuple, public noteEncryptedLogHashes: Tuple, ) {} @@ -32,8 +28,8 @@ export class PrivateKernelResetOutputs { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new PrivateKernelResetOutputs( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), + reader.readArray(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash), + reader.readArray(MAX_NULLIFIERS_PER_TX, ScopedNullifier), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), ); } @@ -50,11 +46,11 @@ export class PrivateKernelResetHints< /** * Contains hints for the transient note hashes to locate corresponding nullifiers. */ - public transientNullifierIndexesForNoteHashes: Tuple, + public transientNullifierIndexesForNoteHashes: Tuple, /** * Contains hints for the transient nullifiers to locate corresponding note hashes. */ - public transientNoteHashIndexesForNullifiers: Tuple, + public transientNoteHashIndexesForNullifiers: Tuple, /** * Contains hints for the transient logs to locate corresponding note hashes. */ @@ -136,8 +132,8 @@ export class PrivateKernelResetHints< ): PrivateKernelResetHints { const reader = BufferReader.asReader(buffer); return new PrivateKernelResetHints( - reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), - reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), + reader.readNumbers(MAX_NOTE_HASHES_PER_TX), + reader.readNumbers(MAX_NULLIFIERS_PER_TX), reader.readNumbers(MAX_NOTE_ENCRYPTED_LOGS_PER_TX), reader.readObject({ fromBuffer: buf => 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 151dbdc1e1cf..eacbf97e365f 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 @@ -1,113 +1,8 @@ -import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { - MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, -} from '../../constants.gen.js'; import { countAccumulatedItems } from '../../utils/index.js'; -import { CallRequest } from '../call_request.js'; -import { NoteLogHash, ScopedEncryptedLogHash, ScopedLogHash } from '../log_hash.js'; -import { ScopedNoteHash } from '../note_hash.js'; -import { ScopedNullifier } from '../nullifier.js'; import { PrivateKernelData } from './private_kernel_data.js'; -export class PrivateKernelTailHints { - constructor( - /* - * The sorted new note hashes. - */ - public sortedNewNoteHashes: Tuple, - /** - * The sorted new note hashes indexes. Maps original to sorted. - */ - public sortedNewNoteHashesIndexes: Tuple, - /** - * The sorted new nullifiers. Maps original to sorted. - */ - public sortedNewNullifiers: Tuple, - /** - * The sorted new nullifiers indexes. - */ - public sortedNewNullifiersIndexes: Tuple, - /** - * The sorted encrypted note log hashes. - */ - public sortedNoteEncryptedLogHashes: Tuple, - /** - * The sorted encrypted note log hashes indexes. Maps original to sorted. - */ - public sortedNoteEncryptedLogHashesIndexes: 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 sorted public call requests. - */ - public sortedCallRequests: Tuple, - /** - * The sorted public call requests indexes. Maps original to sorted. - */ - public sortedCallRequestsIndexes: Tuple, - ) {} - - toBuffer() { - return serializeToBuffer( - this.sortedNewNoteHashes, - this.sortedNewNoteHashesIndexes, - this.sortedNewNullifiers, - this.sortedNewNullifiersIndexes, - this.sortedNoteEncryptedLogHashes, - this.sortedNoteEncryptedLogHashesIndexes, - this.sortedEncryptedLogHashes, - this.sortedEncryptedLogHashesIndexes, - this.sortedUnencryptedLogHashes, - this.sortedUnencryptedLogHashesIndexes, - this.sortedCallRequests, - this.sortedCallRequestsIndexes, - ); - } - - /** - * Deserializes from a buffer or reader. - * @param buffer - Buffer or reader to read from. - * @returns The deserialized instance. - */ - static fromBuffer(buffer: Buffer | BufferReader) { - const reader = BufferReader.asReader(buffer); - return new PrivateKernelTailHints( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash), - reader.readNumbers(MAX_NEW_NOTE_HASHES_PER_TX), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, ScopedNullifier), - reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), - reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, NoteLogHash), - reader.readNumbers(MAX_NOTE_ENCRYPTED_LOGS_PER_TX), - reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedEncryptedLogHash), - reader.readNumbers(MAX_ENCRYPTED_LOGS_PER_TX), - reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash), - reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), - reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, CallRequest), - reader.readNumbers(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX), - ); - } -} - /** * Input to the private kernel circuit - tail call. */ @@ -117,11 +12,13 @@ export class PrivateKernelTailCircuitPrivateInputs { * The previous kernel data */ public previousKernel: PrivateKernelData, - public hints: PrivateKernelTailHints, ) {} isForPublic() { - return countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallStack) > 0; + return ( + countAccumulatedItems(this.previousKernel.publicInputs.end.publicCallStack) > 0 || + !this.previousKernel.publicInputs.publicTeardownCallRequest.isEmpty() + ); } /** @@ -129,7 +26,7 @@ export class PrivateKernelTailCircuitPrivateInputs { * @returns The buffer. */ toBuffer() { - return serializeToBuffer(this.previousKernel, this.hints); + return serializeToBuffer(this.previousKernel); } /** @@ -139,9 +36,6 @@ export class PrivateKernelTailCircuitPrivateInputs { */ static fromBuffer(buffer: Buffer | BufferReader): PrivateKernelTailCircuitPrivateInputs { const reader = BufferReader.asReader(buffer); - return new PrivateKernelTailCircuitPrivateInputs( - reader.readObject(PrivateKernelData), - reader.readObject(PrivateKernelTailHints), - ); + return new PrivateKernelTailCircuitPrivateInputs(reader.readObject(PrivateKernelData)); } } 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 c3b4276d2175..1c60ce004aaa 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 @@ -187,25 +187,26 @@ export class PrivateKernelTailCircuitPublicInputs { numberOfPublicCallRequests() { return this.forPublic ? countAccumulatedItems(this.forPublic.endNonRevertibleData.publicCallStack) + - countAccumulatedItems(this.forPublic.end.publicCallStack) + countAccumulatedItems(this.forPublic.end.publicCallStack) + + countAccumulatedItems(this.forPublic.publicTeardownCallStack) : 0; } getNonEmptyNoteHashes() { const noteHashes = this.forPublic - ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.newNoteHashes, this.forPublic.end.newNoteHashes).map( + ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.noteHashes, this.forPublic.end.noteHashes).map( n => n.value, ) - : this.forRollup!.end.newNoteHashes; + : this.forRollup!.end.noteHashes; return noteHashes.filter(n => !n.isZero()); } getNonEmptyNullifiers() { const nullifiers = this.forPublic - ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.newNullifiers, this.forPublic.end.newNullifiers).map( + ? mergeAccumulatedData(this.forPublic.endNonRevertibleData.nullifiers, this.forPublic.end.nullifiers).map( n => n.value, ) - : this.forRollup!.end.newNullifiers; + : this.forRollup!.end.nullifiers; return nullifiers.filter(n => !n.isZero()); } 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 29fb8928da29..2ca2bb573227 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 @@ -7,10 +7,10 @@ import { inspect } from 'util'; import { MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -27,15 +27,15 @@ export class PublicAccumulatedData { /** * The new note hashes made in this transaction. */ - public readonly newNoteHashes: Tuple, + public readonly noteHashes: Tuple, /** * The new nullifiers made in this transaction. */ - public readonly newNullifiers: Tuple, + public readonly nullifiers: Tuple, /** * All the new L2 to L1 messages created in this transaction. */ - public readonly newL2ToL1Msgs: Tuple, + public readonly l2ToL1Msgs: Tuple, /** * Accumulated encrypted note logs hashes from all the previous kernel iterations. * Note: Truncated to 31 bytes to fit in Fr. @@ -69,9 +69,9 @@ export class PublicAccumulatedData { getSize() { return ( - arraySerializedSizeOfNonEmpty(this.newNoteHashes) + - arraySerializedSizeOfNonEmpty(this.newNullifiers) + - arraySerializedSizeOfNonEmpty(this.newL2ToL1Msgs) + + arraySerializedSizeOfNonEmpty(this.noteHashes) + + arraySerializedSizeOfNonEmpty(this.nullifiers) + + arraySerializedSizeOfNonEmpty(this.l2ToL1Msgs) + arraySerializedSizeOfNonEmpty(this.noteEncryptedLogsHashes) + arraySerializedSizeOfNonEmpty(this.encryptedLogsHashes) + arraySerializedSizeOfNonEmpty(this.unencryptedLogsHashes) + @@ -83,9 +83,9 @@ export class PublicAccumulatedData { toBuffer() { return serializeToBuffer( - this.newNoteHashes, - this.newNullifiers, - this.newL2ToL1Msgs, + this.noteHashes, + this.nullifiers, + this.l2ToL1Msgs, this.noteEncryptedLogsHashes, this.encryptedLogsHashes, this.unencryptedLogsHashes, @@ -101,9 +101,9 @@ export class PublicAccumulatedData { isEmpty(): boolean { return ( - this.newNoteHashes.every(x => x.isEmpty()) && - this.newNullifiers.every(x => x.isEmpty()) && - this.newL2ToL1Msgs.every(x => x.isZero()) && + this.noteHashes.every(x => x.isEmpty()) && + this.nullifiers.every(x => x.isEmpty()) && + this.l2ToL1Msgs.every(x => x.isZero()) && this.noteEncryptedLogsHashes.every(x => x.isEmpty()) && this.encryptedLogsHashes.every(x => x.isEmpty()) && this.unencryptedLogsHashes.every(x => x.isEmpty()) && @@ -116,15 +116,15 @@ export class PublicAccumulatedData { [inspect.custom]() { // print out the non-empty fields return `PublicAccumulatedData { - newNoteHashes: [${this.newNoteHashes + noteHashes: [${this.noteHashes .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], - newNullifiers: [${this.newNullifiers + nullifiers: [${this.nullifiers .filter(x => !x.isEmpty()) .map(h => inspect(h)) .join(', ')}], - newL2ToL1Msgs: [${this.newL2ToL1Msgs + l2ToL1Msgs: [${this.l2ToL1Msgs .filter(x => !x.isZero()) .map(h => inspect(h)) .join(', ')}], @@ -160,9 +160,9 @@ export class PublicAccumulatedData { static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new this( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), + reader.readArray(MAX_NOTE_HASHES_PER_TX, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_TX, Nullifier), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, Fr), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), @@ -175,9 +175,9 @@ export class PublicAccumulatedData { static fromFields(fields: Fr[] | FieldReader) { const reader = FieldReader.asReader(fields); return new this( - reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Nullifier), - reader.readFieldArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX), + reader.readArray(MAX_NOTE_HASHES_PER_TX, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_TX, Nullifier), + reader.readFieldArray(MAX_L2_TO_L1_MSGS_PER_TX), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, LogHash), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash), @@ -198,9 +198,9 @@ export class PublicAccumulatedData { static empty() { return new this( - makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, NoteHash.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), + makeTuple(MAX_NOTE_HASHES_PER_TX, NoteHash.empty), + makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty), + makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, Fr.zero), makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty), makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, LogHash.empty), makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, LogHash.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts index 764fe280429f..52505461fefb 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data_builder.ts @@ -3,10 +3,10 @@ import { Fr } from '@aztec/foundation/fields'; import { MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, @@ -26,9 +26,9 @@ import { PublicAccumulatedData } from './public_accumulated_data.js'; * */ export class PublicAccumulatedDataBuilder { - private newNoteHashes: NoteHash[] = []; - private newNullifiers: Nullifier[] = []; - private newL2ToL1Msgs: Fr[] = []; + private noteHashes: NoteHash[] = []; + private nullifiers: Nullifier[] = []; + private l2ToL1Msgs: Fr[] = []; private noteEncryptedLogsHashes: LogHash[] = []; private encryptedLogsHashes: LogHash[] = []; private unencryptedLogsHashes: LogHash[] = []; @@ -36,33 +36,33 @@ export class PublicAccumulatedDataBuilder { private publicCallStack: CallRequest[] = []; private gasUsed: Gas = Gas.empty(); - pushNewNoteHash(newNoteHash: NoteHash) { - this.newNoteHashes.push(newNoteHash); + pushNoteHash(newNoteHash: NoteHash) { + this.noteHashes.push(newNoteHash); return this; } - withNewNoteHashes(newNoteHashes: NoteHash[]) { - this.newNoteHashes = newNoteHashes; + withNoteHashes(noteHashes: NoteHash[]) { + this.noteHashes = noteHashes; return this; } - pushNewNullifier(newNullifier: Nullifier) { - this.newNullifiers.push(newNullifier); + pushNullifier(newNullifier: Nullifier) { + this.nullifiers.push(newNullifier); return this; } - withNewNullifiers(newNullifiers: Nullifier[]) { - this.newNullifiers = newNullifiers; + withNullifiers(nullifiers: Nullifier[]) { + this.nullifiers = nullifiers; return this; } - pushNewL2ToL1Msg(newL2ToL1Msg: Fr) { - this.newL2ToL1Msgs.push(newL2ToL1Msg); + pushL2ToL1Msg(newL2ToL1Msg: Fr) { + this.l2ToL1Msgs.push(newL2ToL1Msg); return this; } - withNewL2ToL1Msgs(newL2ToL1Msgs: Fr[]) { - this.newL2ToL1Msgs = newL2ToL1Msgs; + withL2ToL1Msgs(l2ToL1Msgs: Fr[]) { + this.l2ToL1Msgs = l2ToL1Msgs; return this; } @@ -123,9 +123,9 @@ export class PublicAccumulatedDataBuilder { build(): PublicAccumulatedData { return new PublicAccumulatedData( - padArrayEnd(this.newNoteHashes, NoteHash.empty(), MAX_NEW_NOTE_HASHES_PER_TX), - padArrayEnd(this.newNullifiers, Nullifier.empty(), MAX_NEW_NULLIFIERS_PER_TX), - padArrayEnd(this.newL2ToL1Msgs, Fr.ZERO, MAX_NEW_L2_TO_L1_MSGS_PER_TX), + padArrayEnd(this.noteHashes, NoteHash.empty(), MAX_NOTE_HASHES_PER_TX), + padArrayEnd(this.nullifiers, Nullifier.empty(), MAX_NULLIFIERS_PER_TX), + padArrayEnd(this.l2ToL1Msgs, Fr.ZERO, MAX_L2_TO_L1_MSGS_PER_TX), padArrayEnd(this.noteEncryptedLogsHashes, LogHash.empty(), MAX_NOTE_ENCRYPTED_LOGS_PER_TX), padArrayEnd(this.encryptedLogsHashes, LogHash.empty(), MAX_ENCRYPTED_LOGS_PER_TX), padArrayEnd(this.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX), @@ -141,9 +141,9 @@ export class PublicAccumulatedDataBuilder { static fromPublicAccumulatedData(publicAccumulatedData: PublicAccumulatedData): PublicAccumulatedDataBuilder { return new PublicAccumulatedDataBuilder() - .withNewNoteHashes(publicAccumulatedData.newNoteHashes) - .withNewNullifiers(publicAccumulatedData.newNullifiers) - .withNewL2ToL1Msgs(publicAccumulatedData.newL2ToL1Msgs) + .withNoteHashes(publicAccumulatedData.noteHashes) + .withNullifiers(publicAccumulatedData.nullifiers) + .withL2ToL1Msgs(publicAccumulatedData.l2ToL1Msgs) .withNoteEncryptedLogsHashes(publicAccumulatedData.noteEncryptedLogsHashes) .withEncryptedLogsHashes(publicAccumulatedData.encryptedLogsHashes) .withUnencryptedLogsHashes(publicAccumulatedData.unencryptedLogsHashes) 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 b30b04bb4cd6..e6ee1f1249dc 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 @@ -3,7 +3,7 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { type IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; import { - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, } from '../constants.gen.js'; @@ -101,7 +101,7 @@ export type NullifierNonExistentReadRequestHints = NonExistentReadRequestHints< typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, typeof NULLIFIER_TREE_HEIGHT, IndexedTreeLeafPreimage, - typeof MAX_NEW_NULLIFIERS_PER_TX, + typeof MAX_NULLIFIERS_PER_TX, Nullifier >; @@ -113,7 +113,7 @@ export function nullifierNonExistentReadRequestHintsFromBuffer( MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, NullifierLeafPreimage, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, Nullifier, ); } @@ -123,8 +123,8 @@ export class NullifierNonExistentReadRequestHintsBuilder { private readRequestIndex = 0; constructor( - sortedPendingNullifiers: Tuple, - sortedPendingNullifierIndexHints: Tuple, + sortedPendingNullifiers: Tuple, + sortedPendingNullifierIndexHints: Tuple, ) { this.hints = new NonExistentReadRequestHints( makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, () => @@ -137,8 +137,8 @@ export class NullifierNonExistentReadRequestHintsBuilder { } static empty() { - const emptySortedPendingNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Nullifier.empty); - const emptySortedPendingNullifierIndexHints = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, () => 0); + const emptySortedPendingNullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty); + const emptySortedPendingNullifierIndexHints = makeTuple(MAX_NULLIFIERS_PER_TX, () => 0); return new NullifierNonExistentReadRequestHintsBuilder( emptySortedPendingNullifiers, emptySortedPendingNullifierIndexHints, 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 b7776d1e6eed..e8acb0c239b8 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 @@ -15,11 +15,11 @@ import { GeneratorIndex, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, @@ -86,11 +86,11 @@ export class PrivateCircuitPublicInputs { /** * New note hashes created by the corresponding function call. */ - public newNoteHashes: Tuple, + public noteHashes: Tuple, /** * New nullifiers created by the corresponding function call. */ - public newNullifiers: Tuple, + public nullifiers: Tuple, /** * Private call requests made within the current kernel iteration. */ @@ -106,7 +106,7 @@ export class PrivateCircuitPublicInputs { /** * New L2 to L1 messages created by the corresponding function call. */ - public newL2ToL1Msgs: Tuple, + public l2ToL1Msgs: Tuple, /** * The side effect counter at the start of this call. */ @@ -170,12 +170,12 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_KEY_VALIDATION_REQUESTS_PER_CALL, KeyValidationRequestAndGenerator), - reader.readArray(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), + reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr), reader.readObject(Fr), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash), @@ -198,12 +198,12 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest), reader.readArray(MAX_KEY_VALIDATION_REQUESTS_PER_CALL, KeyValidationRequestAndGenerator), - reader.readArray(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), + reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest), reader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), reader.readField(), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash), @@ -229,12 +229,12 @@ export class PrivateCircuitPublicInputs { makeTuple(MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, ReadRequest.empty), makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_CALL, ReadRequest.empty), makeTuple(MAX_KEY_VALIDATION_REQUESTS_PER_CALL, KeyValidationRequestAndGenerator.empty), - makeTuple(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier.empty), + makeTuple(MAX_NOTE_HASHES_PER_CALL, NoteHash.empty), + makeTuple(MAX_NULLIFIERS_PER_CALL, Nullifier.empty), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, PrivateCallRequest.empty), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr.zero), Fr.ZERO, - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), + makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, NoteLogHash.empty), @@ -257,12 +257,12 @@ export class PrivateCircuitPublicInputs { isEmptyArray(this.noteHashReadRequests) && isEmptyArray(this.nullifierReadRequests) && isEmptyArray(this.keyValidationRequestsAndGenerators) && - isEmptyArray(this.newNoteHashes) && - isEmptyArray(this.newNullifiers) && + isEmptyArray(this.noteHashes) && + isEmptyArray(this.nullifiers) && isEmptyArray(this.privateCallRequests) && isZeroArray(this.publicCallStackHashes) && this.publicTeardownFunctionHash.isZero() && - isEmptyArray(this.newL2ToL1Msgs) && + isEmptyArray(this.l2ToL1Msgs) && isEmptyArray(this.noteEncryptedLogsHashes) && isEmptyArray(this.encryptedLogsHashes) && isEmptyArray(this.unencryptedLogsHashes) && @@ -287,12 +287,12 @@ export class PrivateCircuitPublicInputs { fields.noteHashReadRequests, fields.nullifierReadRequests, fields.keyValidationRequestsAndGenerators, - fields.newNoteHashes, - fields.newNullifiers, + fields.noteHashes, + fields.nullifiers, fields.privateCallRequests, fields.publicCallStackHashes, fields.publicTeardownFunctionHash, - fields.newL2ToL1Msgs, + fields.l2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, fields.noteEncryptedLogsHashes, diff --git a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts index 354986b7842c..2ffbbcf8a4e3 100644 --- a/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts +++ b/yarn-project/circuits.js/src/structs/public_call_stack_item.test.ts @@ -34,7 +34,7 @@ describe('PublicCallStackItem', () => { callStack.contractAddress = AztecAddress.fromField(new Fr(1)); callStack.functionData = new FunctionData(new FunctionSelector(2), /*isPrivate=*/ false); callStack.isExecutionRequest = true; - callStack.publicInputs.newNoteHashes[0] = new NoteHash(new Fr(1), 0); + callStack.publicInputs.noteHashes[0] = new NoteHash(new Fr(1), 0); const hash = callStack.hash(); expect(hash.toString()).toMatchSnapshot(); @@ -52,7 +52,7 @@ describe('PublicCallStackItem', () => { callStack.contractAddress = AztecAddress.fromField(new Fr(1)); callStack.functionData = new FunctionData(new FunctionSelector(2), /*isPrivate=*/ false); - callStack.publicInputs.newNoteHashes[0] = new NoteHash(new Fr(1), 0); + callStack.publicInputs.noteHashes[0] = new NoteHash(new Fr(1), 0); const hash = callStack.hash(); expect(hash.toString()).toMatchSnapshot(); 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 28ad816def01..efffffd65471 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 @@ -15,10 +15,10 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { GeneratorIndex, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, @@ -95,15 +95,15 @@ export class PublicCircuitPublicInputs { /** * New note hashes created within a public execution call */ - public newNoteHashes: Tuple, + public noteHashes: Tuple, /** * New nullifiers created within a public execution call */ - public newNullifiers: Tuple, + public nullifiers: Tuple, /** * New L2 to L1 messages generated during the call. */ - public newL2ToL1Msgs: Tuple, + public l2ToL1Msgs: Tuple, /** * The side effect counter when this context was started. */ @@ -169,9 +169,9 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest.empty), makeTuple(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead.empty), makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr.zero), - makeTuple(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier.empty), - makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), + makeTuple(MAX_NOTE_HASHES_PER_CALL, NoteHash.empty), + makeTuple(MAX_NULLIFIERS_PER_CALL, Nullifier.empty), + makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash.empty), @@ -197,9 +197,9 @@ export class PublicCircuitPublicInputs { isEmptyArray(this.contractStorageUpdateRequests) && isEmptyArray(this.contractStorageReads) && isFrArrayEmpty(this.publicCallStackHashes) && - isEmptyArray(this.newNoteHashes) && - isEmptyArray(this.newNullifiers) && - isEmptyArray(this.newL2ToL1Msgs) && + isEmptyArray(this.noteHashes) && + isEmptyArray(this.nullifiers) && + isEmptyArray(this.l2ToL1Msgs) && this.startSideEffectCounter.isZero() && this.endSideEffectCounter.isZero() && isEmptyArray(this.unencryptedLogsHashes) && @@ -230,9 +230,9 @@ export class PublicCircuitPublicInputs { fields.contractStorageUpdateRequests, fields.contractStorageReads, fields.publicCallStackHashes, - fields.newNoteHashes, - fields.newNullifiers, - fields.newL2ToL1Msgs, + fields.noteHashes, + fields.nullifiers, + fields.l2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, fields.unencryptedLogsHashes, @@ -282,9 +282,9 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, Fr), - reader.readArray(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), + reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), @@ -312,9 +312,9 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ContractStorageUpdateRequest), reader.readArray(MAX_PUBLIC_DATA_READS_PER_CALL, ContractStorageRead), reader.readFieldArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL), - reader.readArray(MAX_NEW_NOTE_HASHES_PER_CALL, NoteHash), - reader.readArray(MAX_NEW_NULLIFIERS_PER_CALL, Nullifier), - reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), + reader.readArray(MAX_NOTE_HASHES_PER_CALL, NoteHash), + reader.readArray(MAX_NULLIFIERS_PER_CALL, Nullifier), + reader.readArray(MAX_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, LogHash), diff --git a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts index 0bb2f4603ece..d814dd1861ce 100644 --- a/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/base_or_merge_rollup_public_inputs.ts @@ -15,11 +15,9 @@ export class BaseOrMergeRollupPublicInputs { */ public rollupType: RollupTypes, /** - * Rollup sub tree height. - * Note 1: Base rollup circuit always have a sub tree height of 0. - * Note 2: With each merge, the sub tree height increases by 1. + * Number of txs in this rollup. */ - public rollupSubtreeHeight: Fr, + public numTxs: number, /** * Data which is forwarded through the rollup circuits unchanged. */ @@ -59,7 +57,7 @@ export class BaseOrMergeRollupPublicInputs { const reader = BufferReader.asReader(buffer); return new BaseOrMergeRollupPublicInputs( reader.readNumber(), - Fr.fromBuffer(reader), + reader.readNumber(), reader.readObject(ConstantRollupData), reader.readObject(PartialStateReference), reader.readObject(PartialStateReference), @@ -77,7 +75,7 @@ export class BaseOrMergeRollupPublicInputs { toBuffer() { return serializeToBuffer( this.rollupType, - this.rollupSubtreeHeight, + this.numTxs, this.constants, this.start, diff --git a/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts b/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts index 5ff06e422c06..288f5c5d85bb 100644 --- a/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts +++ b/yarn-project/circuits.js/src/structs/rollup/state_diff_hints.ts @@ -4,7 +4,7 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { type FieldsOf } from '@aztec/foundation/types'; import { - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, @@ -22,23 +22,23 @@ export class StateDiffHints { * The nullifiers which need to be updated to perform the batch insertion of the new nullifiers. * See `StandardIndexedTree.batchInsert` function for more details. */ - public nullifierPredecessorPreimages: Tuple, + public nullifierPredecessorPreimages: Tuple, /** * Membership witnesses for the nullifiers which need to be updated to perform the batch insertion of the new * nullifiers. */ public nullifierPredecessorMembershipWitnesses: Tuple< MembershipWitness, - typeof MAX_NEW_NULLIFIERS_PER_TX + typeof MAX_NULLIFIERS_PER_TX >, /** * The nullifiers to be inserted in the tree, sorted high to low. */ - public sortedNullifiers: Tuple, + public sortedNullifiers: Tuple, /** * The indexes of the sorted nullifiers to the original ones. */ - public sortedNullifierIndexes: Tuple, + public sortedNullifierIndexes: Tuple, /** * Sibling path "pointing to" where the new note hash subtree should be inserted into the note hash tree. */ @@ -85,12 +85,12 @@ export class StateDiffHints { static fromBuffer(buffer: Buffer | BufferReader): StateDiffHints { const reader = BufferReader.asReader(buffer); return new StateDiffHints( - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, NullifierLeafPreimage), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, { + reader.readArray(MAX_NULLIFIERS_PER_TX, NullifierLeafPreimage), + reader.readArray(MAX_NULLIFIERS_PER_TX, { fromBuffer: buffer => MembershipWitness.fromBuffer(buffer, NULLIFIER_TREE_HEIGHT), }), - reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Fr), - reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), + reader.readArray(MAX_NULLIFIERS_PER_TX, Fr), + reader.readNumbers(MAX_NULLIFIERS_PER_TX), reader.readArray(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, Fr), reader.readArray(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, Fr), reader.readArray(PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, Fr), @@ -99,10 +99,10 @@ export class StateDiffHints { static empty() { return new StateDiffHints( - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, NullifierLeafPreimage.empty), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, () => MembershipWitness.empty(NULLIFIER_TREE_HEIGHT)), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, Fr.zero), - makeTuple(MAX_NEW_NULLIFIERS_PER_TX, () => 0), + makeTuple(MAX_NULLIFIERS_PER_TX, NullifierLeafPreimage.empty), + makeTuple(MAX_NULLIFIERS_PER_TX, () => MembershipWitness.empty(NULLIFIER_TREE_HEIGHT)), + makeTuple(MAX_NULLIFIERS_PER_TX, Fr.zero), + makeTuple(MAX_NULLIFIERS_PER_TX, () => 0), makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, Fr.zero), makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, Fr.zero), makeTuple(PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, Fr.zero), diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index c6fc3c783ec4..f380c4320419 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -49,16 +49,16 @@ import { MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_KEY_VALIDATION_REQUESTS_PER_TX, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_CALL, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_CALL, + MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_CALL, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, @@ -332,9 +332,9 @@ export function makeCombinedAccumulatedData(seed = 1, full = false): CombinedAcc const tupleGenerator = full ? makeTuple : makeHalfFullTuple; return new CombinedAccumulatedData( - tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x120, Fr.zero), - tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x200, Fr.zero), - tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), + tupleGenerator(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x120, Fr.zero), + tupleGenerator(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200, Fr.zero), + tupleGenerator(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), fr(seed + 0x700), // note encrypted logs hash fr(seed + 0x800), // encrypted logs hash fr(seed + 0x900), // unencrypted logs hash @@ -364,9 +364,9 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul const tupleGenerator = full ? makeTuple : makeHalfFullTuple; return new PublicAccumulatedData( - tupleGenerator(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x120, NoteHash.empty), - tupleGenerator(MAX_NEW_NULLIFIERS_PER_TX, makeNullifier, seed + 0x200, Nullifier.empty), - tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), + tupleGenerator(MAX_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x120, NoteHash.empty), + tupleGenerator(MAX_NULLIFIERS_PER_TX, makeNullifier, seed + 0x200, Nullifier.empty), + tupleGenerator(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), tupleGenerator(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x700, LogHash.empty), // note encrypted logs hashes tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x800, LogHash.empty), // encrypted logs hashes tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x900, LogHash.empty), // unencrypted logs hashes @@ -428,9 +428,9 @@ export function makePublicCircuitPublicInputs( ), tupleGenerator(MAX_PUBLIC_DATA_READS_PER_CALL, makeContractStorageRead, seed + 0x500, ContractStorageRead.empty), tupleGenerator(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x600, Fr.zero), - tupleGenerator(MAX_NEW_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x700, NoteHash.empty), - tupleGenerator(MAX_NEW_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x800, Nullifier.empty), - tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x900, L2ToL1Message.empty), + tupleGenerator(MAX_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x700, NoteHash.empty), + tupleGenerator(MAX_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x800, Nullifier.empty), + tupleGenerator(MAX_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x900, L2ToL1Message.empty), fr(seed + 0xa00), fr(seed + 0xa01), tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_CALL, makeLogHash, seed + 0x901, LogHash.empty), @@ -682,8 +682,8 @@ export function makePublicKernelCircuitPrivateInputs(seed = 1): PublicKernelCirc export function makeCombineHints(seed = 1): CombineHints { return CombineHints.from({ - sortedNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x100), - sortedNoteHashesIndexes: makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, i => i, seed + 0x200), + sortedNoteHashes: makeTuple(MAX_NOTE_HASHES_PER_TX, makeNoteHash, seed + 0x100), + sortedNoteHashesIndexes: makeTuple(MAX_NOTE_HASHES_PER_TX, i => i, seed + 0x200), sortedUnencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, makeLogHash, seed + 0x300), sortedUnencryptedLogsHashesIndexes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, i => i, seed + 0x400), sortedPublicDataUpdateRequests: makeTuple( @@ -793,12 +793,12 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn makeKeyValidationRequestAndGenerators, seed + 0x320, ), - newNoteHashes: makeTuple(MAX_NEW_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x400), - newNullifiers: makeTuple(MAX_NEW_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x500), + noteHashes: makeTuple(MAX_NOTE_HASHES_PER_CALL, makeNoteHash, seed + 0x400), + nullifiers: makeTuple(MAX_NULLIFIERS_PER_CALL, makeNullifier, seed + 0x500), privateCallRequests: makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, makePrivateCallRequest, seed + 0x600), publicCallStackHashes: makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, fr, seed + 0x700), publicTeardownFunctionHash: fr(seed + 0x800), - newL2ToL1Msgs: makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), + l2ToL1Msgs: makeTuple(MAX_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), endSideEffectCounter: fr(seed + 0x850), noteEncryptedLogsHashes: makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_CALL, makeNoteLogHash, seed + 0x875), @@ -922,7 +922,7 @@ export function makeBaseOrMergeRollupPublicInputs( ): BaseOrMergeRollupPublicInputs { return new BaseOrMergeRollupPublicInputs( RollupTypes.Base, - new Fr(0n), + 1, makeConstantBaseRollupData(seed + 0x200, globalVariables), makePartialStateReference(seed + 0x300), makePartialStateReference(seed + 0x400), @@ -1111,20 +1111,20 @@ export function makePublicDataTreeLeafPreimage(seed = 0): PublicDataTreeLeafPrei */ export function makeStateDiffHints(seed = 1): StateDiffHints { const nullifierPredecessorPreimages = makeTuple( - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, x => new NullifierLeafPreimage(fr(x), fr(x + 0x100), BigInt(x + 0x200)), seed + 0x1000, ); const nullifierPredecessorMembershipWitnesses = makeTuple( - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, x => makeMembershipWitness(NULLIFIER_TREE_HEIGHT, x), seed + 0x2000, ); - const sortedNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x3000); + const sortedNullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x3000); - const sortedNullifierIndexes = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => i, seed + 0x4000); + const sortedNullifierIndexes = makeTuple(MAX_NULLIFIERS_PER_TX, i => i, seed + 0x4000); const noteHashSubtreeSiblingPath = makeTuple(NOTE_HASH_SUBTREE_SIBLING_PATH_LENGTH, fr, seed + 0x5000); @@ -1285,6 +1285,7 @@ export function makeAvmExternalCallHint(seed = 0): AvmExternalCallHint { new Fr(seed % 2), makeArray((seed % 100) + 10, i => new Fr(i), seed + 0x1000), new Gas(seed + 0x200, seed), + new Fr(seed + 0x300), ); } diff --git a/yarn-project/circuits.js/src/types/public_keys.ts b/yarn-project/circuits.js/src/types/public_keys.ts index 4086261b2e65..942b834de4b4 100644 --- a/yarn-project/circuits.js/src/types/public_keys.ts +++ b/yarn-project/circuits.js/src/types/public_keys.ts @@ -1,5 +1,5 @@ import { poseidon2Hash } from '@aztec/foundation/crypto'; -import { type Fr, Point } from '@aztec/foundation/fields'; +import { Fr, Point } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { GeneratorIndex } from '../constants.gen.js'; @@ -19,13 +19,28 @@ export class PublicKeys { ) {} hash() { - return poseidon2Hash([ - this.masterNullifierPublicKey, - this.masterIncomingViewingPublicKey, - this.masterOutgoingViewingPublicKey, - this.masterTaggingPublicKey, - GeneratorIndex.PUBLIC_KEYS_HASH, - ]); + return this.isEmpty() + ? Fr.ZERO + : poseidon2Hash([ + this.masterNullifierPublicKey, + this.masterIncomingViewingPublicKey, + this.masterOutgoingViewingPublicKey, + this.masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + } + + isEmpty() { + return ( + this.masterNullifierPublicKey.isZero() && + this.masterIncomingViewingPublicKey.isZero() && + this.masterOutgoingViewingPublicKey.isZero() && + this.masterTaggingPublicKey.isZero() + ); + } + + static empty(): PublicKeys { + return new PublicKeys(Point.ZERO, Point.ZERO, Point.ZERO, Point.ZERO); } /** diff --git a/yarn-project/end-to-end/Earthfile b/yarn-project/end-to-end/Earthfile index 2b3eda22113f..278edefd1530 100644 --- a/yarn-project/end-to-end/Earthfile +++ b/yarn-project/end-to-end/Earthfile @@ -142,6 +142,9 @@ e2e-private-voting-contract: e2e-fees-private-payments: DO +E2E_TEST --test=./src/e2e_fees/private_payments.test.ts +e2e-fees-private-refunds: + DO +E2E_TEST --test=./src/e2e_fees/private_refunds.test.ts + e2e-fees-gas-estimation: DO +E2E_TEST --test=./src/e2e_fees/gas_estimation.test.ts diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index 0f146badc93f..1932986a768f 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -54,7 +54,7 @@ describe('benchmarks/process_history', () => { const node = await AztecNodeService.createAndSync(nodeConfig); // call getPublicStorageAt (which calls #getWorldState, which calls #syncWorldState) to force a sync with // world state to ensure the node has caught up - await node.getPublicStorageAt(AztecAddress.random(), Fr.random()); + await node.getPublicStorageAt(AztecAddress.random(), Fr.random(), 'latest'); return node; }); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index 9420e68a48f0..7dde1b74f29d 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -18,6 +18,9 @@ jest.setTimeout(1_800_000); const txTimeoutSec = 3600; +// This makes AVM proving throw if there's a failure. +process.env.AVM_PROVING_STRICT = '1'; + describe('benchmarks/proving', () => { let ctx: EndToEndContext; diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index b3bb55d64897..67b3a8f1c7f6 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -37,7 +37,7 @@ describe('benchmarks/publish_rollup', () => { // world state to ensure the node has caught up context.logger.info(`Starting new aztec node`); const node = await AztecNodeService.createAndSync({ ...context.config, disableSequencer: true }); - await node.getPublicStorageAt(AztecAddress.random(), Fr.random()); + await node.getPublicStorageAt(AztecAddress.random(), Fr.random(), 'latest'); // Spin up a new pxe and sync it, we'll use it to test sync times of new accounts for the last block context.logger.info(`Starting new pxe`); diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 17340f066750..628bfaf8db39 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -22,9 +22,9 @@ import { GasFees, type Header, KernelCircuitPublicInputs, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, type Proof, @@ -183,10 +183,10 @@ describe('L1Publisher integration', () => { const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); - processedTx.data.end.newNoteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x100); - processedTx.data.end.newNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x200); - processedTx.data.end.newNullifiers[processedTx.data.end.newNullifiers.length - 1] = Fr.ZERO; - processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); + processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); + processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x200); + processedTx.data.end.nullifiers[processedTx.data.end.nullifiers.length - 1] = Fr.ZERO; + processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash()); processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash()); @@ -262,7 +262,7 @@ describe('L1Publisher integration', () => { contentCommitment: { inHash: `0x${block.header.contentCommitment.inHash.toString('hex').padStart(64, '0')}`, outHash: `0x${block.header.contentCommitment.outHash.toString('hex').padStart(64, '0')}`, - txTreeHeight: Number(block.header.contentCommitment.txTreeHeight.toBigInt()), + numTxs: Number(block.header.contentCommitment.numTxs), txsEffectsHash: `0x${block.header.contentCommitment.txsEffectsHash.toString('hex').padStart(64, '0')}`, }, globalVariables: { @@ -370,12 +370,12 @@ describe('L1Publisher integration', () => { } // Ensure that each transaction has unique (non-intersecting nullifier values) - const totalNullifiersPerBlock = 4 * MAX_NEW_NULLIFIERS_PER_TX; + const totalNullifiersPerBlock = 4 * MAX_NULLIFIERS_PER_TX; const txs = [ - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 1 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 2 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 3 * MAX_NEW_NULLIFIERS_PER_TX), - makeBloatedProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NEW_NULLIFIERS_PER_TX), + makeBloatedProcessedTx(totalNullifiersPerBlock * i + 1 * MAX_NULLIFIERS_PER_TX), + makeBloatedProcessedTx(totalNullifiersPerBlock * i + 2 * MAX_NULLIFIERS_PER_TX), + makeBloatedProcessedTx(totalNullifiersPerBlock * i + 3 * MAX_NULLIFIERS_PER_TX), + makeBloatedProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NULLIFIERS_PER_TX), ]; const globalVariables = new GlobalVariables( @@ -396,7 +396,7 @@ describe('L1Publisher integration', () => { blockSource.getL1ToL2Messages.mockResolvedValueOnce(currentL1ToL2Messages); blockSource.getBlocks.mockResolvedValueOnce([block]); - const newL2ToL1MsgsArray = block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); + const l2ToL1MsgsArray = block.body.txEffects.flatMap(txEffect => txEffect.l2ToL1Msgs); const [emptyRoot] = await outbox.read.roots([block.header.globalVariables.blockNumber.toBigInt()]); @@ -439,7 +439,7 @@ describe('L1Publisher integration', () => { expect(newToConsume).toEqual(toConsume + 1n); toConsume = newToConsume; - const treeHeight = Math.ceil(Math.log2(newL2ToL1MsgsArray.length)); + const treeHeight = Math.ceil(Math.log2(l2ToL1MsgsArray.length)); const tree = new StandardTree( openTmpStore(true), @@ -449,7 +449,7 @@ describe('L1Publisher integration', () => { 0n, Fr, ); - await tree.appendLeaves(newL2ToL1MsgsArray); + await tree.appendLeaves(l2ToL1MsgsArray); const expectedRoot = tree.getRoot(true); const [actualRoot] = await outbox.read.roots([block.header.globalVariables.blockNumber.toBigInt()]); @@ -484,6 +484,7 @@ describe('L1Publisher integration', () => { GasFees.empty(), ); const blockTicket = await buildBlock(globalVariables, txs, l1ToL2Messages); + await builder.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); const blockResult = await builder.finaliseBlock(); diff --git a/yarn-project/end-to-end/src/e2e_authwit.test.ts b/yarn-project/end-to-end/src/e2e_authwit.test.ts index 471aca74685d..ee4748632cec 100644 --- a/yarn-project/end-to-end/src/e2e_authwit.test.ts +++ b/yarn-project/end-to-end/src/e2e_authwit.test.ts @@ -36,8 +36,8 @@ describe('e2e_authwit_tests', () => { it('happy path', async () => { // What are we doing here: // 1. We compute an inner hash which is here just a hash of random data - // 2. We then compute the outer, which is binding it to a "consumer" (here the "auth" contract) - // 3. We then create an authwit for this outer hash. + // 2. We then compute the message hash, which is binding it to a "consumer" (here the "auth" contract) + // 3. We then create an authwit for this message hash. // 4. We add this authwit to the wallet[1] // 5. We check that the authwit is valid in private for wallet[0] (check that it is signed by 0) // 6. We check that the authwit is NOT valid in private for wallet[1] (check that it is not signed by 1) @@ -45,10 +45,10 @@ describe('e2e_authwit_tests', () => { // docs:start:compute_inner_authwit_hash const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead')]); // docs:end:compute_inner_authwit_hash - // docs:start:compute_outer_authwit_hash + // docs:start:compute_arbitrary_authwit_hash const intent = { consumer: auth.address, innerHash }; - // docs:end:compute_outer_authwit_hash + // docs:end:compute_arbitrary_authwit_hash // docs:start:create_authwit const witness = await wallets[0].createAuthWit(intent); // docs:end:create_authwit diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 9a308a2e523a..206e19e00b4d 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -246,24 +246,6 @@ describe('e2e_block_building', () => { testContract = await TestContract.deploy(owner).send().deployed(); }, 60_000); - it('calls a method with nested unencrypted logs', async () => { - const tx = await testContract.methods.emit_unencrypted_logs([1, 2, 3, 4, 5], true).send().wait(); - const logs = (await pxe.getUnencryptedLogs({ txHash: tx.txHash })).logs.map(l => l.log); - - // First log should be contract address - expect(logs[0].data).toEqual(testContract.address.toBuffer()); - - // Second log should be array of fields - let expectedBuffer = Buffer.concat([1, 2, 3, 4, 5].map(num => new Fr(num).toBuffer())); - expect(logs[1].data.subarray(-32 * 5)).toEqual(expectedBuffer); - - // Third log should be string "test" - expectedBuffer = Buffer.concat( - ['t', 'e', 's', 't'].map(num => Buffer.concat([Buffer.alloc(31), Buffer.from(num)])), - ); - expect(logs[2].data.subarray(-32 * 5)).toEqual(expectedBuffer); - }, 60_000); - it('calls a method with nested note encrypted logs', async () => { // account setup const privateKey = new Fr(7n); diff --git a/yarn-project/end-to-end/src/e2e_card_game.test.ts b/yarn-project/end-to-end/src/e2e_card_game.test.ts index 24629f1e8f7a..7f7f3e6fa98d 100644 --- a/yarn-project/end-to-end/src/e2e_card_game.test.ts +++ b/yarn-project/end-to-end/src/e2e_card_game.test.ts @@ -15,6 +15,8 @@ import { toBufferLE } from '@aztec/foundation/bigint-buffer'; import { sha256 } from '@aztec/foundation/crypto'; import { CardGameContract } from '@aztec/noir-contracts.js/CardGame'; +import { jest } from '@jest/globals'; + import { setup } from './fixtures/utils.js'; /* eslint-disable camelcase */ @@ -59,7 +61,11 @@ const GAME_ID = 42; const PLAYER_SECRET_KEYS = INITIAL_TEST_SECRET_KEYS; +const TIMEOUT = 600_000; + describe('e2e_card_game', () => { + jest.setTimeout(TIMEOUT); + let pxe: PXE; let logger: DebugLogger; let teardown: () => Promise; diff --git a/yarn-project/end-to-end/src/e2e_event_logs.test.ts b/yarn-project/end-to-end/src/e2e_event_logs.test.ts index 02122e165d12..d49bef63dd1d 100644 --- a/yarn-project/end-to-end/src/e2e_event_logs.test.ts +++ b/yarn-project/end-to-end/src/e2e_event_logs.test.ts @@ -1,4 +1,12 @@ -import { type AccountWalletWithSecretKey, type AztecNode, Fr, L1EventPayload, TaggedLog } from '@aztec/aztec.js'; +import { + type AccountWalletWithSecretKey, + type AztecNode, + EventType, + Fr, + L1EventPayload, + type PXE, + TaggedLog, +} from '@aztec/aztec.js'; import { deriveMasterIncomingViewingSecretKey } from '@aztec/circuits.js'; import { EventSelector } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; @@ -17,30 +25,36 @@ describe('Logs', () => { let wallets: AccountWalletWithSecretKey[]; let node: AztecNode; + let pxe: PXE; let teardown: () => Promise; beforeAll(async () => { - ({ teardown, wallets, aztecNode: node } = await setup(2)); + ({ teardown, wallets, aztecNode: node, pxe } = await setup(2)); await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); testLogContract = await TestLogContract.deploy(wallets[0]).send().deployed(); + + await pxe.registerRecipient(wallets[1].getCompleteAddress()); }); afterAll(() => teardown()); describe('functionality around emitting an encrypted log', () => { - it('emits multiple events as encrypted logs and decodes them', async () => { + it('emits multiple events as encrypted logs and decodes them one manually', async () => { const randomness = makeTuple(2, Fr.random); const preimage = makeTuple(4, Fr.random); - const tx = await testLogContract.methods.emit_encrypted_events(randomness, preimage).send().wait(); + const tx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness, preimage) + .send() + .wait(); const txEffect = await node.getTxEffect(tx.txHash); const encryptedLogs = txEffect!.encryptedLogs.unrollLogs(); - expect(encryptedLogs.length).toBe(2); + expect(encryptedLogs.length).toBe(3); const decryptedLog0 = TaggedLog.decryptAsIncoming( encryptedLogs[0], @@ -66,7 +80,8 @@ describe('Logs', () => { expect(badEvent0).toBe(undefined); const decryptedLog1 = TaggedLog.decryptAsIncoming( - encryptedLogs[1], + // We want to skip the second emitted log as it is irrelevant in this test. + encryptedLogs[2], deriveMasterIncomingViewingSecretKey(wallets[0].getSecretKey()), L1EventPayload, ); @@ -94,26 +109,112 @@ describe('Logs', () => { const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; let i = 0; - const firstTx = await testLogContract.methods.emit_encrypted_events(randomness[i], preimage[i]).send().wait(); + const firstTx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[i], preimage[i]) + .send() + .wait(); await Promise.all( [...new Array(3)].map(() => - testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait(), + testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i]) + .send() + .wait(), ), ); - const lastTx = await testLogContract.methods.emit_encrypted_events(randomness[++i], preimage[i]).send().wait(); + const lastTx = await testLogContract.methods + .emit_encrypted_events(wallets[1].getAddress(), randomness[++i], preimage[i]) + .send() + .wait(); + // We get all the events we can decrypt with either our incoming or outgoing viewing keys const collectedEvent0s = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + ); + + const collectedEvent0sWithIncoming = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent0, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, + // This function can be called specifying the viewing public keys associated with the encrypted event. + [wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], + ); + + const collectedEvent0sWithOutgoing = await wallets[0].getEvents( + EventType.Encrypted, TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey], ); const collectedEvent1s = await wallets[0].getEvents( + EventType.Encrypted, + TestLogContract.events.ExampleEvent1, firstTx.blockNumber!, lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey], + ); + + expect(collectedEvent0sWithIncoming.length).toBe(5); + expect(collectedEvent0sWithOutgoing.length).toBe(5); + expect(collectedEvent0s.length).toBe(10); + expect(collectedEvent1s.length).toBe(5); + + const emptyEvent1s = await wallets[0].getEvents( + EventType.Encrypted, TestLogContract.events.ExampleEvent1, - // This function can also be called specifying the incoming viewing public key associated with the encrypted event. - wallets[0].getCompleteAddress().publicKeys.masterIncomingViewingPublicKey, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + [wallets[0].getCompleteAddress().publicKeys.masterOutgoingViewingPublicKey], + ); + + expect(emptyEvent1s.length).toBe(0); + + const exampleEvent0Sort = (a: ExampleEvent0, b: ExampleEvent0) => (a.value0 > b.value0 ? 1 : -1); + expect(collectedEvent0sWithIncoming.sort(exampleEvent0Sort)).toStrictEqual( + preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort), + ); + + expect(collectedEvent0sWithOutgoing.sort(exampleEvent0Sort)).toStrictEqual( + preimage.map(preimage => ({ value0: preimage[0], value1: preimage[1] })).sort(exampleEvent0Sort), + ); + + expect([...collectedEvent0sWithIncoming, ...collectedEvent0sWithOutgoing].sort(exampleEvent0Sort)).toStrictEqual( + collectedEvent0s.sort(exampleEvent0Sort), + ); + + const exampleEvent1Sort = (a: ExampleEvent1, b: ExampleEvent1) => (a.value2 > b.value2 ? 1 : -1); + expect(collectedEvent1s.sort(exampleEvent1Sort)).toStrictEqual( + preimage.map(preimage => ({ value2: preimage[2], value3: preimage[3] })).sort(exampleEvent1Sort), + ); + }); + + it('emits multiple events as unencrypted logs and decodes them', async () => { + const preimage = makeTuple(5, makeTuple.bind(undefined, 4, Fr.random)) as Tuple, 5>; + + let i = 0; + const firstTx = await testLogContract.methods.emit_unencrypted_events(preimage[i]).send().wait(); + await Promise.all( + [...new Array(3)].map(() => testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait()), + ); + const lastTx = await testLogContract.methods.emit_unencrypted_events(preimage[++i]).send().wait(); + + const collectedEvent0s = await wallets[0].getEvents( + EventType.Unencrypted, + TestLogContract.events.ExampleEvent0, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, + ); + + const collectedEvent1s = await wallets[0].getEvents( + EventType.Unencrypted, + TestLogContract.events.ExampleEvent1, + firstTx.blockNumber!, + lastTx.blockNumber! - firstTx.blockNumber! + 1, ); expect(collectedEvent0s.length).toBe(5); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index 2de576931315..83fb65f5775b 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -14,7 +14,7 @@ import { createDebugLogger, } from '@aztec/aztec.js'; import { DefaultMultiCallEntrypoint } from '@aztec/aztec.js/entrypoint'; -import { EthAddress, GasSettings } from '@aztec/circuits.js'; +import { EthAddress, GasSettings, computePartialAddress } from '@aztec/circuits.js'; import { createL1Clients } from '@aztec/ethereum'; import { PortalERC20Abi } from '@aztec/l1-artifacts'; import { @@ -23,6 +23,8 @@ import { CounterContract, FPCContract, GasTokenContract, + PrivateFPCContract, + PrivateTokenContract, } from '@aztec/noir-contracts.js'; import { getCanonicalGasToken } from '@aztec/protocol-contracts/gas-token'; @@ -65,6 +67,8 @@ export class FeesTest { public gasTokenContract!: GasTokenContract; public bananaCoin!: BananaCoin; public bananaFPC!: FPCContract; + public privateToken!: PrivateTokenContract; + public privateFPC!: PrivateFPCContract; public counterContract!: CounterContract; public subscriptionContract!: AppSubscriptionContract; public gasBridgeTestHarness!: IGasBridgingTestHarness; @@ -73,6 +77,7 @@ export class FeesTest { public gasBalances!: BalancesFn; public bananaPublicBalances!: BalancesFn; public bananaPrivateBalances!: BalancesFn; + public privateTokenBalances!: BalancesFn; public readonly INITIAL_GAS_BALANCE = BigInt(1e15); public readonly ALICE_INITIAL_BANANAS = BigInt(1e12); @@ -94,6 +99,14 @@ export class FeesTest { await this.snapshotManager.teardown(); } + /** Alice mints PrivateToken */ + async mintPrivateTokens(amount: bigint) { + const balanceBefore = await this.privateToken.methods.balance_of_private(this.aliceAddress).simulate(); + await this.privateToken.methods.privately_mint_private_note(amount).send().wait(); + const balanceAfter = await this.privateToken.methods.balance_of_private(this.aliceAddress).simulate(); + expect(balanceAfter).toEqual(balanceBefore + amount); + } + /** Alice mints bananaCoin tokens privately to the target address and redeems them. */ async mintPrivateBananas(amount: bigint, address: AztecAddress) { const balanceBefore = await this.bananaCoin.methods.balance_of_private(address).simulate(); @@ -136,13 +149,13 @@ export class FeesTest { } public async applyBaseSnapshots() { - await this.applyDeployGasTokenSnapshot(); await this.applyInitialAccountsSnapshot(); await this.applyPublicDeployAccountsSnapshot(); + await this.applyDeployGasTokenSnapshot(); await this.applyDeployBananaTokenSnapshot(); } - private async applyInitialAccountsSnapshot() { + async applyInitialAccountsSnapshot() { await this.snapshotManager.snapshot( 'initial_accounts', addAccounts(3, this.logger), @@ -156,6 +169,11 @@ export class FeesTest { [this.aliceWallet, this.bobWallet] = this.wallets.slice(0, 2); [this.aliceAddress, this.bobAddress, this.sequencerAddress] = this.wallets.map(w => w.getAddress()); this.gasTokenContract = await GasTokenContract.at(getCanonicalGasToken().address, this.aliceWallet); + const bobInstance = await this.bobWallet.getContractInstance(this.bobAddress); + if (!bobInstance) { + throw new Error('Bob instance not found'); + } + await this.aliceWallet.registerAccount(accountKeys[1][0], computePartialAddress(bobInstance)); this.coinbase = EthAddress.random(); const { publicClient, walletClient } = createL1Clients(aztecNodeConfig.rpcUrl, MNEMONIC); @@ -172,24 +190,43 @@ export class FeesTest { ); } - private async applyPublicDeployAccountsSnapshot() { + async applyPublicDeployAccountsSnapshot() { await this.snapshotManager.snapshot('public_deploy_accounts', () => publicDeployAccounts(this.aliceWallet, this.wallets), ); } - private async applyDeployGasTokenSnapshot() { - await this.snapshotManager.snapshot('deploy_gas_token', async context => { - await deployCanonicalGasToken( - new SignerlessWallet( - context.pxe, - new DefaultMultiCallEntrypoint(context.aztecNodeConfig.chainId, context.aztecNodeConfig.version), - ), - ); - }); + async applyDeployGasTokenSnapshot() { + await this.snapshotManager.snapshot( + 'deploy_gas_token', + async context => { + await deployCanonicalGasToken( + new SignerlessWallet( + context.pxe, + new DefaultMultiCallEntrypoint(context.aztecNodeConfig.chainId, context.aztecNodeConfig.version), + ), + ); + }, + async (_data, context) => { + this.gasTokenContract = await GasTokenContract.at(getCanonicalGasToken().address, this.aliceWallet); + + this.gasBalances = getBalancesFn('⛽', this.gasTokenContract.methods.balance_of_public, this.logger); + + const { publicClient, walletClient } = createL1Clients(context.aztecNodeConfig.rpcUrl, MNEMONIC); + this.gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + aztecNode: context.aztecNode, + pxeService: context.pxe, + publicClient: publicClient, + walletClient: walletClient, + wallet: this.aliceWallet, + logger: this.logger, + mockL1: false, + }); + }, + ); } - private async applyDeployBananaTokenSnapshot() { + async applyDeployBananaTokenSnapshot() { await this.snapshotManager.snapshot( 'deploy_banana_token', async () => { @@ -205,6 +242,46 @@ export class FeesTest { ); } + async applyPrivateTokenAndFPC() { + await this.snapshotManager.snapshot( + 'private_token_and_private_fpc', + async context => { + // Deploy token/fpc flavors for private refunds + const gasTokenContract = this.gasBridgeTestHarness.l2Token; + expect(await context.pxe.isContractPubliclyDeployed(gasTokenContract.address)).toBe(true); + + const privateToken = await PrivateTokenContract.deploy(this.aliceWallet, this.aliceAddress, 'PVT', 'PVT', 18n) + .send() + .deployed(); + + this.logger.info(`PrivateToken deployed at ${privateToken.address}`); + const adminKeyHash = this.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); + + const privateFPCSent = PrivateFPCContract.deploy(this.bobWallet, privateToken.address, adminKeyHash).send(); + const privateFPC = await privateFPCSent.deployed(); + + this.logger.info(`PrivateFPC deployed at ${privateFPC.address}`); + await this.gasBridgeTestHarness.bridgeFromL1ToL2( + this.INITIAL_GAS_BALANCE, + this.INITIAL_GAS_BALANCE, + privateFPC.address, + ); + + return { + privateTokenAddress: privateToken.address, + privateFPCAddress: privateFPC.address, + }; + }, + async data => { + this.privateFPC = await PrivateFPCContract.at(data.privateFPCAddress, this.bobWallet); + this.privateToken = await PrivateTokenContract.at(data.privateTokenAddress, this.aliceWallet); + + const logger = this.logger; + this.privateTokenBalances = getBalancesFn('🕵️.private', this.privateToken.methods.balance_of_private, logger); + }, + ); + } + public async applyFPCSetupSnapshot() { await this.snapshotManager.snapshot( 'fpc_setup', @@ -238,7 +315,6 @@ export class FeesTest { const logger = this.logger; this.bananaPublicBalances = getBalancesFn('🍌.public', this.bananaCoin.methods.balance_of_public, logger); this.bananaPrivateBalances = getBalancesFn('🍌.private', this.bananaCoin.methods.balance_of_private, logger); - this.gasBalances = getBalancesFn('⛽', this.gasTokenContract.methods.balance_of_public, logger); this.getCoinbaseBalance = async () => { const { walletClient } = createL1Clients(context.aztecNodeConfig.rpcUrl, MNEMONIC); @@ -264,6 +340,16 @@ export class FeesTest { ); } + public async applyFundAliceWithPrivateTokens() { + await this.snapshotManager.snapshot( + 'fund_alice_with_private_tokens', + async () => { + await this.mintPrivateTokens(BigInt(this.ALICE_INITIAL_BANANAS)); + }, + () => Promise.resolve(), + ); + } + public async applyFundAliceWithGasToken() { await this.snapshotManager.snapshot( 'fund_alice_with_gas_token', diff --git a/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts new file mode 100644 index 000000000000..8ab441d8336a --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_fees/private_refunds.test.ts @@ -0,0 +1,178 @@ +import { + type AztecAddress, + ExtendedNote, + type FeePaymentMethod, + type FunctionCall, + Note, + type Wallet, +} from '@aztec/aztec.js'; +import { Fr, type GasSettings } from '@aztec/circuits.js'; +import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; +import { type PrivateFPCContract, PrivateTokenContract } from '@aztec/noir-contracts.js'; + +import { expectMapping } from '../fixtures/utils.js'; +import { FeesTest } from './fees_test.js'; + +describe('e2e_fees/private_refunds', () => { + let aliceWallet: Wallet; + let aliceAddress: AztecAddress; + let privateToken: PrivateTokenContract; + let privateFPC: PrivateFPCContract; + + let InitialAlicePrivateTokens: bigint; + let InitialBobPrivateTokens: bigint; + let InitialPrivateFPCGas: bigint; + + const t = new FeesTest('private_refunds'); + + beforeAll(async () => { + await t.applyInitialAccountsSnapshot(); + await t.applyPublicDeployAccountsSnapshot(); + await t.applyDeployGasTokenSnapshot(); + await t.applyPrivateTokenAndFPC(); + await t.applyFundAliceWithPrivateTokens(); + ({ aliceWallet, aliceAddress, privateFPC, privateToken } = await t.setup()); + t.logger.debug(`Alice address: ${aliceAddress}`); + }); + + afterAll(async () => { + await t.teardown(); + }); + + beforeEach(async () => { + [[InitialAlicePrivateTokens, InitialBobPrivateTokens], [InitialPrivateFPCGas]] = await Promise.all([ + t.privateTokenBalances(aliceAddress, t.bobAddress), + t.gasBalances(privateFPC.address), + ]); + }); + + it('can do private payments and refunds', async () => { + const bobKeyHash = t.bobWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); + const rebateNonce = new Fr(42); + const tx = await privateToken.methods + .private_get_name() + .send({ + fee: { + gasSettings: t.gasSettings, + paymentMethod: new PrivateRefundPaymentMethod( + privateToken.address, + privateFPC.address, + aliceWallet, + rebateNonce, + bobKeyHash, + ), + }, + }) + .wait(); + + expect(tx.transactionFee).toBeGreaterThan(0); + + const refundedNoteValue = t.gasSettings.getFeeLimit().sub(new Fr(tx.transactionFee!)); + const aliceKeyHash = t.aliceWallet.getCompleteAddress().publicKeys.masterNullifierPublicKey.hash(); + const aliceRefundNote = new Note([refundedNoteValue, aliceKeyHash, rebateNonce]); + await t.aliceWallet.addNote( + new ExtendedNote( + aliceRefundNote, + t.aliceAddress, + privateToken.address, + PrivateTokenContract.storage.balances.slot, + PrivateTokenContract.notes.TokenNote.id, + tx.txHash, + ), + ); + + const bobFeeNote = new Note([new Fr(tx.transactionFee!), bobKeyHash, rebateNonce]); + await t.bobWallet.addNote( + new ExtendedNote( + bobFeeNote, + t.bobAddress, + privateToken.address, + PrivateTokenContract.storage.balances.slot, + PrivateTokenContract.notes.TokenNote.id, + tx.txHash, + ), + ); + + await expectMapping(t.gasBalances, [privateFPC.address], [InitialPrivateFPCGas - tx.transactionFee!]); + await expectMapping( + t.privateTokenBalances, + [aliceAddress, t.bobAddress], + [InitialAlicePrivateTokens - tx.transactionFee!, InitialBobPrivateTokens + tx.transactionFee!], + ); + }); +}); + +class PrivateRefundPaymentMethod implements FeePaymentMethod { + constructor( + /** + * The asset used to pay the fee. + */ + private asset: AztecAddress, + /** + * Address which will hold the fee payment. + */ + private paymentContract: AztecAddress, + + /** + * An auth witness provider to authorize fee payments + */ + private wallet: Wallet, + + /** + * A nonce to mix in with the generated notes. + * Use this to reconstruct note preimages for the PXE. + */ + private rebateNonce: Fr, + + /** + * The hash of the nullifier private key that the FPC sends notes it receives to. + */ + private feeRecipientNPKMHash: Fr, + ) {} + + /** + * The asset used to pay the fee. + * @returns The asset used to pay the fee. + */ + getAsset() { + return this.asset; + } + + getFeePayer(): Promise { + return Promise.resolve(this.paymentContract); + } + + /** + * Creates a function call to pay the fee in the given asset. + * @param gasSettings - The gas settings. + * @returns The function call to pay the fee. + */ + async getFunctionCalls(gasSettings: GasSettings): Promise { + const maxFee = gasSettings.getFeeLimit(); + + await this.wallet.createAuthWit({ + caller: this.paymentContract, + action: { + name: 'setup_refund', + args: [this.feeRecipientNPKMHash, this.wallet.getCompleteAddress().address, maxFee, this.rebateNonce], + selector: FunctionSelector.fromSignature('setup_refund(Field,(Field),Field,Field)'), + type: FunctionType.PRIVATE, + isStatic: false, + to: this.asset, + returnTypes: [], + }, + }); + + return [ + { + name: 'fund_transaction_privately', + to: this.paymentContract, + selector: FunctionSelector.fromSignature('fund_transaction_privately(Field,(Field),Field)'), + type: FunctionType.PRIVATE, + isStatic: false, + args: [maxFee, this.asset, this.rebateNonce], + returnTypes: [], + }, + ]; + } +} 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 index d667eef74e36..a9d3a3c3d586 100644 --- a/yarn-project/end-to-end/src/e2e_key_registry.test.ts +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -58,7 +58,7 @@ describe('Key Registry', () => { await expect( keyRegistry .withWallet(wallets[0]) - .methods.register( + .methods.register_npk_and_ivpk( account, account.partialAddress, // TODO(#6337): Make calling `toNoirStruct()` unnecessary @@ -108,7 +108,18 @@ describe('Key Registry', () => { it('registers', async () => { await keyRegistry .withWallet(wallets[0]) - .methods.register( + .methods.register_npk_and_ivpk( + account, + account.partialAddress, + // TODO(#6337): Make calling `toNoirStruct()` unnecessary + account.publicKeys.toNoirStruct(), + ) + .send() + .wait(); + + await keyRegistry + .withWallet(wallets[0]) + .methods.register_ovpk_and_tpk( account, account.partialAddress, // TODO(#6337): Make calling `toNoirStruct()` unnecessary diff --git a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts index 1728f637e1e7..54e377ad4e93 100644 --- a/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts +++ b/yarn-project/end-to-end/src/e2e_non_contract_account.test.ts @@ -1,13 +1,4 @@ -import { - type DebugLogger, - ExtendedNote, - Fr, - Note, - type PXE, - SignerlessWallet, - type Wallet, - toBigInt, -} from '@aztec/aztec.js'; +import { type DebugLogger, ExtendedNote, Fr, Note, type PXE, SignerlessWallet, type Wallet } from '@aztec/aztec.js'; import { siloNullifier } from '@aztec/circuits.js/hash'; import { TestContract } from '@aztec/noir-contracts.js/Test'; @@ -50,20 +41,6 @@ describe('e2e_non_contract_account', () => { expect(siloedNullifier.equals(expectedSiloedNullifier)).toBeTruthy(); }); - it('msg.sender is 0 when a non-contract account calls a private function on a contract', async () => { - const contractWithNoContractWallet = await TestContract.at(contract.address, nonContractAccountWallet); - - // Send transaction as arbitrary non-contract account - const tx = contractWithNoContractWallet.methods.emit_msg_sender().send(); - await tx.wait({ interval: 0.1 }); - - const logs = (await tx.getUnencryptedLogs()).logs; - expect(logs.length).toBe(1); - - const msgSender = toBigInt(logs[0].log.data); - expect(msgSender).toBe(0n); - }); - // Note: This test doesn't really belong here as it doesn't have anything to do with non-contract accounts. I needed // to test the TestNote functionality and it doesn't really fit anywhere else. Creating a separate e2e test for this // seems wasteful. Move this test if a better place is found. diff --git a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts index 46df722fee25..6e24dddfd329 100644 --- a/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_pending_note_hashes_contract.test.ts @@ -1,7 +1,7 @@ import { type AztecAddress, type AztecNode, type DebugLogger, Fr, type Wallet } from '@aztec/aztec.js'; import { - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_CALL, + MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, } from '@aztec/circuits.js'; @@ -290,8 +290,8 @@ describe('e2e_pending_note_hashes_contract', () => { it('Should handle overflowing the kernel data structures in nested calls', async () => { // Setting the outgoing viewer to owner not have to bother with setting up another account. const outgoingViewer = owner; - const notesPerIteration = Math.min(MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL); - const minToNeedReset = Math.min(MAX_NEW_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + 1; + const notesPerIteration = Math.min(MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL); + const minToNeedReset = Math.min(MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX) + 1; const deployedContract = await deployContract(); await deployedContract.methods .test_recursively_create_notes(owner, outgoingViewer, Math.ceil(minToNeedReset / notesPerIteration)) 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 d306d976ffb7..400a25e9f361 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 @@ -94,7 +94,7 @@ describe('e2e_state_vars', () => { // Jest executes the tests sequentially and the first call to initialize_shared_immutable was executed // in the previous test, so the call below should fail. await expect(contract.methods.initialize_shared_immutable(1).prove()).rejects.toThrow( - "Assertion failed: SharedImmutable already initialized 'fields_read[0] == 0'", + 'Assertion failed: SharedImmutable already initialized', ); }); }); @@ -114,7 +114,7 @@ describe('e2e_state_vars', () => { // Jest executes the tests sequentially and the first call to initialize_public_immutable was executed // in the previous test, so the call below should fail. await expect(contract.methods.initialize_public_immutable(1).prove()).rejects.toThrow( - "Assertion failed: PublicImmutable already initialized 'fields_read[0] == 0'", + 'Assertion failed: PublicImmutable already initialized', ); }); }); diff --git a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts index 4d1536e4df41..8ac1bf96cda1 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract/transfer_private.test.ts @@ -1,10 +1,12 @@ import { AztecAddress, CompleteAddress, + EventType, Fr, computeAuthWitMessageHash, computeInnerAuthWitHashFromAction, } from '@aztec/aztec.js'; +import { TokenContract } from '@aztec/noir-contracts.js'; import { DUPLICATE_NULLIFIER_ERROR } from '../fixtures/fixtures.js'; import { TokenContractTest } from './token_contract_test.js'; @@ -32,8 +34,16 @@ describe('e2e_token_contract transfer private', () => { const balance0 = await asset.methods.balance_of_private(accounts[0].address).simulate(); const amount = balance0 / 2n; expect(amount).toBeGreaterThan(0n); - await asset.methods.transfer(accounts[1].address, amount).send().wait(); + const tx = await asset.methods.transfer(accounts[1].address, amount).send().wait(); tokenSim.transferPrivate(accounts[0].address, accounts[1].address, amount); + + const events = await wallets[1].getEvents(EventType.Encrypted, TokenContract.events.Transfer, tx.blockNumber!, 1); + + expect(events[0]).toEqual({ + from: accounts[0].address, + to: accounts[1].address, + amount: new Fr(amount), + }); }); it('transfer less than balance to non-deployed account', async () => { diff --git a/yarn-project/foundation/src/log/logger.ts b/yarn-project/foundation/src/log/logger.ts index 3b28a279d2ca..a653b233393d 100644 --- a/yarn-project/foundation/src/log/logger.ts +++ b/yarn-project/foundation/src/log/logger.ts @@ -11,7 +11,7 @@ const DefaultLogLevel = process.env.NODE_ENV === 'test' ? ('silent' as const) : export type LogLevel = (typeof LogLevels)[number]; const envLogLevel = process.env.LOG_LEVEL?.toLowerCase() as LogLevel; -const currentLevel = LogLevels.includes(envLogLevel) ? envLogLevel : DefaultLogLevel; +export const currentLevel = LogLevels.includes(envLogLevel) ? envLogLevel : DefaultLogLevel; const namespaces = process.env.DEBUG ?? 'aztec:*'; debug.enable(namespaces); diff --git a/yarn-project/merkle-tree/src/index.ts b/yarn-project/merkle-tree/src/index.ts index 7ac5cb2dc6ee..412a545aad38 100644 --- a/yarn-project/merkle-tree/src/index.ts +++ b/yarn-project/merkle-tree/src/index.ts @@ -8,6 +8,7 @@ export * from './sparse_tree/sparse_tree.js'; export { StandardIndexedTree } from './standard_indexed_tree/standard_indexed_tree.js'; export { StandardIndexedTreeWithAppend } from './standard_indexed_tree/test/standard_indexed_tree_with_append.js'; export * from './standard_tree/standard_tree.js'; +export * from './unbalanced_tree.js'; export { INITIAL_LEAF, getTreeMeta } from './tree_base.js'; export { newTree } from './new_tree.js'; export { loadTree } from './load_tree.js'; diff --git a/yarn-project/merkle-tree/src/unbalanced_tree.test.ts b/yarn-project/merkle-tree/src/unbalanced_tree.test.ts new file mode 100644 index 000000000000..14ee0252ee44 --- /dev/null +++ b/yarn-project/merkle-tree/src/unbalanced_tree.test.ts @@ -0,0 +1,273 @@ +import { sha256Trunc } from '@aztec/foundation/crypto'; +import { Fr } from '@aztec/foundation/fields'; +import { type FromBuffer } from '@aztec/foundation/serialize'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { type Hasher } from '@aztec/types/interfaces'; + +import { SHA256Trunc } from './sha_256.js'; +import { StandardTree } from './standard_tree/standard_tree.js'; +import { UnbalancedTree } from './unbalanced_tree.js'; + +const noopDeserializer: FromBuffer = { + fromBuffer: (buffer: Buffer) => buffer, +}; + +// Follows sol implementation and tests in UnbalancedMerkle.t.sol +describe('Wonky tree', () => { + let hasher: Hasher; + let tree: UnbalancedTree; + let leaves: Buffer[]; + + const createAndFillTree = async (size: number) => { + const depth = Math.ceil(Math.log2(size)); + const tree = new UnbalancedTree(hasher, `test`, depth, noopDeserializer); + const leaves = Array(size) + .fill(0) + .map((_, i) => sha256Trunc(new Fr(i).toBuffer())); + // For the final test, we make the final (shifted up) leaf be H(1, 2), so we can calculate the root + // with a standard tree easily. + if (leaves[30]) { + leaves[30] = hasher.hash(new Fr(1).toBuffer(), new Fr(2).toBuffer()); + } + await tree.appendLeaves(leaves); + return { tree, leaves }; + }; + + beforeAll(() => { + hasher = new SHA256Trunc(); + }); + + // Example - 2 txs: + // + // root + // / \ + // base base + describe('2 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(2); + tree = res.tree; + leaves = res.leaves; + }); + + it("Shouldn't accept more leaves", () => { + expect(() => tree.appendLeaves([Buffer.alloc(32)])).toThrow( + "Can't re-append to an unbalanced tree. Current has 2 leaves.", + ); + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(1); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const expectedRoot = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(1); + const expectedSibPath = [leaves[1]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 3 txs: + // + // root + // / \ + // merge base + // / \ + // base base + describe('3 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(3); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(2); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const mergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + const expectedRoot = sha256Trunc(Buffer.concat([mergeNode, leaves[2]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(2); + const expectedSibPath = [leaves[1], leaves[2]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 5 txs: + // + // root + // / \ + // merge base + // / \ + // merge merge + // / \ / \ + // base base base base + describe('5 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(5); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + let leftMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + const rightMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + leftMergeNode = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + const expectedRoot = sha256Trunc(Buffer.concat([leftMergeNode, leaves[4]])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [leaves[1], sha256Trunc(Buffer.concat([leaves[2], leaves[3]])), leaves[4]]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 6 txs: + // + // root + // / \ + // merge4 merge3 + // / \ / \ + // merge1 merge2 base base + // / \ / \ + // base base base base + describe('6 Transactions', () => { + beforeAll(async () => { + const res = await createAndFillTree(6); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + let leftMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + let rightMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + leftMergeNode = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + rightMergeNode = sha256Trunc(Buffer.concat([leaves[4], leaves[5]])); + const expectedRoot = sha256Trunc(Buffer.concat([leftMergeNode, rightMergeNode])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [ + leaves[1], + sha256Trunc(Buffer.concat([leaves[2], leaves[3]])), + sha256Trunc(Buffer.concat([leaves[4], leaves[5]])), + ]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 7 txs: + // + // root + // / \ + // merge3 merge5 + // / \ / \ + // merge1 merge2 merge4 base + // / \ / \ / \ + // base base base base base base + describe('7 Transactions', () => { + let secondMergeNode: Buffer; + let fifthMergeNode: Buffer; + beforeAll(async () => { + const res = await createAndFillTree(7); + tree = res.tree; + leaves = res.leaves; + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(3); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const firstMergeNode = sha256Trunc(Buffer.concat([leaves[0], leaves[1]])); + secondMergeNode = sha256Trunc(Buffer.concat([leaves[2], leaves[3]])); + const thirdMergeNode = sha256Trunc(Buffer.concat([firstMergeNode, secondMergeNode])); + const fourthMergeNode = sha256Trunc(Buffer.concat([leaves[4], leaves[5]])); + fifthMergeNode = sha256Trunc(Buffer.concat([fourthMergeNode, leaves[6]])); + const expectedRoot = sha256Trunc(Buffer.concat([thirdMergeNode, fifthMergeNode])); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling path', async () => { + const sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + expect(sibPath.pathSize).toEqual(3); + const expectedSibPath = [leaves[1], secondMergeNode, fifthMergeNode]; + expect(sibPath.toBufferArray()).toEqual(expectedSibPath); + }); + }); + + // Example - 31 txs: + // The same as a standard 32 leaf balanced tree, but with the last 'leaf' shifted up one. + describe('31 Transactions', () => { + let stdTree: StandardTree; + beforeAll(async () => { + const res = await createAndFillTree(31); + tree = res.tree; + leaves = res.leaves; + stdTree = new StandardTree(openTmpStore(true), hasher, `temp`, 5, 0n, noopDeserializer); + // We have set the last leaf to be H(1, 2), so we can fill a 32 size tree with: + await stdTree.appendLeaves([...res.leaves.slice(0, 30), new Fr(1).toBuffer(), new Fr(2).toBuffer()]); + }); + + it('Correctly computes tree information', () => { + expect(tree.getNumLeaves()).toEqual(BigInt(leaves.length)); + expect(tree.getDepth()).toEqual(5); + expect(tree.findLeafIndex(leaves[0])).toEqual(0n); + }); + + it('Correctly computes root', () => { + const root = tree.getRoot(); + const expectedRoot = stdTree.getRoot(true); + expect(root).toEqual(expectedRoot); + }); + + it('Correctly computes sibling paths', async () => { + let sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[0].toString('hex'))); + let expectedSibPath = await stdTree.getSiblingPath(0n, true); + expect(sibPath).toEqual(expectedSibPath); + sibPath = await tree.getSiblingPath(BigInt('0x' + leaves[27].toString('hex'))); + expectedSibPath = await stdTree.getSiblingPath(27n, true); + expect(sibPath).toEqual(expectedSibPath); + }); + }); +}); diff --git a/yarn-project/merkle-tree/src/unbalanced_tree.ts b/yarn-project/merkle-tree/src/unbalanced_tree.ts new file mode 100644 index 000000000000..6920b5d12781 --- /dev/null +++ b/yarn-project/merkle-tree/src/unbalanced_tree.ts @@ -0,0 +1,239 @@ +import { SiblingPath } from '@aztec/circuit-types'; +import { type Bufferable, type FromBuffer, serializeToBuffer } from '@aztec/foundation/serialize'; +import { type Hasher } from '@aztec/types/interfaces'; + +import { HasherWithStats } from './hasher_with_stats.js'; +import { type MerkleTree } from './interfaces/merkle_tree.js'; + +const indexToKeyHash = (name: string, level: number, index: bigint) => `${name}:${level}:${index}`; + +/** + * An ephemeral unbalanced Merkle tree implementation. + * Follows the rollup implementation which greedily hashes pairs of nodes up the tree. + * Remaining rightmost nodes are shifted up until they can be paired. See proving-state.ts -> findMergeLevel. + */ +export class UnbalancedTree implements MerkleTree { + // This map stores index and depth -> value + private cache: { [key: string]: Buffer } = {}; + // This map stores value -> index and depth, since we have variable depth + private valueCache: { [key: string]: string } = {}; + protected size: bigint = 0n; + protected readonly maxIndex: bigint; + + protected hasher: HasherWithStats; + root: Buffer = Buffer.alloc(32); + + public constructor( + hasher: Hasher, + private name: string, + private maxDepth: number = 0, + protected deserializer: FromBuffer, + ) { + this.hasher = new HasherWithStats(hasher); + this.maxIndex = 2n ** BigInt(this.maxDepth) - 1n; + } + + /** + * Returns the root of the tree. + * @returns The root of the tree. + */ + public getRoot(): Buffer { + return this.root; + } + + /** + * Returns the number of leaves in the tree. + * @returns The number of leaves in the tree. + */ + public getNumLeaves() { + return this.size; + } + + /** + * Returns the max depth of the tree. + * @returns The max depth of the tree. + */ + public getDepth(): number { + return this.maxDepth; + } + + /** + * @remark A wonky tree is (currently) only ever ephemeral, so we don't use any db to commit to. + * The fn must exist to implement MerkleTree however. + */ + public commit(): Promise { + throw new Error("Unsupported function - cannot commit on an unbalanced tree as it's always ephemeral."); + return Promise.resolve(); + } + + /** + * Rolls back the not-yet-committed changes. + * @returns Empty promise. + */ + public rollback(): Promise { + this.clearCache(); + return Promise.resolve(); + } + + /** + * Clears the cache. + */ + private clearCache() { + this.cache = {}; + this.size = 0n; + } + + /** + * @remark A wonky tree can validly have duplicate indices: + * e.g. 001 (index 1 at level 3) and 01 (index 1 at level 2) + * So this function cannot reliably give the expected leaf value. + * We cannot add level as an input as its based on the MerkleTree class's function. + */ + public getLeafValue(_index: bigint): undefined { + throw new Error('Unsupported function - cannot get leaf value from an index in an unbalanced tree.'); + } + + /** + * Returns the index of a leaf given its value, or undefined if no leaf with that value is found. + * @param leaf - The leaf value to look for. + * @returns The index of the first leaf found with a given value (undefined if not found). + * @remark This is NOT the index as inserted, but the index which will be used to calculate path structure. + */ + public findLeafIndex(value: T): bigint | undefined { + const key = this.valueCache[serializeToBuffer(value).toString('hex')]; + const [, , index] = key.split(':'); + return BigInt(index); + } + + /** + * Returns the first index containing a leaf value after `startIndex`. + * @param value - The leaf value to look for. + * @param startIndex - The index to start searching from. + * @returns The index of the first leaf found with a given value (undefined if not found). + * @remark This is not really used for a wonky tree, but required to implement MerkleTree. + */ + public findLeafIndexAfter(value: T, startIndex: bigint): bigint | undefined { + const index = this.findLeafIndex(value); + if (!index || index < startIndex) { + return undefined; + } + return index; + } + + /** + * Returns the node at the given level and index + * @param level - The level of the element (root is at level 0). + * @param index - The index of the element. + * @returns Leaf or node value, or undefined. + */ + public getNode(level: number, index: bigint): Buffer | undefined { + if (level < 0 || level > this.maxDepth) { + throw Error('Invalid level: ' + level); + } + + if (index < 0 || index >= this.maxIndex) { + throw Error('Invalid index: ' + index); + } + + return this.cache[indexToKeyHash(this.name, level, index)]; + } + + /** + * Returns a sibling path for the element at the given index. + * @param value - The value of the element. + * @returns A sibling path for the element. + * Note: The sibling path is an array of sibling hashes, with the lowest hash (leaf hash) first, and the highest hash last. + */ + public getSiblingPath(value: bigint): Promise> { + const path: Buffer[] = []; + const [, depth, _index] = this.valueCache[serializeToBuffer(value).toString('hex')].split(':'); + let level = parseInt(depth, 10); + let index = BigInt(_index); + while (level > 0) { + const isRight = index & 0x01n; + const key = indexToKeyHash(this.name, level, isRight ? index - 1n : index + 1n); + const sibling = this.cache[key]; + path.push(sibling); + level -= 1; + index >>= 1n; + } + return Promise.resolve(new SiblingPath(parseInt(depth, 10) as N, path)); + } + + /** + * Appends the given leaves to the tree. + * @param leaves - The leaves to append. + * @returns Empty promise. + */ + public appendLeaves(leaves: T[]): Promise { + this.hasher.reset(); + if (this.size != BigInt(0)) { + throw Error(`Can't re-append to an unbalanced tree. Current has ${this.size} leaves.`); + } + if (this.size + BigInt(leaves.length) - 1n > this.maxIndex) { + throw Error(`Can't append beyond max index. Max index: ${this.maxIndex}`); + } + const root = this.batchInsert(leaves); + this.root = root; + + return Promise.resolve(); + } + + /** + * Calculates root while adding leaves and nodes to the cache. + * @param leaves - The leaves to append. + * @returns Resulting root of the tree. + */ + private batchInsert(_leaves: T[]): Buffer { + // If we have an even number of leaves, hash them all in pairs + // Otherwise, store the final leaf to be shifted up to the next odd sized level + let [layerWidth, nodeToShift] = + _leaves.length & 1 + ? [_leaves.length - 1, serializeToBuffer(_leaves[_leaves.length - 1])] + : [_leaves.length, Buffer.alloc(0)]; + // Allocate this layer's leaves and init the next layer up + let thisLayer = _leaves.slice(0, layerWidth).map(l => serializeToBuffer(l)); + let nextLayer = []; + // Store the bottom level leaves + thisLayer.forEach((leaf, i) => this.storeNode(leaf, this.maxDepth, BigInt(i))); + for (let i = 0; i < this.maxDepth; i++) { + for (let j = 0; j < layerWidth; j += 2) { + // Store the hash of each pair one layer up + nextLayer[j / 2] = this.hasher.hash(serializeToBuffer(thisLayer[j]), serializeToBuffer(thisLayer[j + 1])); + this.storeNode(nextLayer[j / 2], this.maxDepth - i - 1, BigInt(j >> 1)); + } + layerWidth /= 2; + if (layerWidth & 1) { + if (nodeToShift.length) { + // If the next layer has odd length, and we have a node that needs to be shifted up, add it here + nextLayer.push(serializeToBuffer(nodeToShift)); + this.storeNode(nodeToShift, this.maxDepth - i - 1, BigInt((layerWidth * 2) >> 1)); + layerWidth += 1; + nodeToShift = Buffer.alloc(0); + } else { + // If we don't have a node waiting to be shifted, store the next layer's final node to be shifted + layerWidth -= 1; + nodeToShift = nextLayer[layerWidth]; + } + } + // reset the layers + thisLayer = nextLayer; + nextLayer = []; + } + this.size += BigInt(_leaves.length); + // return the root + return thisLayer[0]; + } + + /** + * Stores the given node in the cache. + * @param value - The value to store. + * @param depth - The depth of the node in the full tree. + * @param index - The index of the node at the given depth. + */ + private storeNode(value: T | Buffer, depth: number, index: bigint) { + const key = indexToKeyHash(this.name, depth, index); + this.cache[key] = serializeToBuffer(value); + this.valueCache[serializeToBuffer(value).toString('hex')] = key; + } +} diff --git a/yarn-project/noir-contracts.js/package.json b/yarn-project/noir-contracts.js/package.json index 881226f0a933..6bf009796dfb 100644 --- a/yarn-project/noir-contracts.js/package.json +++ b/yarn-project/noir-contracts.js/package.json @@ -3,14 +3,14 @@ "version": "0.1.0", "type": "module", "exports": { - ".": "./dest/src/index.js", - "./artifacts/*": "./dest/artifacts/*.json", - "./*": "./dest/src/*.js" + ".": "./dest/index.js", + "./artifacts/*": "./artifacts/*.json", + "./*": "./dest/*.js" }, "scripts": { "build": "yarn clean && yarn generate", "build:dev": "tsc -b --watch", - "clean": "rm -rf .tsbuildinfo ./artifacts ./codegenCache.json", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src ./codegenCache.json", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", diff --git a/yarn-project/noir-contracts.js/package.local.json b/yarn-project/noir-contracts.js/package.local.json index 5dd3e0100f96..4cab71fc4ddf 100644 --- a/yarn-project/noir-contracts.js/package.local.json +++ b/yarn-project/noir-contracts.js/package.local.json @@ -3,6 +3,6 @@ "build": "yarn clean && yarn generate", "generate": "yarn generate:noir-contracts", "generate:noir-contracts": "./scripts/generate-types.sh && run -T prettier -w ./src --loglevel warn", - "clean": "rm -rf .tsbuildinfo ./artifacts ./codegenCache.json" + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src ./codegenCache.json" } -} +} \ 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 f7355440508a..8c1168b24e81 100755 --- a/yarn-project/noir-contracts.js/scripts/generate-types.sh +++ b/yarn-project/noir-contracts.js/scripts/generate-types.sh @@ -19,12 +19,21 @@ echo "// Auto generated module - do not edit!" >"$INDEX" # Ensure the artifacts directory exists mkdir -p artifacts +decl=$(cat < "artifacts/$dts_file" done # Generate types for the contracts diff --git a/yarn-project/noir-contracts.js/tsconfig.json b/yarn-project/noir-contracts.js/tsconfig.json index caf5e40c8018..92add33fb362 100644 --- a/yarn-project/noir-contracts.js/tsconfig.json +++ b/yarn-project/noir-contracts.js/tsconfig.json @@ -2,7 +2,7 @@ "extends": "..", "compilerOptions": { "outDir": "dest", - "rootDir": ".", + "rootDir": "src", "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ @@ -15,8 +15,7 @@ ], "include": [ "src", - "artifacts", - "artifacts/*.json" + "artifacts/*.d.json.ts" ], "exclude": [ "dest" diff --git a/yarn-project/noir-protocol-circuits-types/.prettierignore b/yarn-project/noir-protocol-circuits-types/.prettierignore index 595a24e06112..2adf7da0bda7 100644 --- a/yarn-project/noir-protocol-circuits-types/.prettierignore +++ b/yarn-project/noir-protocol-circuits-types/.prettierignore @@ -1,2 +1,2 @@ crates -src/target +artifacts diff --git a/yarn-project/noir-protocol-circuits-types/package.json b/yarn-project/noir-protocol-circuits-types/package.json index dab1d3a0e72f..4f1b5e1fd38d 100644 --- a/yarn-project/noir-protocol-circuits-types/package.json +++ b/yarn-project/noir-protocol-circuits-types/package.json @@ -12,12 +12,12 @@ ], "scripts": { "build": "yarn clean && yarn generate && tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo src/types src/target", + "clean": "rm -rf ./dest .tsbuildinfo src/types artifacts", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "formatting:fix:types": "NODE_OPTIONS='--max-old-space-size=8096' run -T eslint --fix ./src/types && run -T prettier -w ./src/types", "generate": "yarn generate:noir-circuits", - "generate:noir-circuits": "mkdir -p ./src/target && cp ../../noir-projects/noir-protocol-circuits/target/* ./src/target && node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types", + "generate:noir-circuits": "mkdir -p ./artifacts && cp ../../noir-projects/noir-protocol-circuits/target/* ./artifacts && node --no-warnings --loader ts-node/esm src/scripts/generate_declaration_files.ts && node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", "codegen": "yarn noir-codegen", "build:dev": "tsc -b --watch" @@ -82,7 +82,8 @@ "files": [ "dest", "src", - "!*.test.*" + "!*.test.*", + "artifacts" ], "types": "./dest/index.d.ts", "engines": { diff --git a/yarn-project/noir-protocol-circuits-types/package.local.json b/yarn-project/noir-protocol-circuits-types/package.local.json index 9ade866233ee..e3deaa112a7b 100644 --- a/yarn-project/noir-protocol-circuits-types/package.local.json +++ b/yarn-project/noir-protocol-circuits-types/package.local.json @@ -1,6 +1,12 @@ { "scripts": { "build": "yarn clean && yarn generate && tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo src/types src/target" - } -} + "clean": "rm -rf ./dest .tsbuildinfo src/types artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index b6ba9bd4097e..789ff0f92f7b 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -30,40 +30,40 @@ import { type Abi, abiDecode, abiEncode } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; import { strict as assert } from 'assert'; -import EmptyNestedJson from './target/empty_nested.json' assert { type: 'json' }; -import EmptyNestedSimulatedJson from './target/empty_nested_simulated.json' assert { type: 'json' }; -import BaseParityJson from './target/parity_base.json' assert { type: 'json' }; -import RootParityJson from './target/parity_root.json' assert { type: 'json' }; -import PrivateKernelEmptyJson from './target/private_kernel_empty.json' assert { type: 'json' }; -import PrivateKernelEmptySimulatedJson from './target/private_kernel_empty_simulated.json' assert { type: 'json' }; -import PrivateKernelInitJson from './target/private_kernel_init.json' assert { type: 'json' }; -import PrivateKernelInitSimulatedJson from './target/private_kernel_init_simulated.json' assert { type: 'json' }; -import PrivateKernelInnerJson from './target/private_kernel_inner.json' assert { type: 'json' }; -import PrivateKernelInnerSimulatedJson from './target/private_kernel_inner_simulated.json' assert { type: 'json' }; -import PrivateKernelResetJson from './target/private_kernel_reset.json' assert { type: 'json' }; -import PrivateKernelResetBigJson from './target/private_kernel_reset_big.json' assert { type: 'json' }; -import PrivateKernelResetMediumJson from './target/private_kernel_reset_medium.json' assert { type: 'json' }; -import PrivateKernelResetSimulatedJson from './target/private_kernel_reset_simulated.json' assert { type: 'json' }; -import PrivateKernelResetBigSimulatedJson from './target/private_kernel_reset_simulated_big.json' assert { type: 'json' }; -import PrivateKernelResetMediumSimulatedJson from './target/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; -import PrivateKernelResetSmallSimulatedJson from './target/private_kernel_reset_simulated_small.json' assert { type: 'json' }; -import PrivateKernelResetSmallJson from './target/private_kernel_reset_small.json' assert { type: 'json' }; -import PrivateKernelTailJson from './target/private_kernel_tail.json' assert { type: 'json' }; -import PrivateKernelTailSimulatedJson from './target/private_kernel_tail_simulated.json' assert { type: 'json' }; -import PrivateKernelTailToPublicJson from './target/private_kernel_tail_to_public.json' assert { type: 'json' }; -import PrivateKernelTailToPublicSimulatedJson from './target/private_kernel_tail_to_public_simulated.json' assert { type: 'json' }; -import PublicKernelAppLogicJson from './target/public_kernel_app_logic.json' assert { type: 'json' }; -import PublicKernelAppLogicSimulatedJson from './target/public_kernel_app_logic_simulated.json' assert { type: 'json' }; -import PublicKernelSetupJson from './target/public_kernel_setup.json' assert { type: 'json' }; -import PublicKernelSetupSimulatedJson from './target/public_kernel_setup_simulated.json' assert { type: 'json' }; -import PublicKernelTailJson from './target/public_kernel_tail.json' assert { type: 'json' }; -import PublicKernelTailSimulatedJson from './target/public_kernel_tail_simulated.json' assert { type: 'json' }; -import PublicKernelTeardownJson from './target/public_kernel_teardown.json' assert { type: 'json' }; -import PublicKernelTeardownSimulatedJson from './target/public_kernel_teardown_simulated.json' assert { type: 'json' }; -import BaseRollupJson from './target/rollup_base.json' assert { type: 'json' }; -import BaseRollupSimulatedJson from './target/rollup_base_simulated.json' assert { type: 'json' }; -import MergeRollupJson from './target/rollup_merge.json' assert { type: 'json' }; -import RootRollupJson from './target/rollup_root.json' assert { type: 'json' }; +import EmptyNestedJson from '../artifacts/empty_nested.json' assert { type: 'json' }; +import EmptyNestedSimulatedJson from '../artifacts/empty_nested_simulated.json' assert { type: 'json' }; +import BaseParityJson from '../artifacts/parity_base.json' assert { type: 'json' }; +import RootParityJson from '../artifacts/parity_root.json' assert { type: 'json' }; +import PrivateKernelEmptyJson from '../artifacts/private_kernel_empty.json' assert { type: 'json' }; +import PrivateKernelEmptySimulatedJson from '../artifacts/private_kernel_empty_simulated.json' assert { type: 'json' }; +import PrivateKernelInitJson from '../artifacts/private_kernel_init.json' assert { type: 'json' }; +import PrivateKernelInitSimulatedJson from '../artifacts/private_kernel_init_simulated.json' assert { type: 'json' }; +import PrivateKernelInnerJson from '../artifacts/private_kernel_inner.json' assert { type: 'json' }; +import PrivateKernelInnerSimulatedJson from '../artifacts/private_kernel_inner_simulated.json' assert { type: 'json' }; +import PrivateKernelResetJson from '../artifacts/private_kernel_reset.json' assert { type: 'json' }; +import PrivateKernelResetBigJson from '../artifacts/private_kernel_reset_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumJson from '../artifacts/private_kernel_reset_medium.json' assert { type: 'json' }; +import PrivateKernelResetSimulatedJson from '../artifacts/private_kernel_reset_simulated.json' assert { type: 'json' }; +import PrivateKernelResetBigSimulatedJson from '../artifacts/private_kernel_reset_simulated_big.json' assert { type: 'json' }; +import PrivateKernelResetMediumSimulatedJson from '../artifacts/private_kernel_reset_simulated_medium.json' assert { type: 'json' }; +import PrivateKernelResetSmallSimulatedJson from '../artifacts/private_kernel_reset_simulated_small.json' assert { type: 'json' }; +import PrivateKernelResetSmallJson from '../artifacts/private_kernel_reset_small.json' assert { type: 'json' }; +import PrivateKernelTailJson from '../artifacts/private_kernel_tail.json' assert { type: 'json' }; +import PrivateKernelTailSimulatedJson from '../artifacts/private_kernel_tail_simulated.json' assert { type: 'json' }; +import PrivateKernelTailToPublicJson from '../artifacts/private_kernel_tail_to_public.json' assert { type: 'json' }; +import PrivateKernelTailToPublicSimulatedJson from '../artifacts/private_kernel_tail_to_public_simulated.json' assert { type: 'json' }; +import PublicKernelAppLogicJson from '../artifacts/public_kernel_app_logic.json' assert { type: 'json' }; +import PublicKernelAppLogicSimulatedJson from '../artifacts/public_kernel_app_logic_simulated.json' assert { type: 'json' }; +import PublicKernelSetupJson from '../artifacts/public_kernel_setup.json' assert { type: 'json' }; +import PublicKernelSetupSimulatedJson from '../artifacts/public_kernel_setup_simulated.json' assert { type: 'json' }; +import PublicKernelTailJson from '../artifacts/public_kernel_tail.json' assert { type: 'json' }; +import PublicKernelTailSimulatedJson from '../artifacts/public_kernel_tail_simulated.json' assert { type: 'json' }; +import PublicKernelTeardownJson from '../artifacts/public_kernel_teardown.json' assert { type: 'json' }; +import PublicKernelTeardownSimulatedJson from '../artifacts/public_kernel_teardown_simulated.json' assert { type: 'json' }; +import BaseRollupJson from '../artifacts/rollup_base.json' assert { type: 'json' }; +import BaseRollupSimulatedJson from '../artifacts/rollup_base_simulated.json' assert { type: 'json' }; +import MergeRollupJson from '../artifacts/rollup_merge.json' assert { type: 'json' }; +import RootRollupJson from '../artifacts/rollup_root.json' assert { type: 'json' }; import { mapBaseOrMergeRollupPublicInputsFromNoir, mapBaseParityInputsToNoir, diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts new file mode 100644 index 000000000000..98a5f2f06b4f --- /dev/null +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_declaration_files.ts @@ -0,0 +1,17 @@ +import { fileURLToPath } from '@aztec/foundation/url'; + +import { readdir, writeFile } from 'fs/promises'; +import { join } from 'path'; + +const content = `\ +import { type NoirCompiledCircuit } from '@aztec/types/noir'; +const circuit: NoirCompiledCircuit; +export = circuit; +`; + +const target = fileURLToPath(new URL('../../artifacts', import.meta.url).href); +const files = await readdir(target); +for (const file of files) { + const name = file.replace('.json', ''); + await writeFile(join(target, `${name}.d.json.ts`), content); +} diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts index 4c3734e42e62..acb52af5f5b8 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts @@ -45,7 +45,7 @@ const main = async () => { const programs: [string, CompiledCircuit][] = []; // Collect all circuits for (const circuit of circuits) { - const rawData = await fs.readFile(`./src/target/${circuit}.json`, 'utf-8'); + const rawData = await fs.readFile(`./artifacts/${circuit}.json`, 'utf-8'); const abiObj: CompiledCircuit = JSON.parse(rawData); programs.push([pascalCase(circuit), abiObj]); } 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 c276fc8a16d3..1db7ea736361 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -37,11 +37,11 @@ import { LogHash, MAX_ENCRYPTED_LOGS_PER_TX, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, @@ -89,7 +89,6 @@ import { type PrivateKernelResetOutputs, type PrivateKernelTailCircuitPrivateInputs, PrivateKernelTailCircuitPublicInputs, - type PrivateKernelTailHints, PublicAccumulatedData, type PublicCallData, type PublicCallStackItem, @@ -205,9 +204,7 @@ import type { PrivateKernelResetHints as PrivateKernelResetHintsNoir, PrivateKernelResetOutputs as PrivateKernelResetOutputsNoir, PrivateKernelTailCircuitPrivateInputs as PrivateKernelTailCircuitPrivateInputsNoir, - PrivateKernelTailHints as PrivateKernelTailHintsNoir, PrivateKernelTailToPublicCircuitPrivateInputs as PrivateKernelTailToPublicCircuitPrivateInputsNoir, - PrivateKernelTailToPublicHints as PrivateKernelTailToPublicHintsNoir, PublicAccumulatedData as PublicAccumulatedDataNoir, PublicCallData as PublicCallDataNoir, PublicCallStackItem as PublicCallStackItemNoir, @@ -940,12 +937,12 @@ export function mapPrivateCircuitPublicInputsToNoir( privateCircuitPublicInputs.keyValidationRequestsAndGenerators, mapKeyValidationRequestAndGeneratorToNoir, ), - new_note_hashes: mapTuple(privateCircuitPublicInputs.newNoteHashes, mapNoteHashToNoir), - new_nullifiers: mapTuple(privateCircuitPublicInputs.newNullifiers, mapNullifierToNoir), + note_hashes: mapTuple(privateCircuitPublicInputs.noteHashes, mapNoteHashToNoir), + nullifiers: mapTuple(privateCircuitPublicInputs.nullifiers, mapNullifierToNoir), private_call_requests: mapTuple(privateCircuitPublicInputs.privateCallRequests, mapPrivateCallRequestToNoir), public_call_stack_hashes: mapTuple(privateCircuitPublicInputs.publicCallStackHashes, mapFieldToNoir), public_teardown_function_hash: mapFieldToNoir(privateCircuitPublicInputs.publicTeardownFunctionHash), - new_l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), + l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.l2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.endSideEffectCounter), note_encrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.noteEncryptedLogsHashes, mapNoteLogHashToNoir), @@ -1247,13 +1244,9 @@ export function mapPrivateAccumulatedDataFromNoir( privateAccumulatedData: PrivateAccumulatedDataNoir, ): PrivateAccumulatedData { return new PrivateAccumulatedData( - mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapScopedNoteHashFromNoir), - mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapScopedNullifierFromNoir), - mapTupleFromNoir( - privateAccumulatedData.new_l2_to_l1_msgs, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - mapScopedL2ToL1MessageFromNoir, - ), + mapTupleFromNoir(privateAccumulatedData.note_hashes, MAX_NOTE_HASHES_PER_TX, mapScopedNoteHashFromNoir), + mapTupleFromNoir(privateAccumulatedData.nullifiers, MAX_NULLIFIERS_PER_TX, mapScopedNullifierFromNoir), + mapTupleFromNoir(privateAccumulatedData.l2_to_l1_msgs, MAX_L2_TO_L1_MSGS_PER_TX, mapScopedL2ToL1MessageFromNoir), mapTupleFromNoir( privateAccumulatedData.note_encrypted_logs_hashes, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, @@ -1284,9 +1277,9 @@ export function mapPrivateAccumulatedDataFromNoir( export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): PrivateAccumulatedDataNoir { return { - new_note_hashes: mapTuple(data.newNoteHashes, mapScopedNoteHashToNoir), - new_nullifiers: mapTuple(data.newNullifiers, mapScopedNullifierToNoir), - new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapScopedL2ToL1MessageToNoir), + note_hashes: mapTuple(data.noteHashes, mapScopedNoteHashToNoir), + nullifiers: mapTuple(data.nullifiers, mapScopedNullifierToNoir), + l2_to_l1_msgs: mapTuple(data.l2ToL1Msgs, mapScopedL2ToL1MessageToNoir), note_encrypted_logs_hashes: mapTuple(data.noteEncryptedLogsHashes, mapNoteLogHashToNoir), encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapScopedEncryptedLogHashToNoir), unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapScopedLogHashToNoir), @@ -1299,9 +1292,9 @@ export function mapPublicAccumulatedDataFromNoir( publicAccumulatedData: PublicAccumulatedDataNoir, ): PublicAccumulatedData { return new PublicAccumulatedData( - mapTupleFromNoir(publicAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapNoteHashFromNoir), - mapTupleFromNoir(publicAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapNullifierFromNoir), - mapTupleFromNoir(publicAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(publicAccumulatedData.note_hashes, MAX_NOTE_HASHES_PER_TX, mapNoteHashFromNoir), + mapTupleFromNoir(publicAccumulatedData.nullifiers, MAX_NULLIFIERS_PER_TX, mapNullifierFromNoir), + mapTupleFromNoir(publicAccumulatedData.l2_to_l1_msgs, MAX_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), mapTupleFromNoir( publicAccumulatedData.note_encrypted_logs_hashes, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, @@ -1327,9 +1320,9 @@ export function mapPublicAccumulatedDataToNoir( publicAccumulatedData: PublicAccumulatedData, ): PublicAccumulatedDataNoir { return { - new_note_hashes: mapTuple(publicAccumulatedData.newNoteHashes, mapNoteHashToNoir), - new_nullifiers: mapTuple(publicAccumulatedData.newNullifiers, mapNullifierToNoir), - new_l2_to_l1_msgs: mapTuple(publicAccumulatedData.newL2ToL1Msgs, mapFieldToNoir), + note_hashes: mapTuple(publicAccumulatedData.noteHashes, mapNoteHashToNoir), + nullifiers: mapTuple(publicAccumulatedData.nullifiers, mapNullifierToNoir), + l2_to_l1_msgs: mapTuple(publicAccumulatedData.l2ToL1Msgs, mapFieldToNoir), note_encrypted_logs_hashes: mapTuple(publicAccumulatedData.noteEncryptedLogsHashes, mapLogHashToNoir), encrypted_logs_hashes: mapTuple(publicAccumulatedData.encryptedLogsHashes, mapLogHashToNoir), unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapLogHashToNoir), @@ -1392,9 +1385,9 @@ export function mapCombinedAccumulatedDataFromNoir( combinedAccumulatedData: CombinedAccumulatedDataNoir, ): CombinedAccumulatedData { return new CombinedAccumulatedData( - mapTupleFromNoir(combinedAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapFieldFromNoir), - mapTupleFromNoir(combinedAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapFieldFromNoir), - mapTupleFromNoir(combinedAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(combinedAccumulatedData.note_hashes, MAX_NOTE_HASHES_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(combinedAccumulatedData.nullifiers, MAX_NULLIFIERS_PER_TX, mapFieldFromNoir), + mapTupleFromNoir(combinedAccumulatedData.l2_to_l1_msgs, MAX_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), mapFieldFromNoir(combinedAccumulatedData.note_encrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.encrypted_logs_hash), mapFieldFromNoir(combinedAccumulatedData.unencrypted_logs_hash), @@ -1414,9 +1407,9 @@ export function mapCombinedAccumulatedDataToNoir( combinedAccumulatedData: CombinedAccumulatedData, ): CombinedAccumulatedDataNoir { return { - new_note_hashes: mapTuple(combinedAccumulatedData.newNoteHashes, mapFieldToNoir), - new_nullifiers: mapTuple(combinedAccumulatedData.newNullifiers, mapFieldToNoir), - new_l2_to_l1_msgs: mapTuple(combinedAccumulatedData.newL2ToL1Msgs, mapFieldToNoir), + note_hashes: mapTuple(combinedAccumulatedData.noteHashes, mapFieldToNoir), + nullifiers: mapTuple(combinedAccumulatedData.nullifiers, mapFieldToNoir), + l2_to_l1_msgs: mapTuple(combinedAccumulatedData.l2ToL1Msgs, mapFieldToNoir), note_encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.noteEncryptedLogsHash), encrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.encryptedLogsHash), unencrypted_logs_hash: mapFieldToNoir(combinedAccumulatedData.unencryptedLogsHash), @@ -1602,7 +1595,6 @@ export function mapPrivateKernelTailCircuitPublicInputsForPublicFromNoir( function mapPrivateKernelInitHintsToNoir(inputs: PrivateKernelInitHints): PrivateKernelInitHintsNoir { return { note_hash_nullifier_counters: mapTuple(inputs.noteHashNullifierCounters, mapNumberToNoir), - first_revertible_private_call_request_index: mapNumberToNoir(inputs.firstRevertiblePrivateCallRequestIndex), }; } @@ -1640,38 +1632,6 @@ function mapPrivateKernelResetOutputsToNoir(inputs: PrivateKernelResetOutputs): }; } -function mapPrivateKernelTailHintsToNoir(inputs: PrivateKernelTailHints): PrivateKernelTailHintsNoir { - return { - sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapScopedNoteHashToNoir), - sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), - sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapScopedNullifierToNoir), - sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), - sorted_note_encrypted_log_hashes: mapTuple(inputs.sortedNoteEncryptedLogHashes, mapNoteLogHashToNoir), - sorted_note_encrypted_log_hashes_indexes: mapTuple(inputs.sortedNoteEncryptedLogHashesIndexes, mapNumberToNoir), - sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapScopedEncryptedLogHashToNoir), - sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), - sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapScopedLogHashToNoir), - sorted_unencrypted_log_hashes_indexes: mapTuple(inputs.sortedUnencryptedLogHashesIndexes, mapNumberToNoir), - }; -} - -function mapPrivateKernelTailToPublicHintsToNoir(inputs: PrivateKernelTailHints): PrivateKernelTailToPublicHintsNoir { - return { - sorted_new_note_hashes: mapTuple(inputs.sortedNewNoteHashes, mapScopedNoteHashToNoir), - sorted_new_note_hashes_indexes: mapTuple(inputs.sortedNewNoteHashesIndexes, mapNumberToNoir), - sorted_new_nullifiers: mapTuple(inputs.sortedNewNullifiers, mapScopedNullifierToNoir), - sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), - sorted_note_encrypted_log_hashes: mapTuple(inputs.sortedNoteEncryptedLogHashes, mapNoteLogHashToNoir), - sorted_note_encrypted_log_hashes_indexes: mapTuple(inputs.sortedNoteEncryptedLogHashesIndexes, mapNumberToNoir), - sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapScopedEncryptedLogHashToNoir), - sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), - sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapScopedLogHashToNoir), - sorted_unencrypted_log_hashes_indexes: mapTuple(inputs.sortedUnencryptedLogHashesIndexes, mapNumberToNoir), - sorted_call_requests: mapTuple(inputs.sortedCallRequests, mapCallRequestToNoir), - sorted_call_requests_indexes: mapTuple(inputs.sortedCallRequestsIndexes, mapNumberToNoir), - }; -} - function mapPrivateKernelResetHintsToNoir< NH_RR_PENDING extends number, NH_RR_SETTLED extends number, @@ -1738,7 +1698,6 @@ export function mapPrivateKernelTailCircuitPrivateInputsToNoir( ): PrivateKernelTailCircuitPrivateInputsNoir { return { previous_kernel: mapPrivateKernelDataToNoir(inputs.previousKernel), - hints: mapPrivateKernelTailHintsToNoir(inputs.hints), }; } @@ -1747,7 +1706,6 @@ export function mapPrivateKernelTailToPublicCircuitPrivateInputsToNoir( ): PrivateKernelTailToPublicCircuitPrivateInputsNoir { return { previous_kernel: mapPrivateKernelDataToNoir(inputs.previousKernel), - hints: mapPrivateKernelTailToPublicHintsToNoir(inputs.hints), }; } @@ -1924,9 +1882,9 @@ export function mapPublicCircuitPublicInputsToNoir( ), contract_storage_reads: mapTuple(publicInputs.contractStorageReads, mapStorageReadToNoir), public_call_stack_hashes: mapTuple(publicInputs.publicCallStackHashes, mapFieldToNoir), - new_note_hashes: mapTuple(publicInputs.newNoteHashes, mapNoteHashToNoir), - new_nullifiers: mapTuple(publicInputs.newNullifiers, mapNullifierToNoir), - new_l2_to_l1_msgs: mapTuple(publicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), + note_hashes: mapTuple(publicInputs.noteHashes, mapNoteHashToNoir), + nullifiers: mapTuple(publicInputs.nullifiers, mapNullifierToNoir), + l2_to_l1_msgs: mapTuple(publicInputs.l2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(publicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(publicInputs.endSideEffectCounter), unencrypted_logs_hashes: mapTuple(publicInputs.unencryptedLogsHashes, mapLogHashToNoir), @@ -1965,7 +1923,7 @@ export function mapBaseOrMergeRollupPublicInputsToNoir( ): BaseOrMergeRollupPublicInputsNoir { return { rollup_type: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.rollupType)), - height_in_block_tree: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.rollupSubtreeHeight)), + num_txs: mapFieldToNoir(new Fr(baseOrMergeRollupPublicInputs.numTxs)), constants: mapConstantRollupDataToNoir(baseOrMergeRollupPublicInputs.constants), start: mapPartialStateReferenceToNoir(baseOrMergeRollupPublicInputs.start), end: mapPartialStateReferenceToNoir(baseOrMergeRollupPublicInputs.end), @@ -2012,7 +1970,7 @@ export function mapBaseOrMergeRollupPublicInputsFromNoir( ): BaseOrMergeRollupPublicInputs { return new BaseOrMergeRollupPublicInputs( mapNumberFromNoir(baseOrMergeRollupPublicInputs.rollup_type), - mapFieldFromNoir(baseOrMergeRollupPublicInputs.height_in_block_tree), + mapNumberFromNoir(baseOrMergeRollupPublicInputs.num_txs), mapConstantRollupDataFromNoir(baseOrMergeRollupPublicInputs.constants), mapPartialStateReferenceFromNoir(baseOrMergeRollupPublicInputs.start), mapPartialStateReferenceFromNoir(baseOrMergeRollupPublicInputs.end), @@ -2085,8 +2043,8 @@ export function mapRootRollupInputsToNoir(rootRollupInputs: RootRollupInputs): R return { previous_rollup_data: mapTuple(rootRollupInputs.previousRollupData, mapPreviousRollupDataToNoir), l1_to_l2_roots: mapRootRollupParityInputToNoir(rootRollupInputs.l1ToL2Roots), - new_l1_to_l2_messages: mapTuple(rootRollupInputs.newL1ToL2Messages, mapFieldToNoir), - new_l1_to_l2_message_tree_root_sibling_path: mapTuple( + l1_to_l2_messages: mapTuple(rootRollupInputs.newL1ToL2Messages, mapFieldToNoir), + l1_to_l2_message_subtree_sibling_path: mapTuple( rootRollupInputs.newL1ToL2MessageTreeRootSiblingPath, mapFieldToNoir, ), @@ -2183,7 +2141,7 @@ export function mapHeaderFromNoir(header: HeaderNoir): Header { */ export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment): ContentCommitmentNoir { return { - tx_tree_height: mapFieldToNoir(contentCommitment.txTreeHeight), + num_txs: mapFieldToNoir(contentCommitment.numTxs), txs_effects_hash: mapSha256HashToNoir(contentCommitment.txsEffectsHash), in_hash: mapSha256HashToNoir(contentCommitment.inHash), out_hash: mapSha256HashToNoir(contentCommitment.outHash), @@ -2196,7 +2154,7 @@ export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment) */ export function mapContentCommitmentFromNoir(contentCommitment: ContentCommitmentNoir): ContentCommitment { return new ContentCommitment( - mapFieldFromNoir(contentCommitment.tx_tree_height), + mapFieldFromNoir(contentCommitment.num_txs), mapSha256HashFromNoir(contentCommitment.txs_effects_hash), mapSha256HashFromNoir(contentCommitment.in_hash), mapSha256HashFromNoir(contentCommitment.out_hash), diff --git a/yarn-project/noir-protocol-circuits-types/tsconfig.json b/yarn-project/noir-protocol-circuits-types/tsconfig.json index 632b9eed7788..390735ab54c7 100644 --- a/yarn-project/noir-protocol-circuits-types/tsconfig.json +++ b/yarn-project/noir-protocol-circuits-types/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "outDir": "dest", "rootDir": "src", - "tsBuildInfoFile": ".tsbuildinfo" + "tsBuildInfoFile": ".tsbuildinfo", + "resolveJsonModule": true }, "references": [ { @@ -28,6 +29,5 @@ "path": "../merkle-tree" } ], - "include": ["src", "src/**/*.json"], - "exclude": ["src/contracts"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/protocol-contracts/.prettierignore b/yarn-project/protocol-contracts/.prettierignore index 2ade63ee6f97..eb6b23ceb906 100644 --- a/yarn-project/protocol-contracts/.prettierignore +++ b/yarn-project/protocol-contracts/.prettierignore @@ -1 +1 @@ -src/artifacts/*.json \ No newline at end of file +artifacts/*.json \ No newline at end of file diff --git a/yarn-project/protocol-contracts/package.json b/yarn-project/protocol-contracts/package.json index 48007fea086f..c7bff393480f 100644 --- a/yarn-project/protocol-contracts/package.json +++ b/yarn-project/protocol-contracts/package.json @@ -23,7 +23,7 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts", + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts", "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests" @@ -84,7 +84,8 @@ "files": [ "dest", "src", - "!*.test.*" + "!*.test.*", + "artifacts" ], "engines": { "node": ">=18" diff --git a/yarn-project/protocol-contracts/package.local.json b/yarn-project/protocol-contracts/package.local.json index c5987104cfcc..6e3a34a9358f 100644 --- a/yarn-project/protocol-contracts/package.local.json +++ b/yarn-project/protocol-contracts/package.local.json @@ -5,6 +5,12 @@ "generate:noir-contracts": "./scripts/copy-contracts.sh", "build:dev": "tsc -b --watch", "build:ts": "tsc -b", - "clean": "rm -rf ./dest .tsbuildinfo ./src/artifacts" - } -} + "clean": "rm -rf ./dest .tsbuildinfo ./artifacts" + }, + "files": [ + "dest", + "src", + "artifacts", + "!*.test.*" + ] +} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/scripts/copy-contracts.sh b/yarn-project/protocol-contracts/scripts/copy-contracts.sh index 239445f9bbcf..5001bf8c2548 100755 --- a/yarn-project/protocol-contracts/scripts/copy-contracts.sh +++ b/yarn-project/protocol-contracts/scripts/copy-contracts.sh @@ -1,6 +1,6 @@ #! /bin/bash set -euo pipefail -mkdir -p ./src/artifacts +mkdir -p ./artifacts contracts=( contract_class_registerer_contract-ContractClassRegisterer @@ -11,6 +11,15 @@ contracts=( multi_call_entrypoint_contract-MultiCallEntrypoint ) + +decl=$(cat < ./artifacts/${contract#*-}.d.json.ts done diff --git a/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json b/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json new file mode 100644 index 000000000000..4334baf5a574 --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"AuthRegistry","functions":[{"name":"_set_authorized","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(internal)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/+2ZW0/jRhTHJ4Fw2wKJcUhMLiQQEyD3bGJKU/q4Up/71peql223Ui9SL6raj9hP1TlnZvyPcerVWVELVWvJsX38/825zDjxgZ7aUmpvR+mtpeymr/bUER+KtH+i3Jk+ob1wpArOZHQl2llXMvu6jk0h3aTRi3ym7WortAOrbT7TkSij26YoQjuc2r3QH+WlcoFW6GPvmD73S+SeB97X+0GP0lGR3g9Dl84LxUbaDunDaCiAD3q401OFV/p4ZMQvrPg4LBqjOgZ2bDSH5pTR32F2aJlREpSBloGWLfoTzA6tMEqCCtAK0IpFv4bZoR6jJPCAekA9i/4Gs0NPGCXBCdAToCcW/R5mh/qMksAH6gP1LfozzA6tMkqCKtAq0Ko5ppFyNqK9dWB26CmjJDgFegr01KJfwOzQGqMkqAGtAa1Z9FeYHVpnlAR1oHWgdYu+htmhAaMkCIAGQIN0eYJ4HoXIaTaiA/wSZoeeMUqCM6BnQM/S3s7iJ0OIeNmIDvANzA5tMEqCBtAG0EbaWyNekxmI9vYLzA5tMkqCJtAm0GbaWzN+eDIQ7e0vmB3aYpQELaAtoK20t1a8oDIQ7e0bmB3aZpQEbaBtoO20t3b8vAmRihwJ5Eg5l1z8Jw9Mz88PMDv0nFESnAM9B3pu0T9hdmiHURJ0gHaAdtKBduJyZCDa21cwO7TLKAm6QLtAu2lv3XjZCpGqHKnIkUCOtHNB3qFirVyKfCJHynLEy6VijVxyebZr7DwboY9CE2/ndwwqvJK7d3ASqtC9p+sRtxW2C3Z1kXR1aeCuOXV36PX/Eq/24Q6fhlZ0pb+TiO0XeIg+mWjnMANz5XIkph86WQ/ezI2iMao+Iuqr2BkhYYe6oLWwHgUcFWy2d0ZDIx7EtdlHbQ6Sncse0tNVLankxpXixowLdmGG2bfDdDdV0k7agQ3uYBNSykYSIblkDlfba5p985vwOF7aLk28VJVL09S5IpV67E6FJT6WbHl7xsnHer+OK3aFil0nK9ZHeNd6wM/08caIr6z4lpO8oTNgt0ZzbU7pmEY8OeLLkYYcCbIRXYbvYHbogFESDIAOgA7S3gbxF6cQqcqRmhxpyxFfjnhPnr6enynMDh0ySoIh0CHQYdrbMPYmRMpyxJcjXi65BHKknQvylorpVfAHzA4dMUqCEdAR0FHa2yh+SoVIKxvRAY5hduiYURKMgY6BjtPexvHUCpEbOeLJEV+ONORIIEdu5Ug9l3mpyZF2LvPi5ZLLWyqmn5sfYXbohFESTIBOgE7S3ibx39OESE2OeHKk+lwDC+RI4zlUTC+cb2F26JRREkyBToFO096mcU5CxJcjYzlSzUZ0GWYwO3TGKAlmQGdAZ2lvs/inKgOhbqT4KfqOBwYVmg3XXcy4V3EdyCzZxc7Z1Tzp6qWBZ+bU3aHG5iWalqXpYpdWFNku9s50sdRTU38ZcZivzJXLkZi70MkW8GZuFI3RtaBW55wRsuzoQVdrYT0KmLtYyvYBjd88rk0JtZkne7Jeb/3OltGa6nBU3Y1TMreuNyI72Qjim8WN6dwOMjNt59y2nd2S63J5NneQ/mLTtC+Sqa3N3AIriUTL+JVlCfnSaBa26BsRT474cqQhRwI5citH6nKkKkdqcqSdy7x4uaQ/yMVL+X9UsSCXBZPPGhvm8lS25Mgol6l8/538/jv5v579Wi4VG8uR41xy8Z7rgvFyecQaz7Vik1xy8XNZye+Q/vTJf5Kobdh6g77hgUGVbAmUVZt2cWFGXG8XI3YVJV09bs7QmNyh6bg37eK9FX1k28WVaRdXZKKdw3xtrlyOxKxCJ/sQ3syNojGqFSJaqdgZIfcdff35WliPAuZ2kbJ9MP/z21WJ/ytGcZl2UaYo2V7t9NbvbNlBonh2uhtnJ7JRRLiDXi76115ueV2wDug4vySk/jft/wAulotePisAAA==","debug_symbols":"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"},{"name":"is_reject_all","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/83Z6W7bRhAH8JUsKq5ikaIuU6dFS7R123HkokCafMwL9AGK3mjRA+iBoq/Yp+rO7PGXzILGFAURArRWw/nt7C6lmOss1JlS54HSx0TZo6YjKlR1/VKl851yLd2gsxKqigtldJGUaem4OsssUDVu6QoquNY/LjJlejivPdKFGvW1UBVCLwLqk2qrF/qsL2hg6qDPRuYGpuuc2WaDfpgcYh8tcEV3+F6/vjTJ5zb5IquaoLoAuzA5DdNk+gfCjjaZUkITtAnatPRnhB0NmVJCCBqChpZ+hbCjEVNKiEAj0MjS3xF2tMWUElqgLdCWpd8j7GjMlBJi0Bg0tvQXhB1tM6WENmgbtG1e86RZTHS1GcKOdphSQge0A9rJV+v4uRUQXe03hB3tMqWELmgXtGvp5wg72mNKCT3QHmjP0l8RdrTPlBL6oH3QvqXfIOzoJVNKuAS9BL209AeEHU2YUkICmoAm+ZVNfDUhCeUkkpNuMdHL8AXCjg6YUsIAdAA6sPRHhB0dMqWEIegQdJgf6H8mbTkJ5SSRk2Ypc4lLGdgz90V/Cv5C2NERU0oYgY5AR/lqI78MBURX+xJhR8dMKWEMOgYd56uN/bdWSNpyEspJIieDUsgzK6bvz9cIOzphSgkT0AnoJF9t4hdbSDpyEslJUkqVlpyEpcxlUAoZFpPUPI375+VHhgoPye6pmB/uM/fkrHusKRxTLjU9LXVl8MQ03RV6IL/Cw3Za52Zqk67tw/y8wl3MKUQnD/OleefmSLF55tJmqGYuVE1QzTGiufLFiKQzCh8N68mAP67Y2T6aHJ5jdrTJcZOYnu4l6pjedKECdXrwXeDNEVeyN6Rmu2nwuCfmnwHXob0NUzuc6b+RoJicDMlN5upN7SinZu7M0/HSMTPjpeWcBdxs2LfBgsupa7P7CuwNS02RT+kz41dsjhXLTldsgeFlusPP9OuNSZ7b5Fue5A21wG5NTmaa9JonkZzEctKTk6SY6GX4DmFHl0wpYQm6BF3mqy39rxwhactJR04GchLLSfS/T1/fn3uEHV0xpYQV6Ap0la+28tWEpCknsZxEpcwlkZNBKeSZFdOfgj8RdnTNlBLWoGvQdb7a2n9LhWRcTPQA9wg7umFKCRvQDegmX23jb62Q3MhJJCexnPTkJJGTWznpl3JfOnIyKOW+RKXM5ZkV09+bnxB2dMuUEragW9BtvtrW/+1XSDpyEslJ+0MdWCInvQ9hxfQH51uEHd0xpYQd6A50l6+283MSklhONnLSLiZ6GV4h7OieKSXsQfeg+3y1vf9VVUBoR1d9g33HW4YKmw23u9j7zUdmejzexd5xqbvTUvcG703TXaGNzT02LQ9mF/tgk17bXezB7GJpb/maTh7mJ+admyOZQ+bSXqGauVA1QXXAiA7KFyPyMNOd7o6G9WTAvIul2b5FF3d+bQKszd3pniy9rdp9Hm/sclvL1F5Nj7qt+00nryLP970fhD3OTFlO22f2dqpG6PeVwTs7Mj7x/4UmZPKomZomD4RJw55HhEP+zxYpt3hYc2omf9P5D3fVp4nDHAAA","debug_symbols":"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"},{"name":"set_authorized_private","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"7P3fjizLcuQHv8u5JgYVER7/5lUEQRiJM8IAA44gUlcE3111yFXZvWZXdkbv7dnh7ma6+aQPfXql/Xyz0sy72/xf//aP//X//P/+7//jv//Tf/uf//y3//y//evf/sf//L/+y7/89//5T8//r3/9W2r//v/fP/8//+Wf/v7/+c//8l/+33/5239+/MPf/us//ePz//ff/uFv/+2//4//+rf/XFL9t3/4w9flXsuvL8291+OrU2pvvlpy6r++WvKQi6+eNadfXz3r+Pjeucx/+9//4W+pe33w8YMPXh7yevDS/uqDz7/y4FJKOx6l5+OrZ/r7986PG793eve9S8qvb19S7xf/Qm8vjuMT9JrefGmp7fUwpaX+9RdfIM/5rz/6GMe/IBdPk/LxH1eSJBdf3HoZr69uvc7P2N9gSeP11SUn+cn/i8sFlaLm//lnMU1xzIPiyO1//Qiopp+9t6+evVl+9lH68exT0tf/9abRW319+ZjjD1I7jtSBI3XCSC0PHKkJR6ppF6Yr1bRV0pUqOFJN2x9dqThuqeC4pYLjlgqOWxIctyQ4bklw3JLguCURHKk4bklw3JLguCXBcUuC45YqjluqOG6p4riliuOWquBIxXFLFcctVRy3VHHcUsVxSw3HLTUct9Rw3FLDcUtNcKTiuKWG45YajltqOG6p4biljuOWOo5b6jhuqeO4pS44UnHcUsdxSx3HLXUct9Rx3NLAcUsDxy0NHLc0cNzSEBypOG5p4LilgeOWBo5bGjhuaeK4pYnjliaOW5o4bmkKjlQctzRx3NLEcUsTxy1NHLeUHjh2KT1w/FJ64Bim9MBxTOkhQFpxPFN64Jim9MBxTemBY5vSA8g3JSDflIB8UwLyTQnINyUB0grkmxKQb0pAvikB+aYE5JsykG/KQL7JdnW4slYg32S7hltZK5BvAqr5TkA93wmo6DsBNX0noKrvBNT1nYDKvhNQ23cCqvtOQH3fCajwOwE1fiegyu8E1PmdgEq/E1DrdwKq/U5Avd8JqPg7ATV/J6Dq7wTU/Z2Ayr8TUPt3Aqr/TkD93wmoADwBNYAnoArwBNQBnoBKwBNQC3gCqgFPQD3gCagIPAE1gSegKvAE1AWegMrAE1AbeAKqA09AfeAJqBA8ATWCJ6BK8ATUCZ6ASsETUCt4AqoFT0C94AmoGDwBNYMnoGrwBNQNnoDKwRNQO3gCqgdPQP3gCaggPAE1hCegivAE1BGegErCE1BLeAKqCU9APeEJqCg8ATWFJ6Cq8ATUFZ5ClYXPeXz5fLzRGsg3zcdsh9bndukPWgP5ppk/zbVk+YPWQL7pQmuO1Bc+55RfX/7UVdoftMbxTU999UNrepQ/aI3jm576cv7Q2v6oNY5ves6tz0Nr+fQoL60SSGs5vMRTV55/0BrHN+X0kNc3z+mp4A9a4/imp756/Df8/IfqH7TG8U059Y/PptRLufjyMl7fPEvNxxfnv3+A/+GrZ82HyDo+MOYy/4NjHE+2l2Mcv7eV484O9Ty+/uIur4fo9QPK6G++tKbXI1Rpn7/03zUmAI05hsbjv+2W8tdfWp759qUtp4/vm1L7DyKFRP4XIoJHZHwiIr8RefPV/XGQ6I/+R36V/L7iJ8+316+vfj7v1VdfvpkaaX9Juzxe2wQp7S/T7jFo13bQLn94R/6w9xZJh8b2m8Z/f5ofdrD9+No0Sv76i0tPL45l5Pb1F1/9p/XTdfOjjENov/hPq4m81hlN2m+b1jfOe+T6+tbP//fxh0XPT5fNb1R6YjePD7tSHo8LpSmVx/H8qcinZ3r8xz9SVP6RY+n63HHU/vkfeSNciuSPdNX+sN8662K/9ZnqTMcztTK/nl2R8lLw3EV+/J9jKu8+MPvxo4bx+PjGzxfRf6itUGoblNoOpXZAqZ1Ias962YOqTVBqM5TaYl5t7S8bWVqaV2r7ofZTHMvt7YM8Rju24J9+sPhcUX+fo5CjCkf7/s8HR/vO0gdH+57VB0f7btgHR/s+2wVHse/gfXC0nw18cLSfOnxwRM4zqR3PkUb+jeO/sxGyOWWDnDuu2CBniSs2yPngig2y579ig+zjL9hUZG9+xQbZb1+xQfbQT+f8eo786Re6DzbIvviKjZDNKRtkX3zFBtkXX7FB9sVXbJB98RUbZF98waYh++IrNsi++IoNtC9ux68V5zH+yAbaF1+wEbI5ZQPtiy/YQPviCzbQvviCDbQvvmAD7Yu/ZtOhffEFG2hffMFmhy9ucrTeyGiPr9k8Xxft9Zd8TzGP/PnL/11CsS9h5E8S/vj3bV0cSDj+RPL5QfxGQrUvYX50uPRHHn+Q0MxL6On4C+7n/+nm9AcJ3b6EXI4v7+WPfXx92Jcw08d/SHP+oSqyT/MSxqMc/yGN9MdGubHDT4yjSSXLzH9opRzJ4DPteH/O/uEt5shfj3rMl7WYn8r0UnvnLFIuR2dxnp/dgrz56qsKglHI5pSNWGczixwC5gWb8TgaQJ6WVD6xyX+GTbXOps+XnUuPR/0Nzt8FyH96+wJo5fW/ap+qWVPO/5Fu/9NJVcrzo/pF69OrJpWP/9n8U/+z9w0h1/+z9Of+Z/nP/c/Kn/ufyZ/7n739L+8546PE5SH5t//hm//yZjtKdj7Xvr9vCmxH5Uv7VA/z9yz3eqRm75G6vUca9h5p3vtIv/6Z93+Gr//PpJ/5Z/LP/DPlZ/4Z+Zl/pv7MP9N+5p/pP/PPjJ/5ZxQ+BfJDPtq/5+PigymlftynyI9PPnWk10PJw+JDpZ9+qD7mYVp//wj/zs719fjZ9+MX348vvh+/+n785vvxu+/HH74ff7p+/Prw/fi+37rV91u3+n7rVt9v3er7rVt9v3Wr77du9f3Wrb7fus33W7f5fus232/d5vut23y/dZvvt24z/blfjx71Ku8f3/Tn/uXjd9OfPPWo76+tv3180588149v+pPn+vFNf/JcP75pv3/9+Kb9/vXjm/7cv/xpdDf9uX/5+MO0379+fNN+//rxTb91rx/f9Fv3+vFNv3WvH9/0W/f68U2/da8f3/Rb9/rxfb91h++37vT91p0//9b9xl/mpY+7sSl/unv66VdiZvYuoHgXIN4FVO8CmncB3buAYUfA65GmtUcqD4135XMar0dKn66Fnv1OZX49U0ry+x8kvR4qWXyo/NMPpfkDgPIovh9ffD9+9f34zffjd9+PP3w//nT9+Onh+/GT78f3/dZNvt+6yfdbN/l+6ybfb93k+62bfL91k++3bvb91s2+37rZ91s3+37rZt9v3ez7rZt9v3Wz77du9v3Wzb7fusX3W7eY/ty/+i3hUkx/7l8/vulPnqvflCzF9CfP9eOb/uS5fHwx/clz/fim/f7145v2+9ePb/pz/+oXfoqY/ty/fnzTfv/68U37/evHN/3WvX5802/d68c3/da9fPxq+q17/fim37rXj2/6rXv9+L7fuiotIBsf3/dbt/78W/c7v174GB+/DvaptPnTr4PV7l3A8C5gOhfQHt4FJO8CsncBxbaAI7k/BaTfBLz5zvP4zo9Pzf1jHGIFSWxFEmvbDfz2y+Hv/+/QthtYEGDbDSwIsO0GrgV0225gQYBtN7AgwLYbWBBg2w1c/42NSlPPVgG239oLAgy9iV+PZOjd+noklbflPE7Z5ZovHunjgGKq8vaRprlHUmm/+dYjqf42iUr7zcbHz74fv/h+fPH9+NX34zffj999P/7w/fjT9eNP32/d6futO32/dafvt65K783Gx/f91p2+37rT91t3+n7rTtdvXXm4fuvKw/VbVx6u37rycP3WlYfrt648XL915eH6rSsP129debh+68rD91s3+X7rJt9v3eT7rZt8v3V1unn2Pb7vt27y/dZNvt+6yfdbN/l+62bfb93s+62bfb91s++3rk43z77H9/3Wzb7futn3Wzf7futm32/d4vutW3y/dYvvt27x/dbVaUba9/i+37rF91u3+H7rFt9v3eL7rSu+37ri+60rvt+64vutq9NLte/xfb91xfdbV3y/dcX3W1d8v3Wr77du9f3Wrb7futX3W1enl2rf4/t+61bfb93q+61bfb91q++3bvP91m2+37rN91u3+X7r6nRL7Xt832/d5vut23y/dZvvt27z/dbtvt+63fdbt/t+63bfb12dvqd9j+/7rdt9v3W777du9/3W7b7fur67qcR3N5X47qYS391U4rubSnx3U4nvbirx3U0lvrupxHc3lfjuphLf3VTiu5tKfHdTie9uKvHdTSW+u6nEdzeV+O6mEt/dVNV3N1X13U1VfXdTVd/dVPXh+q1bfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1Xz3U3VfHdTNd/dVM13N1V7uH7rNt/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfXdTdd/dVN13N1X33U3VH67fut13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTDd/dVMN3N9Xw3U01fHdTjYfrt+7w3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVNN3N9X03U01fXdTTd/dVPPh+q07fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9XzOV2/dv/+nM6f3/WL9/mcrt+8z+d0/ep9Pqfrd+/zOV2/fJ/P6frt+3xO16/f53M6f//6rql6Pr/z96/voqrn8zt///quqno+v/P3r++yqufzO3//+q6rej6/8/ev78Kq5/M7f//6rqx6Pr/z96/v0qrn8zt///qurXo+v/P3r+/iqufzO3//+q6uej6/8/ev7/Kq5/M7f//6rq96Pr/z96/vAqvn8zt///qusHo+v/P3r+8Sq+fDOX//+q6xej6c8/ev7yKr58M5f//6rrJ6Ppzz96/vMqvnwzl///qus3o+v/P3r+9Cq+fzO3//+q60ej6/8/ev71Kr5/M7f//6rrV6Pr/z96/vYqvn8zt///qutno+v/P3r+9yq+fzO3//+q63ej6/8/ev74Kr5/M7f//6rrh6Pr/z96/vkqvn8zt///quuXo+v/P3r++iq+fzO3//+q66ej6/8/ev77Kr5/M7f//6rrt6Pr/z96/vwqvn8zt///quvHo+v/P3r+/Sq+fzO3//+q69ej6/8/ev7+Kr5/M7f//6rr56Pr/z96/v8qvn8zt///quv3o+v+/3b3Lef5Wc918l5/1XyXn/1fPpnD+/7/dvct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3X2Xn/VfZef9Vdt5/lZ33X+WH7/dvdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfFef9Vcd5/VZz3XxXn/Vfl4fv9W5z3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef+VOO+/Euf9V+K8/0qc91/Jw/f7V5z3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X1Xn/VXXef1Wd919V5/1X9eH7/Vud919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXPef9Wc91815/1XzXn/VXv4fv825/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wd91915/1X3Xn/VXfef9Ufvt+/3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd918N5/1Xw3n/1XDefzWc91+Nh+/373DefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1X03n/1XTefzWd919N5/1X8+H7/Tud919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03f/VX747r96Pr/r9+/z+V2/f5/P7/r9+3x+1+/f5/O7fv8+n9/1+/f5/K7fv8/nd/3+fT6/8/ev7/6r5/M7f//67r96Pr/z96/v/qvn8zt///ruv3o+v/P3r+/+q+fzO3//+u6/ej6/8/ev7/6r5/M7f//67r96Pr/z96/v/qvn8zt///ruv3o+v/P3r+/+q+e/4Pz967v/6vkvOH//+u6/ev4Lzt+/vvuvnv+C8/ev7/6r57/g/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v+/2bnPdfJef9V8l5/1Vy3n/1fDrnz+/7/Zuc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1X2Xn/VXbef5Wd919l5/1X+eH7/Zud919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Vt9y9Vyb++tsrJ85v+/F94ftOfP7WO1/O3/v75TX/+LDy/6c+fhec3/fmz8Pym/f/189vu/1l4ftOf/y21X1/bSn7//KY//xee37T/X3h+cf78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eSnjrcfaaqG8lPHGY221UF7KeNuxtlooL2W86VhbLZSXqlBeyniHtbJa4x3W2mqhvFSD8lLG+8m11QqUWigvZbyfXFstlJcy3k+urRbKSxnvJ9dWC+WljPeTa6uF8lLG+8m11UJ5KeNd5tpqobwUVO95huo9z1C95xmq9zxD9Z5nqN7zDNV7nqF6zzNU73mG6j3PUL3nGar3PEP1nmeo3vMM1XueoXrPM1TveYbqPc9QvecZqvc8Q/WeZ6je8wLVe16ges8LVO95geo9Lw+BUovkpQpU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN5zgeo9F6jec4HqPReo3nN5CJRaJC8lUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsukdqiZ8+vL+7lvdpAb6BrtZEahecYry+e/b3aQJ9SC2oDfUotqBUotYES34LaQIlvQW2k9+212kjv22u1gRLftdpIjcILaqG8VKRG4QW1br3UoUDcK7DteXqeLwUj96vU/Zjt9dQpfXrqVj/02nY9+npt+x59vbadj75e295HXa/xDmB9vbb9j75e2w5IX69tD6SvV8D0gvkr433A+nrB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"},{"name":"is_consumable","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/+2aWW/iVhTHLwSYmVKMYwiENRBw2CEsyUSaZh771Lc+VOpL1V2VukhdVPUr9lP1nnOXP2Dk0R1Nr6LRWHK4Pv7/7lmuMT5yhuJMiOcFIbeO0FteWkQgpPF5lvbXwozkgPZMIDLGFNNJotRI2sVZrAGR49EZzcmjnPxTuJZ/SrFQcz3P39GJPM06FJmMOqCPnJ742ZBCFDu5F2MT4gvBRtqK9EdpCPtoiDNywk/l58dK/EKLS3FWGUUJWElpimrI6F8wGzRglAQB0ABooNFfYTZomVESlIGWgZY1+i3MBg0ZJUEINAQaavRPmA16zigJzoGeAz3X6E8wGzRilAQR0AhopNHfYDZohVESVIBWgFbUZxIJ0hHprQezQauMkqAKtAq0mvRWtbmlINLbHzAb9IJRElwAvQB6odGvYDZojVES1IDWgNaSgdbs0jsikTsSuCNVd6SUjsjK/QKzQeuMkqAOtA60rtGvYTboJaMkuAR6CfRSo9/AbNAGoyRoAG0AbWj0Z5gN2mSUBE2gTaBNjX4Ps0FbjJKgBbQFtJWsbMt+AxyRsjtSd0cCL7lEXgJrpCNySf+B2aBtRknQBtoG2k56a9syOCKX7kjTS2Bld6TujjS8IG+omLwKvoPZoB1GSdAB2gHaSXrr2GI7IlV3JHRH6l68nLsjZS+5NLwgrXSkr57H7XPyHYMCD8fmaZgf72PzxCxnzAlsXXbVPXR1peCOGpoz9CB+hYfsfoGHfS261g/xgwxPMSAT7RxmUR2ZHMk2iI2sB2/qRFYZxQARDYR1Rki/R+a9sI4Cvs/obO+UhnO0tcmhNt3DHuIZ0usOqR062GiWDrdH7EkvSE5PU+S4O+o2YCbUy9DV4XRPIfl05CAkk8zVq9yeJqdW5jhe2noqXipnL8/Doj7MD9mduFZdV14vWF85+YSuGVuxASoWH1ZsiPBiOeHn8vNGiQdaPOIkb2gEbKQ0sRrSZxIJ3ZEoHZEB/g6zQceMkmAMdAx0nPQ2tneOFER6+xFmg04YJcEE6AToJOltYn96HJGKO1J1RxruSOSOhO88fbk+tzAbdMooCaZAp0CnSW9T680RCdyRyB0JveRSd0caXpA3VExeBX/DbNAZoySYAZ0BnSW9zey31BFppyMywCXMBp0zSoI50DnQedLb3C6tI3LjjoTuSOSOjNyRujsydkeaXtal6o40vKxL6CWXt6hYzR0pecklfKoXTOjlKzZ6ChWTN9ofYDboglESLIAugC6S3hY2J0ckckdq7kglHZFlWMNs0CWjJFgCXQJdJr0t7U9UCkIdXfYV+o5HBgWaDdNdLG3zEasZ97vYFbtaHbq6VfBSDc0Zamxu0bRsVBe70aKt7mJ3qoul3nJLO4f5oI5MjsTsYiNbw5s6kVVGsUNEO2GdEbLpyUkXe2EdBcxdLGX7iMZvZWuTR21Whz1Zf7h/5kxpVXU4quLJJVlp1yeRQjqC+Ja2MV3pSZaq7VzptrOg2s2CbjeLSH99atnXh6ntrdwaVxKJNvZRZQP5RmnWuugnkdAdidyRkTtSd0fG7kjTHam4I1V3pOFlXUIv6U+8eAneo4rVvVwwfq6xqZdvZdsdmXlZyg/35A/35P979ateKlZzR0pecgmf6gUTevmKjZ5qxeZecom8XMlvkf7inf8kUR929iX6hkcGxWFLILRatYtrNeN+u7hlV9tDV8fNGRqTHZqOe9Uu3mvRS90uPqh2kRrEl7RzmF+oI5MjMQ+xkd3BmzqRVUbxgIgehHVGyH1PHn+2F9ZRwNwurlW7ePwqkFsu9SqQ970Kn3plzNWDZjsy7XVGHLyr1L3iVp/d7k1bsG8xsXD0OmzNYerNvNDucvtn4l8FtmMsvtaR8Y5/QVWmwL7Q3KohB8LISu97CJtic3LLIwKyAxpe/kv7f2Q7N08WKwAA","debug_symbols":"1d3RapVXEMXxd8m1lD2zZ/bM9lVKKWlrS0BiqbFQxHfvseaYigdyVonN+V8V9TtmcF0sXfn49f3VL69+evfbjze3v755e/Xy+/dXr9/8fH138+b28KP3V+M7m//87Nvfr28//sTbu+s/7q5ejhdXr25/Ofz3w4urX29ev7p6OS0//PDi4wdC/UCqH1jqB0r9QKsf2OIHfKgfMPUDrn5ATdrVpF1N2tWkXU3a1aRdTXqqSU816akmPdWkp5r0VJOeatJTTXqqSU816VCTDjXpUJMONelQkw416VCTDjXpUJMONelUk0416VSTTjXpVJNONelUk0416VSTTjXppSa91KSXmvRSk15q0ktNeqlJLzXppSa91KRLTbrUpEtNutSkS0261KRLTbrUpEtNutSkW0261aRbTbrVpFtNutWkW0261aRbTbrVpLea9FaT3mrSW016q0lvNemtJr3VpLea9FaTtjHkT5j8CZc/Ia8nQ55PhryfDHlAGfKCMuQJZciZm5y5yZmbnLm+mOmTmb6Z6aOZvprps5m8m5k8nJm8nJk8nZm8nZk8npm8npk8n5m8n5k8oJm8oJk8oZm8oZk8opm8opk8o5m8o5k8pJm8pJk8pZm8pZk8ppm8ppk8p1no3w2RM5cXNZMnNZM3NZNHNZNXNZNnNZN3NZOHNZOXNZOnNZO3NZPHNZPXNZPnNZP3NZMHNpMXNpMnNpM3NpNHNlv69z3lzOWdzeShzeSlzeSpzeStzeSxzeS1zeS5zeS9zUr/ZrecuTy5mby5mTy6mby6mTy7mby7mTy8mby8mTy9WetvOMiZy+ubyfObyfubyQOcyQucyROcyRucySOcySucbf21Fv29FvnFFnmHc3mHc3mHc3mHc3mHc3mHc3mHc3mHc3mHc9NfZpIzl3c4l3c4l3c4l3c4l3c4l3c4l3c4199f019g+w9vsMmZ6++w6S+x6W+x6a+x6e+x6S+yyTucyzucyzucT/21RTlzeYdzeYdzeYdzeYdzeYdzeYdzeYdzeYdzeYfz0N9VlTOXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdzhf+lvpcubyDufyDufyDuend7iosPsPRbV/8bkXXz29Z98/vLs/P3v41sqJZw8D//2zh3+Kfn728Je2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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fGs0oWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+Flf31O+/x2dxutMNpuZBQZlYy2Mppl1GS0yKjLSIrYShGzFDFLEbMUMUsRsxQxSxGzFDFLEbMUMUsRTYpoUkSTIpoU0aSIJkU0KaJJEU2KaFLEIkUsUsQiRSxSxCJFLFLEIkUsUsQiRSxSRJciuhTRpYguRXQpoksRXYroUkSXIroUMaSIIUUMKWJIEUOKGFLEkCKGFDGkiCFFrFLEKkWsUsQqRaxSxCpFrFLEKkWsUsQqRWSzoVVoVbTa0mqmVaPVQqtOq0EraiPURqiNUBuhNkJthNoItRFqI9RGqI2iNoraKGqjqI2iNoraKGqjqA0CzZBohkgzZJoh1AypZog1Q64Zgs2QbIZoM2SbIdwM6WaIN0O+GQLOkHCGiDNknCHkDClniDlDzhmCzpB0hqgzZJ0h7AxpZ4g7Q94ZAs+QeIbIM2SeIfQMqWeIPUPuGYLPkHyG6DNknyH8DOlniD9D/hkC0JCAhgg0ZKAhBA0paIhBQw4agtCQhIYoNGShIQwNaWiIQ0MeGgLRkIiGSDRkoiEUDaloiEVDLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5adtGTXLTIRYtctMhFi1y0yEWLXLT+20Wvp5+798Pu4WV/u9t7+/hxfPx31fd6PP96+/vl+u9v"},{"name":"unconstrained_is_consumable","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"},{"name":"set_reject_all","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"reject","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/83X2Y7TMBQGYKcb7XSmM9MmTZtuaZqllArBBUgIhiskHoAnQGK5YZFYxDvyVPgc++RvCWTkm2oipXGPz+djO1ONnKqmUt2W0tdC2Ut/66qB6uhHg+6XSlq6Qbc3UJ6ETB4N0uS8prkP8ziUUSeN3uCWjisTo8RWZqlqJ/pj8ETJpK7po5MqGbKXySzvKQ7S1aMPk0PjdlP0pKqtji/KOONZqzNzN81oPEw/a9iOPgbsm5yeadKzSjr15GhKspjz562DHBrvvDpfui7MfC/obptS9qveGiqnLtv8pK5L2kFT5IW+h+WOXWHHhsc7do3pDfWAb/RzZJKvbLLPixxRC8w3OUPTZPoDYaEBU0oIQAPQwNKvCAsdM6WEMegYdGzpN4SFhkwpIQQNQUNL3yIsdMKUEiagE9CJpR8RFjplSglT0Cno1NL3CAuNmFJCBBqBRpbGCAudMaWEGegMdGbpd4SFzplSwhx0Djq39BPCQhdMKWEBugBdmGeVBO7EdydRPdFreoSw0CVTSliCLkGX1WrLsloN0dW+ICx0xZQSVqAr0FW12qrcQUfiu5PInYTuZH4ScsuO6ffzC2GhMVNKiEFj0LhaLS5/xTVEV3uHsNA1U0pYg65B15Y+RFhowpQSEtAENKlONClfsSMZuRPfnQTuZOxOQncycSfTk7yXmTuZn+S9+CdZyy07pn83nxEWumFKCRvQDejG0p8IC02ZUkIKmoKm1Ymm5docie9Oors6sdCdjO/Cjum/gg8IC82YUkIGmoFm1WpZuSZHEriTxJ1E9URvw2OEheZMKSEHzUHzarW8/JdVQ6jbe43zzA1DhUOMnFoom+sbm6qWwlVwqeK41Nbg3DSlhw5MWxyGdh1u7mzSA716snuPh9hTiG6e5ivzTdZIZp9J2n1UMx0NE1R7zGivymJEdrEOPzuY1l8TfurZ1d6Yw2FblQdljxcty29jm4rjY98gPexp2kGK8u10/vl2CjuLAj04Yxb/PWPmW88W4PPxhsjkN91/AGbVK/CEEAAA","debug_symbols":"1dzLSlthGIXhe8lYyr/W9x+9lVJK6qEEJIrGQhHvvbHNTioG4kDa/c6MfkkWGeTFyfO0uLz69vj962p9ffuwOP/8tLi5vVhuVrfr7aOnRfqk/Pu3D3fL9csvHjbL+83iXM75bHG1vnz5sebns8X16uZqcR4qz2dvrot67K6LhvbXI44c15zq7rhmvzr+cvYyqBwfZB8GlRODRvTd8eh9f6vsI7cqaXrhcbi1j20fxZpeuPTDCsfYja/k8Y08vpPHD/B4J/J4k8cHeXwmjydHyuRImRwpkyNlcqSCHKkQeTy5sPEBhVWq039HktOJ+dP4dOJVW5mWt/r3R5J3wwt1eKUOb9ThnTp8QIfnRB0u6nBTh1MDlDN1OLWcmVrOTC1nppYzU8tZqOUs1HIWajkLtZyFWs5CLWehlrNQy1mo5SzUclZqOSu1nJVazkotZ6WWs1LLWanlrNRyVmo5K7WcjVrORi1no5azUcvZqOVs1HI2ajkbtZyNWs5GLWenlrNTy9mp5ezUcnZqOTu1nJ1azk4tZ6eWs1PLOajlHNRyDmo5B7Wcg1rOQS3noJZzUMs5qOUc1HIqUdOpRG2nEjWeStR6KlHzqUTt5/ZNscupBVWiJlQJ21BhGypsQ4VtqLANFbahwjZU2IYK21BhGypsQ41tqLENNbahxjb0Ixyf/7Qc21BjG2psQ41tqLENDWxDA9vQwDYUi/UosA3FOkPCQkPCSkPCUkPCWkPCYkPCakPCckPCekPCgkPCikPCkkPCmkPCokPCqkPCskPCukPCwkPCykPC0kPC2kPC4kPC6kPC8kPC+kPCAkTCCkTCEkTCGkTCIkTCKkTCMkTCOkTCQkTCSkTCUkTCWkTCYkTCakTCckTCekTCgkTCikTCkkTCmkTCokTCqkTCskTCukTCwkTCykTC0kTC2kTC4kTC6kTC8kTC+kTCAkXCCkXCEkXCGkXCIkXCKkXCMkXCOkXGOkXGOkXGOkXGOkVO1IYa6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQF1ikKrFMUWKcosE5RJGpDA+sUBdYpCqxTFFinKLBOUWCdosA6RYF1igLrFAXWKQqsUxRYpyiwTlFgnaLAOkWBdYoC6xQF1ikKrFMUWKcosE5RYJ2ieIdT1Map5Tnl6To7Xr3L2+sY06Lt0/a3jjQt6h+xKPafZW6nFtUyza+jHm49pkVjbove4QX960Wa3SLPblHMblGe3aIyu0V1dova7BbN7js7ZvednWf3nZ3n9J29ffRjeb9afru5etg+4+WPj+uLzep2vXu4+Xn35y/b218="},{"name":"set_authorized","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/+2Zy27aQBSGBwikTQhJSmwM5mLABgImCYt20ZbuKnXfVZeV0mbTi9SL+o59qs45M+PfjinRVK2FqiANHp/5vzmXMSFHhKIixIOqkK+e0C9590A0RE1eyjReCDOTExqlhigZk9Lt0WDdnhppHZsiWqTdyzyTdlGJ9MZCrVbId6Q3EbWRfDt+LEx4p/S2H1K8vPlBZOKV21b09IDelIY8PAyxEoqqyL5ol0OOXxyqUdFB0jb1qKwX6tiwrjQHakrXPLK/HcmEZJI5eraX0tB+R/l46dVQ8TZoVHla17eyNOROnFT5SlGcUAWVk+dyNJOKnaJizWzFHiG8ptzwtbyeKfGpFjuc5BnNgDlK01RTRr/BbFCXURK4QF2grkY/w2zQFqMkaAFtAW1p9AvMBvUYJYEH1APqafQtzAZtM0qCNtA20LZGb2A2aIdREnSAdoB2NPoOZoP6jJLAB+oD9TUawGzQLqMk6ALtAu1q9CvMBu0xSoIe0B7QnkY/wGzQPqMk6APtA+2rax5x7RHHHvG3IzKnK5gNOmCUBAOgA6CDvLdB4m0LIr19gtmgAaMkCIAGQIO8tyCpoCXi2CO+PeLZI71CkDsqJs/nB8wGHTJKgiHQIdBh3tsw+RRvQaS3a5gNOmKUBCOgI6AjjV7AbNAxoyQYAx0DHecDHSdHbImc2SOOPeLaIy17xLNH2vZIp5Bz6dojvULOxSkklzsqJj83H2E2aMgoCUKgIdBQo99hNmjEKAkioBHQKB9olORmiTj2iL+rgXn2SGsXKiafgvcwG3TCKAkmQCdAJ3lvkyQnS8S1R8b2iL8dkWVYwWzQKaMkmAKdAp3mvU2Tr6wtCH0Zll6hn1kzKNDEmK6F1HwMig3FnsBrxq5mWVfnCp6qqVmhhukczdCixtOFFsUye2KXJd5iSSYaHOZLdWdyJGYZGdkc3tRCWRnFEhEtReKMkEUgzU9TYd0K+ElJZ7tGQzlLarOP2syyvd5xmF6pKK2qDkdV33gkM+16I1LdjiC+adLwzvQmU9XO0i21s1XVxtKG1MbWkf5807HPs6mlTm6OJ4lEi+RflwXkC6WZ66JvRBx7xLVHWvaIZ4+07ZGOPeLbI117pFfIuTiFpN8vxMvgP6qYV8gDU8wzFhTyqRzaI6NCjvL+b/L93+R/ffrdQio2tkfCQnJxdvWBcQr5iLV2tWJRIbm4hTzJf5D+5K9/JdGXXPkGfcOaQZFtCYRWq3ZxrnZMt4sxu4qzrm43Z2hMlmg6LlW7eKlFV7pdXKl2kfpm+snhisO8VncmR2JWkZFdwJtaKCujWCGilUicEXIZyE3fpMK6FTC3i5TtWv2WSKOK3eKkTDWUKc62V/UwvVLRm8TJ6VQ3nk6so4ixgl4u/m0vt5iVtAO6zsaEeD9p/AKfECQnvR4AAA==","debug_symbols":"1dzRahxXFobRd9G1GWrvs/epOn6VYRiUxBkERg6xMhBM3j1yorZiIugLkaTWnVp9uvqnBfWpb9anm+/effPT//57d//9h483b//96eb9h29vH+4+3D8++nSz/Sv6t99+/OH2/vMvPj7c/vhw8/ao483Nu/vvHn+axy9vbr6/e//u5u2I/uXNn852HOPpcMeKL6fXeOHwrG0+HZ6VXx3+z5vPc+aLc3L7MmddmbPGZfo6nqdH5Qtnoy/XjfV8NvOl5aszLhfuo59Pj/U0fXenH+70xU7PzZ0e7vThTi93ervT3SSlm6R0k5RukoabpOEmaaQ73a3peHVNY5uXbz4RuV0Zf7nudu371LrsntvXH8jvs6c5ezdnH+bsRc6uzZwd5uw0Zw9ztpmbanO2WckyK1lmJcusZJuVbLOSbVayzUq2Wck2K9lmJdusZJuVbLOS06zkNCs5zUpOs5LTrOQ0KznNSk6zktOs5DQruZuV3M1K7mYld7OSu1nJ3azkblZyNyu5m5XczUoeZiUPs5KHWcnDrORhVvIwK3mYlTzMSh5mJQ+zksus5DIrucxKLrOSy6zkMiu5zEous5LLrOQyKxmbmcnYzE7GZoYyNrOUsZmpjM1s5eOborvNWsZm5jI2tJeB9jLQXgbay0B7GWgvA+1loL0MtJeB9jLQXibay0R7mWgvE+3l6xWcf2g32stEe5loLxPtZaK9HGgvB9rLgfZyoL1EnZsYaC9RoCdQoSdQoidQoydQpCdQpSdQpidQpydQqCdQqSdQqidQqydQrCdQrSdQridQrydQsCdQsSdQsidQsydQtCdQtSdQtidQtydQuCdQuSdQuidQuydQvCdQvSdQvidQvydQwCdQwSdQwidQwydQxCdQxSdQxidQxydQyCdQySdQyidQyydQzCdQzSdQzidQzydQ0CdQ0SdQ0idQ0ydQ1CdQ1SdQ1idQ1ydQ2CdQ2SdQ2idQ2ydQ3CdQ3SdQ3idQ3ydR3ydR3ydR3ydR3yc3s5eJ+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j4D9X0G6vsM1PcZqO8zNrOXA/V9Bur7DNT3GajvM1DfZ6C+z0B9n4H6PgP1fQbq+wzU9xmo7zNQ32egvs9AfZ+B+j4D9X0G6vsM1PcZqO8zUN9noL7PQH2fcdX3OeaVd1jjeDq7juPK6ujLdWM9n80cL1238zJ99dHPp8e6bF/u9qvOz5m3B7w94e0D3l7w9oa3T3j7Dm+Huzrgrhbc1YK7WnBX69Vd/Wv+d9/7Mnyff/xE6rK70N2N7p7o7h3dfaC7l7m7N3R3oLsT3Y328qoNdNbdaC8b7WWjvWy0l432cqK9nGgvJ9rLifbyqg101t1oLyfay4n2cqK9nGgvd7SXO9rLHe3ljvbyqg101t1oL3e0lzvayx3t5Y728kB7eaC9PNBeHmgvr9pAZ92N9vJAe3mgvTzQXh5oLxfay4X2cqG9XGgvr9pAZ92N9nKhvVxoLxfay2X2sjazl7WZvazN7GVtZi9rM3tZm9nL2sxe1mb2sjazl7WhvQy0l4H2MtBeBtrLqzbQWXejvQy0l4H2MtBeBtrLRHuZaC8T7WWivbxqA511N9rLRHuZaC8T7WWivRxoLwfay4H2cqC9fL0B9A/tRns50F4OtJcD7eVAe1loLwvtZaG9RH2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fRn2fRn2fRn2fRn2f3sxeNur7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7TNT3majvM1HfZ6K+z9zMXk7U95mo7zNR32eivs9EfZ+J+j4T9X0m6vtM1PeZqO8zr/k+axvXdtdWl92V46v3+PPpsS57Hl/25WyO7bJnvn7P+PI51n5tz+zL+Lme/0KR67JnP9me42R71rn2XHNx/vY9cbI9ebI942R76mR7+mR7TnZ/zpPdn/Nk9+c8z/358dH/b3+8u/3m/buPj6/4/ORP998+3H24f3r48PMPvz/zePZX"},{"name":"consume","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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cq6F5FwLybkWknMtJOdaSM61kJxrITnXQnKuheRcC8m5FpJzLSTnWkjOtZCCayEF10IKroUUXAspFramwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k5FpIybWQkmshJddCyoWtaXItpORaSMm1kJJrISXXQsonLKTcj6Zve5m+0159mT8+Hb4vDx//2np7Vvtlkpxvkp5vkp1v0j7fJD/fpDjfpDzfpDrfpD7dJD3fp7ee79Nbz/fprWf69D7+6j9/+PvHH/7004+/HG/8/l/+49OfP3/8+dPlLz//19/+9785nv1v"}],"outputs":{"globals":{"storage":[{"fields":[{"name":"reject_all","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"approved_actions","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_authorized_parameters"}}],"kind":"struct","path":"AuthRegistry::set_authorized_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"reject","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_reject_all_parameters"}}],"kind":"struct","path":"AuthRegistry::set_reject_all_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_authorized_private_parameters"}}],"kind":"struct","path":"AuthRegistry::set_authorized_private_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::_set_authorized_parameters"}}],"kind":"struct","path":"AuthRegistry::_set_authorized_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::consume_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::consume_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"AuthRegistry::is_reject_all_parameters"}},{"name":"return_type","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::is_reject_all_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::is_consumable_parameters"}},{"name":"return_type","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::is_consumable_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"122":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr","source":"#[oracle(packArgumentsArray)]\nunconstrained fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {}\n\n#[oracle(packArguments)]\nunconstrained fn pack_arguments_oracle(_args: [Field]) -> Field {}\n\n/// - Pack arguments (array version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments_array(args: [Field; N]) -> Field {\n pack_arguments_array_oracle(args)\n}\n\n/// - Pack arguments (slice version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments(args: [Field]) -> Field {\n pack_arguments_oracle(args)\n}\n\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"144":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr","source":"use crate::context::{PublicContext, UnconstrainedContext};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:public_mutable_struct\nstruct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl Storage for PublicMutable {}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicMutable { context, storage_slot }\n }\n // docs:end:public_mutable_struct_new\n}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) where T: Serialize {\n let fields = T::serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n pub fn read(self) -> T where T: Deserialize {\n // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the\n // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns\n // historical data.\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"315":{"path":"/usr/src/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr","source":"contract AuthRegistry {\n use dep::aztec::{state_vars::{PublicMutable, Map}, protocol_types::address::AztecAddress};\n use dep::authwit::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash, assert_current_call_valid_authwit};\n\n #[aztec(storage)]\n struct Storage {\n reject_all: Map>,\n // on_behalf_of => authwit hash => authorized\n approved_actions: Map>>,\n }\n\n /**\n * Updates the `authorized` value for `msg_sender` for `message_hash`.\n *\n * @param message_hash The message hash being authorized\n * @param authorize True if the caller is authorized to perform the message hash, false otherwise\n */\n #[aztec(public)]\n fn set_authorized(message_hash: Field, authorize: bool) {\n storage.approved_actions.at(context.msg_sender()).at(message_hash).write(authorize);\n }\n\n /**\n * Updates the `reject_all` value for `msg_sender`.\n * \n * When `reject_all` is `true` any `consume` on `msg_sender` will revert.\n * \n * @param reject True if all actions should be rejected, false otherwise\n */\n #[aztec(public)]\n fn set_reject_all(reject: bool) {\n storage.reject_all.at(context.msg_sender()).write(reject);\n }\n\n /**\n * Consumes an `inner_hash` on behalf of `on_behalf_of` if the caller is authorized to do so.\n * \n * Will revert even if the caller is authorized if `reject_all` is set to true for `on_behalf_of`.\n * This is to support \"mass-revoke\".\n *\n * @param on_behalf_of The address on whose behalf the action is being consumed\n * @param inner_hash The inner_hash of the authwit\n * @return `IS_VALID_SELECTOR` if the action was consumed, revert otherwise\n */\n #[aztec(public)]\n fn consume(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n assert_eq(false, storage.reject_all.at(on_behalf_of).read(), \"rejecting all\");\n\n let message_hash = compute_outer_authwit_hash(\n context.msg_sender(),\n context.chain_id(),\n context.version(),\n inner_hash\n );\n\n let authorized = storage.approved_actions.at(on_behalf_of).at(message_hash).read();\n\n assert_eq(true, authorized, \"unauthorized\");\n storage.approved_actions.at(on_behalf_of).at(message_hash).write(false);\n\n IS_VALID_SELECTOR\n }\n\n /**\n * Updates a public authwit using a private authwit\n * \n * Useful for the case where you want someone else to insert a public authwit for you.\n * For example, if Alice wants Bob to insert an authwit in public, such that they can execute\n * a trade, Alice can create a private authwit, and Bob can call this function with it.\n *\n * @param approver The address of the approver (Alice in the example)\n * @param message_hash The message hash to authorize\n * @param authorize True if the message hash should be authorized, false otherwise\n */\n #[aztec(private)]\n fn set_authorized_private(approver: AztecAddress, message_hash: Field, authorize: bool) {\n assert_current_call_valid_authwit(&mut context, approver);\n AuthRegistry::at(context.this_address())._set_authorized(approver, message_hash, authorize).enqueue(&mut context);\n }\n\n /**\n * Internal function to update the `authorized` value for `approver` for `messageHash`.\n * Used along with `set_authorized_private` to update the public authwit.\n * \n * @param approver The address of the approver\n * @param message_hash The message hash being authorized\n * @param authorize True if the caller is authorized to perform the message hash, false otherwise\n */\n #[aztec(public)]\n #[aztec(internal)]\n fn _set_authorized(approver: AztecAddress, message_hash: Field, authorize: bool) {\n storage.approved_actions.at(approver).at(message_hash).write(authorize);\n }\n\n /**\n * Fetches the `reject_all` value for `on_behalf_of`.\n * \n * @param on_behalf_of The address to check\n * @return True if all actions are rejected, false otherwise\n */\n #[aztec(public)]\n #[aztec(view)]\n fn is_reject_all(on_behalf_of: AztecAddress) -> bool {\n storage.reject_all.at(on_behalf_of).read()\n }\n\n /**\n * Fetches the `authorized` value for `on_behalf_of` for `message_hash`.\n * \n * @param on_behalf_of The address on whose behalf the action is being consumed\n * @param message_hash The message hash to check\n * @return True if the caller is authorized to perform the action, false otherwise\n */\n #[aztec(public)]\n #[aztec(view)]\n fn is_consumable(on_behalf_of: AztecAddress, message_hash: Field) -> bool {\n storage.approved_actions.at(on_behalf_of).at(message_hash).read()\n }\n\n unconstrained fn unconstrained_is_consumable(on_behalf_of: AztecAddress, message_hash: Field) -> pub bool {\n storage.approved_actions.at(on_behalf_of).at(message_hash).read()\n }\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"86":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr","source":"use dep::protocol_types::address::AztecAddress;\n\nstruct UnconstrainedContext {\n block_number: u32,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UnconstrainedContext {\n fn new() -> Self {\n // We could call these oracles on the getters instead of at creation, which makes sense given that they might\n // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user\n // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not\n // available.\n let block_number = block_number_oracle();\n let contract_address = contract_address_oracle();\n let chain_id = chain_id_oracle();\n let version = version_oracle();\n Self { block_number, contract_address, version, chain_id }\n }\n\n fn block_number(self) -> u32 {\n self.block_number\n }\n\n fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n fn version(self) -> Field {\n self.version\n }\n\n fn chain_id(self) -> Field {\n self.chain_id\n }\n}\n\n#[oracle(getContractAddress)]\nunconstrained fn contract_address_oracle() -> AztecAddress {}\n\n#[oracle(getBlockNumber)]\nunconstrained fn block_number_oracle() -> u32 {}\n\n#[oracle(getChainId)]\nunconstrained fn chain_id_oracle() -> Field {}\n\n#[oracle(getVersion)]\nunconstrained fn version_oracle() -> Field {}\n"},"87":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr","source":"use crate::{hash::hash_args_array, oracle::returns::unpack_returns};\nuse dep::protocol_types::traits::Deserialize;\n\nstruct PackedReturns {\n packed_returns: Field,\n}\n\nimpl PackedReturns {\n pub fn new(packed_returns: Field) -> Self {\n PackedReturns { packed_returns }\n }\n\n pub fn assert_empty(self) {\n assert_eq(self.packed_returns, 0);\n }\n\n pub fn raw(self) -> Field {\n self.packed_returns\n }\n\n pub fn unpack(self) -> [Field; N] {\n let unpacked: [Field; N] = unpack_returns(self.packed_returns);\n assert_eq(self.packed_returns, hash_args_array(unpacked));\n unpacked\n }\n\n pub fn unpack_into(self) -> T where T: Deserialize {\n let unpacked: [Field; N] = self.unpack();\n Deserialize::deserialize(unpacked)\n }\n}\n"},"90":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress, traits::Deserialize\n};\n\nuse crate::context::{\n private_context::PrivateContext, public_context::PublicContext, gas::GasOpts,\n public_context::FunctionReturns, inputs::{PrivateContextInputs, PublicContextInputs}\n};\n\nuse crate::oracle::arguments;\n\ntrait CallInterface {\n fn get_args(self) -> [Field];\n fn get_original(self) -> fn[Env](T) -> P;\n fn get_selector(self) -> FunctionSelector;\n fn get_name(self) -> str;\n fn get_contract_address(self) -> AztecAddress;\n fn get_is_static(self) -> bool;\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateCallInterface {\n pub fn call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n );\n let unpacked: T = returns.unpack_into();\n unpacked\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateVoidCallInterface {\n pub fn call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n ).assert_empty();\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty();\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticCallInterface {\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticVoidCallInterface {\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.deserialize_into()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.assert_empty()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicStaticCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n let unpacked: T = returns.deserialize_into();\n unpacked\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n\nimpl CallInterface for PublicStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicStaticVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json b/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json new file mode 100644 index 000000000000..a44a57e1f459 --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"ContractClassRegisterer","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpBattQGIXRvWhsiu9vSU/PWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq82/Cyf/r48f1wej1fhu3X23A8P++uh/PpfroN6y+1/Hl7edudHi8u1937ddhuWq2G/enl8dQ+V8Pr4bgfttU3n99Wj1GH0WYto8ioZLSR0SijSUazjJqMpIiNFDFKEaMUMUoRoxQxShGjFDFKEaMUMUoRoxQxSRGTFDFJEZMUMUkRkxQxSRGTFDFJEZMUMUsRsxQxSxGzFDFLEbMUMUsRsxQxSxGzFNGkiCZFNCmiSRFNimhSRJMimhTRpIgmRSxSxCJFLFLEIkUsUsQiRSxSxCJFLFLEIkV0KaJLEV2K6FJElyK6FNGliC5FdCmiSxFZr2kVWhWtNrQaaTXRaqZVo9VCK2oj1EaojVAboTZCbYTaCLURaiPURqiNojaK2ihqo6iNojaK2ihqo6gNAs2QaIZIM2SaIdQMqWaINUOuGYLNkGyGaDNkmyHcDOlmiDdDvhkCzpBwhogzZJwh5AwpZ4g5Q84Zgs6QdIaoM2SdIewMaWeIO0PeGQLPkHiGyDNkniH0DKlniD1D7hmCz5B8hugzZJ8h/AzpZ4g/Q/4ZAtCQgIYINGSgIQQNKWiIQUMOGoLQkISGKDRkoSEMDWloiENDHhoC0ZCIhkg0ZKIhFA2paIhFQy5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWnbRk1y0yEWLXLTIRYtctMhFi1y0/ttF76efu/fD7um4f9ztfXz8OD3/u+p7P15/vf39cv/3Nw=="},{"name":"broadcast_private_function","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"artifact_metadata_hash","type":{"kind":"field"},"visibility":"private"},{"name":"unconstrained_functions_artifact_tree_root","type":{"kind":"field"},"visibility":"private"},{"name":"private_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"private_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"vk_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::private_function_broadcasted::PrivateFunction"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZrdattAFITfRdcmaM/vrl+llKIkTjEYOcROoRi/e+VUkptmwfS4CZkre62Z1Zgd6ZOEDs396vb5+7d1/7DdNcsvh2azvev2620/jA5Nspffdo9dfxru9t3Tvlm2i2bV3w+fx0XzsN6smiUVPi7e6MiVRym566xOySpqzq6jmovQBXVRSqO6aD7PTVyOXxdNctTgGTV4AQ1OLWrwhBqcUIMzanBBDa6owVHJSajkJFRyEio5GZWcjEpORiUno5KTUcnJqORkVHIyKjkZlZyMSk5BJaegklNQySmo5BRUcgoqOQWVnIJKTkElp6CSU1HJqajkVFRyKio5FZWcikpORSWnopJTUcmpqOQ0VHIaKjkNlZz2geQUSj6qhbJcGVxQg38gOYVbmYKzXRv8KnIKs81R/Nzakl7m9necu8ofpkTTUWRterWHk6l67mdLaTY5X4iVZAg2yofv+ipYZWkzaZ7WNlP2v/6Ht58vUvovkdznSOr+Zvlu6g8NPE978WJ/lJUmVw65SsRVv1e96EohF4VcHHJJyKUhl4VcoW5oqBsa6oaFumGhblioGxbqhoW6YaFuWKgbFuqGhbphoW54qBse6obXu6FldnnNxf/s8nSTqi7mdr5ylfZM9UTDmX4Y/eie1t3tZnV6Ifm08bm/m95PHob7n4+/twzaXw=="},{"name":"broadcast_unconstrained_function","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"artifact_metadata_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_artifact_tree_root","type":{"kind":"field"},"visibility":"private"},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::unconstrained_function_broadcasted::UnconstrainedFunction"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZrdTuMwFITfxdcVis+Pj91XWa1WAcqqUpUiWpBQ1XcnhSTlx1LFKSDmqnUz407iST5fZBeuF5f3//8tu5v1Jsz/7MJqfdVul+uuH+1CTM+/bW7b7jDcbNu7bZg3s7DorvvP/SzcLFeLMKfC+9kHHZnyICUzndQxpoqas+mg5iJ0Ql2U4qAumo9zE5f931mIhho8owYvoMGpQQ0eUYMTanBGDS6owRU1OCo5CZWchEpOQiUno5KTUcnJqORkVHIyKjkZlZyMSk5GJSejkpNRySmo5BRUcgoqOQWVnIJKTkElp6CSU1DJKajkFFRyKio5FZWcikpORSWnopJTUcmpqORUVHIqKjkVlZwJlZwJlZwJlZzpB8kpFG1QC2U5M7igBv9Bcgo3MgbndG7ws8gpzGmKYsfWlvg8t33j3FX+iDTjyYqpvvmHg6n67BdL460nmexErCh9sEHef9c3wSpLm0nzuLaZsr07D2t+X6T4JZHMpkhq9mH5Lurbe8vjAlpJr8pKo0tcLnW5kstlLld2uYrHVd9JnHRFl4tcLlc3kqsbydWN5OpGcnUjubqRXN0wVzfM1Q1zdcNc3TBXN8zVDXN1w1zdsHo3tEwuq7nKp10WL2L1yjM3085VmiPVI/VP+n700N4t28vV4vBC8uHgfXc1vp/cD7ePty9Heu0T"},{"name":"register","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"artifact_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_root","type":{"kind":"field"},"visibility":"private"},{"name":"public_bytecode_commitment","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZfdbuIwEIXfxdcIef5tXmW1WqUtXSGhUBW60grx7mvYOKXFUtShrdorcHI+z5n4xEn24W558/T716q/32zD4sc+rDe33W616ctoH0BOx7YPXX8cbnfd4y4s4iws+7vye5iF+9V6GRaY6TC70KEJDVI0k1ENoA01I9igZkw8oc6CMKizpOe5kfLh5yyAflfj9onGKXI1Tnqt8XSNcSbS0YrhqM5wmjt/3NwYW3MDal1TwPSywhGCJkQ5VUhIJmxlxioGtWcx66kCNiukWNcXkuJEBWWWQa18tr6l8UZ0Ekp1X/4ne32d6KsZ4qahTDWliPFy4ZobGiLEEbKpLoBLomrTpSO8sg/9epbsXSzZeAux2EWNOG9vGcS1E1I6K8KVyh6qfZtPUuCi8O0Uz6nZl6UaZ8t6tufiQHF0UeCi0EWRi2IXJS5KXZS5qOSiXNkQVzbElQ1xZUNc2RBXNsSVDXFlQ1zZEFc2xJUNdWVDXdlQVzbUlQ1tZ0PySFmLkrdTNoemQ6JYX3KIz95AAMtzr4z+dI+r7ma9PH5gHU8+9bf1e6sMd38f/p8p2n8="}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"artifact_hash","type":{"kind":"field"}},{"name":"private_functions_root","type":{"kind":"field"}},{"name":"public_bytecode_commitment","type":{"kind":"field"}}],"kind":"struct","path":"ContractClassRegisterer::register_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::register_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"artifact_metadata_hash","type":{"kind":"field"}},{"name":"unconstrained_functions_artifact_tree_root","type":{"kind":"field"}},{"name":"private_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"private_function_tree_leaf_index","type":{"kind":"field"}},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"}},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"vk_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::private_function_broadcasted::PrivateFunction"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_private_function_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_private_function_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"artifact_metadata_hash","type":{"kind":"field"}},{"name":"private_functions_artifact_tree_root","type":{"kind":"field"}},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"}},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::unconstrained_function_broadcasted::UnconstrainedFunction"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_unconstrained_function_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_unconstrained_function_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"246":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr","source":"use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF;\nuse crate::traits::{ToField, FromField, Hash, Serialize, Deserialize};\n\nstruct ContractClassId {\n inner: Field\n}\n\nimpl Eq for ContractClassId {\n fn eq(self, other: ContractClassId) -> bool {\n other.inner == self.inner\n }\n}\n\nimpl ToField for ContractClassId {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for ContractClassId {\n fn from_field(value: Field) -> Self {\n Self { inner: value }\n }\n}\n\nimpl Serialize<1> for ContractClassId {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n}\n\nimpl Deserialize<1> for ContractClassId {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self { inner: fields[0] }\n }\n}\n\nimpl ContractClassId {\n pub fn compute(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field\n ) -> Self {\n let hash = dep::std::hash::pedersen_hash_with_separator(\n [\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ],\n GENERATOR_INDEX__CONTRACT_LEAF\n ); // TODO(@spalladino): Update generator index\n\n ContractClassId::from_field(hash)\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"293":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr","source":"mod events;\nmod capsule;\n\ncontract ContractClassRegisterer {\n use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector};\n use dep::aztec::protocol_types::{\n contract_class_id::ContractClassId,\n constants::{\n ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT,\n MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE\n },\n traits::Serialize\n };\n\n use crate::events::{\n class_registered::ContractClassRegistered,\n private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction},\n unconstrained_function_broadcasted::{ClassUnconstrainedFunctionBroadcasted, UnconstrainedFunction}\n };\n\n // docs:start:import_pop_capsule\n use crate::capsule::pop_capsule;\n // docs:end:import_pop_capsule\n\n #[aztec(private)]\n fn register(artifact_hash: Field, private_functions_root: Field, public_bytecode_commitment: Field) {\n // TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode\n // TODO: Validate packed_public_bytecode is legit public bytecode\n\n // docs:start:pop_capsule\n let packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] = pop_capsule();\n // docs:end:pop_capsule\n\n // Compute contract class id from preimage\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n\n // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered\n let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode };\n context.push_new_nullifier(contract_class_id.to_field(), 0);\n\n // Broadcast class info including public bytecode\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ContractClassRegistered: {}\",\n [\n contract_class_id.to_field(),\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_private_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n unconstrained_functions_artifact_tree_root: Field,\n private_function_tree_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n private_function_tree_leaf_index: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: PrivateFunction\n ) {\n let event = ClassPrivateFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n private_function_tree_sibling_path,\n private_function_tree_leaf_index,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassPrivateFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.vk_hash,\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_unconstrained_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n private_functions_artifact_tree_root: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: UnconstrainedFunction\n ) {\n let event = ClassUnconstrainedFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassUnconstrainedFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n}\n"},"294":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr","source":"// We should extract this to a shared lib in aztec-nr once we settle on a design for capsules\n\n// docs:start:pop_capsule\n#[oracle(popCapsule)]\nunconstrained fn pop_capsule_oracle() -> [Field; N] {}\n\n// A capsule is a \"blob\" of data that is passed to the contract through an oracle.\nunconstrained pub fn pop_capsule() -> [Field; N] {\n pop_capsule_oracle()\n}\n// docs:end:pop_capsule"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json b/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json new file mode 100644 index 000000000000..9fa3c02fa69d --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"ContractInstanceDeployer","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpBattQGIXRvWhsiu9vSe/JWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq82/Cyf/r48f1wej1fhu3X23A8P++uh/PpfroN6y/V/7y9vO1OjxeX6+79Omw3rVbD/vTyeGqfq+H1cNwP2+r989vqMVpgtFnLKDIqGW1kNMpoktEsoyYjKWIjRYxSxChFjFLEKEWMUsQoRYxSxChFjFLEKEVMUsQkRUxSxCRFTFLEJEVMUsQkRUxSxCRFzFLELEXMUsQsRcxSxCxFzFLELEXMUsQsRTQpokkRTYpoUkSTIpoU0aSIJkU0KaJJEV2K6FJElyK6FNGliC5FdCmiSxFdiuhSxCJFLFLEIkUsUsQiRSxSxCJFLFLEIkUsUkTWa1qFVkWrDa1GWk20mmnVaNVpRW2E2gi1EWoj1EaojVAboTZCbYTaCLVR1EZRG0VtFLVR1EZRG0VtFLVBoBkSzRBphkwzhJoh1QyxZsg1Q7AZks0QbYZsM4SbId0M8WbIN0PAGRLOEHGGjDOEnCHlDDFnyDlD0BmSzhB1hqwzhJ0h7QxxZ8g7Q+AZEs8QeYbMM4SeIfUMsWfIPUPwGZLPEH2G7DOEnyH9DPFnyD9DABoS0BCBhgw0hKAhBQ0xaMhBQxAaktAQhYYsNIShIQ0NcWjIQ0MgGhLREImGTDSEoiEVDbFoyEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFyy56kosWuWiRixa5aJGLFrlokYvWf7vo/fRz937YPR33j7u9j48fp+d/V33vx+uvt79f7v/+Bg=="},{"name":"deploy","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"salt","type":{"kind":"field"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"initialization_hash","type":{"kind":"field"},"visibility":"private"},{"name":"public_keys_hash","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::public_keys_hash::PublicKeysHash"},"visibility":"private"},{"name":"universal_deploy","type":{"kind":"boolean"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2dB3wUVbTGN7P03rsQeoe9abuh99679FR6EUEERVHsvUuv9l5RFMWu2KV37L1XEMX3XXMnzh6TbDuDOe+9/f3+3nxLuHxnzuzszHzjTJwn57WsqMdzY5Gcn+OAF1gg3qG95mdbFyG6KPn94kSXJbo80RWJrkx0ddDFoeuRP48nuj7RDYhuQnRL87PzZesuZkz0pSQlZfkTslSiSvMlpKYHkn1JyekpARVQyYHkzIRAYmJWICngT01P9ftSVVJilspOTk3M9uW8fon7Zy5fjC/traTDW1NwEjQzY3MztjBjSzNqD/8//u8bW4Ff43LWWed68ev/L5//8+vFb3GeoJdlxi5m9MX2Uk08fNvIY3F8vnTZetuu54w3c8aR2mP1q+do6cIy5fR4PI7/e8dr5rO/d+zvm+NmvasNfndsj+zlY38//e74vRNk/eTu0R989We76fPP6H0m0je0N73PZHbrcvcDTpjl/ocZ/zSj/Xsnof+Ky2lYnPXP+/aLez13ft5jXX6Wxb/t0HPGe3L2b5316z+v48n7xeMhKdGdeVOyXZo3y515/UkuzZvg0nJQLs3r0vrg1vJNSnVpObi1nglbvq6tZy4tX7fW35Rkd+ZNcqtvLvn1+1zym+HSvC59D/nd2u641LcUl9azxDR35k1waT3zp7s0b6beVyvhyftF/41AcgA7oan+lMSUjGx/cnJalj89M8uXmJ2Q4s/I8qm05ARfakBlJKiMxJRAQlpaNv6Tkpi7LY5j9e5TJxmP3ULVHq1Ht2pv6uGvndtjMwEemwvw2EKAx+Nx7nnMfXGZdc7JfdDuPNCO9aDd68JBu9cctFtk2RbmjXO8macITBcFxUBxUAKUBKVAaVAGlAXlQHlQAVQElUBlUAVUBdVAdVAD1AS1QG1QB5wG6oJ6ejmB+qABaGjlLCR7OWovJTyOkI/oYkQXJ7oE0SWJLkV0aaLLEF2W6HJElye6AtEVia5EdGWiqxBdlehqRFcnugbRNYmuRXRtousQfRrRdYmuR3Q80fWJbkB0Q+vfO0r2CcAuZvTF9gr6zMS67SjCsB3KytYvnyrKuE370OvOThvtRSw1614UY1l+OX0tHvtcCWb5qRKMvfioMPciKdenKhlbzT5HzapULHMlBC0/VZqxFx8Xzl74iE9VJsqaU7L/VbMqG91cgTyWnyrH2ItPClsvAnn6VOUjr9mfT82qQqRz+fNdfqoiYy8+LTy9SCjAp6oUSc3+AmtWlcOfKyPE8lNVGHvxWWHohT+kT1U1vJp9YdSsqoUzly+s5aeqM/bi8/+2F8lh+lQ1QtWcFHbNqmaBcyVlR7D8VC3GXnzxX/XCH5FPVTv/mgMR1qzq5DNXanbEy0+dxtiLL099L3xR+FR186rZF1XNqt6/51JRLj8Vz9iLr05lLzKj9qnqB9ecGEPNqoFjroTsmJafasjYi69PUS98sb0U4/kBxXh8q5zHZ7H24hshvWA8DlKM+/HqM8ZefCukF4z7e4pxf0V9ydiL74T0gvF7TTFul9U3jL343qVeeJl7wfj5VYzrn+JcfpYn+FWYLyaIN/M0gunGoAloCpqB5qAFaAlagdagDWgLdJEKJIBEkASSQQrwgwBIBe1Ae9ABdASdQGe9nwS6gm6gu+UJyuq0F2eW05joJkQ3JboZ0c2JbkF0S6JbEd2a6DZEtyXaR7QiOoHoRKKTiE4mOoVoP9EBolOJbkd0e6I7EN2R6E5Edya6C9Fdie5GdHfL/azO+ZmJdVvbiGE/387qGjMeM+iFxrS8XM3qmrAsP9PX2OfKzeqaMfYirjD3wpHVNY+t5qCsrkUsc5GsriVjL6zC2Yt/ZXWtoqw5r6yudXRz5ZnVtWHshbew9SKfrK5t5DXnm9X5Ip2rgKxOMfaiSOHpRYFZXUIkNYfI6hLDnytkVpfE2IuihaEXYWR1yeHVHFZWlxLOXGFmdX7GXhT7b3sRdlYXCFVzBFldqsWX1bVj7EXx/6oXEWZ17S2+rK6DxZfVdWTsRYlT34uosrpOFl9W19niy+q6MPai5KnsRQxZXVeLL6vrZvFldd0Ze1HqFPXCF9tLMZ4fUIzHt8p5fBZrL0oL6QXjcZBi3I9XRRl7UUZILxj39xTj/ooqwdiLskJ6wfi9phi3y6o0Yy/KudQL7qyO8fOrGNc/xbn8LE/wqzD/T7XxZp4eMN0T9AK9QR/QF/QD/cEAMBAMAoPBEDAUDAPDwQgwEowCo8EYcDoYC8aB8WACmAgmgckgDaSDDMsTlNVpL84spyfRvYjuTXQfovsS3Y/o/kQPIHog0YOIHkz0EKKHEj2M6OFEjyB6JNGjiB5N9BiiTyd6LNHjiB5P9ASiJxI9iejJRKcRnU50huV+Vuf8zMS6re3BsJ9vZ3U9GY8Z6grJ6nqxLL+cvvaOfa7crK4PYy/qCcnq+sZWc1BW1y+WuUhW15+xF/FCsroBUdacV1Y3MLq58szqBjH2or6QrG5w5DXnm9UNiXSuArK6oYy9aCAkqxsWSc0hsrrh4c8VMqsbwdiLhkKyupHh1RxWVjcqnLnCzOpGM/aikZCsbkyomiPI6k63+LK6sYy9aCwkqxtn8WV14y2+rG4CYy+aCMnqJlp8Wd0kiy+rm8zYi6ZCsro0iy+rS7f4sroMxl40E3IenPH8gGI8vlXxjOfBmwvpBeNxkGLcj1cNGXvRQkgvGPf3FOP+imrC2IuWQnrB+L2mGLfLqjljL1oJyeoYP7+Kcf1TnMvP8gS/CvPNZePNPJkwnQWywRQwFUwD08EMMBPMArPBHDAXnAHmgTPBfLAAnAUWgrPBIrAYnAPOBUvAeeB8sBRcAC4EyyxPUFanvTiznCyis4meQvRUoqcRPZ3oGUTPJHoW0bOJnkP0XKLPIHoe0WcSPZ/oBUSfRfRCos8mehHRi4k+h+hziV5C9HlEn0/0UqIvIPpCopdZ7md1zs9MrNvaTIb9fDury2I8ZuggJKvLZll+OX2dEvtcuVndVMZedBSS1U2LreagrG56LHORrG4GYy86CcnqZkZZc15Z3azo5sozq5vN2IvOQrK6OZHXnG9WNzfSuQrI6s5g7EUXIVndvEhqDpHVnRn+XCGzuvmMvegqJKtbEF7NYWV1Z4UzV5hZ3ULGXnQTktWdHarmCLK6RRZfVreYsRfdhWR151h8Wd25Fl9Wt4SxFz2EZHXnWXxZ3fkWX1a3lLEXPYVkdRdYfFndhRZfVreMsRe9hJwHZzw/oBiPb1UnxvPgvYX0gvE4SDHux6uujL3oI6QXjPt7inF/RfVg7EVfIb1g/F5TjNtl1ZuxF/2EZHWMn1/FuP4pzuVneYJf3Fkd50MW4808F8H0xeAScCm4DFwOrgBXgqvA1eAacC24DlwPbgA3gpvAzeAWcCtYDlaAlWAVWA3WgLVgHVgPNoCNYJPlCcrqtBdnlnMx0ZcQfSnRlxF9OdFXEH0l0VcRfTXR1xB9LdHXEX090TcQfSPRNxF9M9G3EH0r0cuJXkH0SqJXEb2a6DVEryV6HdHrid5A9EaiN1nuZ3XOz0ys29qLGPbz7azuYsZjhrFCsrpLWJZfTl8vjX2u3KzuMsZejBOS1V0eW81BWd0VscxFsrorGXsxXkhWd1WUNeeV1V0d3Vx5ZnXXMPZigpCs7trIa843q7su0rkKyOquZ+zFRCFZ3Q2R1Bwiq7sx/LlCZnU3MfZikpCs7ubwag4rq7slnLnCzOpuZezFZCFZ3fJQNUeQ1a2w+LK6lYy9SBOS1a2y+LK61RZfVreGsRfpQrK6tRZfVrfO4svq1jP2IkNIVrfB4svqNlp8Wd0mxl5kCjkPznh+QDEe36rxjOfBs4T0gvE4SDHux6tJjL3IFtILxv09xbi/otIZezFFSC8Yv9cU43ZZZTH2YqqQrI7x86sY1z/FufwsT/CLO6s7Hsef1d0G07eDO8Cd4C5wN7gH3AvuA/eDB8CD4CHwMHgEPAoeA4+DzeAJ8CTYAp4CT4Ot4BnwLNgGngPPgxfAi5YnKKvTXpxZzu1E30H0nUTfRfTdRN9D9L1E30f0/UQ/QPSDRD9E9MNEP0L0o0Q/RvTjRG8m+gminyR6C9FPEf000VuJfoboZ4neRvRzRD9P9AtEv2i5n9U5PzOxbmtvY9jPt7O62xmPGc4WktXdwbL8cvp6Z+xz5WZ1dzH2YpGQrO7u2GoOyuruiWUuktXdy9iLxUKyuvuirDmvrO7+6ObKM6t7gLEX5wjJ6h6MvOZ8s7qHIp2rgKzuYcZenCskq3skkppDZHWPhj9XyKzuMcZeLBGS1T0eXs1hZXWbw5krzKzuCcZenCckq3syVM0RZHVbLL6s7inGXpwvJKt72uLL6rZafFndM4y9WCokq3vW4svqtll8Wd1zjL24QEhW97zFl9W9YPFldS8y9uJCIefBGc8PKMbjW7WY8Tz4MiG9YDwOUoz78WoJYy8uEtILxv09xbi/opYy9uJiIb1g/F5TjNtltYyxF5cIyeoYP7+Kcf1TnMvP8gS/uLO6ky5kdS/B9MvgFfAqeA1sB6+DN8Cb4C3wNngHvAveAzvATrAL7AZ7wF6wD+wHB8BBcAgcBkfAUfA++AB8CD6yPEFZnfbizHJeJvoVol8l+jWitxP9OtFvEP0m0W8R/TbR7xD9LtHvEb2D6J1E7yJ6N9F7iN5L9D6i9xN9gOiDRB8i+jDRR4g+SvT7RH9A9IdEf2S5n9WdZMzqXmLYz7ezupcZjxluEZLVvcKy/HL6+mrsc+Vmda8x9uJWIVnd9thqDsrqXo9lLpLVvcHYi+VCsro3o6w5r6zurejmyjOre5uxFyuEZHXvRF5zvlndu5HOVUBW9x5jL1YKyep2RFJziKxuZ/hzhczqdjH2YpWQrG53eDWHldXtCWeuMLO6vYy9WC0kq9sXquYIsrr9Fl9Wd4CxF2uEZHUHLb6s7pDFl9UdZuzFWiFZ3RGLL6s7avFlde8z9mKdkKzuA4svq/vQ4svqPmLsxXoh58EZzw8oxuNbtZzxPPgGIb1gPA5SjPvxahVjLzYK6QXj/p5i3F9Raxl7sUlILxi/1xTjdlltYOzFbUKyOsbPr2Jc/xTn8rM8wS/urK4p31y5Wd3HMP0J+BR8Bj4HX4AvwVfga/AN+BZ8B74HP4AfwU/gZ/AL+BX8Bo6B4+B3cAL8Af4EJ8FfVs6KFQcs4PV6grI67cWZ5XxC9KdEf0b050R/QfSXRH9F9NdEf0P0t0R/R/T3RP9A9I9E/0T0z0T/QvSvRP9G9DGijxP9O9EniP6D6D+JPkn0X0Tr/zh1HNEW0V6v+1md8zMT67b2Y4b9fDur+4TxmOExIVndpyzLL6evn8U+V25W9zljLx4XktV9EVvNQVndl7HMRbK6rxh7sVlIVvd1lDXnldV9E91ceWZ13zL24gkhWd13kdecb1b3faRzFZDV/cDYiyeFZHU/RlJziKzup/DnCpnV/czYiy1Csrpfwqs5rKzu13DmCjOr+42xF08JyeqOhao5gqzuuMWX1f3O2IunhWR1Jyy+rO4Piy+r+5OxF1uFZHUnLb6s7i+LL6vTB7tcvXhGSFYX5+XL6iwvX1bnZezFs0LOgzOeH1CMx7dqM+N58G1CesF4HKQY9+PVFsZePCekF4z7e4pxf0VtZezF80J6wfi9phi3y2obYy9eEJLVMX5+FeP6pziXn+UJfnFndc345srN6oqg0UVBMVBcZyegJCgFSoMyoCwoB8qDCqAiqAQqgyqgKqgGqoMaoCaoBWqDOuA0UBfUA/GgPmgAGpKsrgjJcooSXYzo4kSXILok0aWILk10GaLLEl2O6PJEVyC6ItGViK5MdBWiqxJdjejqRNcguibRtYiuTXQdok8jui7R9YiOJ7o+0Q2Ibuh1P6tzfmZi3dYWYdjPt7O6oozHDDuEZHXFWJZfTl+Lxz5XblZXgrEXO4VkdSVjqzkoqysVy1wkqyvN2ItdQrK6MlHWnFdWVza6ufLM6sox9mK3kKyufOQ155vVVYh0rgKyuoqMvdgjJKurFEnNIbK6yuHPFTKrq8LYi71Csrqq4dUcVlZXLZy5wszqqjP2Yp+QrK5GqJojyOpqevmyulqMvdgvJKur7eXL6up4+bK60xh7cUBIVlfXy5fV1fPyZXXxjL04KCSrq+/ly+oaePmyuoaMvTgk5Dw44/kBxXh8q3Yxngc/LKQXjMdBinE/Xu1l7MURIb1g3N9TjPsr6gBjL44K6QXj95pi3C6rw4y9eF9IVsf4+VWM65/iXH5uZ3XN+ebKzeoaodGNQRPQFDQDzUEL0BK0Aq1BG9AW+IACCSARJIFkkAL8IABSQTvQHnQAHUEn0FnvJ4GuoBvo7vUEZXWNSJbTmOgmRDcluhnRzYluQXRLolsR3ZroNkS3JdpHtCI6gehEopOITiY6hWg/0QGiU4luR3R7ojsQ3ZHoTkR3JroL0V2J7kZ0d6/7WZ3zMxPrtrYRS9aUk9U1Zjxm+F5IVteEZfnl9LVp7HPlZnXNGHvxg5CsrnlsNQdldS1imYtkdS0Ze/GjkKyuVZQ155XVtY5urjyzujaMvfhJSFbXNvKa883qfJHOVUBWpxh78bOQrC4hkppDZHWJ4c8VMqtLYuzFL0KyuuTwag4rq0sJZ64wszo/Yy9+FZLVBULVHEFWl+rly+raMfbiNyFZXXsvX1bXwcuX1XVk7MUxIVldJy9fVtfZy5fVdWHsxXEhWV1XL19W183Ll9V1Z+zF70LOgzOeH1CMx7fqR8bz4CeE9ILxOEgx7serXxh78YeQXjDu7ynG/RV1jLEXfwrpBeP3mmLcLqsTjL04KSSrY/z8Ksb1T3EuP7ezuhZ8c+VmdT3Q6J6gF+gN+oC+oB/oDwaAgWAQGAyGgKFgGBgORoCRYBQYDcaA08FYMA6MBxPARDAJTAZpIB1keD1BWV0PkuX0JLoX0b2J7kN0X6L7Ed2f6AFEDyR6ENGDiR5C9FCihxE9nOgRRI8kehTRo4keQ/TpRI8lehzR44meQPREoicRPZnoNKLTic7wup/VOT8zsW5re7BkTTlZXU/GY4ZyRWVkdb1Yll9OX3vHPlduVteHsRflC3MvHFld39hqDsrq+sUyF8nq+jP2okLh7MW/sroBUdacV1Y3MLq58szqBjH2omJh60U+Wd3gyGvON6sbEulcBWR1Qxl7Uanw9KLArG5YJDWHyOqGhz9XyKxuBGMvKheGXoSR1Y0Mr+awsrpR4cwVZlY3mrEXVf7bXoSd1Y0JVXMEWd3pXr6sbixjL6r+V72IMKsb5+XL6sZ7+bK6CYy9qHbqexFVVjfRy5fVTfLyZXWTGXtR/VT2IoasLs3Ll9Wle/myugzGXtQ4Rb3wxfZSjOcHFOPxrXIen8Xai5pCesF4HKQY9+NVZcZe1BLSC8b9PcW4v6KqMfaitpBeMH6vKcbtsqrJ2Is6LvXCy9wLxs+vYlz/FOfyczurOx7Hn9VlotFZIBtMAVPBNDAdzAAzwSwwG8wBc8EZYB44E8wHC8BZYCE4GywCi8E54FywBJwHzgdLwQXgQrDM6wnK6jJJlpNFdDbRU4ieSvQ0oqcTPYPomUTPIno20XOInkv0GUTPI/pMoucTvYDos4heSPTZRC8iejHR5xB9LtFLiD6P6POJXkr0BURfSPQyr/tZnfMzE+u2NpMla8rJ6rIYjxlaCcnqslmWX05fp8Q+V25WN5WxF62FZHXTYqs5KKubHstcJKubwdiLNkKyuplR1pxXVjcrurnyzOpmM/airZCsbk7kNeeb1c2NdK4CsrozGHvhE5LVzYuk5hBZ3ZnhzxUyq5vP2AslJKtbEF7NYWV1Z4UzV5hZ3ULGXiQIyerODlVzBFndIi9fVreYsReJQrK6c7x8Wd25Xr6sbgljL5KEZHXnefmyuvO9fFndUsZeJAvJ6i7w8mV1F3r5srpljL1IEXIenPH8gGI8vlVtGM+D+4X0gvE4SDHuxyvF2IuAkF4w7u8pxv0VlcTYi1QhvWD8XlOM22XlZ+xFOyFZHePnVzGuf6qdoKwujm+u3KzuIjT6YnAJuBRcBi4HV4ArwVXganANuBZcB64HN4AbwU3gZnALuBUsByvASrAKrAZrwFqwDqwHG8BGsMnrCcrqLiJZzsVEX0L0pURfRvTlRF9B9JVEX0X01URfQ/S1RF9H9PVE30D0jUTfRPTNRN9C9K1ELyd6BdEriV5F9Gqi1xC9luh1RK8negPRG4ne5HU/q3N+ZmLd1l7EkjXlZHUXMx4z9BOS1V3Csvxy+npp7HPlZnWXMfaiv5Cs7vLYag7K6q6IZS6S1V3J2IsBQrK6q6KsOa+s7uro5sozq7uGsRcDhWR110Zec75Z3XWRzlVAVnc9Yy8GCcnqboik5hBZ3Y3hzxUyq7uJsReDhWR1N4dXc1hZ3S3hzBVmVncrYy+GCMnqloeqOYKsboWXL6tbydiLoUKyulVevqxutZcvq1vD2IthQrK6tV6+rG6dly+rW8/Yi+FCsroNXr6sbqOXL6vbxNiLEULOgzOeH1CMx7dqAON58JFCesF4HKQY9+PVYMZejBLSC8b9PcW4v6KGMfZitJBeMH6vKcbtshrJ2IsxQrI6xs+vYlz/lFvLj+Z0sfb5Ni+bz2Q3fd7O51O56fMONp8BV5fnnXw+U9z0eRebz6QkN33ezeYz1e+mz3vYfKYkuunzXj6fGW76vI/NZ7arfb+fzWeyq9ulB9h8pmW56fNBNp/+dDd9PsTmM9PV5fkw3/e7q9ulR/g+7wlu+nyUb/vp6nbpMTafGa6un4/zbZdc3X5uZvOZ4OpxxxN8+0sBN30+yeZTubofsoWv764eHz3F93l3dTv/NN/209X1cytf39Pc9PkM3/Yz202fz/IdF7v6/b6Nb3m6evz+HJvPxL+vj9XncpsZk/Y1ufa1uvY1vPa1vfY1v/a1wPY1wva1w/Y1xfa1xvY1yPa1yfY1y/a1zPY1zva1z/Y10fa10vY11Pa11fY11/a12PY12va12/Y13fa13vY14Pa14fY14/a15PY15va157/E5T3els+f3x7i79HxDvP7d5rxLjPebcZ7zHivGe8z4/1mfMCMD5rxITM+bMZHzPioGR/zBvt83IybzfiEGZ804xYzPmXGp8241YzPmPFZM24z43Nm/MjKGT804wdmfN+MR814xIyHzXjIjAfNeMCM+824z4x7zbjHjLvNuMuMO824w4zvmfFdM75jxrfN+JYZ3zTjG2Z83YzbzfiaGV814ytmfNmML1mRrQf/20Z7/fKa0TJjnBk9ZvzLLKeTZvzTjH+Y8YQZfzfjcTMeM+NvZvzVXt5m/NmMP5nxRzP+YMbvzfidGb814zdm/NqMX5nxSzN+YcbPzfiZGT814ydm/NiMDU2dDcxY34zxZqxnxrpmPM2MdcxY24y1zFjTjDXMWN2M1cxY1YxVzFjZjJXMWNGMFcxY3ozlzFjWjGXMWNqMpcxY0owlzFjcjMXMWNSMRczY3YzdzNjVjF3M2NmMnczY0YwdzNjejO3MmGrGgBn9ZkwxY7IZk8yYaMYEMyoz+szY1oxtzNjajK3M2NKMLczY3IzNzNjUjE3M2NiMjcxoPyvKfoaU/WypyWa0n0VlP6PKfnaV/Uwr+1lX9jOw7Gdj2c/Msp+lZT9jy372lv1MLvtZXfYzvOxne9nP/LKfBWY/I8x+dpj9TDH7WWP2M8jsZ5PZzyyzn2VmP+PMfvaZ/Uw0+/579n357Pv1LTWjfX8/+75/9v0A7fsE2vcPtO8raN9v0L4PoX1/Qvu+hfb9DO37HNr3P7Tvi2jfL9G+j6J9f0X7vov2/Rjt+zTa92+07+to3+/Rvg+kfX9I+76R9v0k7ftMPo/xBfAieAm8DF4Br4LXwHbwOngDvAneAm+Dd8C74D2wA+wEu8BusAfsBfvAfnAAHASHwGFwBBwF7wNEpB57n46+CvP/j5iHXbYMVfss4cn7Rf+NQHIAO+ep/pTElIxsf3JyWpY/PTPLl5idkOLPyPKptOQEnB1RGQkqIzElkJCWlo3/pCQqt5bxyTj3ljGXR7dqb+rhr53bYzMBHpsL8Mj5zFC3PB536bPI7dOy+HzGOXx+4P3Ha+6Ly7RzTovMHesJE06frTzurATcNTN+OavWQmq2GGtuI6RmL2PNbYXUXISxZp+Qmosy1qxOUc2+2F4qgXH5/SbkyzvRI8NnkhCfyUJ8pgjx6RfiMyDEZ6oQn+2E+GwvxGcHIT47CvHZSYjPzkJ8dhHis6sQn92E+OwuxGcPIT57CvHZS4jP3kJ89hHis68Qn/2E+OwvxOcAIT4HCvE5SIjPwUJ8DhHic6gQn8OE+BwuxOcIIT5HCvE5SojP0UJ8jhHi83QhPscK8TlOiM/xQnxOEOJzohCfk4T4nCzEZ5oQn+lCfGYI8ZkpxGeWEJ/ZQnxOEeJzqhCf04T4nC7E5wwhPmcK8TlLiM/ZQnzOEeJzrhCfZwjxOU+IzzOF+JwvxOcCIT7PEuJzoRCfZwvxuUiIz8VCfJ4jxOe5QnwuEeLzPCE+zxfic6kQnxcI8XmhEJ/LhPi8SIjPi4X4vESIz0uF+LxMiM/Lhfi8QojPK4X4vEqIz6uF+LxGiM9rhfi8TojP64X4vEGIzxuF+LxJiM+bhfi8RYjPW4X4XC7E5wohPlcK8blKiM/VQnyuEeJzrRCf64T4XC/E5wYhPjcK8blJiM/bhPi8XYjPO4T4vFOIz7uE+LxbiM97hPi8V4jP+4T4vF+IzweE+HxQiM+HhPh8WIjPR4T4fFSIz8eE+HxciM/NQnw+IcTnk0J8bhHi8ykhPp8W4nOrEJ/PCPH5rBCf24T4fE6Iz+eF+HxBiM8Xhfh8SYjPl4X4fEWIz1eF+HxNiM/tQny+LsTnG0J8vinE51tCfL4txOc7Qny+K8Tne0J87hDic6cQn7uE+NwtxOceIT73CvG5T4jP/UJ8HhDi86AQn4eE+DwsxOcRIT6PCvH5vhCfHwjx+aEQnx8J8fmxEJ+fCPH5qRCfnwnx+bkQn18I8fmlEJ9fCfH5tRCf3wjx+a0Qn98J8fm9EJ8/CPH5oxCfPwnx+bMQn78I8fmrEJ+/CfF5TIjP40J8/i7E5wkhPv8Q4vNPIT5PCvH5lxCfekIJPuOE+LSE+PQK8VlEiM+iQnwWE+KzuBCfJYT4LCnEZykhPksL8VlGiM+yQnyWE+KzvBCfFYT4rCjEZyUhPisL8VlFiM+qQnxWE+Kzuks+LWafNRw+E30pSUlZ/oQslajSfAmp6YFkX1JyekpABVRyIDkzIZCYmBVICvhT01P9vlSVlJilspNTE7PNZCeF1FyTseZjQtbHWkJ81hbis44Qn6cJ8VlXiM96QnzGC/FZX4jPBkJ8NhTis5EQn42F+GwixGdTIT6bCfHZXIjPFkJ8thTis5UQn62F+GwjxGdbIT59QnwqIT4ThPhMFOIzSYjPZCE+U4T49AvxGRDiM1WIz3ZCfLYX4rODEJ8dhfjsJMRnZyE+uwjx2VWIz25CfHYX4rOHEJ89hfjsJcRnbyE++wjx2VeIz35CfPYX4nOAEJ8DhfgcJMTnYCE+hwjxOVSIz2FCfA4X4nOEEJ8jhfgcJcTnaCE+xwjxeboQn2OF+BwnxOd4IT4nCPE5UYjPSUJ8ThbiM02Iz3QhPjOE+MwU4jNLiM9sIT6nCPE5VYjPaUJ8Thfic4YQnzOF+JwlxOdsIT7nCPE5V4jPM4T4nCfE55lCfM4X4nOBEJ9nueTTIj5j/f+1mzDWvPAU1eyL7aXOjuNbfl5Lxvq4SMjnZrEQn+cI8XmuEJ9LhPg8T4jP84X4XCrE5wVCfF4oxOcyIT4vEuLzYiE+LxHi81IhPi8T4vNyIT6vEOLzSiE+rxLi82ohPq8R4vNaIT6vE+LzeiE+bxDi80YhPm8S4vNmIT5vEeLzViE+lwvxuUKIz5VCfK4S4nO1EJ9rhPhcK8TnOiE+1wvxuUGIz41CfG4S4vM2IT5vF+LzDiE+7xTi8y4hPu8W4vMeIT7vFeLzPiE+7xfi8wEhPh8U4vMhIT4fFuLzESE+HxXi8zEhPh8X4nOzEJ9PCPH5pBCfW4T4fEqIz6eF+NwqxOczQnw+K8TnNiE+nxPi83khPl8Q4vNFIT5fEuLzZSE+XxHi81UhPl9zyWcR4jPRl5IYw/8npZ73Bs2VlJQZ/Vwv0Lmy/CrauV7891xR/79gU4uesl7k+PRFV/NLedfsi2aul/NZfqnZkc/1CmMvpp3qXuT4DERa86sF1eyPbK7XClx+SdmRzLWdsRfT/5te5PhMCr/m10PXnBzuXG+Es/x84c31JmMvZvyXvcjx6Qun5rfCrdkfeq63w19+GaHmeoexFzP/+17k+PQXXPO7kdWcUNBc70W6/Pz5z7WDsRezCksvcnz686t5ZzQ1B/Kea1d0yy+Q11y7GXsxu3D14m+fKdn/rnlP9DX76Fx7Y1l+CcFz7WPsxZxC2Avj0+eseX+sNSf9M9eB2Jdfgj3XQcZezC28vfjbZ1aOUXXIyzFXtp5NHWaaC7OpI4y9OKOQ98L2edTLd66B8fhWOY/PYq1x3inqhS+2l2I8DlKM+/FqJmMvzhTSC8b9PcW4v6LmMPZivpBeMH6vKcbtsprH2IsFQnqxne98smLcFijGdVm51QuLuRevx/Gtf5YlI894I45pfy8rM9lNn28KyYfeEuLzbSE+3xHi810hPt8T4nOHEJ87hfjcFXdqvoNj/d4sxljzbiE1F2eseY+Qmksw1rxXSM0lGWveJ6TmUow17xdSc2nGmg8IqbkMY80HhdRclrHmQ0JqLsdY82EhNZdnrPmIkJorMNZ8VEjNFRlrfl9IzZUYa/5ASM2VGWv+UEjNVRhr/khIzVUZa/5YSM3VGGv+REjN1Rlr/lRIzTUYa/5MSM01GWv+XEjNtRhr/kJIzbUZa/5SSM11GGv+SkjNpzHW/LWQmusy1vyNkJrrMdb8rZCa4xlr/k5IzfUZa/5eSM0NGGv+QUjNDRlr/lFIzY0Ya/5JSM2NGWv+mbFmnY3b1+G1ctQfZ5aB1/x5UaDzZJ2v6rxR5286j9L5jM4r9Pl7fT5bn9/V5zv1+T99PkyfH9LnS/T5A308rY8v9fGWPv7Q++N6/1Tvr+n9F/19rr/f4oHe/untgf586PVFLz/9vM+moBloDlqAlg7P2+P+qaM1aAPa6mUEFEjQfQRJQF9glQL8IABSQTvQHnQAHUEn0Nn0rSvoBrqDHqAn6AV6gz6gL+gH+oMBYCAYBAaDIWAoGAaGgxFgJBgFRoMx4HQwFowD48EEMBFMApNBGkgHGSATZIFsMAVMBdPAdDADzASzwGwwB8wFZ4B54EwwHywAZ4GF4GywCCwG54BzwRJwHjgfLAUXgAvBMnARuBhcAi4Fl4HLwRXgSnAVuBpcA64F14HrwQ3gRnATuBncAm4Fy8EKsBKsAqvBGrAWrAPrwQawEWwCt4HbwR3gTnAXuBvcA+4F94H7wQPgQfAQeBg8Ah4Fj4HHwWbwBHgSbAFPgafBVvAMeBZsA8+B58EL4EXwEngZvAJeBa+B7eB18AZ4E7wF3gbvgHfBe2AH2Al2gd1gD9gL9oH94AA4CA6Bw+AIOAreBx+AD8FH4GPwCfgUfAY+B1+AL8FX4GvwDfgWfAe+Bz+AH8FP4GfwC/gV/AaOgePgd3AC/AH+BCfBX0BvDOKABbygCCgKioHioAQoCUqB0qAMKAvKgfKgAqgIKoHKoAqoCqqB6qAGqAlqgdqgDjgN1AX1QDyoDxqAhqARaAyagKagGWgOWoCWoBVoDdqAtkBv5BRIAIkgCSSDFOAHAZAK2oH2oAPoCDqBznpbC7qCbqA76AF6gl6gN+gD+oJ+oD8YAAaCQWAwGAKGgmFgOBgBRoJRYDQYA04HY8E4MB5MABPBJDAZpIF0kAEyQRbIBlPAVDANTAczwEwwC8wG+hnz+vnt+tno+rnj+pne+nnZ+lnU+jnP+rnH+pnC+hm7+vm1+tmw+rmr+pmm+nmh+lmcS4F+hqR+PqN+9qF+rqB+Zp9+Hp5+1px+jpt+Rpp+/ph+tpd+bpZ+JpV+3pN+lpJ+TpF+BpB+vo5+do1+Lox+5op+nol+Voh+Dod+xoV+foR+NoN+7oF+poC+X7++F/56oO/hru+Pru89ru/rre+Zre9Hre/1rO+jrO9RrO//q++tq+9bq+8Jq++3qu9lqu8Tqu/Bqe9vqe8dqe/LqO95qO8nqO/Vp++Dp+8xp+/fpu+Npu87pu/ppe+Xpe9Fpe/zpO+hpO9PpO/9o++ro+9Zo+8Ho++1ou9jor979DXP+hpgfX2tvnZVXxeqr7nU1zPqawX1dXj6Gjd9/Zi+nkpfX6Svt9HXn+jrMfT1CTqv1/m1znN1vqnzPp1/6TxI5yM6L9Dnz/X5ZH1+VZ9v1Off9PkofX5Gn6/Qx+/6eFYf3+njHb3/r/eH9f6h3l/S+w/6e91+VXH8XMeMafPnZ82aOz9+/pz4tMzM+IXT5k+Nn3NW1rzsmXMWOn8vkr9TL8K/E2fvhPUwYwnHBPEepp2gQEJSMcfkjTzBL8v5D5f4Z9DvxxkdR963jLbI+16jveT9IkYXIe8XNbooeb+Y0cXI+8WNLk7eL2Fr8n5Jo0uS90sZXYq8X9ro0uT9MkaXIe+XLZGj7dF+v5zR5cj75Y0uT96vYHQF8n5FoyuS9ysZXYm8X9noyuT9KkZXIe9XNboqeb+a0dXI+9WNrk7er2F0DfJ+TaNrkvdrGV2LvF/b6NqO9+0/0694D9dnIueiQi/3vDh40fMWYferMvS8RV3wqw9wipm57OVc2vFzMcd79s9FHO8VIb+nD6CamZ/1QVIj00v7pWUp/joCJYwf7uWD75K/DwDtuuMdfSjteN/+ndZm1L/T1vF7xR2/a/95pzz+3H7FER3v+LmUY1mW46/574Pm8g6f8Y5/x/lvV3B4Zfq3lfPfjjPY/055xzK0f+7o+F379+zlYS9r23tZg4d4p3+vOPl75Ry/UzaP+uOZ6y9H/JQjnnVPEhw/O9cj++Pm7FNJF3w6twfOf8uFbVSglKOuzKz0BVMGzJniIS97W66Xn73tcu7E2b7+3o9w+KV/1/m5K0HmiDd/3/k7+iBSL9+KZE7WZRDwZTj34Up7gl957dPEe4K3486/m1uv43uW/zvLl3AqvrNKOeqi21jn91Nxx1jW8ef2vp69nCo63rP7rNe/SubnrFnT5o+cnTU7Y96iufOzMrEmOtcG+1+ha0gRh7YcPzvXPPt3nGsQ/ca157PHuDz+LboGOpeW7S+vb3i9Fv8P4JxUBuEKAwA=","debug_symbols":"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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"salt","type":{"kind":"field"}},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"public_keys_hash","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::public_keys_hash::PublicKeysHash"}},{"name":"universal_deploy","type":{"kind":"boolean"}}],"kind":"struct","path":"ContractInstanceDeployer::deploy_parameters"}}],"kind":"struct","path":"ContractInstanceDeployer::deploy_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"127":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr","source":"use dep::protocol_types::address::AztecAddress;\n\n// TODO: this is awful but since we can't have a fn that maps [Field; N] -> [u8; 480 + N * 32]\n// (where N is the note pre-image size and 480 + N * 32 is the encryption output size)\n// The fns for LensForEncryptedLog are never used, it's just to tell the compiler what the lens are\n\n// The to_bytes fn for ToBytesForUnencryptedLog is used to allow us to hash some generic T\n\n// I could have omitted N from the trait, but wanted to keep it strictly for field arrs\n// TODO(1139): Once we enc inside the circuit, we will no longer need the oracle to return\n// anything, so we can remove this trait\ntrait LensForEncryptedLog {\n // N = note preimage input in fields\n // M = encryption output len in bytes (= 480 + N * 32)\n fn output_fields(self: [Field; N]) -> [Field; N];\n fn output_bytes(self: [Field; N]) -> [u8; M];\n}\n\nimpl LensForEncryptedLog<1, 512> for [Field; 1] {\n fn output_fields(self) -> [Field; 1] {[self[0]; 1]}\n fn output_bytes(self) -> [u8; 512] {[self[0] as u8; 512]}\n}\nimpl LensForEncryptedLog<2, 544> for [Field; 2] {\n fn output_fields(self) -> [Field; 2] {[self[0]; 2]}\n fn output_bytes(self) -> [u8; 544] {[self[0] as u8; 544]}\n}\nimpl LensForEncryptedLog<3, 576> for [Field; 3] {\n fn output_fields(self) -> [Field; 3] {[self[0]; 3]}\n fn output_bytes(self) -> [u8; 576] {[self[0] as u8; 576]}\n}\nimpl LensForEncryptedLog<4, 608> for [Field; 4] {\n fn output_fields(self) -> [Field; 4] {[self[0]; 4]}\n fn output_bytes(self) -> [u8; 608] {[self[0] as u8; 608]}\n}\nimpl LensForEncryptedLog<5, 640> for [Field; 5] {\n fn output_fields(self) -> [Field; 5] {[self[0]; 5]}\n fn output_bytes(self) -> [u8; 640] {[self[0] as u8; 640]}\n}\nimpl LensForEncryptedLog<6, 672> for [Field; 6] {\n fn output_fields(self) -> [Field; 6] {[self[0]; 6]}\n fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]}\n}\n\ntrait LensForEncryptedEvent {\n // N = event preimage input in bytes\n // M = encryption output len in bytes (= 480 + M)\n fn output(self: [u8; N]) -> [u8; M];\n}\n\nimpl LensForEncryptedEvent<96, 512> for [u8; 96] {\n fn output(self) -> [u8; 512] {[self[0] as u8; 512]}\n}\nimpl LensForEncryptedEvent<128, 544> for [u8; 128] {\n fn output(self) -> [u8; 544] {[self[0] as u8; 544]}\n}\nimpl LensForEncryptedEvent<160, 576> for [u8; 160] {\n fn output(self) -> [u8; 576] {[self[0] as u8; 576]}\n}\nimpl LensForEncryptedEvent<192, 608> for [u8; 192] {\n fn output(self) -> [u8; 608] {[self[0] as u8; 608]}\n}\nimpl LensForEncryptedEvent<224, 640> for [u8; 224] {\n fn output(self) -> [u8; 640] {[self[0] as u8; 640]}\n}\nimpl LensForEncryptedEvent<256, 672> for [u8; 256] {\n fn output(self) -> [u8; 672] {[self[0] as u8; 672]}\n}\n\n// This trait defines the length of the inputs in bytes to\n// the unencrypted log hash fn, where the log can be any type T\n// as long as the ACVM can convert to fields.\ntrait ToBytesForUnencryptedLog {\n // N = preimage input in bytes (32 * num fields or chars)\n // M = full log input in bytes ( = N + 40 = N + 32 for addr, + 4 for selector, + 4 for len)\n fn to_be_bytes_arr(self) -> [u8; N];\n fn output_bytes(self) -> [u8; M];\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for Field {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n self.to_be_bytes(32).as_array()\n }\n fn output_bytes(self) -> [u8; 72] {[self as u8; 72]}\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for AztecAddress {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n self.to_field().to_be_bytes(32).as_array()\n }\n fn output_bytes(self) -> [u8; 72] {[self.to_field() as u8; 72]}\n}\n\nfn arr_to_be_bytes_arr(fields: [Field; L]) -> [u8; N] {\n let mut bytes: [u8] = &[];\n for i in 0..L {\n // Note that bytes.append() results in bound error\n let to_add = fields[i].to_be_bytes(32);\n for j in 0..32 {\n bytes = bytes.push_back(to_add[j]);\n }\n }\n bytes.as_array()\n}\n\n// each character of a string is converted into a byte\n// then an ACVM field via the oracle => we recreate here\nfn str_to_be_bytes_arr(string: str) -> [u8; N] {\n let chars_bytes = string.as_bytes();\n let mut bytes: [u8] = &[];\n for i in 0..L {\n let to_add = (chars_bytes[i] as Field).to_be_bytes(32);\n for j in 0..32 {\n bytes = bytes.push_back(to_add[j]);\n }\n }\n bytes.as_array()\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for [Field; 1] {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 72] {\n [self[0] as u8; 72]\n }\n}\n\nimpl ToBytesForUnencryptedLog<64, 104> for [Field; 2] {\n fn to_be_bytes_arr(self) -> [u8; 64] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 104] {\n [self[0] as u8; 104]\n }\n}\n\nimpl ToBytesForUnencryptedLog<96, 136> for [Field; 3] {\n fn to_be_bytes_arr(self) -> [u8; 96] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 136] {\n [self[0] as u8; 136]\n }\n}\n\nimpl ToBytesForUnencryptedLog<128, 168> for [Field; 4] {\n fn to_be_bytes_arr(self) -> [u8; 128] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 168] {\n [self[0] as u8; 168]\n }\n}\n\nimpl ToBytesForUnencryptedLog<160, 200> for [Field; 5] {\n fn to_be_bytes_arr(self) -> [u8; 160] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 200] {\n [self[0] as u8; 200]\n }\n}\n\nimpl ToBytesForUnencryptedLog<192, 232> for [Field; 6] {\n fn to_be_bytes_arr(self) -> [u8; 192] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 232] {\n [self[0] as u8; 232]\n }\n}\n\nimpl ToBytesForUnencryptedLog<224, 264> for [Field; 7] {\n fn to_be_bytes_arr(self) -> [u8; 224] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 264] {\n [self[0] as u8; 264]\n }\n}\n\nimpl ToBytesForUnencryptedLog<256, 296> for [Field; 8] {\n fn to_be_bytes_arr(self) -> [u8; 256] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 296] {\n [self[0] as u8; 296]\n }\n}\n\nimpl ToBytesForUnencryptedLog<288, 328> for [Field; 9] {\n fn to_be_bytes_arr(self) -> [u8; 288] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 328] {\n [self[0] as u8; 328]\n }\n}\n\nimpl ToBytesForUnencryptedLog<320, 360> for [Field; 10] {\n fn to_be_bytes_arr(self) -> [u8; 320] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 360] {\n [self[0] as u8; 360]\n }\n}\n\nimpl ToBytesForUnencryptedLog<352, 392> for [Field; 11] {\n fn to_be_bytes_arr(self) -> [u8; 352] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 392] {\n [self[0] as u8; 392]\n }\n}\n\nimpl ToBytesForUnencryptedLog<384, 424> for [Field; 12] {\n fn to_be_bytes_arr(self) -> [u8; 384] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 424] {\n [self[0] as u8; 424]\n }\n}\n\nimpl ToBytesForUnencryptedLog<416, 456> for [Field; 13] {\n fn to_be_bytes_arr(self) -> [u8; 416] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 456] {\n [self[0] as u8; 456]\n }\n}\n\nimpl ToBytesForUnencryptedLog<448, 488> for [Field; 14] {\n fn to_be_bytes_arr(self) -> [u8; 448] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 488] {\n [self[0] as u8; 488]\n }\n}\n\nimpl ToBytesForUnencryptedLog<480, 520> for [Field; 15] {\n fn to_be_bytes_arr(self) -> [u8; 480] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 520] {\n [self[0] as u8; 520]\n }\n}\n\nimpl ToBytesForUnencryptedLog<512, 552> for [Field; 16] {\n fn to_be_bytes_arr(self) -> [u8; 512] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 552] {\n [self[0] as u8; 552]\n }\n}\n\nimpl ToBytesForUnencryptedLog<544, 584> for [Field; 17] {\n fn to_be_bytes_arr(self) -> [u8; 544] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 584] {\n [self[0] as u8; 584]\n }\n}\n\nimpl ToBytesForUnencryptedLog<576, 616> for [Field; 18] {\n fn to_be_bytes_arr(self) -> [u8; 576] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 616] {\n [self[0] as u8; 616]\n }\n}\n\nimpl ToBytesForUnencryptedLog<608, 648> for [Field; 19] {\n fn to_be_bytes_arr(self) -> [u8; 608] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 648] {\n [self[0] as u8; 648]\n }\n}\n\nimpl ToBytesForUnencryptedLog<640, 680> for [Field; 20] {\n fn to_be_bytes_arr(self) -> [u8; 640] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 680] {\n [self[0] as u8; 680]\n }\n}\n\nimpl ToBytesForUnencryptedLog<672, 712> for [Field; 21] {\n fn to_be_bytes_arr(self) -> [u8; 672] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 712] {\n [self[0] as u8; 712]\n }\n}\n\nimpl ToBytesForUnencryptedLog<704, 744> for [Field; 22] {\n fn to_be_bytes_arr(self) -> [u8; 704] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 744] {\n [self[0] as u8; 744]\n }\n}\n\nimpl ToBytesForUnencryptedLog<736, 776> for [Field; 23] {\n fn to_be_bytes_arr(self) -> [u8; 736] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 776] {\n [self[0] as u8; 776]\n }\n}\n\nimpl ToBytesForUnencryptedLog<768, 808> for [Field; 24] {\n fn to_be_bytes_arr(self) -> [u8; 768] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 808] {\n [self[0] as u8; 808]\n }\n}\n\nimpl ToBytesForUnencryptedLog for str where [Field; L]: ToBytesForUnencryptedLog {\n fn to_be_bytes_arr(self) -> [u8; N] {\n str_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; M] {\n [0; M]\n }\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"288":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr","source":"mod events;\n\ncontract ContractInstanceDeployer {\n use dep::aztec::protocol_types::{\n address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress},\n contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE,\n traits::Serialize\n };\n\n use crate::events::{instance_deployed::ContractInstanceDeployed};\n\n #[aztec(private)]\n fn deploy(\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys_hash: PublicKeysHash,\n universal_deploy: bool\n ) {\n // TODO(@spalladino): assert nullifier_exists silo(contract_class_id, ContractClassRegisterer)\n\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.msg_sender()\n };\n\n let partial_address = PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n let address = AztecAddress::compute(public_keys_hash, partial_address);\n\n // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed\n context.push_new_nullifier(address.to_field(), 0);\n\n // Broadcast the event\n let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 };\n let event_payload = event.serialize();\n dep::aztec::oracle::debug_log::debug_log_format(\"ContractInstanceDeployed: {}\", event_payload);\n context.emit_unencrypted_log(event_payload);\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/GasToken.json b/yarn-project/protocol-contracts/src/artifacts/GasToken.json new file mode 100644 index 000000000000..df953de52daa --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/GasToken.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"GasToken","functions":[{"name":"_increase_public_balance","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(internal)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"deploy","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"artifact_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_root","type":{"kind":"field"},"visibility":"private"},{"name":"public_bytecode_commitment","type":{"kind":"field"},"visibility":"private"},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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1JWH76du8v3UTb6fusn3Uzf5furqZPPsO77vp27y/dRNvp+6yfdTN/l+6mbfT93s+6mbfT91s++nrk42z77j+37qZt9P3ez7qZt9P3Wz76du8f3ULb6fusX3U7f4furqJCPtO77vp27x/dQtvp+6xfdTt/h+6orvp674fuqK76eu+H7q6uRS7Tu+76eu+H7qiu+nrvh+6orvp271/dStvp+61fdTt/p+6urkUu07vu+nbvX91K2+n7rV91O3+n7qNt9P3eb7qdt8P3Wb76euTrbUvuP7fuo230/d5vup23w/dZvvp273/dTtvp+63fdTt/t+6urkPe07vu+nbvf91O2+n7rd91O3+37q+s6mEt/ZVOI7m0p8Z1OJ72wq8Z1NJb6zqcR3NpX4zqYS39lU4jubSnxnU4nvbCrxnU0lvrOpxHc2lfjOphLf2VTiO5tKfGdTVd/ZVNV3NlX1nU1VfWdT1Yfrp271nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVM13NlXznU3VfGdTNd/ZVO3h+qnbfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlX3nU3VfWdTdd/ZVN13NlV/uH7qdt/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU01fGdTDd/ZVMN3NtXwnU01Hq6fusN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTTd/ZVNN3NtX0nU01fWdTzYfrp+70nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVM9zun7s/v2czs/v+sH7PKfrJ+/znK4fvc9zun72Ps/p+uH7PKfrp+/znK4fv89zOn/++o6pep7f+fPXd1DV8/zOn7++o6qe53f+/PUdVvU8v/Pnr++4quf5nT9/fQdWPc/v/PnrO7LqeX7nz1/foVXP8zt//vqOrXqe3/nz13dw1fP8zp+/vqOrnud3/vz1HV71PL/z56/v+Krn+Z0/f30HWD3P7/z56zvC6nl+589f3yFWz8M5f/76jrF6Hs7589d3kNXzcM6fv76jrJ6Hc/789R1m9Tyc8+ev7zir5/mdP399B1o9z+/8+es70up5fufPX9+hVs/zO3/++o61ep7f+fPXd7DV8/zOn7++o62e53f+/PUdbvU8v/Pnr+94q+f5nT9/fQdcPc/v/PnrO+LqeX7nz1/fIVfP8zt//vqOuXqe3/nz13fQ1fP8zp+/vqOunud3/vz1HXb1PL/z56/vuKvn+Z0/f30HXj3P7/z56zvy6nl+589f36FXz/M7f/76jr16nt/589d38NXz/M6fv76jr57nd/789R1+9Ty/8+ev7/ir5/l9P3+T8/yr5Dz/KjnPv0rO86+ep3N+ft/P3+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z7/KzvOvsvP8q+w8/yo7z7/KD9/P3+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvivP8q+I8/6o4z78qzvOvysP387c4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8K3GefyXO86/Eef6VOM+/kofv5684z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr6rz/KvqPP+qOs+/qs7zr+rD9/O3Os+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvmPP+qOc+/as7zr5rz/Kv28P38bc7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qO8+/6s7zr7rz/KvuPP+qP3w/f7vz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/Gs7zr4bz/KvhPP9qOM+/Gg/fz9/hPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr6bz/KvpPP9qOs+/ms7zr+bD9/N3Os+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bv/Kv88J1/9Ty/6+fv8/yun7/P87t+/j7P7/r5+zy/6+fv8/yun7/P87t+/j7P7/r5+zy/8+ev7/yr5/mdP3995189z+/8+es7/+p5fufPX9/5V8/zO3/++s6/ep7f+fPXd/7V8/zOn7++86+e53f+/PWdf/U8v/Pnr+/8q+f5nT9/fedfPc/v/PnrO//q+R2cP3995189v4Pz56/v/Kvnd3D+/PWdf/X8Ds6fv77zr57fwfnz13f+1fP8zp+/vvOvnud3/vz1nX/1PL/z56/v/Kvn+Z0/f33nXz3P7/z56zv/6nl+589f3/lXz/M7f/76zr96nt/589d3/tXz/M6fv77zr57nd/789Z1/9Ty/8+ev7/yr5/mdP3995189z+/8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5Z5nqNzzDJV7nqFyzzNU7nmGyj3PULnnGSr3PEPlnheo3PMClXteoHLPC1TueXkIVLVIWqpA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9F6jcc4HKPReo3HOByj2Xh0BVi6SlBCr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPJVJa9Oz59eFe3lcb6Al0XW2kROE5xuvDs7+vNtAttVBtoFtqoVqBqjaQ41uoNpDjW6g20vP2utpIz9vragM5vutqIyUKL1QLpaUiJQovVOtWSx0ViPsKbGuenuergpH7let+zPY6dUqfTt3qR722VY9+vbZ1j369tpWPfr22tY96vcYzgPXrta1/9Ou1rYD067WtgfTrFbB6wfSV8Txg/XrB9JXxTGD9esH0lfFcYP16wfSV8Wxg/XrB9JXxfGD9esH0lfGMYP16wfSV8Zxg/Xqx9FU1nhWsXy+WvqrG84L168XSV/UhYPVi6atqPDdYv14sfVWNZwfr1wumr4znB+vXC6avjGcI69cLpq+M5wjr1wumr4xnCevXC6avjOcJ69cLpq+MZwrr1wumr4znCuvXC6avjGcL69cLpq+M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778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcH7ryp4/1UF77+q4P1X9Yb9/q3g/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQPvv2rg/VcNvP+qgfdftRv2+7eB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vx28/6qD91918P6rDt5/1W/Y798O3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3Xw3w/qsB3n81wPuvBnj/1bhhv38HeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHef3V/UOwX8H8eFF0A9iv4/qDY7+D7g2K/hO8Piv0Wvj8o9mv4/qDY7+H7g2K/iO8Piv4mBq/CugtAfxODl2HdBaC/icHrsO4C0N/E4IVYdwHob2LwSqy7APQ3MXgp1l0A+psYvBbrLgD9TQxejHUXgP4mBq/GugtAfxODl2PdBaC/icHrse4C0N/E4AVZdwHob2Lwiqy7APQ3MXhJ1l0A+psYvCbrLgD9TQxelHV/OvQ3MXhV1v3p0N/E4GVZ96dDfxOD12Xdnw79TQxemHV/OvQ3MXhl1l0A+psYvDTrLgD9TQxem3UXgP4mBi/OugtAfxODV2fdBaC/icHLs+4C0N/E4PVZdwHob2LwAq27APQ3MXiF1l0A+psYvETrLgD9TQxeo3UXgP4mBi/SugtAfxODV2ndBaC/icHLtO4C0N/E4HVadwHob2LwQq27APQ3MXil1l0A+psYvFTrLgD9TQxeq3UXgP4mBi/WugtAfxODV2vdBaC/icHLte4C0N/E4PVadwHob2Lwgq27APQ3MXjF1l0A+Jt4Q+/Y2tA7tjb0jq0NvWPr/njoAsDfxBt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1oXdsbegdWxt6x9aG3rG1o3ds7egdWzt6x9aO3rG138DfxDt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3ds7egdWzt6x9aO3rG1o3dsHegdWwd6x9aB3rF1oHdsHTfwN/GB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdWwd6x9aB3rF1oHdsHegdW4besWXoHVuG3rFl6B1bdgN/Ext6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHlqF3bBl6x5ahd2wZeseWoXdsGXrHVkHv2CroHVsFvWOroHdslRv4m7igd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWxW9Y6uid2xV9I6tit6xVW/gb+KK3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bDX0jq2G3rHV0Du2GnrHVruBv4kbesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXRO7Y6esdWR+/Y6ugdW/0G/ibu6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x9ZA79ga6B1bA71ja6B3bI0b+Jt4oHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BrgHVv7Dbxj6y4A+018F4D9Jr4LwH4T3wVgv4nvArDfxHcB2G/iuwDsN/FdAPab+C4A/U0M3rF1F4D+Jgbv2LoLQH8Tg3ds3QWgv4nBO7buAtDfxOAdW3cB6G9i8I6tuwD0NzF4x9ZdAPqbGLxj6y4A/U0M3rF1F4D+Jgbv2LoLQH8Tg3ds3f8J9DcxeMfW/Z9AfxODd2zd/wn0NzF4x9b9n0B/E4N3bN3/CfQ3MXjH1l0A+psYvGPrLgD9TQzesXUXgP4mBu/YugtAfxODd2zdBaC/icE7tu4C0N/E4B1bdwHob2Lwjq27APQ3MXjH1l0A+psYvGPrLgD9TQzesXUXgP4mBu/YugtAfxODd2zdBaC/icE7tu4C0N/E4B1bdwHob2Lwjq27APQ3MXjH1l0A+psYvGPrLgD9TQzesXUXgP4mBu/YugtAfxODd2zdBaC/icE7tu4C0N/E4B1bdwHob2Lwjq27APQ3MXjH1l0A+psYvGPrLgD9TQzesXUXgP4mBu/YugtAfxODd2zdBaC/icE7tu4CwN/EG3rH1obesbWhd2xt6B1b98dDFwD+Jt7QO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tDb1ja0Pv2NrQO7Y29I6tHb1ja0fv2NrRO7Z29I6t/Qb+Jt7RO7Z29I6tHb1ja0fv2NrRO7Z29I6tHb1ja0fv2NrRO7Z29I6tHb1ja0fv2NrRO7Z29I6tHb1ja0fv2NrRO7Z29I6tHb1ja0fv2NrRO7Z29I6tHb1ja0fv2NpjNzwV2399bbEzAaHfAzMCQn8KldIfAmo7ERD6U2hGQOhPoRkBoT+FZgSEzgMTAmL3C80ICP0eqFv99bX12E8EhH4PzAgInQdmBBi6gNBv4hkBod/EMwJCv4lnBIR+E88ICP0mnhAQu19oRgD6mzh2v9CMAPQ3cex+oRkB6G/i2P1CMwLQ38Sx+4VmBPz9N/HpuvB/v7a38XiO3jd7PUft/2wRuaCNaKncjUvuziX3QJX7kmD4Egq+hIovoeFL6PgSYN3EU0KDdQgvCbBv/ZcE2Df5S0Lst3Nvt8cXj49m5B6VH4/Rtj+bkQXNSkvlxn7rfyXX+Zc9Wmw3sRRNbJeyFE1s97MUTWxXtRJNj+3WlqKJ7QKXoontLpeiSeRavdGY0JyhkRs+RSM3fIpGbvgUjdzwKRq54TM0Q274FI3c8CkaueFTNHLDp2hMaM7QyA2fopEbPkUjN3yKRm74FI3c8Ama4yY3fIpGbvgUjdzwKRq54VM0JjRnaOSGT9HIDZ+ikRs+RSM3fIpGbvgMzSY3fIpGbvgUjdzwKRq54VM0JjRnaOSGT9HIDZ+ikRs+RSM3fIpGbvgMzU7qaz43RR47qa+ZQUP6hvrc7HfspG+oGTSkb6gZNKRvqAk0B+m+ZgYN6b5mBg2pr/ncdHQcpL5mBo0JzRka0n3NDBpSNzyDhtQNz6AhdcMzaEjd8AQaI3XDM2hI3fAMGrnhUzRyw6doLBGaL77z1qs9FN7/lddXb3/66s8dSYdl8s5LQWZy2ktBZvLlS0FmcvFOIF9wMvl4bzglk5N3h5PJy7vDyeTm3eFk8vPucExwzuHIpb+Bw+q8R31852204zc4f1C41/5U2PsJSlbvfQFKVvf9JcqnQCt/jjHBr9/ggAx+VwcIJGsCcAfJmhbcQbImC3eQJpA+IFkTy3cgP29xg999AgJJmm3uz/b40et++/nM/zzbBL+CBYWSNN18i/LjCyf4TTAgkKTpxh8kabrxB0mabvxBmkD6gCRNN/4gSdPNlyA/p5tUV+uWgmTNNtv2ZLPt3SPbpLqJtxZlqht6F6L8+MJJdXFvKUjWdOMOkjXduIM0gfQByZpu3EGypht3kKzp5juQn9NNqpuFS0HS/tym1xfI8QFkG8/vfHt97XZPOU+Qqe4hLgVJ+3Mbb5C0yaZuT5DNPNYWqW4zLkZpQjmD8qOXTHX5cSlI2nTjDZI23XiDpE033iBpf3LjC9JS3bdcCpL25zZfgfy4uLBUtzOXglS22be+/zGt2M0E5xyOEsgbOKyp4r68ej7zXj6+MT+vDCzVfc7FKFmTxZcoP/s41mThDTLVrdClIFmThTtI1mThDpI1WbiDNIH0AcmaWL4D+XlpkOp+6lKQyjb3/7s9/pxWUt1bdYejBHIOZ6dNFT+XANvHN+bEymCnzRX+KGmTxXcoP/q4VHeDl4I0gfQBSZssvEHSJgtvkLTJwhskbQrxBkmbWL4C+XlpkOpe91KQyjZOIJVsnEAq2TiBNIH0Aalk4wRSycYJpJLN+Y4x1c1zdzhKIOdwUt09P/3OL7kU3v8lN7ZDH8/6wz5+fOd/Lje2j3aXa3nkTmySgl/7dpcb2zm6y43t79zlxnZs7nJjezBvucFvUH8n93M2C35V2l1uIlc1IzeRq5qRa1xyM7mqCbnBXVV/BcBx/PuIEPwmsrvc4K7qG7kzNiO4q3KWG/wGsLvc4K7KW25wV+UtN7ir8pZrieR+thnBL8i6y03kqmbkJnJVM3IzuaoJuZlc1We5sW+Pjps9vvO4lfrvI0LsC6H+ckO7qu/kTtiM2Nc2/eUal9zQrspfbmhX5S83tKvylxvaVX0pd8JmhHZV7nJj3zz0l5vIVc3IzeSqJuRmclUTcg1Gbv09AL4k4DilUwk47udUQnBHMx7PMe4P8u+zZuz7bP5ygzuab+RO+NXYt8785QZ3NN5ygzsab7nBHY23XOOSG9z9fCX3s1+NfcvKX24iVzUjN5GrmpGbyVV9lFti31jyl5vJVU3IBXJV448ZtsS+FDQnwUJL2Owl4cef6f75P7q+P3pQ+49n3rfth9zY7sddbmz385Xc1p+/7b7tH77z5w1FiX1DZy2a2K5qKZrYDmwlmth3a9aiie3slqKJ7QKXoontLpeiMaE5Q5PI4XqjkRs+RSM3fIpGbvgUjdzwGZrY91bWopEbPkUjN3yKRm74FI0JzRkaueFTNHLDp2jkhk/RyA2fopEbPkMT+z7HWjRyw6do5IZP0cgNn6IxoTlDQ+prij1+U6LYGRpSXzOBJnYv/IVoyuNEQKntBA3pG2oGDekbagYN6RtqBg3pvmYGDem+ZgYNqa+pW/31tfXYT9CQ+poZNKT7mgk0sTv616IhdcMzaEjd8AwaUjc8g8aE5gwNqRueQUPqhmfQyA2fopEbPkUjN3yGJvZthS/RfPGdW3v8EW/77UTqjz8wjH2HYS2aTG7YGU0mN+yMxoTmDE0mN+yMJpMbdkaTyQ3/MzSjnqDJ5Iad0WRyw75ogt/EuAzNj7qNo5ygIXXDM2hI3fAMGlI3PIPGhOYMDakbnkFD6oZn0JC64YmurOA3R5aiIXXDE2iC3zJxQvOSS+FwX3Jju9Z9f3zxOI7xQe526/Z46ruC11e3n/85x/aiFwg2NsGxfeMFgmO7wQsEx/Z4FwiO7dwuEBzbj/kLDn5f5QLBsX3WBYLZnFbwKysXCDY2wWxOK/itlQsEszmt4PdWLhBM5rRq8JsrFwgmc1o1+N2VCwSTOa16MzbBZE6rBr/rcoFgMqdVg99guUAwm9MKfi/lAsFsTiv4bZMLBLM5reB3SC4QzOa0gt8MuUAwm9MKft/jAsFsTiv4LY4LBLM5reB3My4QzOa0gt+4uEAwm9MKfo/iAsFsTiv47YgLBLM5reB3Hi4QzOa0gt9kuEAwm9MKfj/hAsFsTutgc1rB715cIJjNaR1sTsvYnFbwKyQXCGZzWsEvhlwg2NgEszmt4Dc7LhDM5rSC39e4QDCb0wp+C+MCwWxOK/jdigsEszmt4DcmLhDM5rSC34O4QDCb0wp+u+ECwWxOK/idhQsEszmt4DcRLhDM5rSC3y+4QDCb0wp+a+ACwWxOK/hdgAsEszmt4B3+Fwhmc1rB+/YvEMzmtIJ3418gmM1pBe+xv0Awm9MK3jl/gWA2pxW8H/4CwWxOi60jvrJ1xFe2jvjK1hFf2TriK1tHfGXriK9sHfGVrSO+snXEV7aO+MrWEV/ZOuIrW0d8ZeuIr2wd8ZWtI76ydcQ3to74xtYR39g64htbR3y7GZtgMqfV2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xDe2jvjG1hHf2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xDe2jvjG1hHf2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xDe2jvjG1hHf2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xHe2jvjO1hHf2TriO1tHfL8Zm2Ayp9XZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI75nahAfbX98cfv9O7/kJnoLz8hN9Ak9en988WgnchN9Ps/ITfTpPCM30WfzjNxEGXhCbqZG6Rm5md67E3IzvXcn5CbKvjNyjUsul6vK1CI9IxfWVb0kwDqll4TY7udoz/+ObNw8gnjwnucLBMd2QBcIju2BLhAc2wVdINjYBMd2QhcIju2FLhAc2w1dIDi2d7pAMJvTCt7zfIFgNqcVvOf5AsFsTit4z/MFgtmcVvCe5wsEszmt4D3PFwgmc1ojeM/zBYLJnNYI3vN8gWAypzVuxiaYzGmN4D3PFwgmc1ojeM/zBYLZnFbwnucLBLM5reA9zxcIZnNawXueLxDM5rSC9zxfIJjNaQXveb5AMJvTCt7zfIFgNqcVvOf5AsFsTit4z/MFgtmcVvCe5wsEszmt4D3PFwhmc1rBe54vEMzmtIL3PF8gmM1pBe95vkAwm9MK3vN8gWA2pxW85/kCwWxOK3jP8wWC2ZxW8J7nCwSzOa3gPc8XCGZzWsF7ni8QzOa0gvc8XyCYzWkF73m+QDCb0wre83yBYDanFbzn+QLBbE4reM/zBYLZnFbwnucLBLM5rcrmtII3eV8gmM1pVTanVY1NMJvTCt7YfoFgNqcVvLX9AsFsTit4c/sFgtmcVvD29gsEszmt4A3uFwhmc1rBW9wvEMzmtIK3vl8gmM1psXXED7aO+MHWET/YOuIHW0f8YOuIH2wd8YOtI36wdcQPto74wdYRP9g64gdbR/xg64gfbB3xg60jfrB1xA+2jvjB1hE/yDrijxtZR/xdMJfTugvmclp3wVxO6y7Y2ARzOa27YC6ndRfM5bTugrmc1l0wm9Mi64i/C2ZzWmQd8XfBbE6LrCP+LpjNaZF1xN8Fszktso74u2A2p0XWEX8XzOa0yDri74LZnBZZR/xdMJvTIuuIvwtmc1pkHfF3wWxOi6wj/i6YzWmRdcTfBbM5LbKO+LtgNqdF1hF/F8zmtMg64u+C2ZwWWUf8XTCb0yLriL8LZnNaZB3xd8FsTousI/4umM1pkXXE3wWzOS2yjvi7YDanRdYRfxfM5rTIOuLvgtmcFllH/F0wm9Mi64i/C2ZzWmQd8XfBbE6LrCP+LpjNaZF1xN8Fszktso74u2A2p0XWEX8XzOa0yDri74LZnBZZR/xdMJvTIuuIvwtmc1pkHfF3wWxOi6wj/i6YzWmRdcTfBbM5LbKO+LtgNqdF1hF/F8zmtMg64u+C2ZwWWUf8XTCb0yLriL8LZnNaZB3xd8FsTousI/4umM1pkXXE3wWzOS2yjvi7YDKntbF1xG9sHfEbW0f8xtYRf5fDJpjMaW1sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv7F1xG9sHfEbW0f8xtYRv2VqEB9tf3xx+/07P+Vm6g+fkZvoE3r05xePdiI30efzjNxEn84zchN9Ns/ITZSBZ+QmSsAzcjO9dz/LzdQmPSM3UfadkZso+c7I5XJVmVqkZ+TCuqqXBFin9JIQ2/0Ue0TrUUf/FMTL4zHuG6ST/+hiux93ubHdj7fc4A3P7nJjux93ubHdj7vc2O7HXa5xyY3tftzlxnZK7nK5XFXwRmd3uVyuKnibs7tcLlcVvMnZXS6Xqwre4uwul8tVBW9wdpfL5aqCtze7y6VyVXvw5mZ3uVSuag/e2uwul8pV7Tfjkkvlqvbgbc3ucqlc1R68qdldLperCt7S7C6Xy1UFb2h2l8vlqoK3M7vL5XJVwZuZ3eVyuargrczucrlcVfBGZne5XK4qeBuzu1wuVxW8idldLperCt7C7C6Xy1UFb2B2l8vlqoK3L7vL5XJVwZuX3eVyuargrcvucrlcVfDGZXe5XK4qeNuyu1wuVxW8adldLperCt6y7C6Xy1UFb1h2l8vlqoK3K7vL5XJVwZuV3eVyuargrcrucrlcVfBGZXe5XK4qeJuyu1wuVxW8SdldLperKlyuKnhLtrfc4C3Z7nK5XFXlclXBO9Dd5RqXXC5XFbwD3V0ul6sK3oHuLpfLVQXvQHeXy+Wqgnegu8vlclXBO9Dd5XK5quB96e5yuVwVV7f6ztWtvnN1q+9c3eo7V7f6ztWtvnN1q+9c3eo7V7f6ztWtvnN1q+9c3eo7V7f6ztWtvnN1q+9c3eo7V7f6ztWtvnN1q+9c3eo7V7f6ztWtfnB1qx9c3eoHV7f6wdWtftyMSy6Vqzq4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm71g6tb/eDqVj+4utUPrm514+pWN65udePqVjeubnW7GZdcKldlXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1uXN3qxtWtblzd6sbVrW5c3erG1a1umeqoR9sfX9yOE7mJXkQTcjMVFo/eH1882oncRB9VM3ITfVTNyDUuuYkC4IzcRAFwRm6m9+6E3Ezv3Qm5iQLghNxMhcUzcrlcVabC4hm5sK7qJcHwJcR2P20fDwl9b59i+G3Ux1Nv24+nruWH4Nj+5wLBsR3QBYJje6ALBMd2Qf6Cg1cMXyA4thO6QHBsL3SB4Nhu6ALBxiaYzWkFrxu+QDCb0wpeOXyBYDanFbx2+ALBbE4rePXwBYLZnFbw+uELBLM5reAVxBcIZnNawWuILxBM5rRK8CriCwSTOa0SvI74AsFkTqvcjE0wmdMqwWuJLxBM5rRK8GriCwSzOa3g9cQXCGZzWsErii8QzOa0gtcUXyCYzWkFryq+QDCb0wpeV3yBYDanFbyy+ALBbE4reG3xBYLZnFbw6uILBLM5reD1xRcIZnNawSuMLxDM5rSC1xhfIJjNaQWvMr5AMJvTCl5nfIFgNqcVvNL4AsFsTit4rfEFgtmcVvBq4wsEszmt4PXGFwhmc1rBK44vEMzmtILXHF8gmM1pBa86vkAwm9MKXnd8gWA2pxW88vgCwWxOqxibYDanVdicVvAm7wsEszmtwua0KpvTCt7XfoFgNqcVvLP9AsHGJpjNaQVvbr9AMJvTCt7efoFgNqcVvMH9AsFsTit4i/sFgtmcVvDW9wsEszktto74wtYRX9g64gtbR3xh64gvbB3xha0jvrB1xBe2jvjC1hFf2DriC1tHfGHriC9sHfGFrSO+sHXEF7aO+MLWEV/YOuILW0d8YeuIL2wd8YWtI76wdcRXto74ytYRX9k64itbR3y9GZtgMqdV2TriK1tHfGXriK9sHfGVrSO+snXEV7aO+MrWEV/ZOuIrW0d8ZeuIr2wd8ZWtI76ydcRXto74ytYRX9k64itbR3xl64ivmRrE71/9+OL2+3d+yU30Fp6Qm6lbevT++OLRTuQm+nyekZvo03lGbqLP5hm5iTLwjNxECXhGbqb37oTcTO/dCbmJsu+E3ExN0jNyuVxVphbpGbmwruolwfAlxHY/vbTnf0elfgritj+DuB3l9dVt/BAc2/9cIDi2A7pAcGwPdIHg2C7IX3DwnucLBMd2QhcIju2FLhAc2w1dINjYBLM5reA9zxcIZnNawXueLxDM5rSC9zxfIJjNaQXveb5AMJvTCt7zfIFgNqcVvOf5AsFsTit4z/MFgtmcVvCe5wsEszmt4D3PFwhmc1rBe54vEMzmtIL3PF8gmM1pBe95vkAwm9MK3vN8gWA2pxW85/kCwWxOK3jP8wWC2ZxW8J7nCwSzOa3gPc8XCGZzWsF7ni8QzOa0gvc8XyCYzWkF73m+QDCb0wre83yBYDanFbzn+QLBZE6rBe95vkAwmdNqwXueLxBM5rTazdgEkzmtFrzn+QLBZE6rBe95vkAwm9MK3vN8gWA2pxW85/kCwWxOK3jP8wWC2ZxW8J7nCwSzOa3gPc8XCGZzWsF7ni8QzOa0gvc8XyCYzWkF73m+QDCb09rZnFbwJu8LBLM5rZ3NaR1sTit4X/sFgtmcVvDO9gsEG5tgNqcVvLn9AsFsTit4e/sFgtmcVvAG9wsEszmt4C3uFwhmc1rBW98vEMzmtNg64htbR3xj64hvbB3xja0jvrF1xDe2jvjG1hHf2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xDe2jvjG1hHf2DriG1tHfGPriG9sHfGNrSO+sXXEN7aO+MbWEd/YOuIbW0d8Y+uIb2wd8Y2tI76xdcQ3to74xtYR39g64htbR3xj64hvbB3xja0jvrF1xHe2jvjO1hHf2TriO1tHfL8Zm2Ayp9XZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI75nahAfbX98cfv9O7/kJnoLz8hN9Ak9en9+cTuRm+jzeUZuok/nGbmJPptn5CbKwBNyMzVKz8jN9N6dkJvpvTshN1H2nZFrXHK5XFWmFukZubCu6iUB1im9JMR2P+P5nbfbtm8f/qur2yOI12P/8391wWue/fXG9j/+emMbIH+9sR2Qv14j0xvbA/nrjW2C/PXGdkH+emNbJn+9ZP4qeLmzv14yfxW82tlfL5m/Cl7s7K+XzF8Fr3X210vmr4KXOvvr5fJXI3ils79eLn81ghc6++vl8lfjZmR6ufzVCF7m7K+Xy1+N4FXO/nrJ/FXwImd/vWT+KniNs79eMn8VvMTZXy+Zvwpe4eyvl8xfBS9w9tdL5q+C1zf76yXzV8HLm/31kvmr4NXN/nrJ/FXw4mZ/vWT+Knhts79eMn8VvLTZXy+Zvwpe2eyvl8xfBS9s9tdL5q+C1zX76yXzV8HLmv31kvmr4FXN/nrJ/FXwomZ/vWT+KnhNs79eMn8VvKTZXy+Zvwpe0eyvl8xfBS9o9tdL5q+C1zP76yXzV8HLmf31kvmr4NXM/nrJ/FXwYmZ/vWT+qpL5q+C92/56yfxVJfNX1cj0kvmr4NXq/nrJ/FXwcnV/vWT+Kni9ur9eMn8VvGDdXy+Zvwpese6vl8xfBS9Z99dL5q+CV7L76yXzV2T97YOsv32Q9bcPsv72QdbfPsj62wdZf/sg628fZP3tg6y/fZD1tw+y/vZB1t8+yPrbB1l/+yDrbx9k/e2Dq7/dbqn6vT9eTr/rzfT+ndGb6fP545XPu95Mn88zejN9Ps/ozfT5PKM3U/6d0Zsp/07oTdX/PKM31ft3Qm+m/DujN1P+ndFrZHrJ/BVw//NLA65nemkI7YPuD15fD7Lv+4f/8M6/90twaCN0geDYTc1XCA5tha4QHNoLXSE4tBm6QrCxCQ5th64QHNoPXSE4tHm6QjCb04pd2XyB4NidzVcIZnNasVubrxDM5rRi9zZfIZjNacVubr5CMJvTit3dfIVgNqcVu735CsFsTit2f/MVgtmcVuwG5ysEszmt2B3OVwhmc1qxW5yvEMzmtGL3OF8hmM1pxW5yvkIwm9OK3eV8hWA2pxW7zfkKwWxOK3af8xWC2ZxW7EbnKwSzOa3Ync5XCGZzWrFbna8QzOa0Yvc6XyGYzWnFbna+QjCb04rd7XyFYDanFbvd+QrBbE4rdr/zFYLZnFbshucrBLM5rdgdz1cIZnNasVuerxDM5rRi9zxfIZjNacVuer5CMJvTit31fIVgNqcVu+35CsFsTit23/MVgtmcVuzG5ysEszmt2J3PVwhmc1qxW5+vEMzmtAab0xpkTmuL3ex9hWAyp3X/LmyCU72Wij3a24udCU71WpoQHLsO+WvB5dEvWmo7EZzqQ2tGcKoPrRnBqeLhjGBjE5wqHs4ITvUe/nwlZ4vdoHyF4FTxcEZwqng4IThX3fKM4FROa0ZwKqc1IziV05oRbGyCUzmtGcFsTitX3fKMYGCn9RIB7J6eIqLXIu+1vUT024f/9CbWqdFrkf0FB3dE3wne9+eDWDkRHNwR+Qs2NsHBHZG/4OCOyF9wcEfkLzi4I/pScCmPB2nbieDg7sldcPRaZH/BqZzWjOBcTmtCcC6nNSHY2ATncloTgoM7rWM7fjzI8UHwPQs9djF30/zjSe7rgJfk4F7rCsnB3dYVkoP7rQskR69HvkJycM91heTgrusKycF91xWSjU9ycO91hWQ+9xW9LPkKyXzuK3ph8gWSo1cmXyGZz31Fr02+QjKf+4penXyFZD73Fb0++QrJfO4reoXyFZL53Ff0GuUrJPO5r+hVyldI5nNf0euUr5DM576iVypfIZnPfUWvVb5CMp/7il6tfIVkPvcVvV75Csl87it6xfIVkvncV/Sa5Ssk87mv6FXLV0jmc1/R65avkMznvqIX8n4nebRHTdxov3/vl+BUb+UZwak+rUd/VEyNcVIxFb2u1VvwHr2u1V9wqs/pGcGpMvKM4FQJeUZwrvfwhOBc7+EJwamy8YzgVMl4RjCZ09pvbE4resf0O8EvEcDu6SUiuCOyaq8Hae3Df3qfC4j26F3Q/oKNTXBwR/Sd4M9tLXv0Lmh/wcEdkb/g4I7IX3BwR+QuOHoXtL/g4O7JX3Aqp/W5vGSP3gXtL9jYBOdyWhOCczmtCcG5nNaE4FxOa0IwktPq9uctRvTe6DkRSI7oVERwl1P211KsHPXfbxui9zv7C7ZMgieMe/R+Z3/BwV2Ov+DgLsdfcHCX4y84uMtxFxy93/lLwZ99bPR+Z3/BqZzWjOBUTmtGsLEJzuW0JgTncloTgpGclp38zkT0vuY5EUiO6ExE9E7l0svzQer49ItTvdjt8c1LqT+epP6QHN3nXCA5utO5QHJ0r3OBZOOTHN3vXCA5uuO5QHJ0z3OB5OgO6QLJ0f2Uv+ToncpXSOZzX9E7la+QzOe+oncqXyGZz31F71S+QjKf+4reqXyFZD73Fb1T+QrJfO4reqfyFZL53Ff0TuUrJPO5r+idyldI5nNf0TuVr5DM576idypfIZnPfUXvVL5CMp/7it6pfIVkPvcVvVP5Csl87it6p/IVkvncV/RO5Ssk87mvwee+Bp/7it6cfYVkPvc1+NzX4HNf0TvSr5BM576O6D3pV0imc19H9K70KyTTua/jZnyS6dzXEb0z/QrJdO7riN6bfoVkPvcVvTv9Csl87it6L/sVkvncV/Ru9isk87mv6P3sV0jmc1/RO9qvkMznvqL3tF8hmc99Re9qv0Iyn/uK3td+hWQ+9xW9s/0KyXzuK3pv+xWS+dxX9J73KyTzua/wHfIXSOZzX+F75C+QzOe+wnfJXyCZz32F75O/QDKf+wrfKX+BZD73Fb5X/gLJfO4rfLf8BZL53Ff4fvkLJPO5r/B99BdI5nNffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/XvfF13Rtf173xdd0bX9e93YxPMp37Mr6ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67ovfF33ha/rvvB13Re+rvtyMz7JdO6r8HXdF76u+8LXdV/4uu4LX9d94eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33ha/rvvB13Re+rvvC13Vf+LruC1/XfeHrui+5WtBH23999Wi/f++X4FRv5RnBqT6tR+8PwaOdCE71WT0jONUn9YzgVJ/TM4JTZeQZwakS8oTgXH3YM4JzvYcnBKfKxjOCUyXjGcHGJpjNaSF3YL9EALunl4jgjqgdt+eDdPv0n95/imt/ffl/iuP+HNWj91RfIDl6T/UVkoP7oiskB3dGV0gO7o2ukGx8koP7oyskB3dIV0gO7qeu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rL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bdXsv72StbfXsn62ytZf3u9GZleLn9VyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXlP1e98f+/b88n18+ObfPMi+H/0psdvrOfr4t9/5Vh7PvN9G+QHP/vSd+3h+5/3Ddy62//raYsfJ9DO5EU3/y+mn6n7X9L+dfianqul/O/1Mvl3T/3b6mVKMpv/t9E3TJ55+poSr6X87/Uw/T9H0v51+pp8uafrfTl+7Pubpa9eXdvr98Y3Lz+/7c/qp7hBp+t9OX7s+5ulr18c8fe360k6/vaZfT6Zvmj7x9LXrY56+dn3M09euj3n62vUxT1+7vrTTL49HLvXkd3pT3cTU9L+dvnZ9zNPXro95+tr1MU/fNH3i6WvXxzx97fqYp69dH/P0tetjnr52fcTTT3WfXdP/dvra9TFPX7s+5ulr18c8fdP0iaevXR/z9LXrY56+dn3M09euj3n62vURT39o18c8fe36mKevXR/z9LXrY56+afrE09euj3n62vUxT1+7Pubpa9fHPH3t+nin327a9TFPX7s+5ulr18c8fe36mKdvmj7x9LXrY56+dn3M09euj3j6m/L+2ulv9xk8p79Vz+l/vM3RNuV95ukr7zNPX3mfefqm6RNPX3mfefrK+8zTV95nnr5+t4d5+vrdHuLp79r1MU9fu7600/94jbHt2vUxT1+7Pubpm6ZPPH3t+tJO/+NFtrZr18c8fe36mKevXR/z9LXrI57+oV0f8/S160s7/c+/03to18c8fe36mKdvmj7x9LXrY56+dn3M09euj3n62vUxT1+7PuLpm3Z9zNPXro95+tr1MU9fuz7m6ZumTzx97fqYp69dH/P0tetjnr52fczT166PePpFuz7m6WvXxzx9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"},{"name":"claim","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"},{"name":"secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+1dB3gUxRe/27uEhEDoRVAIojRBbi7tAopUCyoqIohSTLkgSicgYu+99967AmLvvWJBVBQL9t4bqCj+35CZZDJcktvb98I+/tnv+32Td9l9+3vz5r3Z3ZnZDQYqt3VNAoH90iv/DgJCAAeQY8gh9beWw5acZu3fxJKbW3ILS25lyW0suQNgsCF3tf6fY8ndLHlrS+6hZHMLqnKwKnMjBXl58cJoXOSK4ki0qCSWH8nLLymIiZjIj+WXRWO5ufFYXqywqKSoMFIk8nLjojy/KLc8Urn9FqzWFfG4SW6ZBreegPWAXqrsrUp5zsZy8y/7An4PVrZZs1383lg///ft4o9goMbmqHKwKiPeNtEjgJcj1wTxeEmzZW6XOnMMu/UWRK6Hnni6IjlKz1og+SfgL8DfgHWAfwD/Sv8C/gtWGhYEOIAQIAxIA6QDmgAyAJmApoAsQDNAc0A2oAWgJaAVoDWgDaAtoB2gvVNZSboeJZeMQLX8pyX/Zcl/W/I6S/7Hkv+15PWW/J8lS7tNOWjJjiWHLDlsyWmWnG7JTSw5w5IzLbmpJWdZcjNLbm7J2ZbcwpJbWnIrS25tyW0sua0lt7Pk9ko2t7AqB6sy4m2rETNec8faoHdd8XK5RcSfQTxef4bx8kJdvvBis/TFXyj1V+nXv73riqr6E+sQffGXn32RV8VT/OPN5ohhs/jXi65ojfoT6xF98bc/fRGxeIr/UrS5oHwjm4Xss1LQFUtQfyLo4Plind98EUvIUzjubS6sxWYRcqursNb6E2FEX/zjH19E6+Ap0tzYXFinzSI9eV2l9dSfaILoi3/94IvCenmKjORsjiRhs8hMRlckqfoTTRF9sX7T+iI/SZ4iqz6b85K2WTSrU1deuYv6E80RffHfpvJFoSueIrt2m2MubRYtatFVVO66/kRLRF/Ih+0N7ItICjxFq0Q2R1KyWbTeWJdIsf5EG0RfBBvSF2Up8xRta9qc68Fm0c7QFS33VH+iPaIvnAbyRcTbJhCfDwjE+1th3p959UWIiS8Q74ME4nW8+BfRF2EmvkC83hOI1yvC7G+9+iKNiS8Q+zWBmJdFCNEX6US+CCH7AjF+BWL7E5j15wRqbthjdb3wdFWN1XUA0h0BWwA6AToDtgRsBegC6ArIAXQDbA3oDtgGsC2gB6AnoBegN6APYDtAX0A/wPaA/gBZMQIQBeQC8gD5gAInUGOsTnIxx3I6WvIWltzJkjtb8paWvJUld7HkrpacY8ndLHlrS+5uydtY8raW3MOSe1pyL0vubcl9LHk7S+5ryf0seXtL7m/JEUsWlhy15FxLzrPkfEsucOjH6syY8ZprOyBc5+uxuo6I9wztG/5eOqWxui1Q6q/Sr52866oaq+uM6IsOfvaFMVa3pTeba4zVbeVFlzVW1wXRFx396YuNxuq6pmhzorG6nNR0JRyr64boiy385otaxuq2dm9zrWN13d3qqmOsbhtEX3Tyjy/qHKvb1o3N9YzV9UheV71jdT0RfdHZD75IYqyuV3I2JzVW1zsZXUmO1fVB9MWWm9YXSY/VbVefzS7G6vo6eGN1/RB9sdWm8oXLsbrtHbyxuv4O3lhdBNEXXZiM1QkHb6wu6uCN1eUi+qIrk7G6PAdvrC7fwRurK0D0RQ6T5+CIzwcE4v2t6Ij4HLwbE18g3gcJxOt40RnRF1sz8QXi9Z5AvF4RXRB90Z2JLxD7NYGYl0U3RF9sw2SsDjF+BWL7E1T1Z4/TefVzoYPFMzdOyTOGxjNWSMmzCI1nSRElzwF4POOSm8yxw5W+QjVWFlNlkSoHqFKve9Pr4fQ6Ob1+Tq+r0+vt9Do8vT5Pr9vT6/n0Oj+9/k+vC9TrBfU6Qr2+UK871OsR9TpFvX6xal2jKgOq1Osj9bpJvZ5Sr7PU6y/1uky9XlOv49TrO/VYoh5j1GOPekxSj1XqMUw9tqnHPPVYqB4j1WOnekxVj7XqMVg9NqvHbPVYrh7j1WO/ekxYjxXrMWQ9tqzHnPVYtB6j1mPXekxbj3XrMXA9Nq7HzAdCuQNgR8AgwE6yLQKGAIYChgGGA0YAdgbsAtgVsBtgJGB3wB6APQGjAHsB9gbsAxgN2BcwBrAfYCxgHGB/wHjAAU4gQBlXB6LFVSQquWUGqtdVS1muOZfnkKV8R8cEp/JdIE0CG6+/TmRfxNsm2gdo+rUADk+h/zDrYqISJjnV9YF1wqoT64kC8mSrA9UTB+RJc6xzYl8EmU7xOsA80cELhkkOTWNxkOsP0+bJCXSVRErL8kVJQRk8lyvOj5WWFuUKES0uKC4oicbK4yX5IpYfA52lxdEYnC5aXCrikeKCuAxsPQnF3rADezKir0y+B1EGHVVFmKSx9BYjNjIqu4sddB8l5IqRWCRXrESg9WL6qAQ5oGSnIXV2C1T2+HJriB6fKolj85yAyDPd4FmqKrlMlXFVlqtyisoVvdT+B4M8FXAI4FDANMB0wAzATMAswGzAHMBcQAVgHmA+4DDAAsDhgIWAIwBHAo4CHA04BnAs4DjA8YATACcCTgKcDDgFcCrgNMDpgDMAZwLOApwNOMdpgCugKUlc8XgNLkRnizLEoD8XsRE2ZO+Pydvkex633l9WxHkEvf/5Pu/9pd3nE/T+aYprQ/RUmD0AJc8yomC7wAw27Euu8x38nkITTlMNpCEyHWblm436QiVcJG2iqPwLCLLSBcgRQ2U31nV+JIHdXjleTFyHEW+bkA3zYgffN5cQ3N9Inccqndj1cBFRPVxKUA+XEtZDGVE95KX5O5dQxUH+prW73hngVO2+gMkMAcR2KRB9LTDrLy1Q/Rb52rZkz1VfezJ1UvRVWHViXkxeVteVccTbJi4m6ABMwi75ivrOIfleRpAQBvhk+pabCzavNl/u+DO5YPpCt8nLjYuSVH1TX31j+uYKQ5fIzYW4gPG38rLy3PzComiJKMgtKCjPKy8siOWVlefnFZcVxkVecW60KF4YKRexeLwwP7e0sKC8qKy0oNxM1qIsNzevrKikVORHC4pLIrGy3OJIeV5hbjRSXJZbWFaWGysoKM7NLSuIlceKYtFocXluLJJfWFgUKYjmFkUpfHOF8k1D3kljPm4xO64rlXAVl6RNxe9KgiR9NUFndTXh3Yqsh6sI6uEagnq4hrAeJhBdxe/g87s2qjjY0ed3bVTtfhCTuzbEdikQfS0GNd612Zu4kuiu7Vpud23XEt+1XUuQEIb+H961Xef4M7kMJbgzuI7ZXdv1iHdtgxDv2ih8c71x11ZbR+DnR2yUPKk6lRu4dSo3EHcqNxB0KsN9/pY3ik4ln+iK1SuvEQ10xe+V542InTJi+xMjCBL/jUl0yl7r8yYHr/Or8fjTR53ycALf3LQZPUq9WQm3OAkmJUW8baK2yTmYM8286kKc4EQy3VTXIXYypapDr7pu9bk/ZMDcSnBBdBvBheFtDt3j5luI6uF2gnq4nfixO0U97Orzx+5UcbCbzx+7U7X7kUweuyO2S4HoazGy8bG7vW3oq7DqxLzIvYPyCcmtBB3AHYRPSCTfOwgSwigmj91vRbz4u9PxZ3IZRXAXeadD/9gd0zd3IT52H4l4h0/hm7s2wR0+1bKjRUpYzCVpU/FbRJCklxB0VksI71ZkPSwmqIe7Cerhbod2iQvFVfzePr9ro4qDfXx+10bV7kczuWtDbJcC0ddidONdm72JRUR3bUu53bUtJb5rW0qQEMb+H9613eP4M7mMJbgzuIfZXdu9iHdtoxHv2ih8c6/T8JOlMB+xUfKk6lTu49ap3EfcqdxH0Knsz2SyFGbi2o3oitUrr/FMJkvdj9gpI7Y/MZ4g8d/v0E+WesDB6/xGpvmzU96fwDcPJPAN9t3tBMS8U46o60HE/qsh3/WHydvk+5DD7F1/siIecvD1PozYyKjsfthB91GDvuuvnMmV+QSiYHvEIXzX38OIVxe6p9CEN4dptY8q4TGH4F1/svIfIchKjyBHDJXdDqHdXjk+TlyHEW+bkA3zcYJb1CcIbtWfcOgGAB8jqocnCerhSYd2+ipFPUzw+UAoVRxM9PlAKFW7n8RkIBSxXQpEX4tJjQOh9rahr8KqE/Ni8imH8Jn14wQdwFOEz6wl36cIEkIJk4HQxxEv/p52/JlcSgie6z3t0A+EYvrmGQfvmeskxGeuFL55xmn46auYj1vMjutZJTzHJWlT8XuWIEk/T9BZPU94tyLr4TmCeniBoB5eIKyHcqKr+DKf37VRxUHc53dtVO2+nMldG2K7FIi+FuWNd232Jp4lumt7kdtd24vEd20vEiSEQ/4P79pecvyZXA4huDN4idld28uId23liHdtFL552Wn46auYj9goeVJ1Ksu4dSrLiDuVZQSdyjQm01cxE9dEoitWr7ymM5m++gpip4zY/sR0gsT/ikM/ffVVB6/zm5Tmz055GoFvXt2MHqW+poTXHYJ3/dU2OQdzpplXXYgTnEimm+o6xE6mVHXoVddyn/tDBsxygguiNwguDN9w6B43v05UDysI6mEF8WN3inqY5fPH7lRxMNvnj92p2v0cJo/dEdulQPS1mNP42N3eNvRVWHViXuS+SfmEZDlBB/Am4RMSyfdNgoQwn8lj9+WIF39vOf5MLvMJ7iLfcugfu2P65m3Ex+5zEO/wKXzz9ia4w6dadrRSCe9wSdpU/FYSJOl3CTqrdwnvVmQ9vENQD6sI6mGVQ7vEheIqfoHP79qo4uBwn9+1UbX7hUzu2hDbpUD0tVjYeNdmb2Il0V3be9zu2t4jvmt7jyAhHP1/eNf2vuPP5HI0wZ3B+8zu2j5AvGtbiHjXRuGbD5yGnyyF+YiNkidVp/Iht07lQ+JO5UOCTuVYJpOlMBPXbKIrVq+8jmMyWWo1YqeM2P7EcQSJf7VDP1nqIwev85uT5s9O+VgC33xkdMoN9a66KUSd3ccOs3fVyYr42MHX+wlioqey+xMH3UcN+sLFcqJG/Cm3Riwr4lOCRvyZzxuxtPszgkaciCvGbEJ59ecg1wHmFeXnDm0dRrxtG5LqZwR3D184/m478qvTtxK0Hcw3j3/p8zqUbVv6GXvcADFmxBeI/vjK5/6Q7eUrglj+2qHtqz2/4g/4fU1g94lp/s7dZUR2n0T0tAE71yL6R5yEPCbYUBfsmB/rNPl+w+2CXVbENwQX7N/6/IJd2v2tg+6jBm3EcaJG/B23Riwr4juCRvy9zxuxtPv7BrrrjHjbNiSE7wl63R98fqco7xJ/ILD7R+TgzwxUP4eXyXE9lHFVTlFluSrl9pNqd9h2yTvrHwnq62fEq3Ej5BLWQcTbJkoRfdtL6fkFdP4K+A3wO+APwBrAWsCfgL8AfwPWAf4B/Ct9DfhPGgu3qkGAAwgBwoA0QDqgCSADkAloCsgCNAM0B2QDWgBaAloBWgPaANoC2gHaAzoAOoaqp26HFNegIf9qyb9Z8u+W/Iclr7HktZb8pyX/Zcl/W/I6S/7Hkv+15PWW/J8lb6hfQw5asmPJIUsOW3KaJadbchNLzrDkTEtuaslZltzMkptbcrYlt7DklpbcypJbW3IbS25rye0sub0ld7DkjqGNL3jcThRyE9Nec9kvCLri5ZXbr4i8TvX53Adlc9lvePVX9DueLvEHoi9OY+GLuFiDVn+lYi2arpj4E9EXp7PwRUT8hVV/8Yj4G0tXaUSsQ/TFGRx8EYuIf7DqD/qef5F0xUHXekRfnMnAF6Vg839I9ReTzz9COLoi8strITxfnOV/X8SlzQ5O/ZVKXSEcXTGpK4zoi7P97wupWqSh1F98g650FF2lG3Q1QfTFOb73RWyDzRko9beBpsjE0BWv1NUU0Rfn+t0XpZU2Z2HUX6xSVzMMXZUmi+aIvjjP574oUzZnI9hconS1QNBVqHS1RPTF+f72RVSvxGzl3WahdbX2rCtWrnW1QfTFBb72RaxE29zWe/1VrbBt51lXYZWu9oi+uNDXvsivsrmDZ5tFla6OIbxnlqcirsW5yCeLbevZBOJzM4H43EecgeiLi5n4AvH5gEC8vxVnI/riEia+QLwPEojX8eI8RF9cysQXiNd7AvF6RVyI6IvLmPgCsV8TiHlZXILoi8uZvDkHMX4FYvsTVPXnWPXnh3FlrWsLxOtQqQN7jo2cv/Szgz/PqFMI19fYdh/sVM+vwbR7kc9n/cv22CmEb/diJu8Y6IwYj4i+Fot93m5kvGxB0G6W+txumSMo4uUeJvGyJWK8IPpaYNafnverryNkjpDze7cMVc/z3UpVLHb7mupUz+vE9Nv9Pn+rp7R5K4K4eoDJ/dJWiM93uyDGKGK7EVx8MRXxer9riCaG/RQXdr7sovJkVyNf5hDly0Oc6nnvpl7Pb4Pweb6UNucQ5MtHmMRoDmJcdUPMl4jtRnDxxSGI+XLrEE0M+yku7HzZTeXJrY182Z0oXx7qVK8LMvV6rZ/HfZ4vpc3dCfLlE0xitDtiXG2DmC8R243g4otDEfPltiGaGPZTXNj5chuVJ7c18mUPonw5zaleN2nq9Vo/T/s8X0qbexDky2eYxGgPxLjqiZgvEduN4OKLaYj5sleIJob9FBd2vuyp8mQvI1/2JsqX053qdeWmXq/187zP86W0uTdBvnyBSYz2RoyrPoj5ErHdCC6+mI6YL7cL0cSwn+LCzpd9VJ7czsiXfYny5Qyn+r0bpl6v9fOyz/OltLkvQb5cxiRG+yLGVT/EfInYbgQXX8xAzJfbh2hi2E9xYefLfipPbm/ky/5E+XKmU/1eIlOv1/p5zef5UtrcnyBfvs4kRvsjxlUEMV8ithvBxRczEfOlCNHEsJ/iws6XEZUnhZEvo0T5cpZT/d42U6/X+lnh83wpbY4S5Ms3mcRoFDGuchHzJWK7EVx8MQsxX+aFaGLYT3Fh58tclSfzjHyZT5QvZzvV77U09Xqtn5U+z5fS5nyCfPkOkxjNR4yrAsR8idhuBBdfzEbMl4Uhmhj2U1zY+bJA5clCI1/GiPLlHKf6vb+mXq/1857P86W0OUaQL99nEqMxxLgqQsyXiO1GcPHFHMR8OSBEE8N+igs7XxapPDnAyJcDifLlXKf6veimXq/1s9rn+VLaPJAgX37EJEYHIsbVDoj5ErHdCC6+mIuYL3cM0cSwn+LCzpc7qDy5o5EvBxHlywqn+rsRpl6v9fOpz/OltHkQQb78jEmMDkKMq50Q8yViuxFcfFGBmC8Hh2hi2E9xYefLnVSeHGzkyyFE+XKeU/1dHVOv1/r50uf5Uto8hCBffsUkRocgxtVQxHyJ2G4EF1/MQ8yXw0I0MeynuLDz5VCVJ4cZ+XI4Ub6c71R/d8zU67V+vvV5vpQ2DyfIl98xidHhiHE1AjFfIrYbwcUX8xHz5c4hmhj2U1zY+XKEypM7G/lyF6J8eZg8KUHe+NHn+VLavAuB3T8xidFdEONqV8R8idhuBBdfHIaYL3cL0cSwn+LCzpe7qjy5m5EvRxLlywVO9XdrTb2e35fm83wpbR5JYPdvTGJ0JGJc7Y6YLxHbjeDiiwWI+XKPEE0M+yku7Hy5u8qTexj5ck+ifHm4U/1db1Ov5/XZPs+X0uY9CexeyyRG90SMq1GI+RKx3QguvjgcMV/uFaKJYT/FhZ0vR6k8uZeRL/cmypcL4aQhgrzxt8/zpbR5bwK71zGJ0b0R42ofxHyJ2G4EF18sRMyXo0M0MeynuLDz5T4qT4428uW+RPnyCDhpmCBvrPd5vpQ270tg939MYnRfxLgag5gvEduN4OKLIxDz5X4hmhj2U1zY+XKMypP7GflyLFG+PBJOmkaQN5x0f+dLafNYArtD6TxidCxiXI1DzJeI7UZw8cWRiPly/xBNDPspLux8OU7lyf2NfDmeKF8eBSdNJ8gb6T7Pl9Lm8QR2N2ESo+MR4+oAxHyJ2G4EF18chZgvDwzRxLCf4sLOlweoPHmgkS8nEOXLo+GkTQjyRlOf50tp8wQCu7OYxOgExLiaiJgvEduN4OKLoxHz5aQQTQz7KS7sfDlR5clJRr6cTJQvj4GTZhDkjWyf50tp82QCu1swidHJiHF1EGK+RGw3gosvjkHMl8Uhmhj2U1zY+fIglSeLjXxZQpQvj4WTZhLkjdY+z5fS5hICu9swidESxLgqRcyXiO1GcPHFsYj5sixEE8N+igs7X5aqPFlm5Ms4Ub48Dk7alCBvtPd5vpQ2xwns7sAkRuOIcVWOmC8R243g4ovjEPPllBBNDPspLux8Wa7y5BQjXx5MlC+Ph5NmEeSNTj7Pl9Lmgwns7swkRg9GjKupiPkSsd0ILr44HjFfHhKiiWE/xYWdL6eqPHmIkS8PJcqXJ8BJmxHkjS4+z5fS5kMJ7O7KJEYPRYyraYj5ErHdCC6+OAExX04P0cSwn+LCzpfTVJ6cbuTLGUT58kQ4aXOCvLG1z/OltHkGgd3dmcToDMS4momYLxHbjeDiixMR8+WsEE0M+yku7Hw5U+XJWUa+nE2UL0+Ck2YT5I0ePs+X0ubZBHb3ZBKjsxHjag5ivkRsN4KLL05CzJdzQzQx7Ke4sPPlHJUn5xr5soIoX54MJ21BkDf6+DxfSpsrCOzejkmMViDG1TzEfInYbgQXX5yMmC/nh2hi2E9xYefLeSpPzjfy5WFE+fIUOGlLgryxvc/zpbT5MAK7+zOJ0cMQ42oBYr5EbDeCiy9OQcyXh4doYthPcWHnywUqTx5u5MuFRPnyVDhpK4K8EfV5vpQ2LySwO5dJjC5EjKsjEPMlYrsRXHxxKmK+PDJEE8N+igs7Xx6h8uSRRr48iihfngYnbU2QNwp8ni+lzUcR2F3IZc0yYlwdjZgvEduN4OKL0xDz5TEhmhj2U1zY+fJolSePMfLlsUT58nQ4aRuCvDHA5/lS2nwsgd0DuawpQYyr4xDzJWK7EVx8cTpivjw+RBPDfooLO18ep/Lk8Ua+PIEoX54BJ21LkDcG+TxfSptPILB7Jy5z/hDj6kTEfInYbgQXX5yBmC9PCtHEsJ/iws6XJ6o8eZKRL08mypdnwknbEeSNoT7Pl9LmkwnsHsZlTBYxrk5BzJeI7UZw8cWZiPny1BBNDPspLux8eYrKk6ca+fI0onx5Fpy0PUHe2Nnn+VLafBqB3btweWaGGFenI+ZLxHYjuPjiLMR8eUaIJob9FBd2vjxd5ckzjHx5JlG+PBtO2oEgb4z0eb6UNp9JYPfuXK5pEOPqLMR8idhuBBdfnI2YL88O0cSwn+LCzpdnqTx5tpEvzyHKl+fASTsS5I1RPs+X0uZzCOzei0mMnoMYV+ci5kvEdiPY+AIxX54XoolhP8WFnS/PVXnyPCNfnh8K1NgcZJ+1DuDVzfkh2lwZ8baJOFTe1w5+rrwghNsmpMulzmuhTANkGHVhbtj1g22H3i4MJeCPRZqqIi4M4eu9CDGpUdl9UQjdRxHKRntRCD8ha469A5WJuC3g4lB18tWbnwMwR+m5BHReCrgMcDngCsCVgKsAVwOukYkGcB3gesANgBsBNwFuBtwCuBVwG+B2wB2AOwF3ARYBFgOWAO4GLAXcA7gXcB/g/lBlJemkJrnoZCblSy35Mku+3JKvsOQrLfkqS77akq+x5Gst+TpLvt6Sb7DkGy35Jku+2ZJvseRbLfk2S77dku+w5Dst+S5LXmTJiy15iSXfbclLLfkeS77Xku+z5PuVbG7YF50XIObUSxB0xcvlFhGXIvIa3UA3AF5slr64DKX+Kv16uXddUVV/4gpEX+zrZ1/kVfEUV3qzOWLYLK7yoitao/7E1Yi+GONPX0QsnuKaFG0uKN/IZnFtarpiCepPXIfoi/385otYQp7ievc2F9Zis7jBra7CWutP3Ijoi7H+8UW0Dp7iJjc2F9Zps7g5eV2l9dSfuAXRF+P84IvCenmKW5OzOZKEzeK2ZHRFkqo/cTuiL/bftL7IT5KnuKM+m/OStlncWaeuvHIX9SfuQvTF+E3li0JXPMWi2m2OubRZLK5FV1G56/oTSxB9cUDD+yKSAk9xdyKbIynZLJZurEukWH/iHkRfHNiQvihLmae4t6bNuR5sFvcZuqLlnupP3I/oiwlMBt4Qnw8IxPtbMQZx4G0iE18g3gcJxOt4MQ7RF5OY+ALxek8gXq+IAxB9MZmJLxD7NYGYl8VERF8cROSLELIvEONXILY/gVl/1GN1W+HpqhqrewAc/SDgIcDDgEcAjwIeAzwOeALwJOApwNOAZwDPAp4DPA94AfAi4CXAy4BlgFcArwJeA7wOWA54A7AC8CbgLcDbgJWhQI2xugessZwHLfkhS37Ykh+x5Ect+TFLftySn7DkJy35KUt+2pKfseRnLfk5S37ekl+w5Bct+SVLftmSl1nyK5b8qiW/ZsmvW/JyS37DkldY8puW/JYlv23JK0P0Y3VmzHjNtQ+gjDVVjtU9iHjPMIvJWN1DKPVX6deHveuqGqt7BNEXs5mM1T3qzeYaY3WPedFljdU9juiLOUzG6p5I0eZEY3VPpqYr4VjdU4i+mMtkrO5p9zbXOlb3jFtddYzVPYvoiwomY3XPubG5nrG655PXVe9Y3QuIvpjHZKzuxeRsTmqs7qVkdCU5Vvcyoi/mMxmrW1afzS7G6l4J4Y3VvYroi8OYjNW9FsIbq3s9hDdWtxzRFwuYjNW9EcIbq1sRwhurexPRF4czGat7K4Q3Vvd2CG+sbiWiLxYyeQ6O+HxAIN7fijmIz8GPYOILxPsggXgdL+Yh+uJIJr5AvN4TiNcrYgGiL45i4gvEfk0g5mVxBKIvjmYyVocYvwKx/YmjGY3VBfF0VY3VvQOOfhewCvAe4H3AB4APAasBHwE+BnwC+BTwGeBzwBeALwFfAb4GfAP4FvAd4HvAD4AfAT8Bfgb8AvgV8Bvgd8AfgDWhQI2xunessZx3LXmVJb9nye9b8geW/KElr7bkjyz5Y0v+xJI/teTPLPlzS/7Ckr+05K8s+WtL/saSv7Xk7yz5e0v+wZJ/tOSfLPlnS/7Fkn+15N8s+XdL/sOS14Tox+rMmPGaa99BGWuqHKt7F/Ge4WwmY3WrUOqv0q/veddVNVb3PqIvzmEyVveBN5trjNV96EWXNVa3GtEX5zIZq/soRZsTjdV9nJquhGN1nyD64jwmY3Wfure51rG6z9zqqmOs7nNEX5zPZKzuCzc21zNW92Xyuuodq/sK0RcXMBmr+zo5m5Maq/smGV1JjtV9i+iLC5mM1X1Xn80uxuq+D+GN1f2A6IuLmIzV/RjCG6v7KYQ3Vvczoi8uZjJW90sIb6zu1xDeWN1viL64hMlY3e8hvLG6P0J4Y3VrEH1xKZcXACM+L0W8vxXnIj4Hv4yJLxDvgwTidby4ANEXlzPxBeL1nkC8XhEXI/riCia+QOzXBGJeFpch+uJKJmN1iPErENufuJLRWF0XPF1VY3VrwdF/Av4C/A1YB/gH8C9gPeC/UGVgBgEOIAQIA9IA6YAmgAxAJqApIAvQDNAckA1oAWgJaAVoDWgDaAtoB2gfDtQYq1trjeX8acl/WfLflrzOkv+x5H8teb0l/2fJ0m5TDlqyY8khSw5bcpolp1tyE0vOsORMS25qyVmW3MySm1tytiW3sOSWltzKkltbchtLbmvJ7Sy5fZh+rM6MGa+5di3iWN2fiPcMdzIZq/sLcazub8SxunWIvriLyVjdP4hjdf8ijtWtR/TFIiZjdf8hjtVJcinoSjhWFwzj+WIxk7E6x73NtY7VhdzqqmOsLozoiyVMxurS3Nhcz1hdevK66h2ra4Loi7uZjNVlJGdzUmN1mcnoSnKsrimiL5YyGavLqs9mF2N1zcJ4Y3XNEX1xD5Oxuuww3lhdizDeWF1LRF/cy2SsrlUYb6yudRhvrK4Noi/uYzJW1zaMN1bXLow3Vtce0Rf3M3kOjvh8QCDe34pFiM/BH2DiC8T7IIF4HS/uRvTFg0x8gXi9JxCvV8S9iL54iIkvEPs1gZiXxQOIvniYyVgdYvwKxPYnHiYcq+u6cR2KiIdtoGNx9aBtB2cju1PWtqOToA5T1DbISeiPlLTt5NTi2xS0DXZqbSeutQ1x6mhzLrUNdepsv660DXPqiQUX2oY79cZV0tpG1K8raW07J6MrSW27JKcrKW27JqsrCW27Ja+rXm0j3eiqR9vu7nTVqW0Pt7rq0Lane121ahuViq5atO2Vmq6E2vZOVVcCbfukrmsjbaO96LK07etNVw1tY7zqMrTt511XlbaxGLqUtnE4ujZo2x9LF2gbj6erak5SB7i56AjYAtAJ0BmwJWArQBdAV0AOoBtga0B3wDaAbQE9AD0BvQC9AX0A2wH6AvoBtgf0B0QAAhAF5ALyAPmAAmtOUgdrzkpHS97CkjtZcmdL3tKSt7LkLpbc1ZJzLLmbJW9tyd0teRtL3taSe1hyT0vuZcm9LbmPJW9nyX0tuZ8lb2/J/S05YsnCkqOWnGvJeZacb8kF4aTmJG329wZe73VfbujnDpvxPYxXXyzbNM+ANst7La++eGVTPo/bzO4Jvfri1U3/bHSzuXf16ovX/PKcejO4x/bqi9f9NWbA+lmAV18s9+P4DdNnFl598YZ/x9LYPVvx6osVfh/XZPQMyKsv3mQyxjwe0eYOCPOI9Fqgjohzkt5ishZoC5T6q/RrJ++6qtYCdUb0xdtM1gJt6c3mGmuBtvKiy1oL1AXRFyuZrAXqmqLNidYC5SCuBeqG6It3mKwF2hpxLVB3xLVA2yD64l0ma4G2RVwL1ANxLVBPRF+sYrIWqBfiWqDeiGuB+iD64j0ma4G2Q1wL1BdxLVA/RF+8z2Qt0PaIa4H6I64FiiD64gMma4EE4lqgKOJaoFxEX3zIZC1QHuJaoHzEtUAFiL5YzeQZCOK4vEAcVxavIM6z/4iJLxDHHwXi+Jl4HdEXHzPxBeI4i0AcJxArEH3xCRNfID5PFojPQ8XbiL74lIkvEJ+bCcTnPuJdRF98xsQXiM8HBOL9rXgf0RefM/EF4n2QQLyOF6sRffEFE18gXu8JxOsV8QmiL75k4gvEfk0g5mXxOaIvvmKyjhcxfgVi+xOY9ecEam7Y79y9OITHNUfpKYSgiwGKAAMAAwE7AHYEDALsJJ9LAIYAhgKGAYYDRgB2BuwC2BWwG2AkYHfAHoA9AaMAewH2BuwDGA3YFzAGsB9gbDhQY31LobX+IWbJRZY8wJIHWvIOlryjJQ+y5J0sebAlD7HkoZY8zJKHW/IIS97Zknex5F0teTdLHmnJu1vyHpa8pyWPsuS9LHlvS97Hkkdb8r6WPMaS97PksWH6d+5ejPgOz0LEeTYxxOd96U14zLMpQpxnMwBxns1ARF808bMvjHk2OyDOs9kRcZ7NIERfZPjTFxvNs9kJcZ7NYMR5NkMQfZHpN1/UMs9mKOI8m2GI82yGI/qiqX98Uec8mxGI82x2RpxnswuiL7L84Isk5tnsijjPZjfEeTYjEX3RbNP6Iul5NrsjzrPZA3GezZ6Ivmi+qXzhcp7NKMR5NnshzrPZG9EX2Q3vi5Tm2eyDOM9mNOI8m30RfdGiIX3hYZ7NGMR5NvshzrMZi+iLlg3ki4i3TSA+HxCI97fCvD/z6otWTHyBeB8kEK/jRRaiL1oz8QXi9Z5AvF4R2Yi+aMPEF4j9mkDMy6IVoi/aEvkCe6wOMX4FYvsTmPUXVG34SaXvfvW9xftUea8q71HlUlXercolqlysykWqvEuVd6ryDlXersrbVHmrKm9R5c2qvEmVN6ryBlVer8rrVHmtKq9R5dWqvEqVV6ryClVersrLVHmpKi9R5UpVvq3Kt1T5pipXqPINVS5X5euqfE2Vr6ryFVUuU+XLqnxJlS+q8gVVPq/K51T5rCqfUeXTqnxKlU+q8glVPq7Kx1T5qCofUeXDqnxIlQ+q8gFVrlHlH6r8XZW/qfJXVf6iyp9V+ZMqf1TlD6r8XpXfqfJbVX6jyq9V+ZUqv1TlF6r8XJWfqfJTVX6iyo9V+ZEqV6vyQ1V+oMr3VfmeKlep8l1VvqNK/f1L/V1M/b1M/R1N/X1N/d1N/T1O/Z1O/f1O/V1P/b1P/R1Q/X1Q/d1Q/T1R/Z1R/f1R/V1S/b1S/R3Tqu+bqlJ/D1V/J1V/P1V/V1V/b1V/h1V/n1V/t1V/z1V/51W/a0+/g0+/m0+/s0+/y0+/40+/+0+/E1C/K1C/Q1C/W1C/c1C/i1C/o1C/u1C/01C/61C/A1G/G1G/M1G/S1G/Y1G/e1G/k1G/q1G/w1G/21G/81G/C1K/I1K/O1K/U1KPxeoxWj12q8d09VivHgPWY8N6zFiPJesxZj32rMek9Vi1HsPWY9t6zFuPhesxcj12rsfU9Vi7HoPXY/N6zF6P5esxfj32r+cE6LkCeg6Bnlug5xyMg3J/wHjAAYADARMAEwGTAJMBBwGKASWAUkAZIA4oB0wBHAyYCjgEcChgGmA6YAZgJmAWYDZgDmAuoAIwDzAfkFbZpKv6cnPDnkcSDNBch2C/t35c2OLpQdv+4Y1sTlnb+HCC+ktR2wHhhL5ISduB4Vr8moK2CeFa24hrbRPDdbQ3l9omhetsu660TQ7XEwcutB0UrjemktZWHE4iPpPUVpKMriS1lSanKyltZcnqSkJbPHld9Word6OrHm1T3OmqU9vBbnXVoW2qe121ajskFV21aDs0NV0JtU1LVVcCbdNT17WRthledFnaZnrTVUPbLK+6DG2zveuq0jYHQ5fSNhdH1wZtFVi6QNu8MM31GPZ1Y288XZGgwbGV+vswqIcFgMMBCwFHAI4EHAU4GnAM4FjAcYDjAScATgScBDgZcEq42uaqDct46sndhyE2gpZKz6mg8zTA6YAzAGcCzgKcDTgHcC7gPMD5gAsAFwIuAlwMuATgBKon656qKlfLp1ny6ZZ8hiWfaclnWfLZlnyOJZ9ryedZ8vmWfIElX2jJF1nyxZZ8SYLGFCb0udeHy6ci6KqcnFxefhoir20YTE6Grex0vPorOgNPlzgT0RfbsvBFXJyFVn+l4mw0XTFxDqIverDwRUSci1V/8Yg4D0tXaUScj+iLnhx8EYuIC7DqD/qeC5F0xUHXRYi+6MXAF6VyYRFS/cVA1yWINxPbIA5Y92YyeQCxXxOIeVn0RPRFHyaTBxDjVyC2P4Fdf8GN84mnSY5ysOPUcEK9ntpNlN5uTxNF9yeyO7ch7PYwKXg8kd15DWN3yhOrDyCyO7+h7E5xcvqBRHYXNJzdKS1EmEBkd2ED2p3KYo6JRHbHGtZu1wtiJhHZXdTQdrtc/DSZyO4BDW63uwVkBxHZPXBT2O1iEV4xkd07bBq7k15wWUJk946byu4kF62WEtk9aNPZndTC3zIiu3falHYnscg7TmT34E1rd70L5cuJ7B6yqe2u52UDU4jsHrrp7a7zxRIHE9k9zA921/FyjqlEdg/3h921vuDkECK7R/jF7lpeZnMokd07+8fuhC8EmkZk9y4+sjvRS5WmE9m9q7/s3ugFWjOI7N7Nb3ZbLyGbSWT3SP/ZXeNFbrOI7N7dj3YbL+2bTWT3Hv60u+rFh3OI7N7Tt3ZXvjxyLpHdo3xst5x/U0Fk914+tVvzm0dk997Edke8bWIBkd37NNxcjs1+0Z9XX4xu6Hk1m/HiRK++2HfTzHHaLBdRevXFmE0532wzW+zp1Rf7bfq5f5vNolSvvhjrl3mYm8HiWa++GOevObGsF/l69cX+fpyfzHQxsldfjPfvXHF2i6a9+uIAv8/bZ7S426svDmSyhgJxEbpAnHMuchHXUExg4gvEOdwCcV60KED0xUQmvkCcZywQ5+6KIkRfTGLiC8S5sAJxfqnYAdEXk5n4AnG+pkCcAyl2QvTFQUx8gTinUCDO0xNDEX1RzMQXiPPeBOJcMjEC0RclTHyBODdLIM53Ersi+qKUiS8Q5w8JxDk5YndEX5Qx8QXiHBeBOG9EjEL0RZyJLxDnYQjEuQ1iH0RflDPxBeK4vEAcVxZjEH0xhYkvEMcfBeL4mRiH6IuDmfgCcZxFII4TiAMQfTGViS8QnycLxOehYiKiLw5h4gvE52YC8bmPOAjRF4cy8QXi8wGBeH8rShF9MY2JLxDvgwTidbwoR/TFdCa+QLzeE4jXK2Iqoi9mMPEFYr8mEPOymIboi5kN5AuvPC9FHO9GzAUCsS2LmUziYgHifIsoYlvGnHuwiElcYF7HY14fL0LktZiJLyYTjWVijsV51bWEiS9KiMZsMMccvOq6m4kv4v58Ni0WI/JaysQXlyFeRyHmAoHYlgWmL+S6zsxA5bdV5CavQ9dDeZkq5Xa5chL22lL5YZ3TCNaWPujztcTS5ssJ7H6IyfX15YjX11cgxjtiuxFcfHE4oi+uDNPEsJ/iws6XV6g8eaWRL68iypfyI2SnE+SNR32eL6XNVxHY/RiTGL0KMa6uRsyXiO1GcPHFQkRfXBOmiWE/xYWdL69WefIaI19eS5Qv5QcbzyDIG0/6PF9Km68lsPspJjF6LWJcXYeYLxHbjeDiiyMQfXF9mCaG/RQXdr68TuXJ6418eQNRvpQftz2TIG886/N8KW2+gcDu55jE6A2IcXUjYr5EbDeCiy+ORPTFTWGaGPZTXNj58kaVJ28y8uXNRPlSfgj8LIK88aLP86W0+WYCu19iEqM3I8bVLYj5ErHdCC6+OArRF7eGaWLYT3Fh58tbVJ681ciXtxHly6NB79kEeeMVn+dLafNtBHa/yiRGb0OMq9sR8yViuxFcfHE0oi/uCNPEsJ/iws6Xt6s8eYeRL+8kypfHgN5zCPLGcp/nS2nznQR2v8EkRu9EjKu7EPMlYrsRXHxxDKIvFoVpYthPcWHny7tUnlxk5MvFRPnyWNB7LkHeeMvn+VLavJjA7reZxOhixLhagpgvEduN4OKLYxF9cXeYJob9FBd2vlyi8uTdRr5cSpQvjwO95xHkjXd9ni+lzUsJ7F7FJEaXIsbVPYj5ErHdCC6+OA7RF/eGaWLYT3Fh58t7VJ6818iX9xHly+NB7/kEeeMDn+dLafN9BHZ/yCRG70OMq/sR8yViuxFcfHE8oi8eCNPEsJ/iws6X96s8+YCRLx8kypcngN4LCPLGxz7Pl9LmBwns/oRJjD6IGFcPIeZLxHYjuPjiBERfPBymiWE/xYWdLx9SefJhI18+QpQvTwS9FxLkjc99ni+lzY8Q2P0Fkxh9BHMdCGK+RGw3gosvTkT0xWNhmhj2U1zY+fJRlScfM/Ll40T58iTQexFB3vja5/lS2vw4gd3fMInRxxHj6gnEfInYbgQXX5yE6IsnwzQx7Ke4sPPlEypPPmnky6eI8uXJoPdigrzxvc/zpbT5KQK7f2ASo08hxtXTiPkSsd0ILr44GdEXz4RpYthPcWHny6dVnnzGyJfPEuXLU0DvJQR542ef50tp87MEdv/CJEafRYyr5xDzJWK7EVx8cQqiL54P08Swn+LCzpfPqTz5vJEvXwgHamyO5TOv9jRD9P8LYR7tFPN7xVTf/fHq19+Z5IwxiPVH9d0fr774g4kvxiHWH9V3f7z6Yg0TXxyAWH+Y3/35HdEXa5m8p/ZFxP4CMRcIxLYs1hJc14SUvhfV9UzvQGV5mJLTAC/Vc30T8baJNUG8dvAyYjsIqvqROnNUXaQZ9ifakM4dDSY4D/b9eM8Afmxjc+wVwG3zeltm3I9jO0/IRpKuECB2YjBAk6Cx6iRaXJabn1+UR1kHy4huarB5vsyEZzjg7zalt6Bhf6b6+xUg/yrgNcDrgOWANwArAG8C3qIOfOikE/YQ2E56NexrJwn9h1kXb6sriZWUTtDdtjzZauscIUInpHjpElWXLuJtxMdpK4kaB/alH6bN7yTQVRIpLcsXJQVlhSJenB8rLS3KFSJaXFBcUBKNlcdL8kUsPwY6S4ujMThdtLhUxCPFBXEZyBmBBI00gB/I74TxM6Lc3qUMMqqKeDeMr3cVYiOjsntVGN1HJGNZKxVXrERQtaYN0UfvIQeU7DSkzm6Byvu/hurhlzPs4d9X7fiDhujh31c9vJY/UDfq5obd4y9H7PHfx1wwxaTHx7T5Q6Y9/odEPf5qbj2+rIjVBD3+Rz7v8aXdHzHp8T9QXLF7fEwffUzQ43+8CXr8N/zd4+statbFJ6odf9oQPb482b/WObB7+DcQGma8vHL7BLGRf8qkh8e0+TNDl4jlRqOFuXK/WFlE5JWVRmPRaFlJXqQ0UlwajRfliaLyvGhebmlZaQnoLBblkfLi0qLyWCWvhuzhPyPq4T/n1sPLivicoIf/wuc9vLT7CyY9/KeKK7beLwl65S/VlUhD9sorGPbKX6m293VD9MpfqV5Zy4lOit1Lr0Dspb/CXCjFpJfGtPkbpr30N0S99LfcemlZEd8S9NLf+byXlnZ/x6SX/lpxRV9tSNBLf78Jeuk3GT4t/0G1vR8bopf+wXpa/mMDPC1/E/Fp+Q+IyeRHJr00ps0/MX1a/hNRL/0zt15aVsTPBL30Lz7vpaXdvzDppX9UXLGflmP66FeCHv9X9bTc3LCTYRDRT68wmYq5EsHvpfnR0uLigrK6fOOnefdcOudliDH5FpP22FCDEF7rE3EKs/iaic2ISwHE6/+HNr/GJO+8jJh3fgvj9s/yWuC3BDeW2NdZvyPw1ktT7DX+Urdc+/ZbsLJsCvgjXL3MYKhTbdN6o/zAOi6sfn9Z/b7M+n9j2Vg2lo1lY9lYNpaNZWPZWDaWjWVj2Vg2lo1lY8mr3A6wxnhOpCdTSFn+/w/1/GeNKlsD1hrjmnLDfj5q6op420SfwP/fM+HtmNjsINrcl4nNIUSb+zGxGXNca3smNqch2ty/gWyOeNtEBLH+/gjyGFsWAR48o0x45jLhmceEZz4TngVMeBYy4RljwrOICc8BTHgOZMJzByY8d2TCcxATnjsx4TmYCc8hTHgOZcJzGBOew5nwHMGE585MeO7ChOeuTHjuxoTnSCY8d2fCcw8mPPdkwnMUE557MeG5NxOe+zDhOZoJz32Z8BzDhOd+THiOZcJzHBOe+zPhOZ4JzwOY8DyQCc8JTHhOZMJzEhOek5nwPIgJz2ImPEuY8CxlwrOMCc84E57lTHhOYcLzYCY8pzLheQgTnocy4TmNCc/pTHjOYMJzJhOes5jwnM2E5xwmPOcy4VnBhOc8JjznM+F5GBOeC5jwPJwJz4VMeB7BhOeRTHgexYTn0Ux4HsOE57FMeB7HhOfxTHiewITniUx4nsSE58lMeJ7ChOepTHiexoTn6Ux4nsGE55lMeJ7FhOfZTHiew4TnuUx4nseE5/lMeF7AhOeFTHhexITnxUx4XsKE56VMeF7GhOflTHhewYTnlUx4XsWE59VMeF7DhOe1THhex4Tn9Ux43sCE541MeN7EhOfNTHjewoTnrUx43saE5+1MeN7BhOedTHjexYTnIiY8FzPhuYQJz7uZ8FzKhOc9THjey4TnfUx43s+E5wNMeD7IhOdDTHg+zITnI0x4PsqE52NMeD7OhOcTTHg+yYTnU0x4Ps2E5zNMeD7LhOdzTHg+z4TnC0x4vsiE50tMeL7MhOcyJjxfYcLzVSY8X2PC83UmPJcz4fkGE54rmPB8kwnPt5jwfJsJz5VMeL7DhOe7THiuYsLzPSY832fC8wMmPD9kwnM1E54fMeH5MROenzDh+SkTnp8x4fk5E55fMOH5JROeXzHh+TUTnt8w4fktE57fMeH5PROePzDh+SMTnj8x4fkzE56/MOH5KxOevzHh+TsTnn8w4bmGCc+1THj+yYTnX0x4/s2E5zomPP9hwvNfJjzXM+H5HxOeUiEHnkEmPB0mPENMeIaZ8ExjwjOdCc8mTHhmMOGZyYRnUyY8s5jwbMaEZ3MmPLOZ8GzBhGdLJjxbMeHZmgnPNkx4tmXCsx0RTweZZ3uDZ26kIC8vXhiNi1xRHIkWlcTyI3n5JQUxERP5sfyyaCw3Nx7LixUWlRQVRopEXm5clOcX5ZYrZS+FedjcAdHmNUzaY0cmPLdgwrMTE56dmfDckgnPrZjw7MKEZ1cmPHOY8OzGhOfWTHh2Z8JzGyY8t2XCswcTnj2Z8OzFhGdvJjz7MOG5HROefZnw7MeE5/ZMePZnwjPChKdgwjPKhGcuE555THjmM+FZwIRnIROeMSY8i5jwHMCE50AmPHdgwnNHJjwHMeG5ExOeg5nwHMKE51AmPIcx4TmcCc8RTHjuzITnLkx47sqE525MeI5kwnN3Jjz3YMJzTyY8RzHhuRcTnnsz4bkPE56jmfDclwnPMUx47seE51gmPMcx4bk/E57jmfA8gAnPA5nwnMCE50Qing4yz0kGT69z3NeGefhmMpM2dBATnsVMeJYw4VnKhGcZE55xJjzLmfCcwoTnwUx4TmXC8xAmPA9lwnMaE57TmfCcwYTnTCY8ZzHhOZsJzzlMeM5lwrOige6xvd4X90C0eR6T5wrzEZ8r/MbkucJhTOJmAROehzPhuZAJzyOY8DySCc+jmPA8mgnPY5jwPJYJz+OY8DyeCc8TmPA8kQnPk5jwPJkJz1OY8DyVCc/TmPA8nQnPM5jwPJMJz7OY8DybCc9zmPA8lwnP85jwPJ8JzwuY8LyQCc+LmPC8mAnPS5jwvJQJz8uY8LycCc8rmPC8kgnPq5jwvJoJz2uY8LyWCc/rmPC8ngnPG5jwvJEJz5uY8LyZCc9bmPC8lQnP25jwvJ0JzzuY8LyTCc+7mPBcxITnYiY8lzDheTcTnkuZ8LyHCc97mfC8jwnP+5nwfIAJzweZ8HyICc+HmfB8hAnPR5nwfIwJz8eZ8HyCCc8nmfB8ignPp5nwfIYJz2eZ8HyOCc/nmfB8gQnPF5nwfIkJz5eZ8FzGhOcrTHi+yoTna0x4vs6E53ImPN9gwnMFEU/H4ul1HXQ6os1vMrG5CaLNbzGxOQPR5reZ2JyJaPNKJjY3RbT5HSY2ZyHa/C4Tm5sh2ryKic3NEW1+j4nN2Yg2v8/E5haINn/AxOaWiDZ/yMTmVog2r2Zic2tEmz9iYnMbRJs/ZmJzW0SbP2FicztEmz9lYnN7RJs/Y2JzB0SbP2dic0dEm79gYvMWiDZ/ycTmTog2f8XE5s6INn/NxOYtEW3+honNWyHa/C0Tm7sg2vwdE5u7Itr8PRObcxBt/oGJzd0Qbf6Ric1bI9r8ExObuyPa/DMTm7dBtPkXJjZvi2jzr4g2y7HxsNLVx7A/qOogpP6fBpDjyXJ8VY43yvE3OR4lx2fkeIV8fi+fZ8vnu/J5p3z+J5+HyedD8nmJfH4g76fl/aW835L3H/J6XF6fyus1ef0i+3PZv+UAZP6T+UDGh2wvsv7ke9F7AnoBehtcXwpW898O0BfQD7A9oL+sI4AARKUfAXmAfEABoBAQAxQBBgAGAnYA7AgYBNhJ+W0IYChgGGA4YARgZ8AugF0BuwFGAnYH7AHYEzAKsBdgb8A+gNGAfQFjAPsBxgLGAfYHjAccADgQMAEwETAJMBlwEKAYUAIoBZQB4oBywBTAwYCpgEMAhwKmAaYDZgBmAmYBZgPmAOYCKgDzAPMBhwEWAA4HLAQcATgScBTgaMAxgGMBxwGOB5wAOBFwEuBkwCmAUwGnAU4HnAE4E3AW4GzAOYBzAecBzgdcALgQcBHgYsAlgEsBlwEuB1wBuBJwFeBqwDWAawHXAa4H3AC4EXAT4GbALYBbAbcBbgfcAbgTcBdgEWAxYAngbsBSwD2AewH3Ae4HPAB4EPAQ4GHAI4BHAY8BHgc8AXgS8BTgacAzgGcBzwGeB7wAeBHwEuBlwDLAK4BXAa8BXgcsB7wBWAF4E/AW4G3ASsA7gHcBqwDvAd4HfAD4ELAa8BHgY8AngE8BnwE+B3wB+BLwFeBrwDeAbwHfAb4H/AD4EfAT4GfAL4BfAb8Bfgf8AVgDWAv4E/AX4G/AOsA/gH8B6wH/AWQyCAIcQAgQBqQB0gFNABmATEBTQBagGaA5IBvQAtAS0ArQGtAG0BbQDtAe0AHQEbAFoBOgM2BLwFaALoCugBxAN8DWgO6AbQDbAnoAegJ6AXoD+gC2A/QF9ANsD+gPkElOAKKAXEAeIB9QACgExABFgAGAgYAdADsCBgF2krkWMAQwFDAMMBwwArAzYBfArgD5fXv57Xj5XXb5zXP5PXH5rW75HWz5jWn5/Wb5bWT53WH5TV/5vVz5LVr5nVf5DVX5fVL57U/5XU35zUr5PUj5rUX57cGDAPKbefJ7dPJbb/I7avIbZfL7X/LbWvK7VfKbUPJ7S/JbRvI7QfIbPPL7NvLbMfK7LPKbJ/J7IvJbHfI7GPK7EPKbC/IbBPL9/vLd+fK99PKd7/J96vJd5fI94PId28cC5Luh5XuX5TuN5fuC5bt45Xtu5Ttk5ftZ5btP5XtF5Ts75fsw5bsm5Xsc5TsS5fsH5bv95Hvz5Dvp5Pve5LvU5HvK5DvA5Pu15Lur5Huh5DuX5PuM5LuC5Ht45DturgXId7PI957Id4rI93XId2HI90zIdzjI9yPIdw/Idf1yzbxcjy7Xest11HKNslz/K9fWynWrck2oXG8p1zLKdYJyDZ5c3ybXjsl1WXLNk1xPJNfqyHUwco2JXL8h10bIdQdyTr+cLy/nost53nIOtZyfLPsgOa9WzlmV80HlXEs5j1HOEZTz7+TcNjlvTM6jkvOK5DwbOe9EzsOQ8xLkOL0ct5bjuHJcU47zyXEvOQ4kx0XkOIF8bi6fI8vnqvI5o3zuJp9Dyecy8jmFvG+X97Hyvk7e58jrfnkdLK8L5XWSvG6QOU1vbYy/t1RlcUVFfPqsipyKmTnFZWU5h02tODhn5vz4nPJpM2VXsSGH662zKkuLp03bcMDcufE5FZOnFy+YXDK1YvLcqQtlL7Uh3bs85Cr3h1zj/pDr3R9yo/tD7nJ/yGL3h9zn/pAH3B/yiPtDHnN/yPPuD3nR/SHL3B/yqvtDVro/5F33h6x2f8jH7g/51v0h37s/5A/3h6x1f8jf7g/5x/0h8irJ5SFN3B/S3P0hLdwf0sb9Ie3cH9LF/SE57g/p7v6Qbd0fsr37QyLuDylwf0jM/SHDjUN6qHLveSXTppbmlBVXFOfMnTazIqdsZnzujJ4VOdOLK0oPltcOM+Jz5Q3nhqvl1I/e2dPRBzjVR2+rj54zc/7UGVNyZlVqmV88bV48Z+qM0mnz5k6dOSOnvHjqtLi8yw5McFzX1LBw9SFtVbkncCmeEs+ZAUSnzsiZW1FcsWHf3Y19k70CO8XlMbLyTrHsl9sWqhwyZ07x4cCqLL4gZ+a8ipyZ5TklM+fNKJtrHtg31QNzUz1wQKoHDk/1wE7B1CvWTFuuTrpNqgcOTYHtWWq/UdWHbnjQZh07d15JxZzi0oraFexrKNB3Ebsl5qsPGRtwaag+cIL7c01O9VyzA+4r9Ry1347J89SHDHbLUx+4pwee+7jnOSZVnmUp8LxM7be3cayrRqoV7Je8ofqQ/d0aqg+c5P5cxamea27AfaVeq/Zz0Uj1IYPd8tQHptJI9bEuGqk+xHUj1Qem0khvU/ul3Ei1AheNVB/iupHqA100Un2I60aqD0ylkS7xWqlL3FfqklQrdYn7Sl2SaqUu8VCpD6r9XES+PmSwW576wFQiXx/rIvL1Ia4jXx+YSuQ/rfZLuZFqBS4aqT7EdSPVB7popPoQ141UH5hKI31J7eeikepDBrvlqQ9MpZHqY100Un2I60aqD0ylka5Q+6XcSLUCF41UH+K6keoDXTRSfYjrRqoPTKWRrvJaqavcV+qqVCt1lftKXZVqpa7yUKlfqP1SviXVClzckupDXN+S6gNd3JLqQ1zfkuoDU7kl/Urt5yKd6kMGu+WpD0wlnepjXaRTfYjrdKoPTCWd/qL2SznytQIXka8PcR35+kAXka8PcR35+sBUIv9PtZ+LRqoPGeyWpz4wlUaqj3XRSPUhrhupPjCVRhpUDwRTbqRagYtGqg9x3Uj1gS4aqT7EdSPVB6bSSDO8VmqG+0rNSLVSM9xXakaqlZrhoVJbqmNdRL4+ZLBbnvrAVCJfH+si8vUhriNfH5hK5Hfy2kg7uW+knVJtpJ3cN9JOqTbSTh4aaTf3jbRbqo20m4dG2s19I+2WaiPt5qGR9vHaSPu4b6R9Um2kfdw30j6pNtI+Hhqp8Fqpwn2lilQrVbivVJFqpYpUKzVT7TRSKcgwFOQEkNZdxKLl6YZyY45BtaxPnFF97ixzX/W7/C2kfgqq3+QajU6B6v871nk2HKN+Cxm/hdVvYeO3NPVbmvFbuvot3aCSiV5HkUKptym23kg0JvU2Q9dbuZameaC6vnKM8zQ16ipb/R3EO7cwzx1U0OfRv4eNv7cw9tX76fpoov5uZhyfpf7OruO4TOu4bGOfrAT25yDb38ziY/KQW5rxt1yfpOOin8GtCTq3aFlWoDp+Akb9BSy+emti8ElH5xMRsi12VLqmxCsqp1INL64oHjMnHh9XOXMqaPDU3PtZ3IOBmnasN/Yxc5r5dyjBbznG8RnGPpg2B4261LrTLU4ZBi/Ec0eo2lUwUN1N6Hyj+evzhY199Ny5loGNN1OX5qn9rnU2t+pKl/i2RQRJn6LqrKlVZ5p/plFnep9+9dRZ01rqrIlRZ7quzD4A37ZIVOrNIqqzZladaf5ZRp3pffLqqbNmtdRZplFnuq6aGXWGb1skNyNQ3Sfi6a2ss2yrzrIM+3Sd6X0G1lNn2bXUmanT7u8c41zm9Y4T2PjaYL363dYh96epo0ie1NsCXW9l3et61HWv+evzhY19Rqiytro3f88JVNd9c6PMtnTQ2BaJZiXgWde1RAuDT2t0PtFYlnGOZPi0Nvi0QudT2W/g21nZh+ub1fWIemVdtbXqqoVVV9nGPm2M+mtLUH9B47xat5b1+Ro5N3Ju5NzIuZFzI+dGzo2cGzk3cm7k3Mi5kXMj50bOjZwbOTdybuTcyLmRcyPnRs6NnAc3cm7k3Mg5Jc6Sjx7v1VyzjP1a+oSj/q2VwVHPI9Xzh+S4+VqDL8G8iw1vNmthnC/H4GHOu9D7tApW77vO2K+FVb9Zgeq5FmadE8zj2VDn+lxat5bNOTLNDW6aT0siPs0tPs0T1I/+O5SgzjKM37QNTY3fdLsx54vqNtXM+E3HpBkLbY060b85CfiZvHSp24Y5n0nP7zDbsp4r2Nr4Tc/xamP8pu1sa+jl3J4I+OQn4mP7IWjUb7q1jznnTO/TOVizLs2NZl5n5Twj3UbsOV6OwVHv07UOjqYuzTPRHC9tbyta22Jm3rfzqGmb3mfbeuq/NQFHGtsr46WNYWNOoDo2TNv1Pn2MPqSv+tuMb7M/Gpjg/3oLWnKO8Xdroy7b4du8YR5Se4NnjnEe89wdDK5I5xbmuYMK+jz697Dx94Bg9b56P10fuq41d+k3nYtN7vZxWdZx2cY+bRPYn4NsfzuLTzuLs/RJf6Od6XZENY8u0bWymXd1Hel9zDULBHNFhdkfaN32dZ157Wf3GeZ8eL3PsDpylnndbV4v2P04TW6rtLeFZW+ie5Wq61iDo22zed1dYfAOYPOORXLrWtfmZv1aE/MYS5+5didoqEvDticSpVq7sUFvBrreiDCvVfVWV7+ibZPtqJ1Rx/KgdGt/ojn4G/oee31BlsXPzCvYfU8zQ695r6N/N9c2dDL2te+JdH2Z12vm9XVA1a++78k0bEtGX7axT9ME9ZITaJh7BnONY7bBg+pazM5VGUZd0p27MkYzifQSxNGG2DfXI8mtrtjXtunYDxkHNbX2J1q3GUn0vCbb4mc+18CO/RaG3mBg42dt5vVCf2Nfe02Iri9zXY3OGXrfROtxMpLUZ16PNE9QLznI9ZJt8bHXt0hfdTd4UK3ZrC0HmesQKfKfeV2it7piqXkCPohtNZJt8DHPRbGWWn/TMVnbzTZqrhkn5Bgxr3PNdXY7kp43mnCNv83DXGc/wth3iFE3ur8yn0naa6OzEuynnycmyiNmLhuMYm/NXKBzZAvDDm2v3mekYe90gxu+L0S56YtgoGaeChu/13ZPaO6r99lLlbU9o7P7KrMtaFtbGfsPRrG10g8tDb4ml1bG73qfMfXYUdv6yCYJdI1LUlcgUPO61Vwfad8318XBMfZpbfAxjzFt1vtMtM5h82xdy/kyE+g6KEldgUDN/tq0WR/b2jjOjBkzZs3nCW2M/QervyPethrjeDqO21icTfunqFLW1TTjODPXJuJv9lPmvQHFO0/M/iY7AV/6HJR4bMzOL3XloERjknOsOjW3rATHmv3eFMPeALa91vOdYAJu9vMd+1lO0HqWYz7f0e2mVYL9Mgy7cwK492LpRHop3ovh9l0y2rZEz3fSrP0lZ/z3LVXe4+nrdp17m1r85LnN5zBI565xD6HznjmeLLew8bf5fKe291SYuV7Hmd5X1q9536rLZPSZ+SwzQb3kINeL/e4S+50bDfV8x36u38SoS31uinHxGvlKbck8LzH5YL4LINvgY56LICaFOVchGdvNNpqRgKMfnmdlJeCD6J8N1xtNE5yL4l1y5v2gGY/9SOtcbMjVmcb5cgIbz5sJG/vEjH2F+tucp+AYv5nxrPXpv81rhHTr2KxajtW89P763jjTOj5R/xMybNF6qccXwhYX89pP7zNIlfW9O8m2Iz2BriFJ6goEavZH5nMmzdXs3+z+c721rxmz2XUcZ+qVW6Z1jJkPzedK5jMPXeL3D5WxYD8HDVlcTX+mW/uYzxf0PqNUWZtP7HZa1/OMutqT3md0Peer7dl7egJd+yWpKxCo2Z7MZ+L2nBgnsPE7IutqT3UdZ55Lbs2sY8y+y+SUbZ3HvK9F6z9EJGJyMvmb/BK996yh3pdpt9u62raZ0/Q+cVXWdt9aV392pGFvANveTTgvQdupS/t5btj4/3xjP7Mt4t+fCqL5ByJCea1u3ifYdazPFzDqTW6J7nu1HvOZW0O/D9jsu/zwPuCtjH2TeR+wPT4p69fO1xlJ6vPje4Jp59dW8si0eNjXrTTnrozRpkR6KZ5VuJ0rq21LNK8h0Zx7gvc0RhKNb7Sw+DXEWJGO/VaW3eb4TtTY156Dbl+vmWOPel/zWsYc901GX3Zg47UfZr3kINdLbXMqzXn8PQweVPMaastB5rwGqrF9N/MaiMdwIrWNFxHE5AbbmweSt91so82Nvwk5Rszn++a92WDS89a819X5yuZhjvPvYuw7XP1d27yGROsADzeOSZQ7Gnq+V6K5AHsYfGca3Aj8Xm7WfzBQMzelGb9rvvp+LJGP9D76k0DJzgGw7/3Nue3YfjDH700u5ni/3mdsPXa0qsWOjAS6xiepKxCoea1qtlF7DkJdHMxnkOaaIvMY02a9z+R6eLap5XxNE+gqSVJXIFCzjzZt1lzNuQlmzJgxa147m2uvB6u/I962GuuzdBy3tTib9k9VpayrGcZxZnwl4m/2TeZ7tCnmWZl9TIsEfBsgByWc92nnl7pykFn3eh+93qS2Z0L2sXZfV/UMJoB7HaD7pJBx3sMNXvb4QG1z8boaXPWWg8U1JvLM51ahBPWXzHOrGn2w8SyrnXEo+tyKWOW3FfDX5AhBNLdiwzWQ9qP9bRBzfp/57B/p3DXWOeicZs8jCAc2Xl9u7qfrQ7cJ8xsk5hhZbcfZ68ayjX1Iv/VVzzwAczxS/y1ztP6Gmdnf4LcL4XrOTUN8v0nPU5kSr9hDjJm5R3TP+PSS+Jy5B0+dVccXnFpZ7IOBmpasN/Yxs435xNz8PZzgt/UJSjMDmavazRX++jfH0m1mNLNFmF7XW04ALXvVmXkd88QZ1edOlJFJniLEKr90gT8jrvIrQvhZu+bKxESz3s0MQ2GXbDvmGy5CCUZvQtboTVPjmFnFpYcOmTNl3vT4jIq5ZtBo4nYgmUHjGKV9aWHul6NkW5eZghIFi/kJJfPxlal3sPo74mWLRWp8utJearqBu67EjJo2VX1y0vq96rOTRuXL36s+PWn87uWSx6zDkPFb1VC38VtVt29cLm1pnJbgcqmAKPCKGi+XAoHOxr7/T5dL5i2t/mwr8dTColSnFlLVldSvP3canzF7XnxevPKTlzvPm1FaMXXmjGHF06aZV0T2/Ma6rpZsh8utvqsluZnXk+axTRL8tt6olESyyc9McuZcObtBJ+o8aptTl279FghsPIfC/M20M5jgbydQ87lYIIEd9m9ZCc7TKsFvierPbnzmuCrm/F2pw3yeYHMLBxJf7QTxuQjT3lBg4zpolaB+/gft7/R2hcQFAA==","debug_symbols":"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"},{"name":"claim_public","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"},{"name":"secret","type":{"kind":"field"},"visibility":"private"},{"name":"leaf_index","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/+1de4gs2Vk/XT09c2e6p3umn9Pz7Jnpmvf7zuPufe29N7suxvhARTD5QyVxzYb43miiiA8URUSJGME/QlZUXIzgX64YJMkfIeAqKGj+EEHFIAiCIiqCKLG/9zlVNXOt66ZZpQb63qpT3+98v/N93zl1zqk6p4au7NytKTf6W3H8Nzq75epucvRfBL+HTo5GB/Ar1V1JkmK4CCg6GqW7cswAN4FHIw2ugkcTo38m8agCevBoEv7ZGP1Tv3BCZQisQIerxsJqxmEi/FXhn1jYzJh0lCUdqXQ5lC5nSZdVesKkUY1KT5j0jLF94Ub9ntahXRliCpSnzJmBcA3VQyFrBqs5ZVKj/wtIASkgBaSAFJACUkAKSAEpIAWkgPyvICgDCBy84igweop02WQG4eGsIes6NqzZ2HAW/nkIeVToAo4HBzZEnJ/Ew3mWbY5GjCDSKqFkC5Lgtw5KvorOyswNMK1YxBo4ZneN0W8uKRNRomsZ25ZTvYCeHxWm9LwNhhtlPJyVHI1wiwi3OMs2E+4Q4Q4kwQ8JfxudCRnAdGIRa8RioHmjNcpGaIHMfClkGRbM8momlURsuE4SEXGJOp5OpyWCvFpgiq+xy6y0zlnUzfnzdtgw+TmNg6bFQUPjYJIuJOOgQ2btsGyXzdojs/YgCX5o1h+gs7KV0fViEWvVNXLaSZmIvdMztj2negHdgcJ/wOKgRXHQkByNcI8I9zjLBSbcJ8J9SIIfEv45OhMygOnHItaKXdon/ZLS6ltYKMuwYJZXN6kkYsP1k4iIS9T3dDotEeTVA1N8JBUmc5yFVyU6WAJInAbMRy0sZshI09ziVMEas9hGgeDHkDc2QNoUedNX3qwRNGkzKA1n06Z6JF6C6buqzVHVJxUGMdtAD7wGR5cliUyT9gK3XlGyAJxD4G/AEZD9TaSI7SKcvpHV2jUsb4z/STV6g1ofDJE2hUibPdBCPb9rbZLU3XYsYl69pwsRV8a2sfeCHSBNIPlbyNRkZi0fMM+83i68Fmhk3NJPWyP/grXR06yUGuPPwFGWRZte01HRVnReS/o5aWM+H7P5XANOv6AWbZhFm6FFvVai+bRW4s+tPtRSrQRbq5G3afhDZOo1dpbPtHomMs9EdI8s/b7dk8FG7Uk1DCjtIOG/gqMsi3rtQruilbCtJf0iHAGxv9OmBN3/r1ktcSe06AIxWZCGgS26SBZd5Lagj3r+xRqJBmMWYxHrWfzRhYjttmjsF50qA8gCkPx7ZJq6MTfZPOSZmnmmTG1P6dNWeV+w5niOlVK7+19wlGXRBc/LFb379aSkEejsj4hF1Edqsvujllq0YxZdCC26REyW+MoyW3SFLAoPIZbhh3qadCYFBsxKLGKLFn90IWK7rRj7FafKALIEJKeQqcl0LZ859UxDjzpBV9DDNa1f0NRuVNdkoIFvZj008CptycSxbbhbZj2dsKXomq5uyKKjGrqpIK648A/l8cEOSnS0fF3vLqf5LVh+/ez88BLl19e7Zj+MnyXNb9HyA384lV5EEWhxy+Cai6FWIY7ash98tS9I8D1nlcsgbc/4hG6zyecxpJ6HI4t5ynxCbiRxSXqCZibqQ4PZOxEmSk9wgnprPQkN7TRQrbf6D9gFwi7yha7TrLrUCCSNG1FnTaRa2e7skkQ3dGIvy4m9MOwmtoVuKVHjzSZYNO/24t267E6j97zo3eE9zwVNZzMuSderbnZLlOpLoz+Qqks/GCpB5UuJP1BKEvN0c654FpG/OZKAKj0XaXZw2kycaqcbs/NwC1N4OMGlwB5P9AE48hvNrFoxUVfkRCWIkgV+5je690uQzGve35vMW9uaLIcm2hGvx9k002PvCiNzKuzONVzQ++LGph22O/V7E54M5FeHUHOz2JWrYUhV7VY+nfX8c9poftb5z0in8zwjXXLayQLhZSzSEt1ABLZsHcRlp6P/AlJACkgBKSAFpIAUkAJSQApIASkgBaSAFJACUkAKSAEpIAWkgBSQAlJACkgBKSAFpIAUkAJSQApIASkg/6chKIMrLfR10+gp0tev6/JeMV7V99mW7X023EsF1/P06EJyPc86vT+5zrIb/Bb0Jr0FvQlJ8IPrlV+lszJzg7TNWMTWaD3PGhELZSJmu2lsN53qBfT66HLlY/YC3xqt51mRHI3wJhHe5CyHTDgmwmCDIfyQ8O/RmZABTByL2FosBlo3WnFJacHl9VLIMiyY5bWRVBKx4eIkIuISxZ5OpyWCvDbBFL+eeg12lX24as7v2eGGya9pHKxbHGxoHMzShWQcDMmsQ+HNZt0is24xtxjN+sdGep0xW7GIDSgOBqGPSSbiYm4Z2y2negE9hMJ/1uJgQHGwEQYQ/G0R4S3OcpsJ7xDhHUiCHxL+WzoTMoDZiUVsEIuBhkZrp6S0QGZYClmGBbO84qSSiA23k0RIldjxdDotEeS1Bab4k9SioDX24VpqcecgDKuBxsHQ4iDWOKjRhWQcbJNZt4U3m3WXzLrL3HbQrP9upIeM2Y1FbLOuLchWUibiYu4a212negG9DYX/B4uDTYqDOAwg+Nslwruc5R4T3ifC+5AEPyA8OUtnQgYw+7GIbcZioG2jtV9SWiCzXQpZhgWzvHaSSiI23H4SIVVi39PptESQ1y6Y4j9SK38H7MOBOb9mh15YbWocbFsc7GgcVOlCMg72yKx7wpvNekBmPWBu+2jWDSO9zZiDWMS26tqC7CZlIi7mgbE9cKoX0Hujwkx2LQ62KA52wgCCvwMifMBZHjLhIyJ8BEnwQ8J36EzIAOYoFrGtWAy0Z7SOSkoLZPZKIcuwYJbXflJJxIY7SiKkShx5Op2WCPI6AFPEqWWXm+zDTXN+1Q69sNrSONizONjXOFikC8k4OCSzHgpvNusxmfWYuR2hWb/aSO8x5jgWsd26tiAHSZmIi3lsbI+d6gX0IRT+scXBLsXBfhhA8HdMhI85yxMmfEqETyEJfkj4vXQmZABzGovYbiwGOjRapyWlBTKHpZBlWDDL6yipJGLDnSYRUiVOPZ1OSwR5HYMpvi61WG+Lfbhlzl+0Qy+sdjUODi0OjjQOGnQhGQcnZNYT4c1mPSOznjG3UzTrh430IWPOYhE7qGsLcpyUibiYZ8b2zKleQJ9A4T9ocXBAcXAUBhD8nRHhM87yNhM+J8LnkAQ/JPzzdCZkAHMei9hBLAY6MVrnJaUFMielkGVYMMvrNKkkYsOdJxFSJc49nU5LBHmdgSl+OLWOZpd9uKuLvWGN2uQvWizwwsc+D1UOwATVz0sL88u6fHsia3xStfFJFccnJT4re+3PtXslejsk2kKcKi42RI3WeOHqG9NVDllMqIayaZggDVmr0/xlULqnYtnrW127J0b2sqpZym8WodKr9vbyaGh+9cSqc5WuW6g2dDkwrMuffMMWEVZtRTfYbxZd9StwBIKfQuPXrQeIWZgfJgwN5cUV9pNg8UZybdwMizVi2ZujSiU0H4NYlRasifNnnFoBF//rMvV6zB0VPgJsjbB1vlB2mn/ZbFd2/v4kVbNdPYweb10WG7jKQjO6DtnboWDGtsaYuQ4ylR9y62YIXanYIfxmcSGbyKBTMS6m9qWyTVGoY2vVoMV50i5P8Rq0CUqecsG2MGA3W583d+36vHlvfd4ow3c5XczNqxB5eby3kUbWxgUj6KklC7SjK/TTO5fIrhYAPXTBThW4S0DWMmBvp4wuQ1+1ZIH2dM1zel8A2WQDoN9tyQJd0AXw3tLThXCRfDML0skPad0MGRE8s2SB0mpmEEjvAdLkdhygA0sW6KItbU71F5p0iNDvtGSBLukq9iVvDXW4BB6g327JAr1pFowX0iP0+y1ZoLR2HgTSa+ebdJi07P8IMqQ9flZC6CpCQWDVm0Yz6CpDv8OSBbqGUBBY82ZeDLqWJrqmZskJ6d8MGRF8xZIFOtCZpoE3JWDQQVrbQC2ZE9LPD1m5GTIq0wctWaDrOmvizditG3Sdod9nyQLdQCgIeDNlGwbdSBPdUH/lhKzcDBkRfJ8lC3RTpwzTk6RNOkToRyxZoEOdRPAmsIYGHaaJDtVvN0BG2r7LkgVKU5ggkJ7CbMpdaAT9kCULdEunw9ITgE06TBLdUpd/+SFrN0NGZXrZkgW6rSN3b9Zo26DbaW3bqi0nZCk/ZONmCFSIqU9aFwLLkbUbzbZjzxF2SJ1t/tvR6a3t6yf0rI/iTdrsTyaH8djtOaRBGvQRDmSEMvW605mDOcYcxiLmzcDQhcjxqNoY8XB3nyH7oxCZ+rhHK0H4UraJ2DrkgQF2+Kas7wVdsltDHbjtZA0idlzWsAevjAr7jeaTGgs3kfq2C7Y/YE/sMKOdLMh6fshafshSfshGfkg/P6SbH9J7y4mNXPpeF2zzB5d2dZu/9IT3jtNZ9TSklx8yzA9Zzg+J80MW80OW8kP6Y7HYePzylOKPYu3DlizQPZ1B9Gav9wy6l9a2p21BTshyfkg3P2QpP2Q4FmL9/JBWfkg7P6QzluL3xkLsGSy2MBZXLo4lkpfHAlnJD1l9y4sP/ZdbP2FdKnzOpl2qHetS7WlflB/S+X3RfX3Etnf9Q0Xrs3kPjo4mk48SsC96Qn1RmJWH5wjHSPNHnT69qDHmJBYx7ykQXYhYmff8gJ8QHDHkaDDK9FWPVoLwpbxgcASn/teAbmXNtd8KO51TVshb2fPj+zTbu+/0keUMZ7OXZU923S2meCsLUrkZElCSwuzg5KjIzNBdLmv+/ZD44hNd2tZMnqAdVPTxEuTFz73uO3i2Juhjs9RpaKkTowVPuL7B6QMoefp2GwsH03S3DcbPjk7pMPnA7ra2sDkhvfyQ9fyQlfyQ1fyQpfyQfn7Icn7IYCx+6b7lxR+F54klC5QeHIJA+sEhP2dMajtXbTkhw/yQXn5IdyxlWckPGYwF8hSLjaLgBy1ZoBcIBYELg14Y9CKt7UJraU7Ixs2QEcEjSxboJUJB4NKglwa9TGu7VNfmhJzlh3TzQ3r5Iev5ISv5Iav5IUtj8ctyfshgLH7pjqUsz2CxxfyQeCxl6b5dA6Y7liq2/na12NZYytIbSyQ/Q/Hb+SFPuSWBdaY/aeOKBwh0NpiQ0QNI0xj1lHL0x6hXqOoqVHWHwJd0KFdg4HLHBiV3aYx6l4Xu8Rj1Po1RQfge/JDm63QmZQTM/VjEnjNtdCGiRHffGN13qgwgdwejTD/u0UoQvpSXHR9YFldqmwOzzVU45jralmc1OHBLDRmP+Kr3CuPVpA4m0YpY3jeUBP/Jy7O30EnsTrdX1/HiUfaW3gckgU+eaONtmRMgRZ8OFdXRt5hf3aRLquWANbG4vzX4JQGA1iUGyFFIcvJ6klckAcW/MpJXGqRvwlGS5GRI8qqkWgB4FFCYdGqFK4JNCMxUczHFPlcT4t9LShUbsLxqgiSj5GV4VNEMMWmoy2fuZL2+fCcMpdOhf0VmUEDoOW3bnzNxrgR3OPQzId2xQJbyQxZvhoxahu+xZIHe1Xp+16B3DXo3re2uliknpD8WLb2xEFvJD9kYC+QZynKeH7L2lrtyFJ7vt2SB3kPoXbqzCfSeQe+ltd1TM+SE9G6GDOnzZfdCKN0n72XeJ++E98UQspQfsp4fspUfMsgP6eWHnN8MgaLOvGLt/QoCXdiUO5ambtUdytHvVj1AVQ9CVQ+ddlge2hW4oTy0m8Uj6k88YqHH3K16Qt2qJ5AEP6T5Mp1JGQHzJBax500bXYgo0T0xRk+cKgPIo5EHZt7j0UoQvuTOobzeiGVU20yabR6E98KroX+lzDfUB+qS/UyXPGDVmZDKzRDjd1/n8R9wJvcrmhfM0ldolh4ynLAeLppNi/bQivYoLNrzQ/9KmS0FQo91xuexiT82gz++DtLND+nlh6znh6zkh6zmhyzlh/TzQ5bzQwZj8Ut3LMW/PRYtw/9HFlsZS8CMJ8bOx1IrN/JDLsbiyqJNLtrkL7f3l8discX8kHgsZem+XQPmGYg9QxVbf7tabGssZemNJZKfofjtt/yWhKtgf8bpuOEBAh3/PbJxA0jTcPER5egPF2lw9iRU9Q4CP6ZDuQIDk3fYoONFGi6+yEJfwcPFl2i4+BIkwQ9p/hSdSRkB81IsYi+YNroQUaJ7yRi95FQZQF4cjDL9IY9WgjAOF6G0DyKdSYXJ2IpN58Koy5tMt4nVyrUTqwepidUKCz3RrQzSQ9w7bN87niuzRvWPQ2VPdmRsCP8/2EyucoZ76QQtuAd/4uLoKTwNVjpXP+EyviUON6858h8svoWVJPg91uqvuYzvscoaXfsea4PmqnGJtK5tbkS6mLlBcrIuGiH6IV9bDd1IvdeGmv2viUaqCE5tmXlZF1fzRzTxI+glXRiTsAeuB8ISwqfLm1n2aJk9cM0vSsOXsNvX2cM+ee59IbVqVph1+jnThlzV1eG11PqJaZEx2lV14+dCN2IAwVVaK6+7FRzobgULqdXD/KFbt6Dfw/X2QIgIglW4Yx9DxXXISOBP4cgIGHJFRf4sFLFNv0Csa9/etU0PWpZNSz30F1keAmlvyUmLvoO9xEAKXvgk+Ty0DH+DVoBaDh8ar/5T1keZE99qbxAT8VOdTTFNrdk0B1gd9fyj06XwB4yZjksWaWUuKF2IJCK9r9Y7VYb7DQDJLyLT1ELzLptnTl/qnku90dtnIktTeorf80aysD3VQla8Nw2Ma68NvKAW/c+wOTBvwX2Wv5k7z2GC38yFCul/M9cQGypSDkVsTzAqZ0kaJHN83T77Dl6YxmzActNZYeIZuk5h0mbgBALxaGSB2lzMMeHm4HQta9eA6TBMvH114MpN++rUVp2+4dx1yX11yraGz/bCwafsN255U2sh09R+J3NsnjLmAy7hzSEeWSj12RLz5ul5qbu17euqNzRi3Yq0I7TeHxH7YWAZIlaRo1DEdv3qB81Q13zHm3XM8y2sjNnApEE5y9Pe3iUTFa1SAMQX1GvPidXuxU6MBKfvzPp+czn09OmkvvQA/5+xp2+X5D1UHMyfoZ6vdPqG9JyTt1dF7MRaX3utFV9avf61ViD5EJmmGg35RPWJ9t35de1vtcDtM5GGebohdbr29dfV6Vq6TlNsfNN1sbGjIt+c1fRvp5p+r04fW4N7rFXmW+Aoy9PeooHjit4esWYg8H1itZdjJ1EFpx/KavpPQk/fJibsK3jPFD19UZJXOXHW6hz1vOr0NdMFxlzEInZmlZ0uyJRP+s3Q2wy5DSRfQaapHX/kFnKmdZp3hPoxOvUrccLT1EL+SNhCmt+w41DRO5vV6R+/rk7vq8hPZtXpvVSdnjbfnZqnT7XK/CwcZXna2/XqlDytNQOBvyBW+6i23linX8uq02ehpy+ICfsK3i5CT1+Rp+WNDXy/pfYJpy8+dRlzFYuYFwJ0QeY2r7xHT06VAeQCSP4SMk0tgFlg85zrrrj8svNrVu/70lkIPU0t5OthC2l+g8FtuSJR5dXp376uTh+pyO9k1enDVJ0um+9um6dva5WBDvd5lqe9F7pvk6dPpGYg8FNitT8I6/QfZdXp89DT/G4U+wofZOP7ISV5TQSHZfjItfam03HYAmOei0XMCwG6EHGUpN86uWLIFZD8DDJN7eAmdfpS7/f2JqTthFxORYhYp6xtShmloZ9HO5vFvKuN7I8DvY9OSb0O//emNC9IwhFO7S9dMMLx+odkQlwerjePv3YZ48MJ6RDq+LBN4yHobfQ0UNo0MupJN4RGRtKCtXWaZNEQ2ePDfl2R/UgVYUbaVHa1JWrb+LBJ9mim7dHU3uk/h71Ts0fD7IGjWJT+Nzi6zh51HbPPEWO4J/fMCvOUJAWYCwrgjd/mLAbmrP8m/SR0I+7S1k6MD7EbOKIe0S0K95XDC4l931qWf8vJ0BoHukMtT8vGqChjY9SycqiFHGzftYjcgFWQ+5Jt6U8iEvsbWchZFWmHIrbsEO9gcUmCmijD9NHCpBYL943CbLCGJN37ggu2lVqo6DAfgIsIhLd/Fgew+5yOvTtweqKtUcdao37YGi1PBkPhFTbFakn2WsJB9ArqOXa6Q1OVMauxiC1Z7aUL8ogkvXXTMkOWgeQQmaY2BZOGYUnrHm9zNXS6knJa2qTQ41UkC41oNctv4NBqRfZKpMqMiPvXxUhDRZ53GXMuTRazOZeq+W7RPI17dWE2MFe4lOVpbyuvxYrWaQAuI/CdYrV36eaRbTh9j3q6bZ5eCj29OqmNL+9xhZ4elHQ7cIijNdTzbqf7VXUYM4hFjEOgrReu3y9qlSGrQPJrkWlqi7Q2m2dF559W1OcTWW1C1dqEqt53+qFM2yIEG2CLkL70TGbfH/ZMYqkdMG9Vwi7cwpvw+28LL2p1+qQAAA==","debug_symbols":"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3/ROvumdfNO7+KZ38U3v4pvexTe9i296F9/0Lr7pXXzTu/imd9FN77nRTe+50U3vudFN77nRTe+50U3vudFN77nRTe+50U3vudFN77nxTW/jm97GN72Nb3ob3/Q2vultfNPb+Ka38U1v45vexje9nW96O9/0dr7p7XzT2/mmt/NNb+eb3s43vZ1vejvf9A6+6R180zv4pnfwTe/gm97BN72Db3oH3/QOvukdfNObz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJbJ57VMPq9l8nktk89rmRvd9E4+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsXntSw+r2XxeS2Lz2tZG930Lj6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1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"},{"name":"mint_public","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"check_balance","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"fee_limit","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"5ZztjpTHFYTvZX+jqM/pqv7gVqIowjaOkNBiGRwpQr73LMl8LNqRlzqZrKfEL3uhe/r0VjHF1rw8n+9+evvDb//4+7v7nz98vHv918937z/8+ObTuw/3D199vmt/ifjPr3785c39l1/4+OnNr5/uXrdXd2/vf3r47++v7n5+9/7t3etc/P1vr75sSHVDVzdA3UB1w1A3THXDUjdscUM2dYOqdKpKp6p0qkqnqnSqSqeqdKpKp6p0V5XuqtJdVbqrSndV6a4q3VWlu6p0V5XuqtJQlYaqNFSloSoNVWmoSkNVGqrSUJWGqjRVpakqTVVpqkpTVZqq0lSVpqo0VaWpKj1UpYeq9FCVHqrSQ1V6qEoPVemhKj1UpYeq9FSVnqrSU1V6qkpPVempKj1Vpaeq9FSVnqrSS1V6qUovVemlKr1UpZeq9FKVXqrSS1V6qUpvVemtKr1Vpbeq9FaV3qrSW1V6q0pvVemtKh2tyTvk7qTJ5UmT25Mm1ydN7k+aXKA0uUFpcoXSZM1D1lzvy/TCTG/M9MpM78z00kxvzfTaTO7NQi7OIvWOVNZc7s5CLs9Cbs9Crs9C7s9CLtBCbtBCrtBC7tCi68W4rLlco4Xco4VcpIXcpIVcpYXcpYVcpoXcpoVcpwX0T0NkzeVGLeRKLeROLeRSLeRWLeRaLeReLeRiLeRmLeRqLeRuLeRyLeR2LeR6LeR+LeSCLeSGLeSKLeSOLeSSLYb+uaesudyzhVy0hdy0hVy1hdy1hVy2hdy2hVy3hdy3xdQ/7JY1lyu3kDu3kEu3kFu3kGu3kHu3kIu3kJu3kKu3WPoTDrLmcvsWcv0Wcv8WcgEXcgMXcgUXcgcXcgkXcgsXW3+sRX+uRX6wRe7hUu7hUu7hUu7hUu7hUu7hUu7hUu7hUu7hMvSHmWTN5R4u5R4u5R4u5R4u5R4u5R4u5R4u9efX9AfYCk+wyZrrz7DpD7HpT7Hpj7Hpz7HpD7LJPVzKPVzKPVx2/bFFWXO5h0u5h0u5h0u5h0u5h0u5h0u5h0u5h0u5h0voz6rKmss9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XA79qXRZc7mHS7mHS7mHS7mHS7mHS7mHS7mHS7mHS7mHy6n/UwRZc7mHS7mHS7mHy8s9HPs+biJif7Xv1ZPVyNUPq9HbeTVwYfHkOqydG+cXzuM8eWPz4Mbm4Y3NM25snnmFeXqu0zx9PJ7ncMh6iUP2NQ4ZPB0y4+khl0tc+RCcDlntwiH5EodcDBaC43TIHM8cwjgZkQ9t9Wn17hcWD7TjSw/kV4sPE11+63i4yXmi+cxEux9Nstc6rQ3khbUPn7Af1j50wY/+ZFwafjPj+ML8cvJxdd/H6Wk9/bCeflpPv6yn38bT98sft9hMn9bTd+vpndOqN+e06s05rXpzTqvenNOqN+u0uvzRss301lkbV8jaaOP481JEtmfmv1xDXfoJ/zj6HI+/JzhODtvJaTv5sJ182k6+bCffrpNns508bCe3TaLstpPbZmjaZmjaZmjaZmjaZmjaZmi3zdBum6HdNkO7bYZ22wztthnabTO022Zot83QbpuhsM1Q2GYobDMUthkK2wyFbYbCNkNhm6GwzVDYZihtM5S2GUrbDKVthtI2Q2mbobTNUNpmKG0zlLYZOmwzdNhm6LDN0GGbocM2Q4dthg7bDB22GTpsM3TYZui0zdBpm6HTNkOnbYZO2wydthk6bTN02mbotM3QaZuhyzZDl22GLtsMXbYZumwzdNlm6LLN0GWbocs2Q5dthm7bDN22GbptM3TbZug1uDt/0uS2GbptM3TbZui2zdDtmqForhmK5pqhaK4ZiuaaoWiuGYrmmqForhmK5pqhaK4ZimaboWGboWGboba0H4RthtpyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKaItp4i2nCLacopoyylic81Q2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4jfwClaeG7y6OfJB7465enqvo4vjTx/TyL3hbW5jtP3WF+tPUw/radf1tNv4+nHN3CLbnn6+P9OfzglX+SUfo1TJk6n7PGMEjHm8e3z4X/3+bV7O86EG5yJNzjTuMGZ5g3OtG5wpv3yM53+MhJjta9meroauY7vHOjtfIOLLz25jn/N2Y+GzsNdo31Hd83v6K79O7orvqO78sbv2nOd7trH47seLjDcLzBv/QKDpwvMuHCBdfMXwOkCj1afL/B8Pu/nOoWx8njIWH09PeQbsDlXOCRe4pC8xiHg6ZBxQZNv4MZc4RC8xCG8iib9fEj+8Tt+j9FOP9PO8+J+HGi99ECZeRwoO54MhKt8h/bxLWHsxqcyfMM/6Xv+kB15OuRRtXA+ZF7lJu18yP7ftGZ76YGe0Xpc4zu0edZ69T8eKPvJqdnZng60b2ygKRv1sG8V9+3avtWK+6K4L4v7enEfivtY3FfUfc3ivqJfVtEvu+iXXfTLLvplF/2yi37ZRb/sol920S+76Jdd88tsrbgvivuyuK8X96G4j8V9o7hvFvet4r6iX6Lolyj6JYp+iaJfouiXKPolin6Jol+i6Jco+iWLfsmiX7Lolyz6JYt+yaJfsuiXLPoli37Jol960S+96Jde9Esv+qUX/dKLfulFv/SiX3rRL73oFxT9gqJfUPQLin5B0S8o+gVFv6DoFxT9gqJfWPQLi35h0S8s+oVFv7DoFxb9wqJfWPQLi34ZRb+Mol9G0S+j6JdR9Mso+mUU/TKKfhlFv4yiX2bRL7Pol1n0yyz6ZRb9Mot+Kfa0cxb9Uux3Z7HfnYV+9+Grf7759d2bH96//fiw58tv/nb/46d3H+4PX3761y///Z2Htf8G"},{"name":"set_portal","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/72WzY7TMBDH3XbbbbtJyva7Tb+Sxg0SFy7sBcGdM08AAgkk4IDgAI/CO/Ai+xC8AXckDotn7PE/aXYrRUIbye14/P/NjD2R4ky1lOqeKfOslXvMrKsi1TF/TRrPlVjGoNGIVENcmhaJspbxq5Z2gDpjy2RQ7dT8XDxRkixTbVV+SN/hrHZUFRT73CrOaWRUO3v7WjSmlJYz+zaPaHp504WmWbcAW6TnkF7mI1xAFHTYvCDTjDCh9ZisqwYqbLnDIFmoaSGkqLZmF7y0qxvzkMoqSBwaxc3RQ0mtgnIHiFFIrSKriGg0fTiahkdT5adBmeues9lzu4h4k4/IwiarbaGnF3my18ZuKRAHeUzWnUGe/rhuls+pXzj523oblHsbcW/71d4GFolkr1gJ0VA6iQGX+Yysuxo64IYOKFTbN6OHqHtu+i3FhuViB3jBTLMbL83/A2Qi8aVuWqe6BHZpNaE1GX0Ht6BDRkkwBDoEOnToK7gFHTFKghHQEdCRQz/DLeiYURKMgY6Bjh36Fm5BJ4ySYAJ0AnTi0DdwCzpllARToFOgU4e+gFvQGaMkmAGdAZ059CPcgs4ZJcEc6Bzo3P7XRky2r3ALumCUBAugC6ALh36BW9AloyRYAl0CXVYLXfpX4ARisr2GW9CYURLEQGOgsUM/wC3oilESrICugK6qha78W3MCMdl2cAu6ZpQEa6BroOtqtrU/lppIXB8Z1UfG97KXyWnEHPY3uAXdMEqCDdAN0E0128b35wRisr2HW9AtoyTYAt0C3Tr0E9yC7hglwQ7oDuiuWujOZ6uJLO4ly7A+Ev/3wsxhf4db0IRREiRAE6BJNVvi3/SayOQ0wp/9v/iIZwwqfLnlU81CLZ9zE/GscIFJOVVaTrW3cGJNWSFzjxuAttcQ7VYO5sCIzRscIicXDc7+x85kj8TkWmQZstmFpttNjopy5ZMRoqkDvwtlHRV8JRfYDCFSfzYBziY9uo1he2nluvjrJ4W2N70EDQlcmJDrTuy74+9qVpO6ctLCGftyUpSzL5cTPnQ3QXvbx4L28B6wLsNZVlyRkyLRgStt26aJ/IATpr7pwtn7ZBrJ8nKyw0P33vCsw5ubX9P4B9hf6AanDQAA","debug_symbols":"5Z3rShtRGEXfJb+lzN7n7quUUlIvRZAoXgpFfPeaxkTFlIAdF2eYf07yzex9GNYZlIXzsDg9+3H/8/vF6vzqdnH89WFxeXWyvLu4Wj0dPSyGL9LfT2+vl6v1B7d3y5u7xXFQGI4WZ6vT9Y85Px4tzi8uzxbHrunx6N20B+fnaQ+p7KYVy57pULfD0a9m3fZduWpXo76Z/Xa0Lh+mXD5NuXyecvky5fJ1yuXbhMt7+NzymxARIR4jJJddSG0HbkPZ3YbS0qsrD8+FQm+FYm+FUm+Fcm+FSm+Fam+FGl4oh12h/KbQ+9kW2vNsy+3AbEl1d934MuvNOsMwk3V6JuuMM1lnnsk6y0zWWWeyzpk8V+JMnitRM1nnTJ6f8fBvV+XtOjenpY+dlj92WvnYaf/YY+v2rgSHQ/dQyX6eVkqJ+4tCGqZcXlMu7ymXD1MuH6dcPn1u+U1IJkLKGCHlJaTmPSGVCGlASB6IEBEhJkLCyCFNe0IiEZKIkEyEFCKkEiENCCkDESIixEQIQXwhiC8E8YUgvhDEF4L4QhBfCeIrQXwliK8E8ZUgvhLEV4L4ShBfCeIrQXwjiG8E8Y0gvhHEN4L4RhDfCOIbQXwjiG8E8RoGJEVIipGUgKREJCUhKRlJKUhKRVIQ9oWwL4R9IewLYV8I+0LYF8K+EPaFsC+EfSPsG2HfCPtG2DfCvhH2jbBvhH0j7BthPyDsB4T9gLAfEPYDwn5A2A8I+wFhPyDsB4T9iLAfEfYjwn5E2I8I+xFhPyLsR4T9iLAfEfYTwn5C2E8I+wlhPyHsJ4T9hLCfEPYTwn5C2M8I+xlhPyPsI86eEGlPiLUnRNsT4u0JEfeEmHtC1D0h7p4QeU+IvSdE3xPi7wkR+IQYfEIUPiEOnxCJT4jFJ0TjE+LxCRH5hJh8QlQ+IS6fEJlPiM0nROcT4vMJEfqEGH1ClD4hTp8QqU+I1SdE6xPi9Rnx+ox4fUa8PiNen4eIpCQkJSMpBUmpSArCPuL1GfH6jHh9Rrw+I16fEa/PiNdnxOsz4vUZ8fqMeH1GvD4jXp8Rr8+I12fE6zPi9Rnx+ox4fUa8PiNenxGvz4jXZ8TrM+L1GfH6jHh9Rrw+I16fEa/PiNdnxOsz4vUZ8fqMeH1GvD4jXp8Rr8+I12fE6zPi9XkUr6+kuE0prb5JeT+dd8P51X8HfXn/xCgO4LiNQneNYneNUneNcneNaneNWm+NRjEax23U3Q6Zu9shc3c7ZO5uh8zd7ZC5ux1yFAu0pu202hD+t1HtrlHrrdEoJuq4jdRdI3fXKHTXKHbXKHXXKHfXqLs9u3S3Z5fu9uza0579dPRreXOx/HF5tn5h7/rL+9XJ9v29T4d3v6833zzN/gE="},{"name":"balance_of_public","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"owner","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/83YW2/rRBAH8E0apyU0ztVp7o2buLm7PSUgjqA8IiQekXgEcRcSN3ER4ivypWBndmf/SX3kaqUj60Ry44zntzO7TtpsF+pMqYtA6cdE2UdFR1SoqvqpTMdHSs70CR2lUJUklNBFUuZMx9VZYoGq8JmuoIIb/eMyUWaEi8q7dKFCYy1UidB5QGNSbXWuj+qCGlPv66OWSGO6zpk9rdEPk0PsrQWu6AE/1s9vm+QLm3yZlE1QXYJdmpyaOWX6F8JC60wpoQ5aB61b+gvCQkOmlBCChqChpd8gLLTBlBIaoA3QhqV/Iiy0yZQSmqBN0KalPyIstMWUElqgLdCWpb8iLLTNlBLaoG3QtnnOkno+0dVmCAvtMKWEDmgHtGPp1wgL7TKlhC5oF7Rr6VcIC42YUkIEGoFGlv6EsNAeU0rogfZAe9nl6blqnqTuT8J8ouf0HcJCr5hSwhXoFeiVpV8iLLTPlBL6oH3QfrbRvnuD5RBd7XuEhQ6YUsIAdAA6yFYbuAZziK72G8JCh0wpYQg6BB1mqw3d7xhP0vEnkT9p+pPQn7QLqdL1J/VC5tIqpLFn7r5+R/+DsNARU0oYgY5AR9lqI7cMnqTjT3qFNBb6k64/iQohz6yYfhd8i7DQMVNKGIOOQcfZamO32DlEV/sDYaETppQwAZ2ATrLVJu6LjyfpFlKl6U/CQuYSFUKG+SSm+BTf/V8yVPjCL9/weaOSyC5Aj1hReEy51PS01LXBE3MqV2hzcY2NQ1zl09gm3diNybzEQ8wpRAe3OTKvZI4UmyeSNkM1c6FsgmqOjubKFSMS68ul5lFbTxp+r2Rn+9Lk8ByTow2bTGJ6ui+qYnrThQrU6YPvAm/0uJK9IRU7TI37npgPqAxob8PUtjN9FQnyyUlLMpnrDypHORVzZ572S4+Z6ZeWcxbwac2+DBZcTt2YnWRgb1hsinxI7xm3YnOsWHK6Ygu0l+gBP9PPtyZ5bpOXPMlbOgNbmpzEnNJzljT8SSuf6AZ/R1joiiklrEBXoKtstZX7zZFDdLUfEBa6ZkoJa9A16Dpbbe3+BHmStj8Z+5PIn7T8SeO1T1/fn3uEhW6YUsIGdAO6yVbbuGqepO5PWv6kUchcuv4kKoQ8s2L6XfA3wkK3TClhC7oF3Warbd2n1JOM8oluMEVY6I4pJexAd6C7bLWdu7We5NafNPxJy58s/UnXn6z8Sa+Q+zL2J1Eh96VRyFyeWTH9ufkZYaF7ppSwB92D7rPV9u5/TZ5k7E8a/qT9pjbW9SfLN3XF+oXMpeVPdq99+vpz8wJhoSlTSkhBU9A0Wy11f6JyCO3oyp9i3/HIUGGzIbuL1G0+EjPi8S72jkvdnZa6Nzg1p3KFNjb32LQ8mF3sg016x+5iD2YXe6AQHdzmJ+aVzJHMIZG0F6hmLpRNUB3Q0UG5YkQeZnrQx6O2njTMu1ia7SOGuHNrE2Bt7k73ZPGybPd5vLHLbC1jezU+GrbqNp28ijzfz10T9nFmynJamtjbqWqh21fqEYP/njzImAyiwTmfxvalKfTFaaGQ7y2PFyK75KoEtpJNP2pQpQZQWym/QWJpsux4asLSEa+G+/dInIgqz+m0/y8d/wMOUhUC9x0AAA==","debug_symbols":"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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fGs0oWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+FlP93XaJ/f7m6jFUbbjYwio5LRVkazjJqMFhl1GUkRWyliliJmKWKWImYpYpYiZililiJmKWKWImYpokkRTYpoUkSTIpoU0aSIJkU0KaJJEU2KWKSIRYpYpIhFilikiEWKWKSIRYpYpIhFiuhSRJciuhTRpYguRXQpoksRXYroUkSXIoYUMaSIIUUMKWJIEUOKGFLEkCKGFDGkiFWKWKWIVYpYpYhVililiFWKWKWIVYpYpYhsNrQKrYpWW1rNtGq0WmjVaTVoRW2E2gi1EWoj1EaojVAboTZCbYTaCLVR1EZRG0VtFLVR1EZRG0VtFLVBoBkSzRBphkwzhJoh1QyxZsg1Q7AZks0QbYZsM4SbId0M8WbIN0PAGRLOEHGGjDOEnCHlDDFnyDlD0BmSzhB1hqwzhJ0h7QxxZ8g7Q+AZEs8QeYbMM4SeIfUMsWfIPUPwGZLPEH2G7DOEnyH9DPFnyD9DABoS0BCBhgw0hKAhBQ0xaMhBQxAaktAQhYYsNIShIQ0NcWjIQ0MgGhLREImGTDSEoiEVDbFoyEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFyy56kosWuWiRixa5aJGLFrlokYvWf7vo9fRz937YPbzsb3d7bx8/jo//rvpej+dfb3+/XP/9DQ=="}],"outputs":{"globals":{"storage":[{"fields":[{"name":"balances","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"portal_address","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"artifact_hash","type":{"kind":"field"}},{"name":"private_functions_root","type":{"kind":"field"}},{"name":"public_bytecode_commitment","type":{"kind":"field"}},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}}],"kind":"struct","path":"GasToken::deploy_parameters"}}],"kind":"struct","path":"GasToken::deploy_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}}],"kind":"struct","path":"GasToken::set_portal_parameters"}}],"kind":"struct","path":"GasToken::set_portal_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::_increase_public_balance_parameters"}}],"kind":"struct","path":"GasToken::_increase_public_balance_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}},{"name":"secret","type":{"kind":"field"}},{"name":"leaf_index","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::claim_public_parameters"}}],"kind":"struct","path":"GasToken::claim_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"owner","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"GasToken::balance_of_public_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::balance_of_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::mint_public_parameters"}}],"kind":"struct","path":"GasToken::mint_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}},{"name":"secret","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::claim_parameters"}}],"kind":"struct","path":"GasToken::claim_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"fee_limit","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::check_balance_parameters"}}],"kind":"struct","path":"GasToken::check_balance_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"122":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr","source":"#[oracle(packArgumentsArray)]\nunconstrained fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {}\n\n#[oracle(packArguments)]\nunconstrained fn pack_arguments_oracle(_args: [Field]) -> Field {}\n\n/// - Pack arguments (array version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments_array(args: [Field; N]) -> Field {\n pack_arguments_array_oracle(args)\n}\n\n/// - Pack arguments (slice version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments(args: [Field]) -> Field {\n pack_arguments_oracle(args)\n}\n\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"139":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr","source":"use dep::protocol_types::{address::AztecAddress};\n\nglobal L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u64 = 17;\n\n// Obtains membership witness (index and sibling path) for a message in the L1 to L2 message tree.\n#[oracle(getL1ToL2MembershipWitness)]\nunconstrained fn get_l1_to_l2_membership_witness_oracle(\n _contract_address: AztecAddress,\n _message_hash: Field,\n _secret: Field\n) -> [Field; L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH] {}\n\nunconstrained pub fn get_l1_to_l2_membership_witness(\n contract_address: AztecAddress,\n message_hash: Field,\n secret: Field\n) -> [Field; L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH] {\n get_l1_to_l2_membership_witness_oracle(contract_address, message_hash, secret)\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"144":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr","source":"use crate::context::{PublicContext, UnconstrainedContext};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:public_mutable_struct\nstruct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl Storage for PublicMutable {}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicMutable { context, storage_slot }\n }\n // docs:end:public_mutable_struct_new\n}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) where T: Serialize {\n let fields = T::serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n pub fn read(self) -> T where T: Deserialize {\n // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the\n // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns\n // historical data.\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n"},"147":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr","source":"use crate::{\n context::{PrivateContext, PublicContext, UnconstrainedContext},\n oracle::{storage::{storage_read, storage_write}}, state_vars::storage::Storage\n};\nuse dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}};\n\n// Just like PublicImmutable but with the ability to read from private functions.\nstruct SharedImmutable{\n context: Context,\n storage_slot: Field,\n}\n\nimpl Storage for SharedImmutable {}\n\nimpl SharedImmutable {\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n}\n\nimpl SharedImmutable {\n // Intended to be only called once. \n pub fn initialize(self, value: T) where T: Serialize {\n // TODO(#4738): Uncomment the following assert\n // assert(\n // self.context.public.unwrap_unchecked().is_deployment(), \"SharedImmutable can only be initialized during contract deployment\"\n // );\n\n // We check that the struct is not yet initialized by checking if the initialization slot is 0\n let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot;\n let fields_read: [Field; 1] = storage_read(initialization_slot);\n assert(fields_read[0] == 0, \"SharedImmutable already initialized\");\n\n // We populate the initialization slot with a non-zero value to indicate that the struct is initialized\n storage_write(initialization_slot, [0xdead]);\n\n let fields_write = T::serialize(value);\n storage_write(self.storage_slot, fields_write);\n }\n\n pub fn read_public(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n\nimpl SharedImmutable {\n pub fn read_public(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n\nimpl SharedImmutable {\n pub fn read_private(self) -> T where T: Deserialize {\n let header = self.context.get_header();\n let mut fields = [0; T_SERIALIZED_LEN];\n\n for i in 0..fields.len() {\n fields[i] =\n header.public_storage_historical_read(\n self.storage_slot + i as Field,\n (*self.context).this_address()\n );\n }\n T::deserialize(fields)\n }\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"246":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr","source":"use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF;\nuse crate::traits::{ToField, FromField, Hash, Serialize, Deserialize};\n\nstruct ContractClassId {\n inner: Field\n}\n\nimpl Eq for ContractClassId {\n fn eq(self, other: ContractClassId) -> bool {\n other.inner == self.inner\n }\n}\n\nimpl ToField for ContractClassId {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for ContractClassId {\n fn from_field(value: Field) -> Self {\n Self { inner: value }\n }\n}\n\nimpl Serialize<1> for ContractClassId {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n}\n\nimpl Deserialize<1> for ContractClassId {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self { inner: fields[0] }\n }\n}\n\nimpl ContractClassId {\n pub fn compute(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field\n ) -> Self {\n let hash = dep::std::hash::pedersen_hash_with_separator(\n [\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ],\n GENERATOR_INDEX__CONTRACT_LEAF\n ); // TODO(@spalladino): Update generator index\n\n ContractClassId::from_field(hash)\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"285":{"path":"/usr/src/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr","source":"mod lib;\n\ncontract GasToken {\n use dep::aztec::{\n protocol_types::{\n contract_class_id::ContractClassId, abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::{DEPLOYER_CONTRACT_ADDRESS, REGISTERER_CONTRACT_ADDRESS}\n },\n state_vars::{SharedImmutable, PublicMutable, Map},\n oracle::get_contract_instance::get_contract_instance, deploy::deploy_contract\n };\n\n use dep::deployer::ContractInstanceDeployer;\n use dep::registerer::ContractClassRegisterer;\n\n use crate::lib::{calculate_fee, get_bridge_gas_msg_hash};\n\n #[aztec(storage)]\n struct Storage {\n // This map is accessed directly by protocol circuits to check balances for fee payment.\n // Do not change this storage layout unless you also update the base rollup circuits.\n balances: Map>,\n portal_address: SharedImmutable,\n }\n\n // Not flagged as initializer to reduce cost of checking init nullifier in all functions.\n // This function should be called as entrypoint to initialize the contract by minting itself funds.\n #[aztec(private)]\n fn deploy(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field,\n portal_address: EthAddress\n ) {\n // Validate contract class parameters are correct\n let self = context.this_address();\n let instance = get_contract_instance(self);\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n assert(\n instance.contract_class_id == contract_class_id, \"Invalid contract class id computed for gas token\"\n );\n\n // Increase self balance and set as fee payer, and end setup\n let deploy_fees = 20000000000;\n GasToken::at(self)._increase_public_balance(self, deploy_fees).enqueue(&mut context);\n context.set_as_fee_payer();\n context.end_setup();\n\n // Register class and publicly deploy contract\n let _register = ContractClassRegisterer::at(AztecAddress::from_field(REGISTERER_CONTRACT_ADDRESS)).register(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ).call(&mut context);\n let _deploy = ContractInstanceDeployer::at(AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS)).deploy(\n instance.salt,\n instance.contract_class_id,\n instance.initialization_hash,\n instance.public_keys_hash,\n true\n ).call(&mut context);\n\n // Enqueue call to set the portal address\n GasToken::at(self).set_portal(portal_address).enqueue(&mut context);\n }\n\n // We purposefully not set this function as an initializer so we do not bind\n // the contract to a specific L1 portal address, since the gas token address\n // is a hardcoded constant in the rollup circuits.\n #[aztec(public)]\n fn set_portal(portal_address: EthAddress) {\n assert(storage.portal_address.read_public().is_zero());\n storage.portal_address.initialize(portal_address);\n }\n\n #[aztec(private)]\n fn claim(to: AztecAddress, amount: Field, secret: Field) {\n let content_hash = get_bridge_gas_msg_hash(to, amount);\n let portal_address = storage.portal_address.read_private();\n assert(!portal_address.is_zero());\n\n // Consume message and emit nullifier\n context.consume_l1_to_l2_message(content_hash, secret, portal_address);\n\n // TODO(palla/gas) Emit an unencrypted log to announce which L1 to L2 message has been claimed\n // Otherwise, we cannot trace L1 deposits to their corresponding claims on L2\n\n GasToken::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context);\n }\n\n #[aztec(public)]\n #[aztec(internal)]\n fn _increase_public_balance(to: AztecAddress, amount: Field) {\n let new_balance = storage.balances.at(to).read().add(U128::from_integer(amount));\n storage.balances.at(to).write(new_balance);\n }\n\n // TODO(palla/gas) Remove this function and use the private claim flow only\n #[aztec(public)]\n fn claim_public(to: AztecAddress, amount: Field, secret: Field, leaf_index: Field) {\n let content_hash = get_bridge_gas_msg_hash(to, amount);\n let portal_address = storage.portal_address.read_public();\n assert(!portal_address.is_zero());\n\n // Consume message and emit nullifier\n context.consume_l1_to_l2_message(content_hash, secret, portal_address, leaf_index);\n\n let new_balance = storage.balances.at(to).read() + U128::from_integer(amount);\n storage.balances.at(to).write(new_balance);\n }\n\n // TODO(@just-mitch): remove this function before mainnet deployment\n // convenience function for testing\n // the true canonical gas token contract will not have this function\n #[aztec(public)]\n fn mint_public(to: AztecAddress, amount: Field) {\n let amount = U128::from_integer(amount);\n let new_balance = storage.balances.at(to).read().add(amount);\n\n storage.balances.at(to).write(new_balance);\n }\n\n #[aztec(public)]\n #[aztec(view)]\n fn check_balance(fee_limit: Field) {\n let fee_limit = U128::from_integer(fee_limit);\n assert(storage.balances.at(context.msg_sender()).read() >= fee_limit, \"Balance too low\");\n }\n\n // utility function for testing\n #[aztec(public)]\n #[aztec(view)]\n fn balance_of_public(owner: AztecAddress) -> pub Field {\n storage.balances.at(owner).read().to_field()\n }\n}\n"},"286":{"path":"/usr/src/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr","source":"use dep::aztec::prelude::{AztecAddress, EthAddress};\nuse dep::aztec::context::PublicContext;\nuse dep::aztec::protocol_types::hash::sha256_to_field;\n\npub fn calculate_fee(context: PublicContext) -> Field {\n context.transaction_fee()\n}\n\npub fn get_bridge_gas_msg_hash(owner: AztecAddress, amount: Field) -> Field {\n let mut hash_bytes = [0; 68];\n let recipient_bytes = owner.to_field().to_be_bytes(32);\n let amount_bytes = amount.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i + 4] = recipient_bytes[i];\n hash_bytes[i + 36] = amount_bytes[i];\n }\n\n // Function selector: 0x3e87b9be keccak256('mint_public(bytes32,uint256)')\n hash_bytes[0] = 0x3e;\n hash_bytes[1] = 0x87;\n hash_bytes[2] = 0xb9;\n hash_bytes[3] = 0xbe;\n\n let content_hash = sha256_to_field(hash_bytes);\n content_hash\n}\n"},"288":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr","source":"mod events;\n\ncontract ContractInstanceDeployer {\n use dep::aztec::protocol_types::{\n address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress},\n contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE,\n traits::Serialize\n };\n\n use crate::events::{instance_deployed::ContractInstanceDeployed};\n\n #[aztec(private)]\n fn deploy(\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys_hash: PublicKeysHash,\n universal_deploy: bool\n ) {\n // TODO(@spalladino): assert nullifier_exists silo(contract_class_id, ContractClassRegisterer)\n\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.msg_sender()\n };\n\n let partial_address = PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n let address = AztecAddress::compute(public_keys_hash, partial_address);\n\n // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed\n context.push_new_nullifier(address.to_field(), 0);\n\n // Broadcast the event\n let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 };\n let event_payload = event.serialize();\n dep::aztec::oracle::debug_log::debug_log_format(\"ContractInstanceDeployed: {}\", event_payload);\n context.emit_unencrypted_log(event_payload);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"293":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr","source":"mod events;\nmod capsule;\n\ncontract ContractClassRegisterer {\n use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector};\n use dep::aztec::protocol_types::{\n contract_class_id::ContractClassId,\n constants::{\n ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT,\n MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE\n },\n traits::Serialize\n };\n\n use crate::events::{\n class_registered::ContractClassRegistered,\n private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction},\n unconstrained_function_broadcasted::{ClassUnconstrainedFunctionBroadcasted, UnconstrainedFunction}\n };\n\n // docs:start:import_pop_capsule\n use crate::capsule::pop_capsule;\n // docs:end:import_pop_capsule\n\n #[aztec(private)]\n fn register(artifact_hash: Field, private_functions_root: Field, public_bytecode_commitment: Field) {\n // TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode\n // TODO: Validate packed_public_bytecode is legit public bytecode\n\n // docs:start:pop_capsule\n let packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] = pop_capsule();\n // docs:end:pop_capsule\n\n // Compute contract class id from preimage\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n\n // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered\n let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode };\n context.push_new_nullifier(contract_class_id.to_field(), 0);\n\n // Broadcast class info including public bytecode\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ContractClassRegistered: {}\",\n [\n contract_class_id.to_field(),\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_private_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n unconstrained_functions_artifact_tree_root: Field,\n private_function_tree_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n private_function_tree_leaf_index: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: PrivateFunction\n ) {\n let event = ClassPrivateFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n private_function_tree_sibling_path,\n private_function_tree_leaf_index,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassPrivateFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.vk_hash,\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_unconstrained_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n private_functions_artifact_tree_root: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: UnconstrainedFunction\n ) {\n let event = ClassUnconstrainedFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassUnconstrainedFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"84":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/messaging.nr","source":"use crate::{\n hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier},\n oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness\n};\n\nuse dep::std::merkle::compute_merkle_root;\nuse dep::protocol_types::{constants::L1_TO_L2_MSG_TREE_HEIGHT, address::{AztecAddress, EthAddress}, utils::arr_copy_slice};\n\npub fn process_l1_to_l2_message(\n l1_to_l2_root: Field,\n storage_contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n chain_id: Field,\n version: Field,\n content: Field,\n secret: Field\n) -> Field {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n portal_contract_address,\n chain_id,\n storage_contract_address,\n version,\n content,\n secret_hash\n );\n\n let returned_message = get_l1_to_l2_membership_witness(storage_contract_address, message_hash, secret);\n let leaf_index = returned_message[0];\n let sibling_path = arr_copy_slice(returned_message, [0; L1_TO_L2_MSG_TREE_HEIGHT], 1);\n\n // Check that the message is in the tree\n // This is implicitly checking that the values of the message are correct\n let root = compute_merkle_root(message_hash, leaf_index, sibling_path);\n assert(root == l1_to_l2_root, \"Message not in state\");\n\n compute_message_nullifier(message_hash, secret, leaf_index)\n}\n"},"87":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr","source":"use crate::{hash::hash_args_array, oracle::returns::unpack_returns};\nuse dep::protocol_types::traits::Deserialize;\n\nstruct PackedReturns {\n packed_returns: Field,\n}\n\nimpl PackedReturns {\n pub fn new(packed_returns: Field) -> Self {\n PackedReturns { packed_returns }\n }\n\n pub fn assert_empty(self) {\n assert_eq(self.packed_returns, 0);\n }\n\n pub fn raw(self) -> Field {\n self.packed_returns\n }\n\n pub fn unpack(self) -> [Field; N] {\n let unpacked: [Field; N] = unpack_returns(self.packed_returns);\n assert_eq(self.packed_returns, hash_args_array(unpacked));\n unpacked\n }\n\n pub fn unpack_into(self) -> T where T: Deserialize {\n let unpacked: [Field; N] = self.unpack();\n Deserialize::deserialize(unpacked)\n }\n}\n"},"90":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress, traits::Deserialize\n};\n\nuse crate::context::{\n private_context::PrivateContext, public_context::PublicContext, gas::GasOpts,\n public_context::FunctionReturns, inputs::{PrivateContextInputs, PublicContextInputs}\n};\n\nuse crate::oracle::arguments;\n\ntrait CallInterface {\n fn get_args(self) -> [Field];\n fn get_original(self) -> fn[Env](T) -> P;\n fn get_selector(self) -> FunctionSelector;\n fn get_name(self) -> str;\n fn get_contract_address(self) -> AztecAddress;\n fn get_is_static(self) -> bool;\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateCallInterface {\n pub fn call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n );\n let unpacked: T = returns.unpack_into();\n unpacked\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateVoidCallInterface {\n pub fn call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n ).assert_empty();\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty();\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticCallInterface {\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticVoidCallInterface {\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.deserialize_into()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.assert_empty()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicStaticCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n let unpacked: T = returns.deserialize_into();\n unpacked\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n\nimpl CallInterface for PublicStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicStaticVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json b/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json new file mode 100644 index 000000000000..bb634cf16c13 --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"KeyRegistry","functions":[{"name":"register","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"partial_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::partial_address::PartialAddress"},"visibility":"private"},{"name":"keys","type":{"fields":[{"name":"npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ivpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ovpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"tpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}}],"kind":"struct","path":"aztec::keys::public_keys::PublicKeys"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"7b3vjiu7duT5LvezMUiSi//8KoPBwN3tHhgwrhtt9wAD47776PStpFS7mJup5DqSgis++dhWVTJ+lVsRi0oF//Mv/+2f/8v/+n/+73/563//t3//yz/+n//5l3/9t//6T//xL//219v/9p9/2f4Pv/3v/+u//49/+usf/4d//49/+p//8Zd/3P7hL//81/92+59/+4e//Pd/+dd//ss/hih/+7/+4Y8fcM/+gH/2B8KzPyDP/kB89gfSsz+Qn/2B8uwP1Cd/IDz7lw7P/qVD9y/t3Za/fsY7V7792D/8eHWM9evFJUt7beq9tCbZX1vz5tuLfaidVwfZVxHKfRG+9F6aouyvTdn//sVpC1+vTZs8vvTvSAKR/IpEiORXJJFIfkWSiORXJJlIfkVSiORXJJVIfkEiG5H8isQRya9ImF5/IGF6/YFELCIJ++9NMf5EYjK9/h6JyfT6eyQm0+vvkZhMr79HYjK9/hZJNBnVfo/EZFT7PRKTUe33SIRIfkXCqPYDCaPaDySMaj+QMKr9QMKo9iuSZHKj8fdImF5/IGF6/YGE6fUHEiGSX5Ewvf5AwvT6AwnT6w8kTK8/kDC9/ookM73+QML0+gMJ0+sPJEyvP5AIkfyKhOn1BxKm1x9ImF5/IGF6/YGE6fVXJIXp9QcSptcfSJhefyBhev2BRIjkVyRMrz+QMKr9QMKo9gMJo9qvSCqj2g8kjGo/kDCq/UDCqPYDiRDJr0gY1X4g4UbjDyRMrz+QML3+QML0+isSt60fX7+Erh9Kv4SuHzW/hK4fIL+EihWh64e9L6HrR7gvoesHsy+h68etL6Hrh6i/C3VWkpGzkoyclWTkrCQjJ1aEWklGzkoyclaSkbOSjJyVZOStJCNvJRl5K8nIW0lG3koy8laSkbeSjLyVZOStJCNvJRkFK8koWElGBo4B+RJqJRkZOLLjS6iVZGTgeI0voVaSkYGjML6EWklGBo6t+BJqJRkZOGLiS6iVZGTgOIgvoVaSkYGjG76EWklGBo5Z+BJqJRlFK8nIwNkPX0KtJCMD5zR8CRUrQq0kIwMnJXwJtZKMDJxq8CXUSjIycALBl1AryWidHvjahOat87XKddrdR0IXedcVl/dfLK7Gyy/+orLIW7QulVU6uZWpLPLmr0xlkRlamcoiA7cyFSGVDpVFIogylUXmfmUqi2wSKFNhtu1RYbbtUFmlsVuZCrNtjwqzbY8Ks22PipBKhwqzbY8Ks22PCrNtjwqzbY8Ks22HyioV58pUmG17VJhte1SYbXtUxCAV72PY5fkcOlQsZtsxFYvZ1vvg71SkQ8ViXvFS9xf7uG0/qPhVOq2VqVjMK2MqFvPKmIrFvDKmIqTSoWIyrwypmMwrQyoW9+LGVCzuxY2pMNt2qKzSSq5Mhdm2R4XZtkdFSKVDhSmuR4UprkfFpDMXaTuUJcnvXxxCbquQ7efGnV+lQvudCE16vi5CkwFBF6HJnTJdhEKEswhNpjddhCajni5Ck7t7ughNbgXqIuR0MotwlRr7dyLkdDKNkNPJNEKGmgHCXNLXa3PtbHWt0rj+NoCrlCf/eQBre/KxxtwBKAQ4B5D/hEcA8/6UaS2xA5AzySRATiRzAFepSH4fQE4jkwA5i0wCZA6cBCgEOAeQn5FMAuRmwiRATiKTADmJTALkJDIA6LYQv17sttLZUl2llPydCDmNTCPkPDKNkBPJNEIhwlmEnEqmEXIumUbIyWQaIWeTaYScTmYRmjxiQxkhp5NphJxOphFyOplGKEQ4i5DTyTRCTifTCDmdTCPkdDKNkNPJLEKTh6Q8h9CVhtCV1EHI6WQaIaeTaYScTqYRChHOIuR0Mo2Q08k0Qk4n0wg5ncwiNHlGizJCRutphIzW0wgZracRChHOImS0nkbIaD2NkNF6GiGj9TRCbvxPIgw2T2TSRcjpZBohp5NphJxOphEKEc4i5HQyjZDTySxCm0fxPIXQu4bQu9pByFAzjZB2MkQYpCGU0EFIO5lGSDuZRsjNrmmE3OyaRsjNrlmEPNtpHiFz4TRCbnZNI+Rm1zRCIcJZhJxOphFyOplGyOlkGiGnk2mEnE5mEfJsp3mEnE6mEXI6mUbI6UQ6VIRUOlQ4Q/SocCzoUWHS71FheO9RYR7vUBFG7B4VpuYeFQbhHhVm2x4VIZUOFWbbHhVm2x4VZtseFWbbDhWbR/5VX3Z5NfgOFZPOPKRi8t22RteodP8FmXy3HVIx+W47pGJyJ2FExeZhY0MqJncShlRs5pURFZt5ZURFSKVDxeROwpAKs22PisVsm/cnEnLsELGYa39PxGKm/S0Rk8dT/Z6IxSz7eyIWc+zviVjMsL8nIiTyCxGL2fX3RCzm1t8TYWb9lQgz669EmFl/IWLyxJ3fE2FC+5UIE9qvRIREfiHChPYrEYsJLdxr5YKrpUPFYkobU7GY1MZULKa1IRWTZ+GMqVjMsWMqFrPsmIpJZ/Z+23+x953P/EweRzGiIia7/YMvdyo1d6iYfLcdUjH5bjukYnH3YExFSKVDxeIuwpiKzbwyomIzr4yomNxJGFIxuZMwomLyiIcxFWbbHhWT2fbhF4fUo2Iy2w6pCKl0qJjMtkMqJrPtkIrJbBty+8W3+bhDxWSKG1ExeSDDmIrJFDekYjPFjajYTHEjKkIqHSo2U9yIis0UN6LCFNejYnKHckiF2bZDxWSd/5gKs22PCrNtjwqzbY+KkEqHCrNtjwqzbY8Ks22PCrNtjwqzbYeKyR79MRVm2x4VZtseFWbbHhUhlQ4VZtseFWbbHhVm2x4VZtseFWbbDpXIbNujwmzbo8Js26PCbNujIqTSocJs26PCbNujwmzbo8Js26PCbNuhYvLUkjEVZtseFWbbHhVm2x4V6VLZWpmNdyENqLjbjt7Xq12MjxdxrwQTUtyb8ULK/vcvTtt+UmHqYonE0sOSiKWHJRNLD0shlh6WSiwdLAfnmJjH4oilh8UTSw9LIJYeFiGWHham3C4Wqyk37L83xdjBYjXlDrBYTbkDLFZT7u+xFKspd4DFasodYLGacgdYrKbcARYhlh4Wqyl3gIUpt4uFKbeLhSm3i4Upt4elMuV2sTDldrEw5XaxMOV2sQix9LAw5XaxMOV2sTDldrEw5XaxMOV2sMSNKbeLhSm3i4Upt4uFKbeLRYilh4Upt4uFKbeLhSm3i4Upt4uFKbeHxTHldrEw5XaxMOV2sTDldrEIsfSwMOV2sTDOdbEwznWxMM71sHjGuS4WxrkuFsa5LhbGuS4WIZYeFsa5LhZuWnaxMOV2sTDldrEw5fawBBMp90uriej6pdVEHv3SaiJkfmkVQ1pNxMEvrSYy3pdWE8HtS6uJNPal1UTE+rtWMZSbxFBuEkO5SQzlJjGUm8RQbhJDuUkM5SYxlJvEUG6KhnJTNJSboqHcFA3lpmgoN0VDuSkayk3RUG6KhnJTNJSbkqHclAzlpmQoNyVDucnGcTFfWg3lJhsHu3xpNZSbbBzB8qXVUG6ycVjKl1ZDucnGsSZfWg3lJhsHkHxpNZSbbBwV8qXVUG6ycajHl1ZDucnG8RtfWg3lJhsHZXxpNZSbbBxp8aXVUG6ycfjEl1ZDucnGMRFfWg3lJhsHOnxpNZSblirTr01r3jrfCV2qIX+kdZ33YXF5/8Xiarz84i8w67xpq4JJC5WZK4NZxw6UwawzcyuDWWdAVwYjBNMHs040UQazzj6BMph1NhWUwTD5HoBh8u2DWajgXBkMk+8BGCbfAzBMvgdghGD6YJh8D8Aw+R6AYfI9AMPkewCGybcPZqEueGUwTL4HYJh8D8Aw+R6AEZtgvI9hV+hz6IAxmnzHYIwmX++Dv4ORDhijOcZL3V/s47b9BLNQ27cyGKM5ZgzGaI4ZgzGaY8ZghGD6YKzmmCEYqzlmCMboDt4YjNEdvDEYJt8+mIX62pXBMPkegGHyPQAjBNMHw4B3AIYB7wCMVbsu0rY2S5LfvziE3FYhW2e7b6FO8XdStBoEdClaTQ26FK1urulSFFJUoGg11elStBoBdSla3RDUpWh191CXImcXBYoL9fq/kyJnFw2KnF00KDLpjCnmsuvLtbMvtlDz/NsYLtQa/ecxrO0Ryxpzh6GQ4TRD/ls+wTDvT7TW0nk2fKGW5fcx5LwyzXChVuj3MeSsMs+Qk8o8Q+bDeYZChtMM+fnKPEPuOcwz5Jwyz5BzyjxDziljhm4LOw63lc4u7EI97O+kyFlFgyKnFQ2KnFc0KAopKlDkzKJBkVOLBkXOLRoUObloUOTsMk8xWz1hRJkiZxcNipxdNChydtGgKKSoQJGziwZFzi4aFDm7aFDk7KJBkbOLAkWrZ8Q8R9E1HLf/TB2KnF00KHJ20aDI2UWDopCiAkXOLhoUObtoUOTsokGRs4sCRavn0yhTZOrWoMjUrUGRqVuDopCiAkWmbg2KTN0aFJm6NSgydWtQ5CcGChTNnkmlS5GziwZFzi4aFDm7aFAUUlSgyNlFgyJnFwWKZs8geoqid42id7VDkUlHgyLd5QzFII2ihA5FuosGRbqLBkXujGlQ5M6YBkXujClQ5LlWKhSZFzUocmdMgyJ3xjQoCikqUOTsokGRs4sGRc4uGhQ5u2hQ5OyiQJHnWqlQ5OyiQZGziwZFzi6/UvwCIwTTB8MJ4wAMh4YDMJwDDsAw2h+AYVrvg8kM4AdgmKkPwDAmH4Bh8j0AIwTTB8PkewCGyfcADJPvARgm3z4Ys2cgVl92hTX4Dhirdj0EY/XNt0bXwHT/KVl98x2CsfrmOwRjddthBMbsuWtDMFa3HYZgzOaYERizOWYERgimD8bqtsMQDJPvARijyTfvzzrk2IFiNPX+HorRxPs7KMXqSV2/h2I06f4eitGU+3soRhPu76EIofyEYjTZ/h6K0VT7eyhMtB0oTLQdKEy0P6FYPXno91AY3jpQGN46UIRQfkJheOtAMRrewr0lL7haOmCMBrgxGKMhbgzGaJAbgrF6LNAYjNGUOwZjNOmOwVi1a++3/Rd7Lx0wVu16BMbquQbBlzuYmjtgrL75DsFYffMdgjG61TAGIwTTB2N0y2EMxmyOGYExm2NGYKxuOwzBWN12GIGxes7FGAyT7wEYq8n34ReH1ANjNfkOwQjB9MFYTb5DMFaT7xCM1eQbcvvFsnV28KyeYjEEY/VgijEYqwFvCMZswBuBMRvwRmCEYPpgzAa8ERizAW8EhgHvAIzVrc0hGCbfPhirxxqMwTD5HoBh8j0Aw+R7AEYIpg+GyfcADJPvARgm3wMwTL4HYJh8+2CsnicwBsPkewCGyfcADJPvARghmD4YJt8DMEy+B2CYfA/AMPkegGHy7YMpTL4HYJh8D8Aw+R6AYfI9ACME0wfD5HsAhsn3AAyT7wEYJt8DMEy+fTBWD3MZg2HyPQDD5HsAhsn3AIx0wbgoDUzx38B8/Vy8+HPp4s/liz9XLv5cvfRz9eBIgvHPuYs/5y/+XLj4c3Lx5+LFn0sXfy5f/Lly8ecu3i/u4v3iLt4v7uL94i7eL+7i/eIu3i/u4v3iLt4v7uL94i7eL/7i/eIv3i/+4v3iL94v/uL94i/eL/7i/eIv3i/+4v3iL94v4eL9Ei7eL+Hi/RIu3i/h4v0SLt4v4eL9Ei7eL+Hi/RIu3i9y8X6Ri/eLXLxf5OL9IhfvF7l4v8jF+0Uu3i9y8X6Ri/dLvHi/xIv3S7x4v8SL90u8eL/Ei/dLvHi/xIv3S7x4v8SL90u6eL+ki/dLuni/pIv3S7p4v6SL90u6eL+ki/dLuni/pIv3S754v+SL90u+eL/ki/dLvni/5Iv3S754v+SL90u+eL/ki/dLuXi/lIv3S7l4v5SL90u5eL+Ui/dLuXi/lIv3S7l4v5SL90u9eL/Ui/dLvXi/1Iv3y8X93Xpxf7de3N+tF/d368X93Xpxf9dtFzd4bz/orv6gv/qD4eoPytUfjFd/MF39wXz1B8vVH7x657ird467eue4q3eOu3rnuKt3jrt657ird467eue4q3eOu3rn+Kt3jr965/ird46/euf4q3eOv3rn+Kt3jr965/ird46/eueEq3dOuHrnhKt3Trh654Srd064eueEq3dOuHrnhKt3Trh658jVO0eu3jly9c6Rq3eOXL1z5OqdI1fvHLl658jVO0eu3jnx6p0Tr9458eqdE6/eOfHqnROv3jnx6p0Tr9458eqdE6/eOenqnZOu3jnp6p2Trt456eqdk67eOenqnZOu3jnp6p2Trt45+eqdk6/eOfnqnZOv3jn56p2Tr945+eqdk6/eOfnqnZOv3jnl6p1Trt455eqdU67eOeXqnVOu3jnl6p1Trt455eqdU67eOfXqnVOv3jn16p1Tr9459eqdU6/eOfXqnVOv3jn16p1zdQ/ZXd1Ddlf3kN3VPWR3dQ/5Nj9c/cF49QfT1R/MV3+wXP3Bq3fO1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95DdwR6yT/tXrXzY4rcf7HzjK5SvF9eH73A58b3vksX9RLZvx5370Pu90bv9F8fy8IWvUNvyI/byE/byM/byC/byK/TyDz4ugVm+x15+wF4+tm0Jtm0Jtm0Jtm0Jtm0Jtm0dfMgLs3xs140KrvvHZ5j7mm67AwMB+/K3wW/1t89i9zXcPs25/9aY2+ID8uIFefERefEJefEZefEFefEVePFpQ168Q148ssMmZIdNyA6bkB02ITtsQnbYhOywCdlhM7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkhy3IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IjtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bAV2WL8BO6zfgB3Wb8AO6zdgh/UbsMP6Ddhh/QbssH4Ddli/ATus35Ad1iE7rEN2WIfssA7ZYR2ywzpkh3XIDuuQHdYhO6xDdliP7LAe2WE9ssN6ZIf1yA7rkR3WIzusR3ZYj+ywHtlhA7LDBmSHDcgOG5AdVqM46X2LR3bYgOywAdlhA7LDBmSHFWSHFWSHFWSHFWSH1eh4et/ikR1WkB1WkB1WkB1WkB02IjtsRHZY5E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzoF5E6ngNzpFJA7nQJyp1PYgB02IHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU6C3OkkyJ1OgtzpJMidTrIBO6wgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6yUGnUwilLT7L4DK1vbiWMli6i/viXb2/1vvQ+73R78uvsdwR+lDb8gP28gV7+RF7+Ql7+Rl7+RV6+QclSTDLd9jLx7YtwbYtwbYtwbYtwbYtwbatg9IkmOUruO7bhpW4IS/eIS/eIy8+IC9ekBcfkRefkBefkRdfkBeP7LAJ2WETssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bEV22ArssHEDdti4ATts3IAdNm7ADhs3YIeNG7DDxg3YYeMG7LBxA3bYuCE7rEN2WIfssA7ZYR2ywzpkh3XIDuuQHdYhO6xDdliH7LAe2WE9ssN6ZIf1yA7rkR3WIzusR3ZYj+ywHtlhPbLDBmSHDcgOG5AdNiA7rEZl0vsWj+ywAdlhA7LDBmSHDcgOK8gOK8gOK8gOK8gOq9Hu9L7FIzusIDusIDusIDsscqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidTgm50ykhdzol5E6nhNzplDZgh03InU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0budMrInU4ZudMpI3c65Q3YYTNyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO53yQaeTbG3xInFwmdqU1lIGS3dxX7yr99d6H3q/N/p9+TWW+yp8qG35Hnv5AXv5gr38iL38hL38gr38Cr38g5okmOVj21bAtq2AbVsB27YCtm0FbNs6KE2CWb6C675tWAkVePGyIS/eIS/eIy8+IC9ekBcfkRefkBefkReP7LCC7LAR2WEjssNGZIeNyA4bkR02IjtsRHbYiOywEdlhI7LDJmSHTcgOm5AdNiE7bEJ22ITssAnZYROywyZkh03IDpuRHTYjO2xGdtiM7LAZ2WEzssNmZIfNyA6bkR02IztsQXbYguywBdlhC7LDFmSHLcgOW5AdtiA7bEF22ILssBXZYSuyw1Zkh63IDluRHbYiO2xFdtiK7LAV2WErsMOWDdhhywbssGUDdtiyATts2YAdtmzADls2YIctG7DDlg3YYcuG7LAO2WEdssM6ZId1yA7rkB3WITusQ3ZYh+ywDtlhHbLDemSH9cgO65Ed1iM7rEZh0vsWj+ywHtlhPbLDemSH9cgOG5AdNiA7bEB22IDssBrdTu9bPLLDBmSHDcgOi9zpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpInc6VeROp4rc6VSRO53qBuywFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1MF7nTyG3Cn023xuA57Wzyuw94Wj+uwt8XjOuxt8bgOe1s8rsPeFo/rsLfF4zrsbfHIDnvU6ZTr/oPRpcFlatiV3jYjBkt3cV/8bfhvr/U+9H5v9Pvyayx3hD7UtnyHvXyPvfyAvXzBXn7EXn7GXn7BXn6FXr7Hti2PbVse27Y8tm15bNvy2LZ1VJqEsnwF133bsOIL8uIr8OLDhrx4h7x4j7z4gLx4QV58RF58Ql48ssMGZIcNyA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4bkR02IjtsRHbYiOywEdlhI7LDRmSHjcgOG5EdNiI7bEJ22ITssAnZYROywyZkh03IDpuQHTYhO2xCdtiE7LAZ2WEzssNmZIfNyA6bkR02IztsRnbYjOywGdlhM7LDFmSHLcgOW5AdtiA7bEF22ILssAXZYQuywxZkhy3IDluRHbYiO2xFdtiK7LAV2WErssNWZIetyA5bkR22Ajus24Ad1m3ADus2YId1G7DDug3YYd0G7LBuA3ZYtwE7rNuAHdZtyA7rkB3WITusQ3ZYh+ywGnVJ71s8ssM6ZId1yA7rkB3WITusR3ZYj+ywHtlhPbLDajQ7vW/xyA7rkR0WudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJI3c6eeROJ4/c6eSRO538BuywHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5M/6HSKcWuLL3lwmRrK14trKYOlu/aLXb2/1vvQ+73R78uvscT7q0P9Wn44aHWCWb7DXr7HXn7AXr5gLz9hLz9jL79gLx/bthy2bTls23LYtuWwbcth29ZBaRLM8hVc913DSnAZefEFefEVePF+Q168Q168R158QF68IC8+Ii8e2WE9ssN6ZIf1yA4bkB02IDtsQHbYgOywAdlhA7LDBmSHDcgOG5AdNiA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7bER22IjssBHZYSOyw0Zkh43IDhuRHTYiO2xEdtiI7LAJ2WETssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bEV22ArssLIBO6xswA4rG7DDygbssLIBO6xswA4rG7DDygbssLIBO6xsyA7rkB3WITusQ3ZYh+ywGr1O71s8ssMidzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp1NE7nSKyJ1OEbnTKSJ3OsUN2GEjcqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1O8aDTKfn2gymWwWVqKF8vrqUMlu4aFVfvr/U+9H5vbKuot/v7/upQ2/Ir9PIPep1glu+wl++xlx+wlx+xl5+wl5+xl49tWxXattIGbVtpg7attEHbVtqgbSttgr18Bdd917CStoS8+Iy8+IK8+Aq8eLchL94hL94jLz4gL16QF4/ssA7ZYR2ywzpkh3XIDuuRHdYjO6xHdliP7LAe2WE9ssN6ZIf1yA7rkR3WIztsQHbYgOywAdlhA7LDBmSHDcgOG5AdNiA7bEB22IDssILssILssILssILssILssILssILssILssILssILssBHZYSOyw0Zkh43IDhuRHTYiO2xEdtiI7LAR2WEjssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDJmSHTcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDpuRHTYjO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsQXbYguywFdlhK7LDVmSHrcgOW5EdtiI7bEV22IrssBXZYSuww+YN2GHzBuyweQN22LwBO2zegB02I3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4FudOpIHc6FeROp4Lc6VQ2YIctyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqR51Otf1g9nlwmRrK14trKYOlu7gv3tX7a70Pvd8bG8IaS7y/OtS2/IK9/Aq9/KNmJ5TlO+zle+zlC/byI/byE/bysW2rYNtWwbatim1bFdu2KrZtHZUmoSxfwXXfNqzUiLz4hLz4jLz4grz4irv4um3Ii3fIi/fIiw/Iiwd22LoBO2zdgB22bsAOWzdgh60bssM6ZId1yA7rkB3WITusQ3ZYh+ywDtlhHbLDOmSHdcgO65Ed1iM7rEd2WI/ssB7ZYT2yw3pkh/XIDuuRHdYjO2xAdtiA7LAB2WEDssMGZIcNyA4bkB02IDtsQHbYgOywguywguywguywguywguywguywguywguywguywguywEdlhI7LDRmSHjcgOG5EdNiI7bER22IjssBHZYSOywyZkh03IDpuQHTYhO2xCdtiE7LAJ2WETssMmZIdNyA6bkR02IztsRnbYjOywGdlhM7LDZmSHzcgOm5EdNiM7bEF22ILssAXZYQuyw2r0PL1v8cgOW5AdtiA7bEF22ILssBXZYSuyw1Zkh63IDovc6VSRO50qcqdTRe50qsidThW40ylswJ1Ot8XjOuxt8bgOe1s8rsPeFo/rsLfF4zrsbfG4DntbPK7D3haP67C3xSM7LHCn023xyA4L3Ol0WzyywwJ3Ot0Wj+ywwJ1Ot8UjOyxwp9Nt8cgOC9zpdFs8ssMCdzrdFo/ssMCdTrfFIzsscKfTbfHIDgvc6XRbPLLDAnc63RaP7LDAnU63xSM7LHCn023xyA4L3Ol0WzyywwJ3Ot0Wj+ywwJ1Ot8UjOyxwp9Nt8cgOC9zpdFs8ssMCdzrdFo/ssMCdTrfFIzsscKfTbfHIDgvc6XRbPLLDAnc63RaP7LDAnU63xSM7LHCn023xyA4L3Ol0WzyywwJ3Ot0Wj+ywwJ1Ot8UjOyxwp9Nt8cgOC9zpdFs8ssMCdzrdFo/ssMCdTrfFIzsscKfTbfHIDgvc6XRbPLLDAnc63RaP7LDAnU63xSM7LHCn023xyA4L3Ol0WzyywwJ3Ot0Wj+ywwJ1Ot8UjOyxwp9Nt8cgOC9zpdFs8ssMCdzrdFo/ssMCdTrfFIzsscKfTbfHADuuQO50ccqeTQ+50csidTm4DdliH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTu6g0ymnrS2+psFlaihfL66lDJZ+GyB2nfX+Wu9D7/dGvy+/xhLvrw61LT9jL79gL79CL/+g2wlm+Q57+QF7+YK9/Ii9fGzbyti2lbFtK2PbVsG2rYJtWwelSTDLV3Ddtw0rRZAXH5EXn5AXn5EXX5AXX4EXXzfkxTvkxXvkxSM7bEV22IrssBXZYSuyw1Zkh63ADus3YIf1G7DD+g3YYf0G7LB+A3ZYvwE7rN+AHdZvwA7rN2CH9Ruywzpkh3XIDuuQHdYhO6xDdliH7LAO2WEdssM6ZId1yA7rkR3WIzusR3ZYj+ywHtlhPbLDemSH9cgO65Ed1iM7bEB22IDssAHZYQOywwZkhw3IDhuQHTYgO2xAdtiA7LCC7LCC7LCC7LCC7LCC7LCC7LCC7LCC7LCC7LCC7LAR2WEjssNGZIeNyA4bkR02IjtsRHbYiOywEdlhI7LDJmSHTcgOm5AdNiE7bEJ22ITssAnZYROywyZkh03IDpuRHTYjO2xGdtiM7LAaLU/vWzyyw2Zkh83IDpuRHTYjO2xBdtiC7LAF2WGRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudAnKnU0DudArInU4BudMpbMAOG5A7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E4nQe50EuROJ0HudBLkTifZgB1WkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSQ46ncqW9x8ssY4uU2rdX119+HaZn6++ZcF9UTd/z4NX+5jT/ruTS4NX19h+d40ltlf7UJvgZE1wtia4WBNcjQk+6LVaWLCzJthbExysCRZrgq0lrWQtaSVrSStZS1rJWtLKb0ha23YXXEaCt7L/6iDttSl1XhrKjkb8A0dfu0vewQRXvr125+LIpcvFk0uXSyCXLhchly6X+NlcXA2NS/w9l5LivoyS0qODpaY2mVKbTaktptRWS2rLh6dD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"},{"name":"rotate_npk_m","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"new_npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fMxopWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLLX/ent52x9uL03n3fp7ut6Pupv3x6fY0Pu+m58PL/vrc2+e3u9tohdF2I6PIqGS0lVGTUZfRLKMhIyliK0U0KaJJEU2KaFJEkyKaFNGkiCZFNCmiSRFdiuhSRJciuhTRpYguRXQpoksRXYroUsQsRcxSxCxFzFLELEXMUsQsRcxSxCxFzFLEkCKGFDGkiCFFDCliSBFDihhSxJAihhSxSBGLFLFIEYsUsUgRixSxSBGLFLFIEYsUsUoRqxSxShGrFLFKEasUsUoRqxSxShGrFJHNhlahVdFqS6tGq06rmVaDVgutqI1QG6E2Qm2E2gi1EWoj1EaojVAboTaK2ihqo6iNojaK2ihqo6iNojYINEOiGSLNkGmGUDOkmiHWDLlmCDZDshmizZBthnAzpJsh3gz5Zgg4Q8IZIs6QcYaQM6ScIeYMOWcIOkPSGaLOkHWGsDOknSHuDHlnCDxD4hkiz5B5htAzpJ4h9gy5Zwg+Q/IZos+QfYbwM6SfIf4M+WcIQEMCGiLQkIGGEDSkoCEGDTloCEJDEhqi0JCFhjA0pKEhDg15aAhEQyIaItGQiYZQNKSiIRYNuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlo2UVPctEiFy1y0SIXLXLRIhctctH6bxe9nn7u3g+7h5f97W7v7ePH8fHfVd/r8fzr7e+X67+/AQ=="}],"outputs":{"globals":{"storage":[{"fields":[{"name":"npk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"npk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}},{"name":"ivpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000003"}}],"kind":"struct"}},{"name":"ivpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000004"}}],"kind":"struct"}},{"name":"ovpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000005"}}],"kind":"struct"}},{"name":"ovpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000006"}}],"kind":"struct"}},{"name":"tpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000007"}}],"kind":"struct"}},{"name":"tpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000008"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"partial_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::partial_address::PartialAddress"}},{"name":"keys","type":{"fields":[{"name":"npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ivpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ovpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"tpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}}],"kind":"struct","path":"aztec::keys::public_keys::PublicKeys"}}],"kind":"struct","path":"KeyRegistry::register_parameters"}}],"kind":"struct","path":"KeyRegistry::register_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"new_npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"KeyRegistry::rotate_npk_m_parameters"}}],"kind":"struct","path":"KeyRegistry::rotate_npk_m_abi"}]}},"file_map":{"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"157":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField};\n\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange}\n};\n\nmod test;\n\nstruct SharedMutable {\n context: Context,\n storage_slot: Field,\n}\n\n// This will make the Aztec macros require that T implements the Serialize trait, and allocate N storage slots to\n// this state variable. This is incorrect, since what we actually store is:\n// - a ScheduledValueChange, which requires 1 + 2 * M storage slots, where M is the serialization length of T\n// - a ScheduledDelayChange, which requires another storage slot\n//\n// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we \n// can actually use it here\nimpl Storage for SharedMutable {}\n\n// SharedMutable stores a value of type T that is:\n// - publicly known (i.e. unencrypted)\n// - mutable in public\n// - readable in private with no contention (i.e. multiple parties can all read the same value without blocking one\n// another nor needing to coordinate)\n// This is famously a hard problem to solve. SharedMutable makes it work by introducing a delay to public mutation:\n// the value is not changed immediately but rather a value change is scheduled to happen in the future after some delay\n// measured in blocks. Reads in private are only valid as long as they are included in a block not too far into the \n// future, so that they can guarantee the value will not have possibly changed by then (because of the delay).\n// The delay for changing a value is initially equal to INITIAL_DELAY, but can be changed by calling \n// `schedule_delay_change`.\nimpl SharedMutable {\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in\n // which we can safely store as much data as we need. \n // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and \n // https://github.com/AztecProtocol/aztec-packages/issues/5736\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n\nimpl SharedMutable {\n pub fn schedule_value_change(self, new_value: T) {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n let current_delay = delay_change.get_current(block_number);\n\n // TODO: make this configurable\n // https://github.com/AztecProtocol/aztec-packages/issues/5501\n let block_of_change = block_number + current_delay;\n value_change.schedule_change(new_value, block_number, current_delay, block_of_change);\n\n self.write_value_change(value_change);\n }\n\n pub fn schedule_delay_change(self, new_delay: u32) {\n let mut delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n\n delay_change.schedule_change(new_delay, block_number);\n\n self.write_delay_change(delay_change);\n }\n\n pub fn get_current_value_in_public(self) -> T {\n let block_number = self.context.block_number() as u32;\n self.read_value_change().get_current_at(block_number)\n }\n\n pub fn get_current_delay_in_public(self) -> u32 {\n let block_number = self.context.block_number() as u32;\n self.read_delay_change().get_current(block_number)\n }\n\n pub fn get_scheduled_value_in_public(self) -> (T, u32) {\n self.read_value_change().get_scheduled()\n }\n\n pub fn get_scheduled_delay_in_public(self) -> (u32, u32) {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange {\n public_storage::read(self.get_value_change_storage_slot())\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange {\n public_storage::read(self.get_delay_change_storage_slot())\n }\n\n fn write_value_change(self, value_change: ScheduledValueChange) {\n public_storage::write(self.get_value_change_storage_slot(), value_change);\n }\n\n fn write_delay_change(self, delay_change: ScheduledDelayChange) {\n public_storage::write(self.get_delay_change_storage_slot(), delay_change);\n }\n}\n\nimpl SharedMutable {\n pub fn get_current_value_in_private(self) -> T where T: FromField {\n // When reading the current value in private we construct a historical state proof for the public value.\n // However, since this value might change, we must constrain the maximum transaction block number as this proof\n // will only be valid for however many blocks we can ensure the value will not change, which will depend on the\n // current delay and any scheduled delay changes.\n\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context);\n\n // We use the effective minimum delay as opposed to the current delay at the historical block as this one also\n // takes into consideration any scheduled delay changes. \n // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that\n // the earliest we could change the value would be at block 251 by scheduling immediately after the historical\n // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 \n // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is \n // earlier than what we'd expect if we only considered the current delay.\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // We prevent this transaction from being included in any block after the block horizon, ensuring that the \n // historical public value matches the current one, since it can only change after the horizon.\n self.context.set_tx_max_block_number(block_horizon);\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n context: PrivateContext\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let header = context.get_header();\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n context.this_address()\n );\n }\n\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = context.historical_header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"354":{"path":"/usr/src/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr","source":"contract KeyRegistry {\n use dep::authwit::auth::assert_current_call_valid_authwit_public;\n\n use dep::aztec::{\n keys::PublicKeys, state_vars::{SharedMutable, Map},\n protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}}\n };\n\n global KEY_ROTATION_DELAY = 5;\n\n #[aztec(storage)]\n struct Storage {\n // The following stores a hash of individual master public keys\n // If you change slots of vars below, you must update the slots in `SharedMutablePrivateGetter` in aztec-nr/keys.\n // We store x and y coordinates in individual shared mutables as shared mutable currently supports only 1 field\n npk_m_x_registry: Map>,\n npk_m_y_registry: Map>,\n\n ivpk_m_x_registry: Map>,\n ivpk_m_y_registry: Map>,\n \n ovpk_m_x_registry: Map>,\n ovpk_m_y_registry: Map>,\n \n tpk_m_x_registry: Map>,\n tpk_m_y_registry: Map>,\n }\n\n #[aztec(public)]\n fn rotate_npk_m(address: AztecAddress, new_npk_m: GrumpkinPoint, nonce: Field) {\n // TODO: (#6137)\n if (!address.eq(context.msg_sender())) {\n assert_current_call_valid_authwit_public(&mut context, address);\n } else {\n assert(nonce == 0, \"invalid nonce\");\n }\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n npk_m_x_registry.schedule_value_change(new_npk_m.x);\n npk_m_y_registry.schedule_value_change(new_npk_m.y);\n }\n\n #[aztec(public)]\n fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) {\n let computed_address = AztecAddress::compute(keys.hash(), partial_address);\n\n assert(computed_address.eq(address), \"Computed address does not match supplied address\");\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address);\n let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address);\n let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address);\n let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address);\n let tpk_m_x_registry = storage.tpk_m_x_registry.at(address);\n let tpk_m_y_registry = storage.tpk_m_y_registry.at(address);\n\n npk_m_x_registry.schedule_value_change(keys.npk_m.x);\n npk_m_y_registry.schedule_value_change(keys.npk_m.y);\n ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x);\n ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y);\n ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x);\n ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y);\n tpk_m_x_registry.schedule_value_change(keys.tpk_m.x);\n tpk_m_y_registry.schedule_value_change(keys.tpk_m.y);\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"66":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/public_storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::oracle::storage::{storage_read, storage_write};\n\npub fn read(storage_slot: Field) -> T where T: Deserialize {\n T::deserialize(storage_read(storage_slot))\n}\n\npub fn write(storage_slot: Field, value: T) where T: Serialize {\n storage_write(storage_slot, value.serialize());\n}\n\n// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633\n// pub fn read_historical(\n// storage_slot: Field,\n// context: PrivateContext\n// ) -> T where T: Deserialize {\n// let mut fields = [0; N];\n// for i in 0..N {\n// fields[i] = public_storage_historical_read(\n// context,\n// storage_slot + i as Field,\n// context.this_address()\n// );\n// }\n// T::deserialize(fields)\n// }\n\nmod tests {\n use dep::std::test::OracleMock;\n use dep::protocol_types::traits::{Deserialize, Serialize};\n use crate::public_storage;\n\n struct TestStruct {\n a: Field,\n b: Field,\n }\n\n impl Deserialize<2> for TestStruct {\n fn deserialize(fields: [Field; 2]) -> TestStruct {\n TestStruct { a: fields[0], b: fields[1] }\n }\n }\n\n impl Serialize<2> for TestStruct {\n fn serialize(self) -> [Field; 2] {\n [self.a, self.b]\n }\n }\n\n #[test]\n fn test_read() {\n let slot = 7;\n let written = TestStruct { a: 13, b: 42 };\n\n OracleMock::mock(\"storageRead\").with_params((slot, 2)).returns(written.serialize());\n\n let read: TestStruct = public_storage::read(slot);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n\n #[test]\n fn test_write() {\n let slot = 7;\n let to_write = TestStruct { a: 13, b: 42 };\n\n let mock = OracleMock::mock(\"storageWrite\").returns([0; 2]); // The return value is unused\n\n public_storage::write(slot, to_write);\n assert_eq(mock.get_last_params(), (slot, to_write.serialize()));\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json b/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json new file mode 100644 index 000000000000..7fcee3263181 --- /dev/null +++ b/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json @@ -0,0 +1 @@ +{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"MultiCallEntrypoint","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/f0swoWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+Flf30e9fnt7jZaYbTdyCgyKhltZTTLaJFRk1GXkRSxlSJmKWKWImYpYpYiZililiJmKWKWImYpYpYiFilikSIWKWKRIhYpYpEiFilikSIWKWKRIpoU0aSIJkU0KaJJEU2KaFJEkyKaFNGkiC5FdCmiSxFdiuhSRJciuhTRpYguRXQpYkgRQ4oYUsSQIoYUMaSIIUUMKWJIEUOKWKWIVYpYpYhVililiFWKWKWIVYpYpYhVishmQ6vQqmi1pdVMq4VWjVadVoNW1EaojVAboTZCbYTaCLURaiPURqiNUBtFbRS1UdRGURtFbRS1UdRGURsEmiHRDJFmyDRDqBlSzRBrhlwzBJsh2QzRZsg2Q7gZ0s0Qb4Z8MwScIeEMEWfIOEPIGVLOEHOGnDMEnSHpDFFnyDpD2BnSzhB3hrwzBJ4h8QyRZ8g8Q+gZUs8Qe4bcMwSfIfkM0WfIPkP4GdLPEH+G/DMEoCEBDRFoyEBDCBpS0BCDhhw0BKEhCQ1RaMhCQxga0tAQh4Y8NASiIRENkWjIREMoGlLREIuGXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y07KInuWiRixa5aJGLFrlokYsWuWj9t4teTz9374fdw8v+drf39vHj+Pjvqu/1eP719vfL9d/f"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"7P3drmy5spwJvsu5FgrBf1Kv0mg01H1UDQEFqVBSXQl69xr77IyIuc6aEYMzl4+gG810U1IhdiTdPJM085j8+D//5V//8//3//7//3/+y3/93//bf/+X//j/+p//8n/8t//ff/of/+W//dfj//U//yW2f/v/99//z//0X//x//zv/+M//V//41/+4+0//Mt//q//evx//9d/+Jf//b/8H//5X/5j6vF//YffPhdbSX99NLZWHp8OoX7z6RxD++vTOfZ88ulRYvjr06P053fHNP7X//s//EvsqAsfH1x4uuX7wlP9w4Wn258sPKdUH0tp8fHpEf7tu8OF3x2/++6c79+e2zj5/jAeMoaR0uPTJX334RrK/cM1PZce+z9Xk1ytJrtaTfnz1Yx4/88j1pPVxJzy49O51PHv/8WpH15OGeGxnJp+Wc7vH0853b875a87QWrffLqN+w7Wb88vDr3/W6GNpdDOUuggKTTfWAoNLIVGlkITS6GZpdDCUqhvZ1Ta3WWmGsZZoe1RaHiuI9bbdwu59XvQiCE+vzmG248l9O25ICT07eYgJPTtExEkLL4dKISEvr0thIS+XTOEhL79OISEWRL+qYS+MwSEhKzp5BivPyTs8RcJ/yELa+I4kYU1RZzIwpoM3stSWd3+iSysDv5EFlZXfiILq9M+kSVLlu9kYXXEJ7KwutwjHjxW/eUPTu6ysLrcE1lYXe6JLKwu970sjdXlnsjC6nJPZGF1uSeysLrcE1myZPlOFlaXeyILrcut/bHqY6z972WhdbnvZaF1ue9loXW5b2XptC73vSy0Lve9LLQu970stC73vSxZsnwnC63LfS/Lp11uzeMhS6+397LE2up9JUcdt39/wbI36NV36NUP5NWPm+/V9/hl9b/dDx0BevURevUJevUZevUFevXOz9qT1Ts/a3t/+K06fl+987P2ZPXOz9r3qw8374ftyfK9n7Yny/d+3J4s3/t5e7J85wfu6PcsGdst9t+W7/zEPVu+8yP3bPm+z9wWviChjp/Tflu+70O3xfT4eEu39NvyfZ+6Z8sPvk/d0+X7PnVPl+/71G0jPHeeMfJvy/d96p4u3/ep22/psXH2r3fO7sv3feqeLt/3qXu6/E+fun08RvR5xPrberqz9Xz6XBzt+VPK6PF9e/u4/5Iy4vPfhFC/+yElxPSgAsbx9ceR/M2n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jt526uhtp47edurobadO3nbq5G2nTt526uRtp07edurkbadO3nbq5G2nTt526uRtp87edursbafO3nbq7G2nzt526uxtp87edursbafO3nbq7G2nLt526uJtpy7eduribacu3nbq4m2nLt526uJtpy7eduribaeu3nbq6m2nrt526uptp67edurqbaeu3nbq6m2nrt526uptp27edurmbadu3nbq5m2nbt526uZtp27edurmbadu3nbq5m2n7t526u5tp+7edurubafu3nbq7m2n7t526u5tp+7edurubace3nbq4W2n9nZHcXi7ozi83VEc3u4oDm93FIe3O4rD2x3F4eyOYrw5u6N4LMjXTn0syNdOfSzI1059LMjXTn0syNdOfSzI1059LMjXTn0syNdOfSzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzo0zv1GPenKP5BWv5mQdXbgpq3BXVvCxrOFvTxO4qnCwreFhS9LejDO/W4jfpYUGj99wVlbwsq3hZUvS3owzv1iF/+pT7+l78vqHtb0Id36jHG49O344eN3xb06TuK5wsK3hb02Z36H38N/FxQuKXfF5S8LSh7W1DxtqDqbUHN24K6twWNDy8oxPhcUP19QR++ozixoOBtQZ/eqWMbjwWl3H5f0Kd36vQYNvzj99Xx+4KytwUVbwv68E4djp+d758OId5+X1DztqAP79QhlMd/ZSGW8vuChq8FhQ/fUZxY0Id36tCeO3Vo6Zed+rvv7vfQFHOJjw/H23dfPkoMf316lP6sNabxV7GRqdgPnzChltuj2B5Oii3lPi8o7fnR/NfSM+7SC+7SK+7SG+7Su+elv3mc/Fj6gF16uOEuPeAuPeIu3fVp+n7prk/T90t3fZq+X7rr0/T90l2fpu+XjnuaBtzTNOKephH3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gPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868qOP+qgvOvKjj/qoLzr+oN+/yt4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsGzr9q4PyrBs6/auD8q3bDPn8bOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qD8686OP+qg/OvOjj/qt+wz98Ozr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ovxrg/KsBzr8a4PyrAc6/Gjfs83eA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzr46FYh/A/1goegHYR/CxUOwz+Fgo9iF8LBT7FD4Win0MHwvFPoePhWIfxMdC0U9icBTWUQD6SQwOwzoKQD+JwXFYRwHoJzE4EOsoAP0kBkdiHQWgn8TgUKyjAPSTGByLdRSAfhKDg7GOAtBPYnA01lEA+kkMDsc6CkA/icHxWEcB6CcxOCDrKAD9JAZHZB0FoJ/E4JCsowD0kxgck3UUgH4Sg4OyjtWhn8TgqKxjdegnMTgs61gd+kkMjss6Vod+EoMDs47VoZ/E4MisowD0kxgcmnUUgH4Sg2OzjgLQT2JwcNZRAPpJDI7OOgpAP4nB4VlHAegnMTg+6ygA/SQGB2gdBaCfxOAIraMA9JMYHKJ1FIB+EoNjtI4C0E9icJDWUQD6SQyO0joKQD+JwWFaRwHoJzE4TusoAP0kBgdqHQWgn8TgSK2jAPSTGByqdRSAfhKDY7WOAtBPYnCw1lEA+kkMjtY6CkA/icHhWkcB6CcxOF7rKAD9JAYHbB0FoJ/E4IitowDwkzigM7YCOmMroDO2Ajpj61geegHgJ3FAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkRnbEV0xlZEZ2xFdMZWvIGfxBGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xldAZWwmdsZXQGVsJnbGVbuAncUJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsZXTGVkZnbGV0xlZGZ2zlG/hJnNEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbBZ2xVdAZWwWdsVXQGVvlBn4SF3TGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWRWdsVXTGVkVnbFV0xla9gZ/EFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbHV0BlbDZ2x1dAZWw2dsdVu4CdxQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2x1dMZWR2dsdXTGVkdnbPUb+Enc0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsdnbHV0RlbHZ2x1dEZWx2dsdXRGVsDnbE10BlbA52xNdAZW+MGfhIPdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA10xtZAZ2wNdMbWQGdsDXTG1kBnbA1wxla8gTO2jgKwT+KjAOyT+CgA+yQ+CsA+iY8CsE/iowDsk/goAPskPgrAPomPAtBPYnDG1lEA+kkMztg6CkA/icEZW0cB6CcxOGPrKAD9JAZnbB0FoJ/E4IytowD0kxicsXUUgH4SgzO2jgLQT2JwxtZRAPpJDM7YOgpAP4nBGVvHPwL9JAZnbB3/CPSTGJyxdfwj0E9icMbW8Y9AP4nBGVvHPwL9JAZnbB0FoJ/E4IytowD0kxicsXUUgH4SgzO2jgLQT2JwxtZRAPpJDM7YOgpAP4nBGVtHAegnMThj6ygA/SQGZ2wdBaCfxOCMraMA9JMYnLF1FIB+EoMzto4C0E9icMbWUQD6SQzO2DoKQD+JwRlbRwHoJzE4Y+soAP0kBmdsHQWgn8TgjK2jAPSTGJyxdRSAfhKDM7aOAtBPYnDG1lEA+kkMztg6CkA/icEZW0cB6CcxOGPrKAD9JAZnbB0FoJ/E4IytowD0kxicsXUUgH4SgzO2jgLQT2JwxtZRAPpJDM7YOgoAP4kDOmMroDO2AjpjK6Azto7loRcAfhIHdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbEV0xlZEZ2xFdMZWRGdsxRv4SRzRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRV9E55Kjn99tuRXBbg+B2YKcL0LldLvBdT2ogDXu9BMAa53oZkCXO9CMwW4zgMTBfjmC80U4PocqKH+9dma4osCXJ8DMwW4zgMzBWT0AlyfxDMFuD6JZwpwfRLPFOD6JJ4pwPVJPFGAb77QTAHoJ7FvvtBMAegnsW++0EwB6Cexb77QTAHoJ7FvvtBMAZ8/iV+OC3//bG/jvo7eQ36uo/a/N4hcQCNaWm7gKjdylZtQy32WkPFLKPglVPwSGn4JHb8EWDfxKKHBOoRnCbCn/rME2JP8WYLv07m32/3D49yMjMc338bzs/1rub5PcvNyfZ/6PyvX9o89mm83sVQa3y5lqTS+3c9SaXy7qpXSdN9ubak0vl3gUml8u8ul0uzkWo2lyZLmlTRywy+lkRt+KY3c8Etp5IZfSiM3/EqaITf8Uhq54ZfSyA2/lEZu+KU0WdK8kkZu+KU0csMvpZEbfimN3PBLaeSGX0iTbnLDL6WRG34pjdzwS2nkhl9KkyXNK2nkhl9KIzf8Uhq54ZfSyA2/lEZu+JU0QW74pTRywy+lkRt+KY3c8EtpsqR5JY3c8Etp5IZfSiM3/FIaueGX0sgNv5Imkvqac1JkiqS+ZkYa0hPqnOyXIukJNSMN6Qk1Iw3pCTUhTSKd18xIQzqvmZGG1Neck45SIvU1M9JkSfNKGtJ5zYw0pG54RhpSNzwjDakbnpGG1A1PSJNJ3fCMNKRueEYaueGX0sgNv5QmbyTND7459JrvFR7/lOenw3efjqXcC2zhhZA7eeelQu7ktJcKuZMvXyrkTi7eSMinODv5eGtxyk5O3lycnby8uTg7uXlzcXby8+biZInzWhy59DfisDrvUe/fHEZLv4jzt0J1YXXe5kKyOu8fCRnjo8BcXgjJ6tKthXT+pg6QkKzu31xI1qRgLiRrqjAXMktIGyFZ08rPhDyf4Dp/8wlISNJkc6zt/rNrvH1d899NNs7fvwISkjTZ/EzIicPG+VtgQEKSJht7IUmTjb2QpMnGXsgsIW2EJE029kKSJpsfCnmebLZ6rW6pkKzJJoSHNiH2P082W72Et1LIrd7Nu0zIicNmq1f2lgrJmmzMhWRNNuZCZglpIyRrsjEXkjXZmAvJmmx+JuR5stnqncKlQtL+ZtPrU8hxImQbj2++PT8ben8KudUbiEuFpP3NxlpI2mRTw0PIlv98aLHVa4xLhcwS8lzICR+51UuPS4WkTTbWQtImG2shaZONtZC0v9nYCpm3es9yqZC0v9n8SMjToUXe6q3MpUIq2cTQf/1Li6c4WeK8FkcJ5I04rKniGFw91hzLHw8M8lavcS4VkjVV/EjIGQ/HmiqshdzqXdClQrKmCnMhWVOFuZCsqcJcyCwhbYRkTSs/E/J8YLDVW6lLhVSyOf67Td/n563eVjUXRwnktTiRNlXU/lhzD38+MIi0qcJaSNpU8RMhJzzcVu8DLxUyS0gbIWlThbWQtKnCWkjaVGEtJG0CsRaSNq38SMjzgcFW73IvFVLJxkhIJRsjIZVsjITMEtJGSCUbIyGVbIyEVLI5hPz1wvdTHKWVN+IogbwWZ6v3zV9+87NcCu//LNe3Qx8P3GEfX77575fr20ebl5v3KXdikuT8VW/zcn07R/Nyffs783J9Ozbzcn17MOtynb81/bNyz7OZ89ejzcvdyFXNlLuRq5opN3OVu5OrmijXuavqzwA40p9HBOevH5uX69xV/aTcGZvh3FUZl+v8vV/zcp27Kutynbsq63KduyrrcvNG5Z7bDOevxZqXu5Grmil3I1c1U+5Ormqi3J1c1Xm5vt8aHbd8/+ZxK/XPI4LvF0Hty3Xtqn5W7oTN8P26pn25matc167KvlzXrsq+XNeuyr5c167qh+VO2AzXrsq8XN/vHNqXu5Grmil3J1c1Ue5Ormqi3AxTbv01AD5LwHFKL0vAcT8vS3DuaMZ9HeNYyJ9nTd9vstmX69zR/KTcCb/q+30z+3KdOxrrcp07GutynTsa63IzV7nO3c+Pyj33q77fsLIvdyNXNVPuRq5qptydXNVpucX320r25e7kqibKBXJV49sMW3y/EDRXQnZdQsjPEr5c0/3+X7oe7wzU/mXNMYQv5fp2P+bl+nY/Pyq39cdfu4d48s3nE4ri+/WctdL4dlVLpfHtwFZK4/vNmrXS+HZ2S6Xx7QKXSuPbXS6VJkuaV9Js5HCtpZEbfimN3PBLaeSGX0ojN/xKGt9vrayVRm74pTRywy+lkRt+KU2WNK+kkRt+KY3c8Etp5IZfSiM3/FIaueFX0vh+n2OtNHLDL6WRG34pjdzwS2mypHklDamvKfn+lxIlv5KG1NdMSOObC3+hNOX+RECp7YU0pCfUjDSkJ9SMNKQn1Iw0pPOaGWlI5zUz0pD6mvMX1otvlv5aaUjnNRPS+Gb0r5WG1A3PSEPqhmekIXXDM9JkSfNKGlI3PCMNqRuekUZu+KU0csMvpZEbfiWN77cVfijND765tfsl3vbLE6lfLhj6fodhrTQ7uWFjaXZyw8bSZEnzSpqd3LCxNDu5YWNpdnLDf0+aUV9Is5MbNpZmJzdsK43zNzEuk+YLbiOVF9KQuuEZaUjd8Iw0pG54RposaV5JQ+qGZ6QhdcMz0pC64QlWlvM3R5ZKQ+qGJ6Rx/paJkTTPcikc7rNc3641xvuHR0rjpNxw6/m+6qOC56fb13+dfXvRCwrObAX79o0XFOzbDV5QsG+Pd0HBvp3bBQX79mP2BTt/X+WCgn37rAsKZnNazl9ZuaDgzFYwm9Ny/tbKBQWzOS3n761cUDCZ06rO31y5oGAyp1Wdv7tyQcFkTqveMlvBZE6rOn/X5YKCyZxWdf4GywUFszkt5++lXFAwm9Ny/rbJBQWzOS3n75BcUDCb03L+ZsgFBbM5Lefve1xQMJvTcv4WxwUFszkt5+9mXFAwm9Ny/sbFBQWzOS3n71FcUDCb03L+dsQFBbM5LefvPFxQMJvTcv4mwwUFszkt5+8nXFAwm9NKbE7L+bsXFxTM5rQSm9PKbE7L+SskFxTM5rScvxhyQcGZrWA2p+X8zY4LCmZzWs7f17igYDan5fwtjAsKZnNazt+tuKBgNqfl/I2JCwpmc1rO34O4oGA2p+X87YYLCmZzWs7fWbigYDan5fxNhAsKZnNazt8vuKBgNqfl/K2BCwpmc1rO3wW4oGA2p+Wc4X9BwWxOyzlv/4KC2ZyWczb+BQWzOS3nHPsLCmZzWs6Z8xcUzOa0nPPhLyiYzWmxMeIrGyO+sjHiKxsjvrIx4isbI76yMeIrGyO+sjHiKxsjvrIx4isbI76yMeIrGyO+sjHiKxsjvrIx4isbI76xMeIbGyO+sTHiGxsjvt0yW8FkTquxMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrEx4hsbI76xMeIbGyO+sTHiGxsjvrMx4jsbI76zMeI7GyO+3zJbwWROq7Mx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHiOxsjvrMx4jsbI76zMeI7GyO+szHi+04E8dHi/cPt129+lrvRKTxT7kY79Oj9/uHRXpS70f48U+5Gu/NMuRvtzTPlbpSBJ8rdiSg9U+5O5+5EuTuduxPlbpR9Z8rNXOVyuaqdKNIz5cK6qmcJsE7pWYJv95Pa49+jPG4WQdw55/mCgn07oAsK9u2BLijYtwu6oODMVrBvJ3RBwb690AUF+3ZDFxTs2ztdUDCb03LOeb6gYDan5ZzzfEHBbE7LOef5goLZnJZzzvMFBbM5Leec5wsKJnNawznn+YKCyZzWcM55vqBgMqc1bpmtYDKnNZxzni8omMxpDeec5wsKZnNazjnPFxTM5rScc54vKJjNaTnnPF9QMJvTcs55vqBgNqflnPN8QcFsTss55/mCgtmclnPO8wUFszkt55znCwpmc1rOOc8XFMzmtJxzni8omM1pOec8X1Awm9Nyznm+oGA2p+Wc83xBwWxOyznn+YKC2ZyWc87zBQWzOS3nnOcLCmZzWs45zxcUzOa0nHOeLyiYzWk55zxfUDCb03LOeb6gYDan5ZzzfEHBbE7LOef5goLZnJZzzvMFBbM5Leec5wsKZnNazjnPFxTM5rQqm9NyTvK+oGA2p1XZnFbNbAWzOS3nxPYLCmZzWs6p7RcUzOa0nJPbLyiYzWk5p7dfUDCb03JOcL+gYDan5ZzifkHBbE7LOfX9goLZnBYbI36wMeIHGyN+sDHiBxsjfrAx4gcbI36wMeIHGyN+sDHiBxsjfrAx4gcbI36wMeIHGyN+sDHiBxsjfrAx4gcbI36QMeLTjYwRfxTM5bSOgrmc1lEwl9M6Cs5sBXM5raNgLqd1FMzltI6CuZzWUTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FszktMkb8UTCb0yJjxB8FkzmtwMaID2yM+MDGiA9sjPijHLaCyZxWYGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxAc2RnxgY8QHNkZ8YGPEBzZGfGBjxIedCOKjxfuH26/f/Ch3J374TLkb7dCjPz482otyN9qfZ8rdaHeeKXejvXmm3I0y8Ey5GyXgmXJ3OnfPy92JJj1T7kbZd6bcjZLvTLlcrmonivRMubCu6lkCrFN6luDb/ZR8j9ajjn4WxMt9GccE6cW/dL7dj3m5vt2PdbnOCc/m5fp2P+bl+nY/5uX6dj/m5Waucn27H/NyfTsl83K5XJVzorN5uVyuyjnN2bxcLlflnORsXi6Xq3JOcTYvl8tVOSc4m5fL5aqc05vNy6VyVdE5udm8XCpXFZ1Tm83LpXJV8Za5yqVyVdE5rdm8XCpXFZ2Tms3L5XJVzinN5uVyuSrnhGbzcrlclXM6s3m5XK7KOZnZvFwuV+WcymxeLperck5kNi+Xy1U5pzGbl8vlqpyTmM3L5XJVzinM5uVyuSrnBGbzcrlclXP6snm5XK7KOXnZvFwuV+WcumxeLperck5cNi+Xy1U5py2bl8vlqpyTls3L5XJVzinL5uVyuSrnhGXzcrlclXO6snm5XK7KOVnZvFwuV+WcqmxeLperck5UNi+Xy1U5pymbl8vlqpyTlM3L5XJVhctVOadkW5frnJJtXi6Xq6pcrso5A9283MxVLpercs5ANy+Xy1U5Z6Cbl8vlqpwz0M3L5XJVzhno5uVyuSrnDHTzcrlclXNeunm5XK6Ki60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6omLrZ642OqJi62euNjq6Za5yqVyVYmLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqmYutnrnY6pmLrZ652Or5lrnKpXJVmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqeScc9Wjx/uGWXpS70UE0Ue5OwOLR+/3Do70od6OtaqbcjbaqmXIzV7kbBcCZcjcKgDPl7nTuTpS707k7Ue5GAXCi3J2AxTPlcrmqnYDFM+XCuqpnCRm/BN/up8VxL6HHdhbDb6PeVx3Cl1XX8qVg3/7ngoJ9O6ALCvbtgS4o2LcLsi/YOWL4goJ9O6ELCvbthS4o2LcbuqDgzFYwm9Nyjhu+oGA2p+UcOXxBwWxOyzl2+IKC2ZyWc/TwBQWzOS3n+OELCmZzWs4RxBcUzOa0nGOILyiY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8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VA++/auD9Vw28/6qB91+1G/b7t4H3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XHbz/qoP3X3Xw/qsO3n/Vb9jv3w7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfDfD+qwHefzXA+68GeP/VuGG/fwd4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/dX9Q7Bfwfx4UXQD2K/j+oNjv4PuDYr+E7w+K/Ra+Pyj2a/j+oNjv4fuDYr+I7w+K/iYGr8K6C0B/E4OXYd0FoL+Jweuw7gLQ38TghVh3AehvYvBKrLsA9DcxeCnWXQD6mxi8FusuAP1NDF6MdReA/iYGr8a6C0B/E4OXY90FoL+Jweux7gLQ38TgBVl3AehvYvCKrLsA9DcxeEnWXQD6mxi8JusuAP1NDF6UdX869DcxeFXW/enQ38TgZVn3p0N/E4PXZd2fDv1NDF6YdX869DcxeGXWXQD6mxi8NOsuAP1NDF6bdReA/iYGL866C0B/E4NXZ90FoL+Jwcuz7gLQ38Tg9Vl3AehvYvACrbsA9DcxeIXWXQD6mxi8ROsuAP1NDF6jdReA/iYGL9K6C0B/E4NXad0FoL+Jwcu07gLQ38TgdVp3AehvYvBCrbsA9DcxeKXWXQD6mxi8VOsuAP1NDF6rdReA/iYGL9a6C0B/E4NXa90FoL+Jwcu17gLQ38Tg9Vp3AehvYvCCrbsA9DcxeMXWXQD4m3hD79ja0Du2NvSOrQ29Y+v+eOgCwN/EG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWjd2zt6B1bO3rH1o7esbXfwN/EO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2wd6B1bB3rH1oHesXWgd2wdN/A38YHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd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D76ue+Pruje+rnvj67o3vq57uxmfZDr3ZXxd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13Vf+LruC1/XfeHrui98XfflZnyS6dxX4eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33ha/rvvB13Re+rvvC13Vf+LruC1/XfeHrui98XfeFr+u+8HXdF76u+8LXdV9ytaCPtv/66tF+/94vwaneyjOCU31aj94fgkc7EZzqs3pGcKpP6hnBqT6nZwSnysgzglMl5AnBufqwZwTneg9PCE6VjWcEp0rGM4KNTTCb00LuwH6JAHZPLxHBHVE7bs8H6fbpP73/FNf++vL/FMf9OapH76m+QHL0nuorJAf3RVdIDu6MrpAc3BtdIdn4JAf3R1dIDu6QrpAc3E9dIZnPfUXvqb5AcvSe6isk87mv6D3VV0jmc1/Re6qvkMznvqL3VF8hmc99Re+pvkIyn/uK3lN9hWQ+9xW9p/oKyXzuK3pP9RWS+dxX9J7qKyTzua/oPdVXSOZzX9F7qq+QzOe+ovdUXyGZz31F76m+QjKf+4reU32FZD73Fb2n+grJfO4rek/1FZL53Ff0nuorJPO5r+g91VdI5nNf0Xuqr5DM576i91RfIZnOfdXoPdVXSKZzXzV6T/UVkuncV70Zn2Q691Wj91RfIZnOfdXoPdVXSOZzX9F7qq+QzOe+ovdUXyGZz31F76m+QjKf+4reU32FZD73Fb2n+grJfO4rek/1FZL53Ff0nuorJPO5r+g91VdI5nNf0Xuqr5DM5752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d/IJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xhd8j9cF3+N1wfd4XfA9XtcD/Z18wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j5fB93gZfI+Xwfd4GXyPlz3Q38kG3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G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XQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpO10Pf6XroO10Pfafroe8Po1PM5rk6XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dD3TB3lo52vL25//85vehO9jaf0JnpOj95fXzzaJ72JntJTehM9o6f0JnpCT+lNlIln9GZqrJ7Sm+n9O6M30/t3Rm+iLDyl18j0kvmrTC3VU3ph/dWbBljP9KYhtg+62tc/JRsPl2QevEd6heLYXmiF4thuaIXi2H5ohWKjUxzbE61QHNsVrVAc2xetUBzbRa1QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUMzmuUbwHukVitk81wjeI71CMZvnGg+jU8zmuUbwHukVitk81wjeI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4j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/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvt0x916Odry9u1ye9id5HM3oz9SGP3l9fPNonvYmeV1N6Ez2vpvQamd5EeXBKb6I8OKU30/t3Rm+m9++M3kR5cEZvpj7kKb1k/ipTH/KUXlh/9abBEmiI7YPaOV4a+tl+yuWPUV+f+jjePnUt74pjO6EVimN7oRWKY7uhFYpj+6EFioM3GK9QHNsTrVAc2xWtUBzbF61QbHSK6TxX8DbjFYrpPFfwRuMViuk8V/BW4xWK6TxX8GbjFYrpPFfwduMViuk8V/CG4xWK6TxX8JbjFYrZPFcJ3nS8QjGb5yrB245XKGbzXOVhdIrZPFcJ3nq8QjGb5yrBm49XKKbzXMHbj1copvNcwRuQVyim81zBW5BXKKbzXMGbkFcopvNcwduQVyim81zBG5FXKKbzXMFbkVcopvNcwZuRVyim81zB25FXKKbzXMEbklcopvNcwVuSVyim81zBm5JXKKbzXMHbklcopvNcwRuTVyim81zBW5NXKKbzXMGbk1copvNcwduTVyim81zBG5RXKKbzXMFblFcopvNcwZuUVyim81zB25RXKKbzXMEblVcopvNcxegU03muQue5gneFr1BM57kKneeqdJ4reCf8CsV0nit4L/wKxUanmM5zBW+HX6GYznMFb4hfoZjOcwVviV+hmM5zBW+KX6GYznMFb5ZfoZjOc9H10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtL10Fe6HvpK10Nf6Xro68PoFLN5rkrXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10Pfc3UUf786tcXt79/5ze9id7GM3ozdVeP3l9fPNonvYme0lN6Ez2jp/QmekJP6U2Uiaf0JkrEU3ozvX9n9GZ6/87oTZSFZ/Rmaqqe0kvmrzK1VE/phfVXbxosgYbYPqiX9vVPqdSfkrmdX8ncrvL91W28K47thFYoju2FViiO7YZWKI7thxYoDt4jvUJxbE+0QnFsV7RCcWxftEKx0Smm81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKGbzXC14j/QKxWyeqwXvkV6hmM1ztYfRKWbzXC14j/QKxWyeqwXvkV6hmM5zBe+RXqGYznMF75FeoZjOcwXvkV6hmM5zBe+RXqGYznMF75FeoZjOcwXvkV6hmM5zBe+RXqGYznMF75FeoZjOc510nit4V/gKxXSe66TzXBed5wreCb9CMZ3nCt4Lv0Kx0Smm81zB2+FXKKbzXMEb4lcopvNcwVviVyim81zBm+JXKKbzXMGb5VcopvNcdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroO10Pfafroe90PfSdroe+P4xOMZvn6nQ99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3zN1lI92vr64/f07v+lN9Dae0pvoOT16//ri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pRtL5R4/lso9fiyVe/xYKvf4sVTu8WLZo19phWKp3OPHUrnHj6Vyjx9LI2b5i09il70WRXaVt03Ro77TZE4+/jSZs48/Teb040+TOf/402ROQO40o19sBaPJnIJ+RbM/vmj28Ykmcw7yp8mchPxpmmg60lQW8qSpLORJU1nIk6ay0O9pjvqJprKQI83oV1zBaCoLzdG04ytZ2vkpWUa/5ApGU1nIk6aJpiNNZSFPmspCnjSVhTxpKgtN0izXF816fqKpLORIM9ct4+00lYU8aSoLedJUFvKkaaLpSFNZ6P+5aTPpzJemp/gor9zzUQK556NMccuH+dL0FB/5/ns+qZz8xO3xnuvG85Rio1OcyrVOKU7lQ6cUp3KWU4pTecUpxanc34ziXNd2pxSncmhTiuk8V677slOKjU4xnefKdVF1SjGd58p1nXRKMZ3nynXpc0oxnefKdTVzSjGd58p1gXJKMZ3nynXNcUoxnefKdRlxSjGd58p1ZXBKMZ3nynWxb0oxnefKdf1uSjGd58p1SW5KMZ3nanSeq9F5rk7nuXLdGpxSTOe5Op3n6kanmM5z5bqgOKWYznPlukY4pZjOc+W67DelmM5z5bqSN6WYznPlujg3pZjOc+W63jalmM5z5bqENqWYzXONXFfFphSzea6R60LXlGI2zzUeRqeYzXONXFejphSzea6R6/rSlGI6z5XritGUYjrPlesa0JRiOs+V66rOlGI6z5XrOs2UYjrPlevKy5RiOs+V61rKlGI6z5Xr6siUYjrPlet6x5RiOs+V6wrGlGI6z5XrmsSUYjrPlesqw5RiOs+V67rBlGI6z5XrSsCUYjrPlaubf0oxnefK1Z8/pZjOc+XquJ9STOe56HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HfuTqKH9+7u8vP8cP37318fVJzh++ttj519cWuz6wzNV+vpllKg+xmWUqd7KZZSrfs5mliaUby1RebTPLVC5wM8tUO73NLFNtCzezVO5xYtkf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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}}],"kind":"struct","path":"MultiCallEntrypoint::entrypoint_parameters"}}],"kind":"struct","path":"MultiCallEntrypoint::entrypoint_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"382":{"path":"/usr/src/noir-projects/noir-contracts/contracts/multi_call_entrypoint_contract/src/main.nr","source":"// An entrypoint contract that allows everything to go through. Only used for testing\n// Pair this with SignerlessWallet to perform multiple actions before any account contracts are deployed (and without authentication)\ncontract MultiCallEntrypoint {\n use dep::std;\n\n use dep::aztec::prelude::AztecAddress;\n use dep::authwit::entrypoint::app::AppPayload;\n\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload) {\n app_payload.execute_calls(&mut context);\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/auth-registry/artifact.ts b/yarn-project/protocol-contracts/src/auth-registry/artifact.ts index d33c2a9820f3..030414f5d45d 100644 --- a/yarn-project/protocol-contracts/src/auth-registry/artifact.ts +++ b/yarn-project/protocol-contracts/src/auth-registry/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import AuthRegistryJson from '../artifacts/AuthRegistry.json' assert { type: 'json' }; +import AuthRegistryJson from '../../artifacts/AuthRegistry.json' assert { type: 'json' }; export const AuthRegistryArtifact = loadContractArtifact(AuthRegistryJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/class-registerer/artifact.ts b/yarn-project/protocol-contracts/src/class-registerer/artifact.ts index 433bf7b269cc..9f1f360b4c56 100644 --- a/yarn-project/protocol-contracts/src/class-registerer/artifact.ts +++ b/yarn-project/protocol-contracts/src/class-registerer/artifact.ts @@ -1,7 +1,7 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import ContractClassRegistererJson from '../artifacts/ContractClassRegisterer.json' assert { type: 'json' }; +import ContractClassRegistererJson from '../../artifacts/ContractClassRegisterer.json' assert { type: 'json' }; export const ContractClassRegistererArtifact = loadContractArtifact( ContractClassRegistererJson as NoirCompiledContract, diff --git a/yarn-project/protocol-contracts/src/gas-token/artifact.ts b/yarn-project/protocol-contracts/src/gas-token/artifact.ts index 0dbaf8c2d747..9d83dd2d21bf 100644 --- a/yarn-project/protocol-contracts/src/gas-token/artifact.ts +++ b/yarn-project/protocol-contracts/src/gas-token/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import GasTokenJson from '../artifacts/GasToken.json' assert { type: 'json' }; +import GasTokenJson from '../../artifacts/GasToken.json' assert { type: 'json' }; export const GasTokenArtifact = loadContractArtifact(GasTokenJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts b/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts index 809e35873ace..03dffc514626 100644 --- a/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts +++ b/yarn-project/protocol-contracts/src/instance-deployer/artifact.ts @@ -1,7 +1,7 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import ContractInstanceDeployerJson from '../artifacts/ContractInstanceDeployer.json' assert { type: 'json' }; +import ContractInstanceDeployerJson from '../../artifacts/ContractInstanceDeployer.json' assert { type: 'json' }; export const ContractInstanceDeployerArtifact = loadContractArtifact( ContractInstanceDeployerJson as NoirCompiledContract, diff --git a/yarn-project/protocol-contracts/src/key-registry/artifact.ts b/yarn-project/protocol-contracts/src/key-registry/artifact.ts index 89436d313e63..5feb280a6240 100644 --- a/yarn-project/protocol-contracts/src/key-registry/artifact.ts +++ b/yarn-project/protocol-contracts/src/key-registry/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import KeyRegistryJson from '../artifacts/KeyRegistry.json' assert { type: 'json' }; +import KeyRegistryJson from '../../artifacts/KeyRegistry.json' assert { type: 'json' }; export const KeyRegistryArtifact = loadContractArtifact(KeyRegistryJson as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts b/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts index b3cf23f9f41e..9f259a2d8247 100644 --- a/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts +++ b/yarn-project/protocol-contracts/src/multi-call-entrypoint/artifact.ts @@ -1,6 +1,6 @@ import { loadContractArtifact } from '@aztec/types/abi'; import { type NoirCompiledContract } from '@aztec/types/noir'; -import MultiCallEntrypoint from '../artifacts/MultiCallEntrypoint.json' assert { type: 'json' }; +import MultiCallEntrypoint from '../../artifacts/MultiCallEntrypoint.json' assert { type: 'json' }; export const MultiCallEntrypointArtifact = loadContractArtifact(MultiCallEntrypoint as NoirCompiledContract); diff --git a/yarn-project/protocol-contracts/tsconfig.json b/yarn-project/protocol-contracts/tsconfig.json index 01c876235ce3..96ab4e32557f 100644 --- a/yarn-project/protocol-contracts/tsconfig.json +++ b/yarn-project/protocol-contracts/tsconfig.json @@ -16,5 +16,5 @@ "path": "../types" } ], - "include": ["src", "src/**/*.json"] + "include": ["src", "artifacts/*.d.json.ts"] } diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index 81a1aff8a141..09934382c597 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -12,9 +12,9 @@ import { GasFees, GlobalVariables, KernelCircuitPublicInputs, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, @@ -96,7 +96,7 @@ export async function getSimulationProvider( } export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, seed = 0x1) => { - seed *= MAX_NEW_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds + seed *= MAX_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds const tx = mockTx(seed); const kernelOutput = KernelCircuitPublicInputs.empty(); kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader(); @@ -113,12 +113,12 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se const processedTx = makeProcessedTx(tx, kernelOutput, makeProof(), []); - processedTx.data.end.newNoteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, fr, seed + 0x100); - processedTx.data.end.newNullifiers = makeTuple(MAX_NEW_NULLIFIERS_PER_TX, fr, seed + 0x100000); + processedTx.data.end.noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, fr, seed + 0x100); + processedTx.data.end.nullifiers = makeTuple(MAX_NULLIFIERS_PER_TX, fr, seed + 0x100000); - processedTx.data.end.newNullifiers[tx.data.forPublic!.end.newNullifiers.length - 1] = Fr.zero(); + processedTx.data.end.nullifiers[tx.data.forPublic!.end.nullifiers.length - 1] = Fr.zero(); - processedTx.data.end.newL2ToL1Msgs = makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); + processedTx.data.end.l2ToL1Msgs = makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x300); processedTx.data.end.noteEncryptedLogsHash = Fr.fromBuffer(processedTx.noteEncryptedLogs.hash()); processedTx.data.end.encryptedLogsHash = Fr.fromBuffer(processedTx.encryptedLogs.hash()); processedTx.data.end.unencryptedLogsHash = Fr.fromBuffer(processedTx.unencryptedLogs.hash()); @@ -137,9 +137,9 @@ export const updateExpectedTreesFromTxs = async (db: MerkleTreeOperations, txs: MerkleTreeId.NOTE_HASH_TREE, txs.flatMap(tx => padArrayEnd( - tx.data.end.newNoteHashes.filter(x => !x.isZero()), + tx.data.end.noteHashes.filter(x => !x.isZero()), Fr.zero(), - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_TX, ), ), ); @@ -147,9 +147,9 @@ export const updateExpectedTreesFromTxs = async (db: MerkleTreeOperations, txs: MerkleTreeId.NULLIFIER_TREE, txs.flatMap(tx => padArrayEnd( - tx.data.end.newNullifiers.filter(x => !x.isZero()), + tx.data.end.nullifiers.filter(x => !x.isZero()), Fr.zero(), - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, ).map(x => x.toBuffer()), ), NULLIFIER_TREE_HEIGHT, diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 507068e36ae5..1573ba7f68da 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -21,7 +21,7 @@ import { type DebugLogger } from '@aztec/foundation/log'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type ContractsDataSourcePublicDB, - type PublicExecution, + type PublicExecutionRequest, type PublicExecutionResult, PublicExecutionResultBuilder, type PublicExecutor, @@ -164,7 +164,7 @@ export class TestContext { txValidator?: TxValidator, ) { const defaultExecutorImplementation = ( - execution: PublicExecution, + execution: PublicExecutionRequest, _globalVariables: GlobalVariables, availableGas: Gas, _txContext: TxContext, @@ -204,7 +204,7 @@ export class TestContext { blockProver?: BlockProver, txValidator?: TxValidator, executorMock?: ( - execution: PublicExecution, + execution: PublicExecutionRequest, globalVariables: GlobalVariables, availableGas: Gas, txContext: TxContext, diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index c09ca0af3887..64e68f7a2715 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -9,7 +9,7 @@ import { type GlobalVariables, KernelData, type L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, MergeRollupInputs, @@ -102,8 +102,8 @@ export async function buildBaseRollupInput( // Update the note hash trees with the new items being inserted to get the new roots // that will be used by the next iteration of the base rollup circuit, skipping the empty ones - const newNoteHashes = tx.data.end.newNoteHashes; - await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, newNoteHashes); + const noteHashes = tx.data.end.noteHashes; + await db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashes); // The read witnesses for a given TX should be generated before the writes of the same TX are applied. // All reads that refer to writes in the same tx are transient and can be simplified out. @@ -112,12 +112,12 @@ export async function buildBaseRollupInput( // Update the nullifier tree, capturing the low nullifier info for each individual operation const { lowLeavesWitnessData: nullifierWitnessLeaves, - newSubtreeSiblingPath: newNullifiersSubtreeSiblingPath, - sortedNewLeaves: sortedNewNullifiers, + newSubtreeSiblingPath: nullifiersSubtreeSiblingPath, + sortedNewLeaves: sortednullifiers, sortedNewLeavesIndexes, } = await db.batchInsert( MerkleTreeId.NULLIFIER_TREE, - tx.data.end.newNullifiers.map(n => n.toBuffer()), + tx.data.end.nullifiers.map(n => n.toBuffer()), NULLIFIER_SUBTREE_HEIGHT, ); if (nullifierWitnessLeaves === undefined) { @@ -130,7 +130,7 @@ export async function buildBaseRollupInput( MembershipWitness.fromBufferArray(l.index, assertLength(l.siblingPath.toBufferArray(), NULLIFIER_TREE_HEIGHT)), ); - const nullifierSubtreeSiblingPathArray = newNullifiersSubtreeSiblingPath.toFields(); + const nullifierSubtreeSiblingPathArray = nullifiersSubtreeSiblingPath.toFields(); const nullifierSubtreeSiblingPath = makeTuple(NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, i => i < nullifierSubtreeSiblingPathArray.length ? nullifierSubtreeSiblingPathArray[i] : Fr.ZERO, @@ -139,18 +139,18 @@ export async function buildBaseRollupInput( const publicDataSiblingPath = txPublicDataUpdateRequestInfo.newPublicDataSubtreeSiblingPath; const stateDiffHints = StateDiffHints.from({ - nullifierPredecessorPreimages: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => + nullifierPredecessorPreimages: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierWitnessLeaves.length ? (nullifierWitnessLeaves[i].leafPreimage as NullifierLeafPreimage) : NullifierLeafPreimage.empty(), ), - nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => + nullifierPredecessorMembershipWitnesses: makeTuple(MAX_NULLIFIERS_PER_TX, i => i < nullifierPredecessorMembershipWitnessesWithoutPadding.length ? nullifierPredecessorMembershipWitnessesWithoutPadding[i] : makeEmptyMembershipWitness(NULLIFIER_TREE_HEIGHT), ), - sortedNullifiers: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortedNewNullifiers[i])), - sortedNullifierIndexes: makeTuple(MAX_NEW_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]), + sortedNullifiers: makeTuple(MAX_NULLIFIERS_PER_TX, i => Fr.fromBuffer(sortednullifiers[i])), + sortedNullifierIndexes: makeTuple(MAX_NULLIFIERS_PER_TX, i => sortedNewLeavesIndexes[i]), noteHashSubtreeSiblingPath, nullifierSubtreeSiblingPath, publicDataSiblingPath, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index c6159039a723..1f68ce4c4ef7 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -135,10 +135,8 @@ export class ProvingOrchestrator { this.initialHeader = await this.db.buildInitialHeader(); } - // Check that the length of the array of txs is a power of two - // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 - if (!Number.isInteger(numTxs) || numTxs < 2 || (numTxs & (numTxs - 1)) !== 0) { - throw new Error(`Length of txs for the block should be a power of two and at least two (got ${numTxs})`); + if (!Number.isInteger(numTxs) || numTxs < 2) { + throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`); } // Cancel any currently proving block before starting a new one this.cancelBlock(); @@ -225,12 +223,17 @@ export class ProvingOrchestrator { logger.info(`Received transaction: ${tx.hash}`); + if (tx.isEmpty) { + logger.warn(`Ignoring empty transaction ${tx.hash} - it will not be added to this block`); + return; + } + const [inputs, treeSnapshots] = await this.prepareTransaction(tx, this.provingState); this.enqueueFirstProof(inputs, treeSnapshots, tx, this.provingState); } /** - * Marks the block as full and pads it to the full power of 2 block size, no more transactions will be accepted. + * Marks the block as full and pads it if required, no more transactions will be accepted. */ @trackSpan('ProvingOrchestrator.setBlockCompleted', function () { if (!this.provingState) { @@ -252,10 +255,15 @@ export class ProvingOrchestrator { const paddingTxCount = this.provingState.totalNumTxs - this.provingState.transactionsReceived; if (paddingTxCount === 0) { return; + } else if (this.provingState.totalNumTxs > 2) { + throw new Error(`Block not ready for completion: expecting ${paddingTxCount} more transactions.`); } logger.debug(`Padding rollup with ${paddingTxCount} empty transactions`); // Make an empty padding transaction + // Required for: + // 0 (when we want an empty block, largely for testing), or + // 1 (we need to pad with one tx as all rollup circuits require a pair of inputs) txs // Insert it into the tree the required number of times to get all of the // base rollup inputs // Then enqueue the proving of all the transactions @@ -579,13 +587,18 @@ export class ProvingOrchestrator { VerificationKeyAsFields, ], ) { - const mergeLevel = currentLevel - 1n; - const indexWithinMergeLevel = currentIndex >> 1n; + const [mergeLevel, indexWithinMergeLevel, indexWithinMerge] = provingState.findMergeLevel( + currentLevel, + currentIndex, + ); const mergeIndex = 2n ** mergeLevel - 1n + indexWithinMergeLevel; - const subscript = Number(mergeIndex); - const indexWithinMerge = Number(currentIndex & 1n); - const ready = provingState.storeMergeInputs(mergeInputs, indexWithinMerge, subscript); - return { ready, indexWithinMergeLevel, mergeLevel, mergeInputData: provingState.getMergeInputs(subscript) }; + const ready = provingState.storeMergeInputs(mergeInputs, Number(indexWithinMerge), Number(mergeIndex)); + return { + ready, + indexWithinMergeLevel, + mergeLevel, + mergeInputData: provingState.getMergeInputs(Number(mergeIndex)), + }; } // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index 01e9ee52eb41..e4ae1e55a4a6 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -70,6 +70,13 @@ describe('prover/orchestrator/errors', () => { ); }); + it('throws if setting an incomplete block completed', async () => { + await context.orchestrator.startNewBlock(3, context.globalVariables, [], getMockVerificationKeys()); + await expect(async () => await context.orchestrator.setBlockCompleted()).rejects.toThrow( + `Block not ready for completion: expecting ${3} more transactions.`, + ); + }); + it('throws if finalising an already finalised block', async () => { const txs = await Promise.all([ makeEmptyProcessedTestTx(context.actualDb), @@ -80,13 +87,10 @@ describe('prover/orchestrator/errors', () => { txs.length, context.globalVariables, [], - getMockVerificationKeys(), ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); @@ -111,7 +115,7 @@ describe('prover/orchestrator/errors', () => { ).rejects.toThrow('Rollup not accepting further transactions'); }); - it.each([[-4], [0], [1], [3], [8.1], [7]] as const)( + it.each([[-4], [0], [1], [8.1]] as const)( 'fails to start a block with %i transactions', async (blockSize: number) => { await expect( @@ -123,7 +127,7 @@ describe('prover/orchestrator/errors', () => { getMockVerificationKeys(), ), - ).rejects.toThrow(`Length of txs for the block should be a power of two and at least two (got ${blockSize})`); + ).rejects.toThrow(`Length of txs for the block should be at least two (got ${blockSize})`); }, ); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index d53cb3aff117..6e31aebd6889 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -7,7 +7,7 @@ import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js'; -import { makeEmptyProcessedTestTx } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; import { ProvingOrchestrator } from './orchestrator.js'; @@ -67,10 +67,9 @@ describe('prover/orchestrator/failures', () => { ] as const)('handles a %s error', async (message: string, fn: () => void) => { fn(); const txs = await Promise.all([ - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), + makeBloatedProcessedTx(context.actualDb, 1), + makeBloatedProcessedTx(context.actualDb, 2), + makeBloatedProcessedTx(context.actualDb, 3), ]); const blockTicket = await orchestrator.startNewBlock( diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index 7cd3a337b8f2..5c686a472a50 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -30,9 +30,8 @@ describe('prover/orchestrator/mixed-blocks', () => { const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - // this needs to be a 4 tx block that will need to be completed const blockTicket = await context.orchestrator.startNewBlock( - 4, + 3, context.globalVariables, l1ToL2Messages, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts index c9f8b930df2f..3000e3490858 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts @@ -7,7 +7,7 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-mixed-blocks-2'); @@ -26,51 +26,37 @@ describe('prover/orchestrator/mixed-blocks', () => { }); describe('blocks', () => { - it.each([ - [0, 2], - [1, 2], - [4, 4], - [5, 8], - ] as const)( - 'builds an L2 block with %i bloated txs and %i txs total', - async (bloatedCount: number, totalCount: number) => { - const noteHashTreeBefore = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); - const txs = [ - ...(await Promise.all(times(bloatedCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), - ...(await Promise.all(times(totalCount - bloatedCount, _ => makeEmptyProcessedTestTx(context.actualDb)))), - ]; + it.each([2, 4, 5, 8] as const)('builds an L2 block with %i bloated txs', async (totalCount: number) => { + const txs = [ + ...(await Promise.all(times(totalCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), + ]; - const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); + const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const blockTicket = await context.orchestrator.startNewBlock( - txs.length, - context.globalVariables, - l1ToL2Messages, + const blockTicket = await context.orchestrator.startNewBlock( + txs.length, + context.globalVariables, + l1ToL2Messages, - getMockVerificationKeys(), - ); + getMockVerificationKeys(), + ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + for (const tx of txs) { + await context.orchestrator.addNewTx(tx); + } - const result = await blockTicket.provingPromise; - expect(result.status).toBe(PROVING_STATUS.SUCCESS); + const result = await blockTicket.provingPromise; + expect(result.status).toBe(PROVING_STATUS.SUCCESS); - const finalisedBlock = await context.orchestrator.finaliseBlock(); + const finalisedBlock = await context.orchestrator.finaliseBlock(); - expect(finalisedBlock.block.number).toEqual(context.blockNumber); + expect(finalisedBlock.block.number).toEqual(context.blockNumber); - await updateExpectedTreesFromTxs(expectsDb, txs); - const noteHashTreeAfter = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); + await updateExpectedTreesFromTxs(expectsDb, txs); + const noteHashTreeAfter = await context.actualDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE); - if (bloatedCount > 0) { - expect(noteHashTreeAfter.root).not.toEqual(noteHashTreeBefore.root); - } - - const expectedNoteHashTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE).then(t => t.root); - expect(noteHashTreeAfter.root).toEqual(expectedNoteHashTreeAfter); - }, - ); + const expectedNoteHashTreeAfter = await expectsDb.getTreeInfo(MerkleTreeId.NOTE_HASH_TREE).then(t => t.root); + expect(noteHashTreeAfter.root).toEqual(expectedNoteHashTreeAfter); + }); }); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index 808aa3dae8d6..635d1dec429a 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -7,7 +7,7 @@ import { sleep } from '@aztec/foundation/sleep'; import { openTmpStore } from '@aztec/kv-store/utils'; import { type MerkleTreeOperations, MerkleTrees } from '@aztec/world-state'; -import { makeBloatedProcessedTx, makeEmptyProcessedTestTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; +import { makeBloatedProcessedTx, updateExpectedTreesFromTxs } from '../mocks/fixtures.js'; import { TestContext } from '../mocks/test_context.js'; const logger = createDebugLogger('aztec:orchestrator-single-blocks'); @@ -27,21 +27,14 @@ describe('prover/orchestrator/blocks', () => { describe('blocks', () => { it('builds an empty L2 block', async () => { - const txs = await Promise.all([ - makeEmptyProcessedTestTx(context.actualDb), - makeEmptyProcessedTestTx(context.actualDb), - ]); - const blockTicket = await context.orchestrator.startNewBlock( - txs.length, + 2, context.globalVariables, [], getMockVerificationKeys(), ); - for (const tx of txs) { - await context.orchestrator.addNewTx(tx); - } + await context.orchestrator.setBlockCompleted(); const result = await blockTicket.provingPromise; expect(result.status).toBe(PROVING_STATUS.SUCCESS); diff --git a/yarn-project/prover-client/src/orchestrator/proving-state.ts b/yarn-project/prover-client/src/orchestrator/proving-state.ts index d2b92000f613..51004578237c 100644 --- a/yarn-project/prover-client/src/orchestrator/proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/proving-state.ts @@ -71,6 +71,32 @@ export class ProvingState { return BigInt(Math.ceil(Math.log2(this.totalNumTxs)) - 1); } + // Calculates the index and level of the parent rollup circuit + // Based on tree implementation in unbalanced_tree.ts -> batchInsert() + public findMergeLevel(currentLevel: bigint, currentIndex: bigint) { + const moveUpMergeLevel = (levelSize: number, index: bigint, nodeToShift: boolean) => { + levelSize /= 2; + if (levelSize & 1) { + [levelSize, nodeToShift] = nodeToShift ? [levelSize + 1, false] : [levelSize - 1, true]; + } + index >>= 1n; + return { thisLevelSize: levelSize, thisIndex: index, shiftUp: nodeToShift }; + }; + let [thisLevelSize, shiftUp] = this.totalNumTxs & 1 ? [this.totalNumTxs - 1, true] : [this.totalNumTxs, false]; + const maxLevel = this.numMergeLevels + 1n; + let placeholder = currentIndex; + for (let i = 0; i < maxLevel - currentLevel; i++) { + ({ thisLevelSize, thisIndex: placeholder, shiftUp } = moveUpMergeLevel(thisLevelSize, placeholder, shiftUp)); + } + let thisIndex = currentIndex; + let mergeLevel = currentLevel; + while (thisIndex >= thisLevelSize && mergeLevel != 0n) { + mergeLevel -= 1n; + ({ thisLevelSize, thisIndex, shiftUp } = moveUpMergeLevel(thisLevelSize, thisIndex, shiftUp)); + } + return [mergeLevel - 1n, thisIndex >> 1n, thisIndex & 1n]; + } + // Adds a transaction to the proving state, returns it's index // Will update the proving life cycle if this is the last transaction public addNewTx(tx: TxProvingState) { diff --git a/yarn-project/pxe/src/database/deferred_note_dao.test.ts b/yarn-project/pxe/src/database/deferred_note_dao.test.ts index efe57f5a6819..542774a11650 100644 --- a/yarn-project/pxe/src/database/deferred_note_dao.test.ts +++ b/yarn-project/pxe/src/database/deferred_note_dao.test.ts @@ -12,7 +12,7 @@ export const randomDeferredNoteDao = ({ txHash = randomTxHash(), storageSlot = Fr.random(), noteTypeId = NoteSelector.random(), - newNoteHashes = [Fr.random(), Fr.random()], + noteHashes = [Fr.random(), Fr.random()], dataStartIndexForTx = randomInt(100), }: Partial = {}) => { return new DeferredNoteDao( @@ -22,7 +22,7 @@ export const randomDeferredNoteDao = ({ storageSlot, noteTypeId, txHash, - newNoteHashes, + noteHashes, dataStartIndexForTx, ); }; diff --git a/yarn-project/pxe/src/database/deferred_note_dao.ts b/yarn-project/pxe/src/database/deferred_note_dao.ts index d1d0c551209e..bc5cfd455ba2 100644 --- a/yarn-project/pxe/src/database/deferred_note_dao.ts +++ b/yarn-project/pxe/src/database/deferred_note_dao.ts @@ -23,7 +23,7 @@ export class DeferredNoteDao { /** The hash of the tx the note was created in. Equal to the first nullifier */ public txHash: TxHash, /** New note hashes in this transaction, one of which belongs to this note */ - public newNoteHashes: Fr[], + public noteHashes: Fr[], /** The next available leaf index for the note hash tree for this transaction */ public dataStartIndexForTx: number, ) {} @@ -36,7 +36,7 @@ export class DeferredNoteDao { this.storageSlot, this.noteTypeId, this.txHash, - new Vector(this.newNoteHashes), + new Vector(this.noteHashes), this.dataStartIndexForTx, ); } diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts index e60353cd405f..2fce75e6581e 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.test.ts @@ -2,8 +2,8 @@ import { Note, type ProofCreator } from '@aztec/circuit-types'; import { FunctionData, FunctionSelector, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_CALL, + MAX_NOTE_HASHES_PER_TX, MembershipWitness, NESTED_RECURSIVE_PROOF_LENGTH, NoteHash, @@ -56,8 +56,8 @@ describe('Kernel Prover', () => { const createExecutionResult = (fnName: string, newNoteIndices: number[] = []): ExecutionResult => { const publicInputs = PrivateCircuitPublicInputs.empty(); - publicInputs.newNoteHashes = makeTuple( - MAX_NEW_NOTE_HASHES_PER_CALL, + publicInputs.noteHashes = makeTuple( + MAX_NOTE_HASHES_PER_CALL, i => i < newNoteIndices.length ? new NoteHash(generateFakeCommitment(notesAndSlots[newNoteIndices[i]]), 0) @@ -86,7 +86,7 @@ describe('Kernel Prover', () => { const createProofOutput = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelCircuitPublicInputs.empty(); - const noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, ScopedNoteHash.empty); + const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash.empty); for (let i = 0; i < newNoteIndices.length; i++) { noteHashes[i] = new NoteHash(generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]), 0).scope( 0, @@ -94,7 +94,7 @@ describe('Kernel Prover', () => { ); } - publicInputs.end.newNoteHashes = noteHashes; + publicInputs.end.noteHashes = noteHashes; return { publicInputs, proof: makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), @@ -104,11 +104,11 @@ describe('Kernel Prover', () => { const createProofOutputFinal = (newNoteIndices: number[]) => { const publicInputs = PrivateKernelTailCircuitPublicInputs.empty(); - const noteHashes = makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, () => Fr.ZERO); + const noteHashes = makeTuple(MAX_NOTE_HASHES_PER_TX, () => Fr.ZERO); for (let i = 0; i < newNoteIndices.length; i++) { noteHashes[i] = generateFakeSiloedCommitment(notesAndSlots[newNoteIndices[i]]); } - publicInputs.forRollup!.end.newNoteHashes = noteHashes; + publicInputs.forRollup!.end.noteHashes = noteHashes; return { publicInputs, @@ -161,7 +161,7 @@ describe('Kernel Prover', () => { proofCreator = mock(); proofCreator.getSiloedCommitments.mockImplementation(publicInputs => - Promise.resolve(publicInputs.newNoteHashes.map(com => createFakeSiloedCommitment(com.value))), + Promise.resolve(publicInputs.noteHashes.map(com => createFakeSiloedCommitment(com.value))), ); proofCreator.createProofInit.mockResolvedValue(createProofOutput([])); proofCreator.createProofInner.mockResolvedValue(createProofOutput([])); diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 068d2ba12f8e..c3d85a5d5245 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -3,10 +3,10 @@ import { CallRequest, Fr, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, NESTED_RECURSIVE_PROOF_LENGTH, @@ -35,7 +35,6 @@ import { buildPrivateKernelInitHints, buildPrivateKernelInnerHints, buildPrivateKernelResetInputs, - buildPrivateKernelTailHints, } from './private_inputs_builders/index.js'; import { type ProvingDataOracle } from './proving_data_oracle.js'; @@ -111,7 +110,6 @@ export class KernelProver { const hints = buildPrivateKernelInitHints( currentExecution.callStackItem.publicInputs, noteHashNullifierCounterMap, - currentExecution.callStackItem.publicInputs.privateCallRequests, ); const proofInput = new PrivateKernelInitCircuitPrivateInputs(txRequest, privateCallData, hints); pushTestData('private-kernel-inputs-init', proofInput); @@ -152,9 +150,7 @@ export class KernelProver { `Calling private kernel tail with hwm ${previousKernelData.publicInputs.minRevertibleSideEffectCounter}`, ); - const hints = buildPrivateKernelTailHints(output.publicInputs); - - const privateInputs = new PrivateKernelTailCircuitPrivateInputs(previousKernelData, hints); + const privateInputs = new PrivateKernelTailCircuitPrivateInputs(previousKernelData); pushTestData('private-kernel-inputs-ordering', privateInputs); return await this.proofCreator.createProofTail(privateInputs); @@ -163,12 +159,12 @@ export class KernelProver { private needsReset(executionStack: ExecutionResult[], output: KernelProofOutput) { const nextIteration = executionStack[executionStack.length - 1]; return ( - getNonEmptyItems(nextIteration.callStackItem.publicInputs.newNoteHashes).length + - getNonEmptyItems(output.publicInputs.end.newNoteHashes).length > - MAX_NEW_NOTE_HASHES_PER_TX || - getNonEmptyItems(nextIteration.callStackItem.publicInputs.newNullifiers).length + - getNonEmptyItems(output.publicInputs.end.newNullifiers).length > - MAX_NEW_NULLIFIERS_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteHashes).length + + getNonEmptyItems(output.publicInputs.end.noteHashes).length > + MAX_NOTE_HASHES_PER_TX || + getNonEmptyItems(nextIteration.callStackItem.publicInputs.nullifiers).length + + getNonEmptyItems(output.publicInputs.end.nullifiers).length > + MAX_NULLIFIERS_PER_TX || getNonEmptyItems(nextIteration.callStackItem.publicInputs.noteEncryptedLogsHashes).length + getNonEmptyItems(output.publicInputs.end.noteEncryptedLogsHashes).length > MAX_NOTE_ENCRYPTED_LOGS_PER_TX || @@ -189,8 +185,8 @@ export class KernelProver { getNonEmptyItems(output.publicInputs.validationRequests.noteHashReadRequests).length > 0 || getNonEmptyItems(output.publicInputs.validationRequests.nullifierReadRequests).length > 0 || getNonEmptyItems(output.publicInputs.validationRequests.scopedKeyValidationRequestsAndGenerators).length > 0 || - output.publicInputs.end.newNoteHashes.find(noteHash => noteHash.nullifierCounter !== 0) || - output.publicInputs.end.newNullifiers.find(nullifier => !nullifier.nullifiedNoteHash.equals(Fr.zero())) + output.publicInputs.end.noteHashes.find(noteHash => noteHash.nullifierCounter !== 0) || + output.publicInputs.end.nullifiers.find(nullifier => !nullifier.nullifiedNoteHash.equals(Fr.zero())) ); } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_init_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_init_hints.ts index b81c952d0232..833a7d252fff 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_init_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_init_hints.ts @@ -1,28 +1,18 @@ import { - type MAX_NEW_NOTE_HASHES_PER_CALL, - type PrivateCallRequest, + type MAX_NOTE_HASHES_PER_CALL, type PrivateCircuitPublicInputs, PrivateKernelInitHints, - countAccumulatedItems, } from '@aztec/circuits.js'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelInitHints( publicInputs: PrivateCircuitPublicInputs, noteHashNullifierCounterMap: Map, - privateCallRequests: PrivateCallRequest[], ) { - const nullifierCounters = publicInputs.newNoteHashes.map( - n => noteHashNullifierCounterMap.get(n.counter) ?? 0, - ) as Tuple; + const nullifierCounters = publicInputs.noteHashes.map(n => noteHashNullifierCounterMap.get(n.counter) ?? 0) as Tuple< + number, + typeof MAX_NOTE_HASHES_PER_CALL + >; - const minRevertibleCounter = publicInputs.minRevertibleSideEffectCounter.toNumber(); - let firstRevertiblePrivateCallRequestIndex = privateCallRequests.findIndex( - r => r.startSideEffectCounter >= minRevertibleCounter, - ); - if (firstRevertiblePrivateCallRequestIndex === -1) { - firstRevertiblePrivateCallRequestIndex = countAccumulatedItems(privateCallRequests); - } - - return new PrivateKernelInitHints(nullifierCounters, firstRevertiblePrivateCallRequestIndex); + return new PrivateKernelInitHints(nullifierCounters); } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.ts index a03ac365947f..3eacc5d07192 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_inner_hints.ts @@ -1,5 +1,5 @@ import { - type MAX_NEW_NOTE_HASHES_PER_CALL, + type MAX_NOTE_HASHES_PER_CALL, type PrivateCircuitPublicInputs, PrivateKernelInnerHints, } from '@aztec/circuits.js'; @@ -9,9 +9,10 @@ export function buildPrivateKernelInnerHints( publicInputs: PrivateCircuitPublicInputs, noteHashNullifierCounterMap: Map, ) { - const nullifierCounters = publicInputs.newNoteHashes.map( - n => noteHashNullifierCounterMap.get(n.counter) ?? 0, - ) as Tuple; + const nullifierCounters = publicInputs.noteHashes.map(n => noteHashNullifierCounterMap.get(n.counter) ?? 0) as Tuple< + number, + typeof MAX_NOTE_HASHES_PER_CALL + >; return new PrivateKernelInnerHints(nullifierCounters); } diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts index 9f60dbbbf8ef..e23698c9715b 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_hints.ts @@ -2,10 +2,10 @@ import { type Fr, KeyValidationHint, MAX_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, @@ -33,7 +33,7 @@ import { buildPrivateKernelResetOutputs } from './build_private_kernel_reset_out function getNullifierReadRequestHints( nullifierReadRequests: Tuple, - nullifiers: Tuple, + nullifiers: Tuple, oracle: ProvingDataOracle, sizePending: PENDING, sizeSettled: SETTLED, @@ -99,7 +99,7 @@ export async function buildPrivateKernelResetInputs( // Use max sizes, they will be trimmed down later. const futureNoteHashes = collectNested(executionStack, executionResult => { - const nonEmptyNoteHashes = getNonEmptyItems(executionResult.callStackItem.publicInputs.newNoteHashes); + const nonEmptyNoteHashes = getNonEmptyItems(executionResult.callStackItem.publicInputs.noteHashes); return nonEmptyNoteHashes.map( noteHash => new ScopedNoteHash( @@ -117,7 +117,7 @@ export async function buildPrivateKernelResetInputs( } = await buildNoteHashReadRequestHints( oracle, publicInputs.validationRequests.noteHashReadRequests, - publicInputs.end.newNoteHashes, + publicInputs.end.noteHashes, noteHashLeafIndexMap, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, @@ -125,7 +125,7 @@ export async function buildPrivateKernelResetInputs( ); const futureNullifiers = collectNested(executionStack, executionResult => { - const nonEmptyNullifiers = getNonEmptyItems(executionResult.callStackItem.publicInputs.newNullifiers); + const nonEmptyNullifiers = getNonEmptyItems(executionResult.callStackItem.publicInputs.nullifiers); return nonEmptyNullifiers.map( nullifier => new ScopedNullifier(nullifier, executionResult.callStackItem.publicInputs.callContext.storageContractAddress), @@ -138,7 +138,7 @@ export async function buildPrivateKernelResetInputs( hints: nullifierReadRequestHints, } = await getNullifierReadRequestHints( publicInputs.validationRequests.nullifierReadRequests, - publicInputs.end.newNullifiers, + publicInputs.end.nullifiers, oracle, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, @@ -164,19 +164,19 @@ export async function buildPrivateKernelResetInputs( transientNoteHashIndexesForNullifiers, transientNoteHashIndexesForLogs, ] = buildTransientDataHints( - publicInputs.end.newNoteHashes, - publicInputs.end.newNullifiers, + publicInputs.end.noteHashes, + publicInputs.end.nullifiers, publicInputs.end.noteEncryptedLogsHashes, futureNoteHashReads, futureNullifierReads, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, ); const expectedOutputs = buildPrivateKernelResetOutputs( - previousKernelData.publicInputs.end.newNoteHashes, - previousKernelData.publicInputs.end.newNullifiers, + previousKernelData.publicInputs.end.noteHashes, + previousKernelData.publicInputs.end.nullifiers, previousKernelData.publicInputs.end.noteEncryptedLogsHashes, transientNullifierIndexesForNoteHashes, transientNoteHashIndexesForNullifiers, diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts index c05ed7a25872..a6426532f398 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_reset_outputs.ts @@ -1,7 +1,7 @@ import { - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, NoteLogHash, PrivateKernelResetOutputs, ScopedNoteHash, @@ -11,28 +11,28 @@ import { padArrayEnd } from '@aztec/foundation/collection'; import { type Tuple } from '@aztec/foundation/serialize'; export function buildPrivateKernelResetOutputs( - prevNoteHashes: Tuple, - prevNullifiers: Tuple, + prevNoteHashes: Tuple, + prevNullifiers: Tuple, prevLogs: Tuple, - transientNullifierIndexesForNoteHashes: Tuple, - transientNoteHashIndexesForNullifiers: Tuple, + transientNullifierIndexesForNoteHashes: Tuple, + transientNoteHashIndexesForNullifiers: Tuple, ) { // Propagate note hashes that are not going to be squashed in the transient arrays. // A value isn't going to be squashed if the symmetrical index in the corresponding array is the length of the array. const noteHashes = padArrayEnd( - prevNoteHashes.filter((_, index) => transientNullifierIndexesForNoteHashes[index] === MAX_NEW_NULLIFIERS_PER_TX), + prevNoteHashes.filter((_, index) => transientNullifierIndexesForNoteHashes[index] === MAX_NULLIFIERS_PER_TX), ScopedNoteHash.empty(), - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_TX, ); const nullifiers = padArrayEnd( - prevNullifiers.filter((_, index) => transientNoteHashIndexesForNullifiers[index] === MAX_NEW_NOTE_HASHES_PER_TX), + prevNullifiers.filter((_, index) => transientNoteHashIndexesForNullifiers[index] === MAX_NOTE_HASHES_PER_TX), ScopedNullifier.empty(), - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, ); const nullifiedNotes = prevNoteHashes - .filter((_, index) => transientNullifierIndexesForNoteHashes[index] < MAX_NEW_NULLIFIERS_PER_TX) + .filter((_, index) => transientNullifierIndexesForNoteHashes[index] < MAX_NULLIFIERS_PER_TX) .map(n => n.counter); const logs = padArrayEnd( diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts deleted file mode 100644 index 09a11570dacf..000000000000 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/build_private_kernel_tail_hints.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { - MAX_ENCRYPTED_LOGS_PER_TX, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, - type PrivateKernelCircuitPublicInputs, - PrivateKernelTailHints, - sortByCounterGetSortedHints, -} from '@aztec/circuits.js'; - -export function buildPrivateKernelTailHints(publicInputs: PrivateKernelCircuitPublicInputs): PrivateKernelTailHints { - const [sortedNoteHashes, sortedNoteHashesIndexes] = sortByCounterGetSortedHints( - publicInputs.end.newNoteHashes, - MAX_NEW_NOTE_HASHES_PER_TX, - ); - - const [sortedNullifiers, sortedNullifiersIndexes] = sortByCounterGetSortedHints( - publicInputs.end.newNullifiers, - MAX_NEW_NULLIFIERS_PER_TX, - ); - - const [sortedNoteEncryptedLogHashes, sortedNoteEncryptedLogHashesIndexes] = sortByCounterGetSortedHints( - publicInputs.end.noteEncryptedLogsHashes, - MAX_NOTE_ENCRYPTED_LOGS_PER_TX, - ); - - const [sortedEncryptedLogHashes, sortedEncryptedLogHashesIndexes] = sortByCounterGetSortedHints( - publicInputs.end.encryptedLogsHashes, - MAX_ENCRYPTED_LOGS_PER_TX, - ); - - const [sortedUnencryptedLogHashes, sortedUnencryptedLogHashesIndexes] = sortByCounterGetSortedHints( - publicInputs.end.unencryptedLogsHashes, - MAX_UNENCRYPTED_LOGS_PER_TX, - ); - - const [sortedCallRequests, sortedCallRequestsIndexes] = sortByCounterGetSortedHints( - publicInputs.end.publicCallStack, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - { - ascending: false, - hintIndexesBy: 'sorted', - }, - ); - - return new PrivateKernelTailHints( - sortedNoteHashes, - sortedNoteHashesIndexes, - sortedNullifiers, - sortedNullifiersIndexes, - sortedNoteEncryptedLogHashes, - sortedNoteEncryptedLogHashesIndexes, - sortedEncryptedLogHashes, - sortedEncryptedLogHashesIndexes, - sortedUnencryptedLogHashes, - sortedUnencryptedLogHashesIndexes, - sortedCallRequests, - sortedCallRequestsIndexes, - ); -} diff --git a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts index 07dee2ce561f..56b9765bf9c3 100644 --- a/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts +++ b/yarn-project/pxe/src/kernel_prover/private_inputs_builders/index.ts @@ -1,5 +1,4 @@ export { buildPrivateKernelInitHints } from './build_private_kernel_init_hints.js'; export { buildPrivateKernelInnerHints } from './build_private_kernel_inner_hints.js'; -export { buildPrivateKernelTailHints } from './build_private_kernel_tail_hints.js'; export { buildPrivateKernelResetInputs } from './build_private_kernel_reset_hints.js'; export { buildPrivateKernelResetOutputs } from './build_private_kernel_reset_outputs.js'; diff --git a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts index 97ca1c230fce..b08dcdaeaacd 100644 --- a/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/test/test_circuit_prover.ts @@ -33,9 +33,7 @@ export class TestProofCreator implements ProofCreator { public getSiloedCommitments(publicInputs: PrivateCircuitPublicInputs) { const contractAddress = publicInputs.callContext.storageContractAddress; - return Promise.resolve( - publicInputs.newNoteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value)), - ); + return Promise.resolve(publicInputs.noteHashes.map(commitment => siloNoteHash(contractAddress, commitment.value))); } public async createProofInit( diff --git a/yarn-project/pxe/src/note_processor/note_processor.test.ts b/yarn-project/pxe/src/note_processor/note_processor.test.ts index 24de16e51436..7904fd9efc09 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.test.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.test.ts @@ -6,7 +6,7 @@ import { type GrumpkinPrivateKey, INITIAL_L2_BLOCK_NUM, KeyValidationRequest, - MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NOTE_HASHES_PER_TX, type PublicKey, computeOvskApp, deriveKeys, @@ -27,7 +27,7 @@ import { type OutgoingNoteDao } from '../database/outgoing_note_dao.js'; import { NoteProcessor } from './note_processor.js'; const TXS_PER_BLOCK = 4; -const NUM_NOTE_HASHES_PER_BLOCK = TXS_PER_BLOCK * MAX_NEW_NOTE_HASHES_PER_TX; +const NUM_NOTE_HASHES_PER_BLOCK = TXS_PER_BLOCK * MAX_NOTE_HASHES_PER_TX; /** A wrapper containing info about a note we want to mock and insert into a block. */ class MockNoteRequest { @@ -48,8 +48,8 @@ class MockNoteRequest { if (blockNumber < INITIAL_L2_BLOCK_NUM) { throw new Error(`Block number should be greater than or equal to ${INITIAL_L2_BLOCK_NUM}.`); } - if (noteHashIndex >= MAX_NEW_NOTE_HASHES_PER_TX) { - throw new Error(`Data index should be less than ${MAX_NEW_NOTE_HASHES_PER_TX}.`); + if (noteHashIndex >= MAX_NOTE_HASHES_PER_TX) { + throw new Error(`Data index should be less than ${MAX_NOTE_HASHES_PER_TX}.`); } if (txIndex >= TXS_PER_BLOCK) { throw new Error(`Tx index should be less than ${TXS_PER_BLOCK}.`); @@ -65,9 +65,7 @@ class MockNoteRequest { get indexWithinNoteHashTree(): bigint { return BigInt( - (this.blockNumber - 1) * NUM_NOTE_HASHES_PER_BLOCK + - this.txIndex * MAX_NEW_NOTE_HASHES_PER_TX + - this.noteHashIndex, + (this.blockNumber - 1) * NUM_NOTE_HASHES_PER_BLOCK + this.txIndex * MAX_NOTE_HASHES_PER_TX + this.noteHashIndex, ); } } diff --git a/yarn-project/pxe/src/note_processor/note_processor.ts b/yarn-project/pxe/src/note_processor/note_processor.ts index 859309439d06..5fb9b4623cf5 100644 --- a/yarn-project/pxe/src/note_processor/note_processor.ts +++ b/yarn-project/pxe/src/note_processor/note_processor.ts @@ -1,11 +1,6 @@ import { type AztecNode, L1NotePayload, type L2Block, TaggedLog } from '@aztec/circuit-types'; import { type NoteProcessorStats } from '@aztec/circuit-types/stats'; -import { - type AztecAddress, - INITIAL_L2_BLOCK_NUM, - MAX_NEW_NOTE_HASHES_PER_TX, - type PublicKey, -} from '@aztec/circuits.js'; +import { type AztecAddress, INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX, type PublicKey } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; import { type Logger, createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; @@ -128,7 +123,7 @@ export class NoteProcessor { const { txLogs } = block.body.noteEncryptedLogs; const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - - block.body.numberOfTxsIncludingPadded * MAX_NEW_NOTE_HASHES_PER_TX; + block.body.numberOfTxsIncludingPadded * MAX_NOTE_HASHES_PER_TX; // We are using set for `userPertainingTxIndices` to avoid duplicates. This would happen in case there were // multiple encrypted logs in a tx pertaining to a user. @@ -138,8 +133,8 @@ export class NoteProcessor { // Iterate over all the encrypted logs and try decrypting them. If successful, store the note. for (let indexOfTxInABlock = 0; indexOfTxInABlock < txLogs.length; ++indexOfTxInABlock) { this.stats.txs++; - const dataStartIndexForTx = dataStartIndexForBlock + indexOfTxInABlock * MAX_NEW_NOTE_HASHES_PER_TX; - const newNoteHashes = block.body.txEffects[indexOfTxInABlock].noteHashes; + const dataStartIndexForTx = dataStartIndexForBlock + indexOfTxInABlock * MAX_NOTE_HASHES_PER_TX; + const noteHashes = block.body.txEffects[indexOfTxInABlock].noteHashes; // Note: Each tx generates a `TxL2Logs` object and for this reason we can rely on its index corresponding // to the index of a tx in a block. const txFunctionLogs = txLogs[indexOfTxInABlock].functionLogs; @@ -172,7 +167,7 @@ export class NoteProcessor { outgoingTaggedNote ? this.ovpkM : undefined, payload, txHash, - newNoteHashes, + noteHashes, dataStartIndexForTx, excludedIndices, this.log, @@ -245,10 +240,10 @@ export class NoteProcessor { }); } - const newNullifiers: Fr[] = blocksAndNotes.flatMap(b => + const nullifiers: Fr[] = blocksAndNotes.flatMap(b => b.block.body.txEffects.flatMap(txEffect => txEffect.nullifiers), ); - const removedNotes = await this.db.removeNullifiedNotes(newNullifiers, this.ivpkM); + const removedNotes = await this.db.removeNullifiedNotes(nullifiers, this.ivpkM); removedNotes.forEach(noteDao => { this.log.verbose( `Removed note for contract ${noteDao.contractAddress} at slot ${ @@ -305,7 +300,7 @@ export class NoteProcessor { const outgoingNotes: OutgoingNoteDao[] = []; for (const deferredNote of deferredNoteDaos) { - const { publicKey, note, contractAddress, storageSlot, noteTypeId, txHash, newNoteHashes, dataStartIndexForTx } = + const { publicKey, note, contractAddress, storageSlot, noteTypeId, txHash, noteHashes, dataStartIndexForTx } = deferredNote; const payload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId); @@ -323,7 +318,7 @@ export class NoteProcessor { isOutgoing ? this.ovpkM : undefined, payload, txHash, - newNoteHashes, + noteHashes, dataStartIndexForTx, excludedIndices, this.log, diff --git a/yarn-project/pxe/src/note_processor/produce_note_dao.ts b/yarn-project/pxe/src/note_processor/produce_note_dao.ts index 9fc246a34fbd..46d64c7125f1 100644 --- a/yarn-project/pxe/src/note_processor/produce_note_dao.ts +++ b/yarn-project/pxe/src/note_processor/produce_note_dao.ts @@ -18,7 +18,7 @@ import { OutgoingNoteDao } from '../database/outgoing_note_dao.js'; * @param ovpkM - The public counterpart to the secret key to be used in the decryption of outgoing note logs. * @param payload - An instance of l1NotePayload. * @param txHash - The hash of the transaction that created the note. Equivalent to the first nullifier of the transaction. - * @param newNoteHashes - New note hashes in this transaction, one of which belongs to this note. + * @param noteHashes - New note hashes in this transaction, one of which belongs to this note. * @param dataStartIndexForTx - The next available leaf index for the note hash tree for this transaction. * @param excludedIndices - Indices that have been assigned a note in the same tx. Notes in a tx can have the same l1NotePayload, we need to find a different index for each replicate. * @param simulator - An instance of AcirSimulator. @@ -30,7 +30,7 @@ export async function produceNoteDaos( ovpkM: PublicKey | undefined, payload: L1NotePayload, txHash: TxHash, - newNoteHashes: Fr[], + noteHashes: Fr[], dataStartIndexForTx: number, excludedIndices: Set, log: Logger, @@ -53,7 +53,7 @@ export async function produceNoteDaos( if (ivpkM) { const { noteHashIndex, nonce, innerNoteHash, siloedNullifier } = await findNoteIndexAndNullifier( simulator, - newNoteHashes, + noteHashes, txHash, payload, excludedIndices, @@ -87,7 +87,7 @@ export async function produceNoteDaos( payload.storageSlot, payload.noteTypeId, txHash, - newNoteHashes, + noteHashes, dataStartIndexForTx, ); } @@ -115,7 +115,7 @@ export async function produceNoteDaos( } else { const { noteHashIndex, nonce, innerNoteHash } = await findNoteIndexAndNullifier( simulator, - newNoteHashes, + noteHashes, txHash, payload, excludedIndices, @@ -148,7 +148,7 @@ export async function produceNoteDaos( payload.storageSlot, payload.noteTypeId, txHash, - newNoteHashes, + noteHashes, dataStartIndexForTx, ); } diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index cf351c5bf9bf..7549f45efef9 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -4,6 +4,7 @@ import { EncryptedNoteTxL2Logs, EncryptedTxL2Logs, type EventMetadata, + EventType, ExtendedNote, type FunctionCall, type GetUnencryptedLogsResponse, @@ -35,7 +36,13 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeNoteHashNonce, siloNullifier } from '@aztec/circuits.js/hash'; -import { type ContractArtifact, type DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; +import { + type ContractArtifact, + type DecodedReturn, + EventSelector, + FunctionSelector, + encodeArguments, +} from '@aztec/foundation/abi'; import { type Fq, Fr, type Point } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; @@ -286,7 +293,7 @@ export class PXEService implements PXE { if (!(await this.getContractInstance(contract))) { throw new Error(`Contract ${contract.toString()} is not deployed`); } - return await this.node.getPublicStorageAt(contract, slot); + return await this.node.getPublicStorageAt(contract, slot, 'latest'); } public async getIncomingNotes(filter: IncomingNotesFilter): Promise { @@ -834,7 +841,43 @@ export class PXEService implements PXE { return !!(await this.node.getContract(address)); } - public async getEvents(from: number, limit: number, eventMetadata: EventMetadata, ivpk: Point): Promise { + public getEvents( + type: EventType.Encrypted, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[], + ): Promise; + public getEvents( + type: EventType.Unencrypted, + eventMetadata: EventMetadata, + from: number, + limit: number, + ): Promise; + public getEvents( + type: EventType, + eventMetadata: EventMetadata, + from: number, + limit: number, + vpks: Point[] = [], + ): Promise { + if (type.includes(EventType.Encrypted)) { + return this.getEncryptedEvents(from, limit, eventMetadata, vpks); + } + + return this.getUnencryptedEvents(from, limit, eventMetadata); + } + + async getEncryptedEvents( + from: number, + limit: number, + eventMetadata: EventMetadata, + vpks: Point[], + ): Promise { + if (vpks.length === 0) { + throw new Error('Tried to get encrypted events without supplying any viewing public keys'); + } + const blocks = await this.node.getBlocks(from, limit); const txEffects = blocks.flatMap(block => block.body.txEffects); @@ -842,11 +885,20 @@ export class PXEService implements PXE { const encryptedLogs = encryptedTxLogs.flatMap(encryptedTxLog => encryptedTxLog.unrollLogs()); - const ivsk = await this.keyStore.getMasterSecretKey(ivpk); + const vsks = await Promise.all(vpks.map(vpk => this.keyStore.getMasterSecretKey(vpk))); + + const visibleEvents = encryptedLogs.flatMap(encryptedLog => { + for (const sk of vsks) { + const decryptedLog = + TaggedLog.decryptAsIncoming(encryptedLog, sk, L1EventPayload) ?? + TaggedLog.decryptAsOutgoing(encryptedLog, sk, L1EventPayload); + if (decryptedLog !== undefined) { + return [decryptedLog]; + } + } - const visibleEvents = encryptedLogs - .map(encryptedLog => TaggedLog.decryptAsIncoming(encryptedLog, ivsk, L1EventPayload)) - .filter(item => item !== undefined) as TaggedLog[]; + return []; + }); const decodedEvents = visibleEvents .map(visibleEvent => { @@ -874,4 +926,40 @@ export class PXEService implements PXE { return decodedEvents; } + + async getUnencryptedEvents(from: number, limit: number, eventMetadata: EventMetadata): Promise { + const { logs: unencryptedLogs } = await this.node.getUnencryptedLogs({ + fromBlock: from, + toBlock: from + limit, + }); + + const decodedEvents = unencryptedLogs + .map(unencryptedLog => { + const unencryptedLogBuf = unencryptedLog.log.data; + if ( + !EventSelector.fromBuffer(unencryptedLogBuf.subarray(unencryptedLogBuf.byteLength - 4)).equals( + eventMetadata.eventSelector, + ) + ) { + return undefined; + } + + if (unencryptedLogBuf.byteLength !== eventMetadata.fieldNames.length * 32 + 32) { + throw new Error( + 'Something is weird here, we have matching FunctionSelectors, but the actual payload has mismatched length', + ); + } + + return eventMetadata.fieldNames.reduce( + (acc, curr, i) => ({ + ...acc, + [curr]: new Fr(unencryptedLogBuf.subarray(i * 32, i * 32 + 32)), + }), + {} as T, + ); + }) + .filter(unencryptedLog => unencryptedLog !== undefined) as T[]; + + return decodedEvents; + } } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index a0bdf943af37..89721ceafb92 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -214,7 +214,7 @@ describe('sequencer', () => { ); // We make a nullifier from tx1 a part of the nullifier tree, so it gets rejected as double spend - const doubleSpendNullifier = doubleSpendTx.data.forRollup!.end.newNullifiers[0].toBuffer(); + const doubleSpendNullifier = doubleSpendTx.data.forRollup!.end.nullifiers[0].toBuffer(); merkleTreeOps.findLeafIndex.mockImplementation((treeId: MerkleTreeId, value: any) => { return Promise.resolve( treeId === MerkleTreeId.NULLIFIER_TREE && value.equals(doubleSpendNullifier) ? 1n : undefined, diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 0a4414537807..fb20cb3507f9 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -258,9 +258,7 @@ export class Sequencer { const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); const numRealTxs = validTxs.length; - const pow2 = Math.log2(numRealTxs); - const totalTxs = 2 ** Math.ceil(pow2); - const blockSize = Math.max(2, totalTxs); + const blockSize = Math.max(2, numRealTxs); const blockBuildingTimer = new Timer(); const blockTicket = await this.prover.startNewBlock(blockSize, newGlobalVariables, l1ToL2Messages); diff --git a/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.test.ts b/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.test.ts index 5cf758a6cfda..cdca28615781 100644 --- a/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.test.ts +++ b/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.test.ts @@ -19,13 +19,13 @@ describe('DoubleSpendTxValidator', () => { it('rejects duplicates in non revertible data', async () => { const badTx = mockTxForRollup(); - badTx.data.forRollup!.end.newNullifiers[1] = badTx.data.forRollup!.end.newNullifiers[0]; + badTx.data.forRollup!.end.nullifiers[1] = badTx.data.forRollup!.end.nullifiers[0]; await expect(txValidator.validateTxs([badTx])).resolves.toEqual([[], [badTx]]); }); it('rejects duplicates in revertible data', async () => { const badTx = mockTxForRollup(); - badTx.data.forRollup!.end.newNullifiers[1] = badTx.data.forRollup!.end.newNullifiers[0]; + badTx.data.forRollup!.end.nullifiers[1] = badTx.data.forRollup!.end.nullifiers[0]; await expect(txValidator.validateTxs([badTx])).resolves.toEqual([[], [badTx]]); }); @@ -34,14 +34,14 @@ describe('DoubleSpendTxValidator', () => { numberOfNonRevertiblePublicCallRequests: 1, numberOfRevertiblePublicCallRequests: 1, }); - badTx.data.forPublic!.end.newNullifiers[0] = badTx.data.forPublic!.endNonRevertibleData.newNullifiers[0]; + badTx.data.forPublic!.end.nullifiers[0] = badTx.data.forPublic!.endNonRevertibleData.nullifiers[0]; await expect(txValidator.validateTxs([badTx])).resolves.toEqual([[], [badTx]]); }); it('rejects duplicates across txs', async () => { const firstTx = mockTxForRollup(1); const secondTx = mockTxForRollup(2); - secondTx.data.forRollup!.end.newNullifiers[0] = firstTx.data.forRollup!.end.newNullifiers[0]; + secondTx.data.forRollup!.end.nullifiers[0] = firstTx.data.forRollup!.end.nullifiers[0]; await expect(txValidator.validateTxs([firstTx, secondTx])).resolves.toEqual([[firstTx], [secondTx]]); }); diff --git a/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.ts b/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.ts index 62db72b5ec9b..2b93fe73eb09 100644 --- a/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/double_spend_validator.ts @@ -32,16 +32,16 @@ export class DoubleSpendTxValidator implements TxValidator { } async #uniqueNullifiers(tx: AnyTx, thisBlockNullifiers: Set): Promise { - const newNullifiers = tx.data.getNonEmptyNullifiers().map(x => x.toBigInt()); + const nullifiers = tx.data.getNonEmptyNullifiers().map(x => x.toBigInt()); // Ditch this tx if it has repeated nullifiers - const uniqueNullifiers = new Set(newNullifiers); - if (uniqueNullifiers.size !== newNullifiers.length) { + const uniqueNullifiers = new Set(nullifiers); + if (uniqueNullifiers.size !== nullifiers.length) { this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for emitting duplicate nullifiers`); return false; } - for (const nullifier of newNullifiers) { + for (const nullifier of nullifiers) { if (thisBlockNullifiers.has(nullifier)) { this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`); return false; @@ -50,9 +50,7 @@ export class DoubleSpendTxValidator implements TxValidator { thisBlockNullifiers.add(nullifier); } - const nullifierIndexes = await Promise.all( - newNullifiers.map(n => this.#nullifierSource.getNullifierIndex(new Fr(n))), - ); + const nullifierIndexes = await Promise.all(nullifiers.map(n => this.#nullifierSource.getNullifierIndex(new Fr(n)))); const hasDuplicates = nullifierIndexes.some(index => index !== undefined); if (hasDuplicates) { diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index d2cd8ddf7d1c..b3f04b974293 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -287,8 +287,18 @@ export class Oracle { return message.toFields().map(toACVMField); } - async storageRead([startStorageSlot]: ACVMField[], [numberOfElements]: ACVMField[]): Promise { - const values = await this.typedOracle.storageRead(fromACVMField(startStorageSlot), +numberOfElements); + async storageRead( + [contractAddress]: ACVMField[], + [startStorageSlot]: ACVMField[], + [blockNumber]: ACVMField[], + [numberOfElements]: ACVMField[], + ): Promise { + const values = await this.typedOracle.storageRead( + fromACVMField(contractAddress), + fromACVMField(startStorageSlot), + +blockNumber, + +numberOfElements, + ); return values.map(toACVMField); } diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 690ccf8ac868..fdda81ac6ae1 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -190,7 +190,12 @@ export abstract class TypedOracle { throw new OracleMethodNotAvailableError('getL1ToL2MembershipWitness'); } - storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise { + storageRead( + _contractAddress: Fr, + _startStorageSlot: Fr, + _blockNumber: number, + _numberOfElements: number, + ): Promise { throw new OracleMethodNotAvailableError('storageRead'); } diff --git a/yarn-project/simulator/src/avm/avm_context.ts b/yarn-project/simulator/src/avm/avm_context.ts index c9c5e13ef76a..b0ca8d3b2df2 100644 --- a/yarn-project/simulator/src/avm/avm_context.ts +++ b/yarn-project/simulator/src/avm/avm_context.ts @@ -43,13 +43,13 @@ export class AvmContext { calldata: Fr[], allocatedGas: Gas, callType: 'CALL' | 'STATICCALL', - temporaryFunctionSelector: FunctionSelector = FunctionSelector.empty(), + functionSelector: FunctionSelector = FunctionSelector.empty(), ): AvmContext { const deriveFn = callType === 'CALL' ? this.environment.deriveEnvironmentForNestedCall : this.environment.deriveEnvironmentForNestedStaticCall; - const newExecutionEnvironment = deriveFn.call(this.environment, address, calldata, temporaryFunctionSelector); + const newExecutionEnvironment = deriveFn.call(this.environment, address, calldata, functionSelector); const forkedWorldState = this.persistableState.fork(); const machineState = AvmMachineState.fromState(gasToGasLeft(allocatedGas)); return new AvmContext(forkedWorldState, newExecutionEnvironment, machineState); diff --git a/yarn-project/simulator/src/avm/avm_message_call_result.ts b/yarn-project/simulator/src/avm/avm_contract_call_result.ts similarity index 92% rename from yarn-project/simulator/src/avm/avm_message_call_result.ts rename to yarn-project/simulator/src/avm/avm_contract_call_result.ts index 49e5355b3d27..7db56bc44dee 100644 --- a/yarn-project/simulator/src/avm/avm_message_call_result.ts +++ b/yarn-project/simulator/src/avm/avm_contract_call_result.ts @@ -5,7 +5,7 @@ import { type AvmRevertReason } from './errors.js'; /** * Results of an contract call's execution in the AVM. */ -export class AvmContractCallResults { +export class AvmContractCallResult { constructor(public reverted: boolean, public output: Fr[], public revertReason?: AvmRevertReason) {} toString(): string { diff --git a/yarn-project/simulator/src/avm/avm_execution_environment.ts b/yarn-project/simulator/src/avm/avm_execution_environment.ts index c4794b1a02b7..27a1e32ec9ca 100644 --- a/yarn-project/simulator/src/avm/avm_execution_environment.ts +++ b/yarn-project/simulator/src/avm/avm_execution_environment.ts @@ -1,15 +1,15 @@ -import { FunctionSelector, type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; +import { FunctionSelector, type GlobalVariables, type Header } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; export class AvmContextInputs { - static readonly SIZE = 3; + static readonly SIZE = 2; - constructor(private selector: Fr, private argsHash: Fr, private isStaticCall: boolean) {} + constructor(private argsHash: Fr, private isStaticCall: boolean) {} public toFields(): Fr[] { - return [this.selector, this.argsHash, new Fr(this.isStaticCall)]; + return [this.argsHash, new Fr(this.isStaticCall)]; } } @@ -17,38 +17,24 @@ export class AvmContextInputs { * Contains variables that remain constant during AVM execution * These variables are provided by the public kernel circuit */ -// TODO(https://github.com/AztecProtocol/aztec-packages/issues/3992): gas not implemented export class AvmExecutionEnvironment { - private readonly calldataPrefixLength; constructor( public readonly address: AztecAddress, public readonly storageAddress: AztecAddress, public readonly sender: AztecAddress, - public readonly feePerL2Gas: Fr, - public readonly feePerDaGas: Fr, + public readonly functionSelector: FunctionSelector, // may be temporary (#7224) public readonly contractCallDepth: Fr, + public readonly transactionFee: Fr, public readonly header: Header, public readonly globals: GlobalVariables, public readonly isStaticCall: boolean, public readonly isDelegateCall: boolean, public readonly calldata: Fr[], - public readonly gasSettings: GasSettings, - public readonly transactionFee: Fr, - - // Function selector is temporary since eventually public contract bytecode will be one blob - // containing all functions, and function selector will become an application-level mechanism - // (e.g. first few bytes of calldata + compiler-generated jump table) - public readonly temporaryFunctionSelector: FunctionSelector, ) { // We encode some extra inputs (AvmContextInputs) in calldata. // This will have to go once we move away from one proof per call. - const inputs = new AvmContextInputs( - temporaryFunctionSelector.toField(), - computeVarArgsHash(calldata), - isStaticCall, - ).toFields(); + const inputs = new AvmContextInputs(computeVarArgsHash(calldata), isStaticCall).toFields(); this.calldata = [...inputs, ...calldata]; - this.calldataPrefixLength = inputs.length; } private deriveEnvironmentForNestedCallInternal( @@ -62,17 +48,14 @@ export class AvmExecutionEnvironment { /*address=*/ targetAddress, /*storageAddress=*/ targetAddress, /*sender=*/ this.address, - this.feePerL2Gas, - this.feePerDaGas, + functionSelector, this.contractCallDepth.add(Fr.ONE), + this.transactionFee, this.header, this.globals, isStaticCall, isDelegateCall, calldata, - this.gasSettings, - this.transactionFee, - functionSelector, ); } @@ -114,6 +97,6 @@ export class AvmExecutionEnvironment { public getCalldataWithoutPrefix(): Fr[] { // clip off the first few entries - return this.calldata.slice(this.calldataPrefixLength); + return this.calldata.slice(AvmContextInputs.SIZE); } } diff --git a/yarn-project/simulator/src/avm/avm_gas.ts b/yarn-project/simulator/src/avm/avm_gas.ts index d951f20fa32b..d571234ee250 100644 --- a/yarn-project/simulator/src/avm/avm_gas.ts +++ b/yarn-project/simulator/src/avm/avm_gas.ts @@ -76,7 +76,7 @@ const BaseGasCosts: Record = { [Opcode.FEEPERL2GAS]: DefaultBaseGasCost, [Opcode.FEEPERDAGAS]: DefaultBaseGasCost, [Opcode.TRANSACTIONFEE]: DefaultBaseGasCost, - [Opcode.CONTRACTCALLDEPTH]: DefaultBaseGasCost, + [Opcode.FUNCTIONSELECTOR]: DefaultBaseGasCost, [Opcode.CHAINID]: DefaultBaseGasCost, [Opcode.VERSION]: DefaultBaseGasCost, [Opcode.BLOCKNUMBER]: DefaultBaseGasCost, diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index e28d9d9b8e7a..b84752772838 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -1,3 +1,4 @@ +import { GasFees } from '@aztec/circuits.js'; import { Grumpkin } from '@aztec/circuits.js/barretenberg'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { FunctionSelector } from '@aztec/foundation/abi'; @@ -6,14 +7,16 @@ import { keccak256, pedersenHash, poseidon2Hash, sha256 } from '@aztec/foundatio import { Fq, Fr } from '@aztec/foundation/fields'; import { type Fieldable } from '@aztec/foundation/serialize'; +import { randomInt } from 'crypto'; import { mock } from 'jest-mock-extended'; import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; -import { isAvmBytecode, markBytecodeAsAvm } from '../public/transitional_adaptors.js'; +import { type AvmContext } from './avm_context.js'; import { type AvmExecutionEnvironment } from './avm_execution_environment.js'; import { AvmMachineState } from './avm_machine_state.js'; import { type MemoryValue, TypeTag, type Uint8 } from './avm_memory_types.js'; import { AvmSimulator } from './avm_simulator.js'; +import { isAvmBytecode, markBytecodeAsAvm } from './bytecode_utils.js'; import { adjustCalldataIndex, getAvmTestContractBytecode, @@ -234,73 +237,58 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe('Environment getters', () => { - const testEnvGetter = async (valueName: string, value: any, functionName: string, globalVar: boolean = false) => { - // Execute - let overrides = {}; - if (globalVar === true) { - const globals = initGlobalVariables({ [valueName]: value }); - overrides = { globals }; - } else { - overrides = { [valueName]: value }; - } - const context = initContext({ env: initExecutionEnvironment(overrides) }); - const bytecode = getAvmTestContractBytecode(functionName); - const results = await new AvmSimulator(context).executeBytecode(bytecode); - - expect(results.reverted).toBe(false); - - const returnData = results.output; - expect(returnData).toEqual([value.toField()]); - }; - - it('address', async () => { - const address = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('address', address, 'get_address'); - }); - - it('storageAddress', async () => { - const storageAddress = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('storageAddress', storageAddress, 'get_storage_address'); - }); - - it('sender', async () => { - const sender = AztecAddress.fromField(new Fr(1)); - await testEnvGetter('sender', sender, 'get_sender'); - }); - - it('getFeePerL2Gas', async () => { - const fee = new Fr(1); - await testEnvGetter('feePerL2Gas', fee, 'get_fee_per_l2_gas'); - }); - - it('getFeePerDaGas', async () => { - const fee = new Fr(1); - await testEnvGetter('feePerDaGas', fee, 'get_fee_per_da_gas'); + const address = AztecAddress.random(); + const storageAddress = AztecAddress.random(); + const sender = AztecAddress.random(); + const functionSelector = FunctionSelector.random(); + const transactionFee = Fr.random(); + const chainId = Fr.random(); + const version = Fr.random(); + const blockNumber = Fr.random(); + const timestamp = new Fr(randomInt(100000)); // cap timestamp since must fit in u64 + const feePerDaGas = Fr.random(); + const feePerL2Gas = Fr.random(); + const gasFees = new GasFees(feePerDaGas, feePerL2Gas); + const globals = initGlobalVariables({ + chainId, + version, + blockNumber, + timestamp, + gasFees, }); - - it('getTransactionFee', async () => { - const fee = new Fr(1); - await testEnvGetter('transactionFee', fee, 'get_transaction_fee'); + const env = initExecutionEnvironment({ + address, + storageAddress, + sender, + functionSelector, + transactionFee, + globals, }); - - it('chainId', async () => { - const chainId = new Fr(1); - await testEnvGetter('chainId', chainId, 'get_chain_id', /*globalVar=*/ true); + let context: AvmContext; + beforeEach(() => { + context = initContext({ env }); }); - it('version', async () => { - const version = new Fr(1); - await testEnvGetter('version', version, 'get_version', /*globalVar=*/ true); - }); + it.each([ + ['address', address.toField(), 'get_address'], + ['storageAddress', storageAddress.toField(), 'get_storage_address'], + ['sender', sender.toField(), 'get_sender'], + ['functionSelector', functionSelector.toField(), 'get_function_selector'], + ['transactionFee', transactionFee.toField(), 'get_transaction_fee'], + ['chainId', chainId.toField(), 'get_chain_id'], + ['version', version.toField(), 'get_version'], + ['blockNumber', blockNumber.toField(), 'get_block_number'], + ['timestamp', timestamp.toField(), 'get_timestamp'], + ['feePerDaGas', feePerDaGas.toField(), 'get_fee_per_da_gas'], + ['feePerL2Gas', feePerL2Gas.toField(), 'get_fee_per_l2_gas'], + ])('%s getter', async (_name: string, value: Fr, functionName: string) => { + const bytecode = getAvmTestContractBytecode(functionName); + const results = await new AvmSimulator(context).executeBytecode(bytecode); - it('blockNumber', async () => { - const blockNumber = new Fr(1); - await testEnvGetter('blockNumber', blockNumber, 'get_block_number', /*globalVar=*/ true); - }); + expect(results.reverted).toBe(false); - it('timestamp', async () => { - const timestamp = new Fr(1); - await testEnvGetter('timestamp', timestamp, 'get_timestamp', /*globalVar=*/ true); + const returnData = results.output; + expect(returnData).toEqual([value]); }); }); @@ -308,7 +296,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { it('selector', async () => { const context = initContext({ env: initExecutionEnvironment({ - temporaryFunctionSelector: FunctionSelector.fromSignature('check_selector()'), + functionSelector: FunctionSelector.fromSignature('check_selector()'), }), }); const bytecode = getAvmTestContractBytecode('check_selector'); @@ -345,8 +333,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { describe('Side effects, world state, nested calls', () => { const address = new Fr(1); - // TODO(dbanks12): should be able to make address and storage address different - const storageAddress = new Fr(1); + const storageAddress = new Fr(2); const sender = new Fr(42); const leafIndex = new Fr(7); const slotNumber = 1; // must update Noir contract if changing this @@ -411,7 +398,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { describe.each([[/*exists=*/ false], [/*exists=*/ true]])('Nullifier checks', (exists: boolean) => { const existsStr = exists ? 'DOES exist' : 'does NOT exist'; - it(`Should return ${exists} (and be traced) when noteHash ${existsStr}`, async () => { + it(`Should return ${exists} (and be traced) when nullifier ${existsStr}`, async () => { const calldata = [value0]; const context = createContext(calldata); const bytecode = getAvmTestContractBytecode('nullifier_exists'); @@ -430,7 +417,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { const tracedLeafIndex = exists && !isPending ? leafIndex : Fr.ZERO; expect(trace.traceNullifierCheck).toHaveBeenCalledWith( storageAddress, - value0, + /*nullifier=*/ value0, tracedLeafIndex, exists, isPending, @@ -451,7 +438,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { ? `at leafIndex=${mockAtLeafIndex.toNumber()} (exists at leafIndex=${leafIndex.toNumber()})` : ''; - it(`Should return ${expectFound} (and be traced) when noteHash ${existsStr} ${foundAtStr}`, async () => { + it(`Should return ${expectFound} (and be traced) when message ${existsStr} ${foundAtStr}`, async () => { const calldata = [value0, leafIndex]; const context = createContext(calldata); const bytecode = getAvmTestContractBytecode('l1_to_l2_msg_exists'); @@ -466,7 +453,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith( address, - /*noteHash=*/ value0, + /*msgHash=*/ value0, leafIndex, /*exists=*/ expectFound, ); @@ -485,7 +472,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { expect(trace.traceNewNoteHash).toHaveBeenCalledTimes(1); expect(trace.traceNewNoteHash).toHaveBeenCalledWith( expect.objectContaining(storageAddress), - /*nullifier=*/ value0, + /*noteHash=*/ value0, ); }); @@ -525,7 +512,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { // leafIndex is returned from DB call for nullifiers, so it is absent on DB miss expect(trace.traceNullifierCheck).toHaveBeenCalledWith( storageAddress, - value0, + /*nullifier=*/ value0, /*leafIndex=*/ Fr.ZERO, /*exists=*/ true, /*isPending=*/ true, @@ -558,7 +545,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(bytecode); expect(results.reverted).toBe(false); - const eventSelector = new Fr(5); const expectedFields = [new Fr(10), new Fr(20), new Fr(30)]; const expectedString = 'Hello, world!'.split('').map(c => new Fr(c.charCodeAt(0))); const expectedCompressedString = [ @@ -567,9 +553,9 @@ describe('AVM simulator: transpiled Noir contracts', () => { ].map(s => new Fr(Buffer.from(s))); expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(3); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedFields); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedString); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, expectedCompressedString); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedFields); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedString); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, expectedCompressedString); }); }); @@ -640,8 +626,8 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(bytecode); expect(results.reverted).toBe(false); - expect(await context.persistableState.peekStorage(address, listSlot0)).toEqual(calldata[0]); - expect(await context.persistableState.peekStorage(address, listSlot1)).toEqual(calldata[1]); + expect(await context.persistableState.peekStorage(storageAddress, listSlot0)).toEqual(calldata[0]); + expect(await context.persistableState.peekStorage(storageAddress, listSlot1)).toEqual(calldata[1]); expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(2); expect(trace.tracePublicStorageWrite).toHaveBeenCalledWith(storageAddress, listSlot0, value0); diff --git a/yarn-project/simulator/src/avm/avm_simulator.ts b/yarn-project/simulator/src/avm/avm_simulator.ts index 64d13a2ffbe9..e62b2a57c74e 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.ts @@ -2,9 +2,9 @@ import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { strict as assert } from 'assert'; -import { decompressBytecodeIfCompressed, isAvmBytecode } from '../public/transitional_adaptors.js'; import type { AvmContext } from './avm_context.js'; -import { AvmContractCallResults } from './avm_message_call_result.js'; +import { AvmContractCallResult } from './avm_contract_call_result.js'; +import { decompressBytecodeIfCompressed, isAvmBytecode } from './bytecode_utils.js'; import { AvmExecutionError, InvalidProgramCounterError, @@ -20,18 +20,16 @@ export class AvmSimulator { private bytecode: Buffer | undefined; constructor(private context: AvmContext) { - this.log = createDebugLogger( - `aztec:avm_simulator:core(f:${context.environment.temporaryFunctionSelector.toString()})`, - ); + this.log = createDebugLogger(`aztec:avm_simulator:core(f:${context.environment.functionSelector.toString()})`); } /** * Fetch the bytecode and execute it in the current context. */ - public async execute(): Promise { + public async execute(): Promise { const bytecode = await this.context.persistableState.getBytecode( this.context.environment.address, - this.context.environment.temporaryFunctionSelector, + this.context.environment.functionSelector, ); // This assumes that we will not be able to send messages to accounts without code @@ -54,7 +52,7 @@ export class AvmSimulator { * Executes the provided bytecode in the current context. * This method is useful for testing and debugging. */ - public async executeBytecode(bytecode: Buffer): Promise { + public async executeBytecode(bytecode: Buffer): Promise { const decompressedBytecode = await decompressBytecodeIfCompressed(bytecode); assert(isAvmBytecode(decompressedBytecode), "AVM simulator can't execute non-AVM bytecode"); @@ -66,7 +64,7 @@ export class AvmSimulator { * Executes the provided instructions in the current context. * This method is useful for testing and debugging. */ - public async executeInstructions(instructions: Instruction[]): Promise { + public async executeInstructions(instructions: Instruction[]): Promise { assert(instructions.length > 0); const { machineState } = this.context; try { @@ -95,7 +93,7 @@ export class AvmSimulator { const output = machineState.getOutput(); const reverted = machineState.getReverted(); const revertReason = reverted ? revertReasonFromExplicitRevert(output, this.context) : undefined; - const results = new AvmContractCallResults(reverted, output, revertReason); + const results = new AvmContractCallResult(reverted, output, revertReason); this.log.debug(`Context execution results: ${results.toString()}`); // Return results for processing by calling context return results; @@ -108,7 +106,7 @@ export class AvmSimulator { const revertReason = revertReasonFromExceptionalHalt(err, this.context); // Note: "exceptional halts" cannot return data, hence [] - const results = new AvmContractCallResults(/*reverted=*/ true, /*output=*/ [], revertReason); + const results = new AvmContractCallResult(/*reverted=*/ true, /*output=*/ [], revertReason); this.log.debug(`Context execution results: ${results.toString()}`); // Return results for processing by calling context return results; diff --git a/yarn-project/simulator/src/avm/bytecode_utils.ts b/yarn-project/simulator/src/avm/bytecode_utils.ts new file mode 100644 index 000000000000..52b0f31032eb --- /dev/null +++ b/yarn-project/simulator/src/avm/bytecode_utils.ts @@ -0,0 +1,32 @@ +import { promisify } from 'util'; +import { gunzip } from 'zlib'; + +import { Mov } from '../avm/opcodes/memory.js'; + +const AVM_MAGIC_SUFFIX = Buffer.from([ + Mov.opcode, // opcode + 0x00, // indirect + ...Buffer.from('000018ca', 'hex'), // srcOffset + ...Buffer.from('000018ca', 'hex'), // dstOffset +]); + +export function markBytecodeAsAvm(bytecode: Buffer): Buffer { + return Buffer.concat([bytecode, AVM_MAGIC_SUFFIX]); +} + +// This is just a helper function for the AVM simulator +export async function decompressBytecodeIfCompressed(bytecode: Buffer): Promise { + try { + return await promisify(gunzip)(bytecode); + } catch { + // If the bytecode is not compressed, the gunzip call will throw an error + // In this case, we assume the bytecode is not compressed and continue. + return Promise.resolve(bytecode); + } +} + +export async function isAvmBytecode(bytecode: Buffer): Promise { + const decompressedBytecode = await decompressBytecodeIfCompressed(bytecode); + const magicSize = AVM_MAGIC_SUFFIX.length; + return decompressedBytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX); +} diff --git a/yarn-project/simulator/src/avm/errors.ts b/yarn-project/simulator/src/avm/errors.ts index 46f759fc7364..06d35a2abc90 100644 --- a/yarn-project/simulator/src/avm/errors.ts +++ b/yarn-project/simulator/src/avm/errors.ts @@ -113,7 +113,7 @@ function createRevertReason(message: string, context: AvmContext, nestedError?: message, /*failingFunction=*/ { contractAddress: context.environment.address, - functionSelector: context.environment.temporaryFunctionSelector, + functionSelector: context.environment.functionSelector, }, /*noirCallStack=*/ [...context.machineState.internalCallStack, context.machineState.pc].map(pc => `0.${pc}`), /*options=*/ { cause: nestedError }, diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index d7926c28dfe0..4534dd905871 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -1,4 +1,4 @@ -import { GasFees, GasSettings, GlobalVariables, Header } from '@aztec/circuits.js'; +import { GasFees, 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'; @@ -72,17 +72,14 @@ export function initExecutionEnvironment(overrides?: Partial { // }), // ]); - // expect(journalUpdates.newNoteHashes).toEqual([ + // expect(journalUpdates.noteHashes).toEqual([ // expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), // expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), // ]); @@ -276,7 +276,7 @@ describe('journal', () => { // expect.objectContaining({ nullifier: commitment, exists: true }), // expect.objectContaining({ nullifier: commitmentT1, exists: true }), // ]); - // expect(journalUpdates.newNullifiers).toEqual([ + // expect(journalUpdates.nullifiers).toEqual([ // expect.objectContaining({ // storageAddress: contractAddress, // nullifier: commitment, @@ -386,7 +386,7 @@ describe('journal', () => { // ]); // // Check that the world state _traces_ are merged even on rejection - // expect(journalUpdates.newNoteHashes).toEqual([ + // expect(journalUpdates.noteHashes).toEqual([ // expect.objectContaining({ noteHash: commitment, storageAddress: contractAddress }), // expect.objectContaining({ noteHash: commitmentT1, storageAddress: contractAddress }), // ]); @@ -394,7 +394,7 @@ describe('journal', () => { // expect.objectContaining({ nullifier: commitment, exists: true }), // expect.objectContaining({ nullifier: commitmentT1, exists: true }), // ]); - // expect(journalUpdates.newNullifiers).toEqual([ + // expect(journalUpdates.nullifiers).toEqual([ // expect.objectContaining({ // storageAddress: contractAddress, // nullifier: commitment, diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 06e6465385fc..f34a2832edd7 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -5,8 +5,8 @@ import { SerializableContractInstance } from '@aztec/types/contracts'; import { type TracedContractInstance } from '../../public/side_effect_trace.js'; import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; +import { type AvmContractCallResult } from '../avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm_execution_environment.js'; -import { type AvmContractCallResults } from '../avm_message_call_result.js'; import { type HostStorage } from './host_storage.js'; import { NullifierManager } from './nullifiers.js'; import { PublicStorage } from './public_storage.js'; @@ -25,10 +25,11 @@ export class AvmPersistableStateManager { constructor( /** Reference to node storage */ - private hostStorage: HostStorage, + private readonly hostStorage: HostStorage, /** Side effect trace */ - private trace: PublicSideEffectTraceInterface, + private readonly trace: PublicSideEffectTraceInterface, /** Public storage, including cached writes */ + // TODO(5818): make private once no longer accessed in executor public readonly publicStorage: PublicStorage, /** Nullifier set, including cached/recently-emitted nullifiers */ private readonly nullifiers: NullifierManager, @@ -197,9 +198,9 @@ export class AvmPersistableStateManager { * @param event - log event selector * @param log - log contents */ - public writeUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]) { - this.log.debug(`UnencryptedL2Log(${contractAddress}) += event ${event} with ${log.length} fields.`); - this.trace.traceUnencryptedLog(contractAddress, event, log); + public writeUnencryptedLog(contractAddress: Fr, log: Fr[]) { + this.log.debug(`UnencryptedL2Log(${contractAddress}) += event with ${log.length} fields.`); + this.trace.traceUnencryptedLog(contractAddress, log); } /** @@ -243,21 +244,23 @@ export class AvmPersistableStateManager { */ public async processNestedCall( nestedState: AvmPersistableStateManager, - success: boolean, nestedEnvironment: AvmExecutionEnvironment, startGasLeft: Gas, endGasLeft: Gas, bytecode: Buffer, - avmCallResults: AvmContractCallResults, + avmCallResults: AvmContractCallResult, ) { - if (success) { + if (!avmCallResults.reverted) { this.acceptNestedCallState(nestedState); } const functionName = (await nestedState.hostStorage.contractsDb.getDebugFunctionName( nestedEnvironment.address, - nestedEnvironment.temporaryFunctionSelector, - )) ?? `${nestedEnvironment.address}:${nestedEnvironment.temporaryFunctionSelector}`; + nestedEnvironment.functionSelector, + )) ?? `${nestedEnvironment.address}:${nestedEnvironment.functionSelector}`; + + this.log.verbose(`[AVM] Calling nested function ${functionName}`); + this.trace.traceNestedCall( nestedState.trace, nestedEnvironment, diff --git a/yarn-project/simulator/src/avm/journal/public_storage.ts b/yarn-project/simulator/src/avm/journal/public_storage.ts index 4dee472ab240..443717963db4 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.ts @@ -16,7 +16,7 @@ type PublicStorageReadResult = { */ export class PublicStorage { /** Cached storage writes. */ - private cache: PublicStorageCache; + private readonly cache: PublicStorageCache; constructor( /** Reference to node storage. Checked on parent cache-miss. */ @@ -134,7 +134,7 @@ class PublicStorageCache { * mapping storage slot to latest staged write value. */ public cachePerContract: Map> = new Map(); - // FIXME: storage ^ should be private, but its value is used in tests for "currentStorageValue" + // FIXME: storage ^ should be private, but its value is used in commitToDB /** * Read a staged value from storage, if it has been previously written to. 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 9f71a34a6f62..dd1e638d6a49 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -180,7 +180,7 @@ describe('Accrued Substate', () => { const tracedLeafIndex = exists && !isPending ? leafIndex : Fr.ZERO; expect(trace.traceNullifierCheck).toHaveBeenCalledWith( storageAddress, - value0, + /*nullifier=*/ value0, tracedLeafIndex, exists, isPending, @@ -292,7 +292,7 @@ describe('Accrued Substate', () => { expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledTimes(1); expect(trace.traceL1ToL2MessageCheck).toHaveBeenCalledWith( address, - /*noteHash=*/ value0, + /*msgHash=*/ value0, leafIndex, /*exists=*/ expectFound, ); @@ -305,16 +305,10 @@ describe('Accrued Substate', () => { const buf = Buffer.from([ EmitUnencryptedLog.opcode, // opcode 0x01, // indirect - ...Buffer.from('02345678', 'hex'), // event selector offset ...Buffer.from('12345678', 'hex'), // log offset ...Buffer.from('a2345678', 'hex'), // length offset ]); - const inst = new EmitUnencryptedLog( - /*indirect=*/ 0x01, - /*eventSelectorOffset=*/ 0x02345678, - /*offset=*/ 0x12345678, - /*lengthOffset=*/ 0xa2345678, - ); + const inst = new EmitUnencryptedLog(/*indirect=*/ 0x01, /*offset=*/ 0x12345678, /*lengthOffset=*/ 0xa2345678); expect(EmitUnencryptedLog.deserialize(buf)).toEqual(inst); expect(inst.serialize()).toEqual(buf); @@ -322,8 +316,6 @@ describe('Accrued Substate', () => { it('Should append unencrypted logs correctly', async () => { const startOffset = 0; - const eventSelector = new Fr(5); - const eventSelectorOffset = 10; const logSizeOffset = 20; const values = [new Fr(69n), new Fr(420n), new Fr(Fr.MODULUS - 1n)]; @@ -331,18 +323,12 @@ describe('Accrued Substate', () => { startOffset, values.map(f => new Field(f)), ); - context.machineState.memory.set(eventSelectorOffset, new Field(eventSelector)); context.machineState.memory.set(logSizeOffset, new Uint32(values.length)); - await new EmitUnencryptedLog( - /*indirect=*/ 0, - eventSelectorOffset, - /*offset=*/ startOffset, - logSizeOffset, - ).execute(context); + await new EmitUnencryptedLog(/*indirect=*/ 0, /*offset=*/ startOffset, logSizeOffset).execute(context); expect(trace.traceUnencryptedLog).toHaveBeenCalledTimes(1); - expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, eventSelector, values); + expect(trace.traceUnencryptedLog).toHaveBeenCalledWith(address, values); }); }); @@ -386,7 +372,7 @@ describe('Accrued Substate', () => { const instructions = [ new EmitNoteHash(/*indirect=*/ 0, /*offset=*/ 0), new EmitNullifier(/*indirect=*/ 0, /*offset=*/ 0), - new EmitUnencryptedLog(/*indirect=*/ 0, /*eventSelector=*/ 0, /*offset=*/ 0, /*logSizeOffset=*/ 0), + new EmitUnencryptedLog(/*indirect=*/ 0, /*offset=*/ 0, /*logSizeOffset=*/ 0), new SendL2ToL1Message(/*indirect=*/ 0, /*recipientOffset=*/ 0, /*contentOffset=*/ 1), ]; diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts index 97a21cf14409..6be6d2d81926 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.ts @@ -217,20 +217,9 @@ export class EmitUnencryptedLog extends Instruction { static type: string = 'EMITUNENCRYPTEDLOG'; static readonly opcode: Opcode = Opcode.EMITUNENCRYPTEDLOG; // Informs (de)serialization. See Instruction.deserialize. - static readonly wireFormat = [ - OperandType.UINT8, - OperandType.UINT8, - OperandType.UINT32, - OperandType.UINT32, - OperandType.UINT32, - ]; + static readonly wireFormat = [OperandType.UINT8, OperandType.UINT8, OperandType.UINT32, OperandType.UINT32]; - constructor( - private indirect: number, - private eventSelectorOffset: number, - private logOffset: number, - private logSizeOffset: number, - ) { + constructor(private indirect: number, private logOffset: number, private logSizeOffset: number) { super(); } @@ -241,22 +230,20 @@ export class EmitUnencryptedLog extends Instruction { const memory = context.machineState.memory.track(this.type); - const [eventSelectorOffset, logOffset, logSizeOffset] = Addressing.fromWire(this.indirect).resolve( - [this.eventSelectorOffset, this.logOffset, this.logSizeOffset], + const [logOffset, logSizeOffset] = Addressing.fromWire(this.indirect).resolve( + [this.logOffset, this.logSizeOffset], memory, ); - memory.checkTag(TypeTag.FIELD, eventSelectorOffset); memory.checkTag(TypeTag.UINT32, logSizeOffset); const logSize = memory.get(logSizeOffset).toNumber(); memory.checkTagsRange(TypeTag.FIELD, logOffset, logSize); const contractAddress = context.environment.address; - const event = memory.get(eventSelectorOffset).toFr(); - const memoryOperations = { reads: 2 + logSize, indirect: this.indirect }; + const memoryOperations = { reads: 1 + logSize, indirect: this.indirect }; context.machineState.consumeGas(this.gasCost(memoryOperations)); const log = memory.getSlice(logOffset, logSize).map(f => f.toFr()); - context.persistableState.writeUnencryptedLog(contractAddress, event, log); + context.persistableState.writeUnencryptedLog(contractAddress, log); memory.assert(memoryOperations); context.machineState.incrementPc(); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts index 3b447af01a43..abf0b7e3936b 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.test.ts @@ -1,5 +1,11 @@ +import { GasFees } from '@aztec/circuits.js'; +import { FunctionSelector as FunctionSelectorType } from '@aztec/foundation/abi'; +import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; +import { randomInt } from 'crypto'; + +import { type AvmContext } from '../avm_context.js'; import { TypeTag } from '../avm_memory_types.js'; import { initContext, initExecutionEnvironment, initGlobalVariables } from '../fixtures/index.js'; import { @@ -8,6 +14,7 @@ import { ChainId, FeePerDAGas, FeePerL2Gas, + FunctionSelector, Sender, StorageAddress, Timestamp, @@ -15,76 +22,84 @@ import { Version, } from './environment_getters.js'; -type EnvInstruction = - | typeof FeePerL2Gas - | typeof FeePerDAGas +type GetterInstruction = | typeof Sender | typeof StorageAddress | typeof Address - | typeof TransactionFee; - -describe.each([ - [FeePerL2Gas, 'feePerL2Gas'], - [FeePerDAGas, 'feePerDaGas'], - [Sender, 'sender'], - [StorageAddress, 'storageAddress'], - [Address, 'address'], - [TransactionFee, 'transactionFee'], -])('Environment getters instructions', (clsValue: EnvInstruction, key: string) => { - it(`${clsValue.name} should (de)serialize correctly`, () => { - const buf = Buffer.from([ - clsValue.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + | typeof FunctionSelector + | typeof TransactionFee + | typeof ChainId + | typeof Version + | typeof BlockNumber + | typeof Timestamp + | typeof FeePerDAGas + | typeof FeePerL2Gas; - expect(clsValue.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); +describe('Environment getters', () => { + const address = AztecAddress.random(); + const storageAddress = AztecAddress.random(); + const sender = AztecAddress.random(); + const functionSelector = FunctionSelectorType.random(); + const transactionFee = Fr.random(); + const chainId = Fr.random(); + const version = Fr.random(); + const blockNumber = Fr.random(); + const timestamp = new Fr(randomInt(100000)); // cap timestamp since must fit in u64 + const feePerDaGas = Fr.random(); + const feePerL2Gas = Fr.random(); + const gasFees = new GasFees(feePerDaGas, feePerL2Gas); + const globals = initGlobalVariables({ + chainId, + version, + blockNumber, + timestamp, + gasFees, }); - - it(`${clsValue.name} should read '${key}' correctly`, async () => { - const value = new Fr(123456n); - const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); - const context = initContext({ env: initExecutionEnvironment({ [key]: value }) }); - - await instruction.execute(context); - - expect(context.machineState.memory.getTag(0)).toBe(TypeTag.FIELD); - const actual = context.machineState.memory.get(0).toFr(); - expect(actual).toEqual(value); + const env = initExecutionEnvironment({ + address, + storageAddress, + sender, + functionSelector, + transactionFee, + globals, }); -}); - -type GlobalsInstruction = typeof ChainId | typeof Version | typeof BlockNumber | typeof Timestamp; -describe.each([ - [ChainId, 'chainId', TypeTag.FIELD], - [Version, 'version', TypeTag.FIELD], - [BlockNumber, 'blockNumber', TypeTag.FIELD], - [Timestamp, 'timestamp', TypeTag.UINT64], -])('Global Variables', (clsValue: GlobalsInstruction, key: string, tag: TypeTag) => { - it(`${clsValue.name} should (de)serialize correctly`, () => { - const buf = Buffer.from([ - clsValue.opcode, // opcode - 0x01, // indirect - ...Buffer.from('12345678', 'hex'), // dstOffset - ]); - const inst = new clsValue(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); - - expect(clsValue.deserialize(buf)).toEqual(inst); - expect(inst.serialize()).toEqual(buf); + let context: AvmContext; + beforeEach(() => { + context = initContext({ env }); }); - it(`${clsValue.name} should read '${key}' correctly`, async () => { - const value = new Fr(123456n); - const instruction = new clsValue(/*indirect=*/ 0, /*dstOffset=*/ 0); - const globals = initGlobalVariables({ [key]: value }); - const context = initContext({ env: initExecutionEnvironment({ globals }) }); + describe.each([ + [Address, address.toField()], + [StorageAddress, storageAddress.toField()], + [Sender, sender.toField()], + [FunctionSelector, functionSelector.toField(), TypeTag.UINT32], + [TransactionFee, transactionFee.toField()], + [ChainId, chainId.toField()], + [Version, version.toField()], + [BlockNumber, blockNumber.toField()], + [Timestamp, timestamp.toField(), TypeTag.UINT64], + [FeePerDAGas, feePerDaGas.toField()], + [FeePerL2Gas, feePerL2Gas.toField()], + ])('Environment getters instructions', (instrClass: GetterInstruction, value: Fr, tag: TypeTag = TypeTag.FIELD) => { + it(`${instrClass.name} should (de)serialize correctly`, () => { + const buf = Buffer.from([ + instrClass.opcode, // opcode + 0x01, // indirect + ...Buffer.from('12345678', 'hex'), // dstOffset + ]); + const instr = new instrClass(/*indirect=*/ 0x01, /*dstOffset=*/ 0x12345678); + + expect(instrClass.deserialize(buf)).toEqual(instr); + expect(instr.serialize()).toEqual(buf); + }); + it(`${instrClass.name} should read '${instrClass.type}' correctly`, async () => { + const instruction = new instrClass(/*indirect=*/ 0, /*dstOffset=*/ 0); - await instruction.execute(context); + await instruction.execute(context); - expect(context.machineState.memory.getTag(0)).toBe(tag); - const actual = context.machineState.memory.get(0).toFr(); - expect(actual).toEqual(value); + expect(context.machineState.memory.getTag(0)).toBe(tag); + const actual = context.machineState.memory.get(0).toFr(); + expect(actual).toEqual(value); + }); }); }); diff --git a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts index 53dbb24cfe58..6373382acf66 100644 --- a/yarn-project/simulator/src/avm/opcodes/environment_getters.ts +++ b/yarn-project/simulator/src/avm/opcodes/environment_getters.ts @@ -1,6 +1,6 @@ import type { AvmContext } from '../avm_context.js'; import type { AvmExecutionEnvironment } from '../avm_execution_environment.js'; -import { Field, type MemoryValue, Uint64 } from '../avm_memory_types.js'; +import { Field, type MemoryValue, Uint32, Uint64 } from '../avm_memory_types.js'; import { Opcode } from '../serialization/instruction_serialization.js'; import { GetterInstruction } from './instruction_impl.js'; @@ -39,21 +39,12 @@ export class Sender extends EnvironmentGetterInstruction { } } -export class FeePerL2Gas extends EnvironmentGetterInstruction { - static type: string = 'FEEPERL2GAS'; - static readonly opcode: Opcode = Opcode.FEEPERL2GAS; - - protected getEnvironmentValue(env: AvmExecutionEnvironment) { - return new Field(env.feePerL2Gas); - } -} - -export class FeePerDAGas extends EnvironmentGetterInstruction { - static type: string = 'FEEPERDAGAS'; - static readonly opcode: Opcode = Opcode.FEEPERDAGAS; +export class FunctionSelector extends EnvironmentGetterInstruction { + static type: string = 'FUNCTIONSELECTOR'; + static readonly opcode: Opcode = Opcode.FUNCTIONSELECTOR; protected getEnvironmentValue(env: AvmExecutionEnvironment) { - return new Field(env.feePerDaGas); + return new Uint32(env.functionSelector.value); } } @@ -101,3 +92,21 @@ export class Timestamp extends EnvironmentGetterInstruction { return new Uint64(env.globals.timestamp.toBigInt()); } } + +export class FeePerL2Gas extends EnvironmentGetterInstruction { + static type: string = 'FEEPERL2GAS'; + static readonly opcode: Opcode = Opcode.FEEPERL2GAS; + + protected getEnvironmentValue(env: AvmExecutionEnvironment) { + return new Field(env.globals.gasFees.feePerL2Gas); + } +} + +export class FeePerDAGas extends EnvironmentGetterInstruction { + static type: string = 'FEEPERDAGAS'; + static readonly opcode: Opcode = Opcode.FEEPERDAGAS; + + protected getEnvironmentValue(env: AvmExecutionEnvironment) { + return new Field(env.globals.gasFees.feePerDaGas); + } +} diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index 19da62cc3a19..b6ce36a0cd80 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -3,9 +3,9 @@ import { Fr } from '@aztec/foundation/fields'; import { mock } from 'jest-mock-extended'; import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; -import { markBytecodeAsAvm } from '../../public/transitional_adaptors.js'; import { type AvmContext } from '../avm_context.js'; import { Field, Uint8, Uint32 } from '../avm_memory_types.js'; +import { markBytecodeAsAvm } from '../bytecode_utils.js'; import { adjustCalldataIndex, initContext, initHostStorage, initPersistableStateManager } from '../fixtures/index.js'; import { type HostStorage } from '../journal/host_storage.js'; import { type AvmPersistableStateManager } from '../journal/journal.js'; diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.ts index 3830d4db0e98..034f666cb7f7 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.ts @@ -2,9 +2,9 @@ import { FunctionSelector, Gas } from '@aztec/circuits.js'; import { padArrayEnd } from '@aztec/foundation/collection'; import type { AvmContext } from '../avm_context.js'; +import { type AvmContractCallResult } from '../avm_contract_call_result.js'; import { gasLeftToGas } from '../avm_gas.js'; import { Field, TypeTag, Uint8 } from '../avm_memory_types.js'; -import { type AvmContractCallResults } from '../avm_message_call_result.js'; import { AvmSimulator } from '../avm_simulator.js'; import { RethrownError } from '../errors.js'; import { Opcode, OperandType } from '../serialization/instruction_serialization.js'; @@ -88,7 +88,7 @@ abstract class ExternalCall extends Instruction { ); const simulator = new AvmSimulator(nestedContext); - const nestedCallResults: AvmContractCallResults = await simulator.execute(); + const nestedCallResults: AvmContractCallResult = await simulator.execute(); const success = !nestedCallResults.reverted; // TRANSITIONAL: We rethrow here so that the MESSAGE gets propagated. @@ -120,7 +120,6 @@ abstract class ExternalCall extends Instruction { // Accept the nested call's state and trace the nested call await context.persistableState.processNestedCall( /*nestedState=*/ nestedContext.persistableState, - /*success=*/ success, /*nestedEnvironment=*/ nestedContext.environment, /*startGasLeft=*/ Gas.from(allocatedGas), /*endGasLeft=*/ Gas.from(nestedContext.machineState.gasLeft), diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts index 82641334b25c..4dd26fb13ddf 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.test.ts @@ -84,7 +84,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), new StaticCall( /*indirect=*/ 0x01, @@ -95,7 +95,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), ]; const bytecode = Buffer.concat(instructions.map(i => i.serialize())); @@ -119,7 +119,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), new StaticCall( /*indirect=*/ 0x01, @@ -130,7 +130,7 @@ describe('Bytecode Serialization', () => { /*retOffset=*/ 0xd2345678, /*retSize=*/ 0xe2345678, /*successOffset=*/ 0xf2345678, - /*temporaryFunctionSelectorOffset=*/ 0xf3345678, + /*functionSelectorOffset=*/ 0xf3345678, ), ]; diff --git a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts index f3afe05e0888..c011b3a33cb2 100644 --- a/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/bytecode_serialization.ts @@ -21,6 +21,7 @@ import { FeePerDAGas, FeePerL2Gas, FieldDiv, + FunctionSelector, GetContractInstance, InternalCall, InternalReturn, @@ -85,16 +86,16 @@ const INSTRUCTION_SET = () => [Address.opcode, Address], [StorageAddress.opcode, StorageAddress], [Sender.opcode, Sender], - [FeePerL2Gas.opcode, FeePerL2Gas], - [FeePerDAGas.opcode, FeePerDAGas], + [FunctionSelector.opcode, FunctionSelector], [TransactionFee.opcode, TransactionFee], - //[Contractcalldepth.opcode, Contractcalldepth], // Execution Environment - Globals [ChainId.opcode, ChainId], [Version.opcode, Version], [BlockNumber.opcode, BlockNumber], [Timestamp.opcode, Timestamp], //[Coinbase.opcode, Coinbase], + [FeePerL2Gas.opcode, FeePerL2Gas], + [FeePerDAGas.opcode, FeePerDAGas], //[Blockl2gaslimit.opcode, Blockl2gaslimit], //[Blockdagaslimit.opcode, Blockdagaslimit], // Execution Environment - Calldata diff --git a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts index 0a4ee888fcf2..27aa64d3e1ff 100644 --- a/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts +++ b/yarn-project/simulator/src/avm/serialization/instruction_serialization.ts @@ -27,15 +27,15 @@ export enum Opcode { ADDRESS, STORAGEADDRESS, SENDER, - FEEPERL2GAS, - FEEPERDAGAS, + FUNCTIONSELECTOR, TRANSACTIONFEE, - CONTRACTCALLDEPTH, CHAINID, VERSION, BLOCKNUMBER, TIMESTAMP, COINBASE, + FEEPERL2GAS, + FEEPERDAGAS, BLOCKL2GASLIMIT, BLOCKDAGASLIMIT, CALLDATACOPY, diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 7da0e48928de..33c2d5beec9f 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -459,9 +459,9 @@ export class ClientExecutionContext extends ViewDataOracle { #checkValidStaticCall(childExecutionResult: ExecutionResult) { if ( - childExecutionResult.callStackItem.publicInputs.newNoteHashes.some(item => !item.isEmpty()) || - childExecutionResult.callStackItem.publicInputs.newNullifiers.some(item => !item.isEmpty()) || - childExecutionResult.callStackItem.publicInputs.newL2ToL1Msgs.some(item => !item.isEmpty()) || + childExecutionResult.callStackItem.publicInputs.noteHashes.some(item => !item.isEmpty()) || + childExecutionResult.callStackItem.publicInputs.nullifiers.some(item => !item.isEmpty()) || + childExecutionResult.callStackItem.publicInputs.l2ToL1Msgs.some(item => !item.isEmpty()) || childExecutionResult.callStackItem.publicInputs.encryptedLogsHashes.some(item => !item.isEmpty()) || childExecutionResult.callStackItem.publicInputs.unencryptedLogsHashes.some(item => !item.isEmpty()) ) { @@ -678,16 +678,25 @@ export class ClientExecutionContext extends ViewDataOracle { /** * Read the public storage data. + * @param contractAddress - The address to read storage from. * @param startStorageSlot - The starting storage slot. + * @param blockNumber - The block number to read storage at. * @param numberOfElements - Number of elements to read from the starting storage slot. */ - public override async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise { + public override async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, + numberOfElements: number, + ): Promise { const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = new Fr(startStorageSlot.value + i); - const value = await this.aztecNode.getPublicStorageAt(this.callContext.storageContractAddress, storageSlot); - this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`); + const value = await this.aztecNode.getPublicStorageAt(contractAddress, storageSlot, blockNumber); + this.log.debug( + `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`, + ); values.push(value); } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index c46153495fbc..7eeb02a34d1e 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -2,6 +2,7 @@ import { type AztecNode, EncryptedNoteFunctionL2Logs, type L1ToL2Message, + type L2BlockNumber, Note, PackedValues, PublicDataWitness, @@ -67,7 +68,7 @@ import { MessageLoadOracleInputs } from '../acvm/index.js'; import { buildL1ToL2Message } from '../test/utils.js'; import { computeSlotForMapping } from '../utils.js'; import { type DBOracle } from './db_oracle.js'; -import { type ExecutionResult, collectSortedEncryptedLogs, collectSortedUnencryptedLogs } from './execution_result.js'; +import { type ExecutionResult, collectSortedEncryptedLogs } from './execution_result.js'; import { AcirSimulator } from './simulator.js'; jest.setTimeout(60_000); @@ -262,45 +263,16 @@ describe('Private Execution test suite', () => { ), ); + node = mock(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + node.getPublicStorageAt.mockImplementation((address: Fr, storageSlot: Fr, blockNumber: L2BlockNumber) => { + return Promise.resolve(Fr.ZERO); + }); + acirSimulator = new AcirSimulator(oracle, node); }); describe('no constructor', () => { - it('emits a field as an unencrypted log', async () => { - const artifact = getFunctionArtifact(TestContractArtifact, 'emit_msg_sender'); - const result = await runSimulator({ artifact, msgSender: owner }); - - const newUnencryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.unencryptedLogsHashes); - expect(newUnencryptedLogs).toHaveLength(1); - - const functionLogs = collectSortedUnencryptedLogs(result); - expect(functionLogs.logs).toHaveLength(1); - - const [unencryptedLog] = newUnencryptedLogs; - expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); - expect(unencryptedLog.length).toEqual(new Fr(functionLogs.getKernelLength())); - // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted - expect(functionLogs.logs[0].data.subarray(-32).toString('hex')).toEqual(owner.toBuffer().toString('hex')); - }); - - it('emits a field array as an unencrypted log', async () => { - const artifact = getFunctionArtifact(TestContractArtifact, 'emit_unencrypted_logs'); - const args = times(5, () => Fr.random()); - const result = await runSimulator({ artifact, msgSender: owner, args: [args, false] }); - - const newUnencryptedLogs = getNonEmptyItems(result.callStackItem.publicInputs.unencryptedLogsHashes); - expect(newUnencryptedLogs).toHaveLength(1); - const functionLogs = collectSortedUnencryptedLogs(result); - expect(functionLogs.logs).toHaveLength(1); - - const [unencryptedLog] = newUnencryptedLogs; - expect(unencryptedLog.value).toEqual(Fr.fromBuffer(functionLogs.logs[0].hash())); - expect(unencryptedLog.length).toEqual(new Fr(functionLogs.getKernelLength())); - // Test that the log payload (ie ignoring address, selector, and header) matches what we emitted - const expected = Buffer.concat(args.map(arg => arg.toBuffer())).toString('hex'); - expect(functionLogs.logs[0].data.subarray(-32 * 5).toString('hex')).toEqual(expected); - }); - it('emits a field array as an encrypted log', async () => { // NB: this test does NOT cover correct enc/dec of values, just whether // the kernels correctly populate non-note encrypted logs @@ -341,7 +313,7 @@ describe('Private Execution test suite', () => { // noteHashes. A TX's real first nullifier (generated by the initial kernel) and a noteHash's // array index at the output of the final kernel/ordering circuit are used to derive nonce via: // `hash(firstNullifier, noteHashIndex)` - const noteHashIndex = randomInt(1); // mock index in TX's final newNoteHashes array + const noteHashIndex = randomInt(1); // mock index in TX's final noteHashes array const nonce = computeNoteHashNonce(mockFirstNullifier, noteHashIndex); const note = new Note([new Fr(amount), ownerNpkMHash, Fr.random()]); const innerNoteHash = pedersenHash(note.items); @@ -380,9 +352,9 @@ describe('Private Execution test suite', () => { expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner)); expect(newNote.noteTypeId).toEqual(valueNoteTypeId); // ValueNote - const newNoteHashes = getNonEmptyItems(result.callStackItem.publicInputs.newNoteHashes); - expect(newNoteHashes).toHaveLength(1); - expect(newNoteHashes[0].value).toEqual( + const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashes).toHaveLength(1); + expect(noteHashes[0].value).toEqual( await acirSimulator.computeInnerNoteHash( contractAddress, newNote.storageSlot, @@ -395,7 +367,7 @@ describe('Private Execution test suite', () => { expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.noteHashCounter).toEqual(noteHashes[0].counter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); expect(encryptedLog.length).toEqual(new Fr(getEncryptedNoteSerializedLength(result))); }); @@ -410,9 +382,9 @@ describe('Private Execution test suite', () => { expect(newNote.storageSlot).toEqual(computeSlotForMapping(new Fr(1n), owner)); expect(newNote.noteTypeId).toEqual(valueNoteTypeId); // ValueNote - const newNoteHashes = getNonEmptyItems(result.callStackItem.publicInputs.newNoteHashes); - expect(newNoteHashes).toHaveLength(1); - expect(newNoteHashes[0].value).toEqual( + const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashes).toHaveLength(1); + expect(noteHashes[0].value).toEqual( await acirSimulator.computeInnerNoteHash( contractAddress, newNote.storageSlot, @@ -425,7 +397,7 @@ describe('Private Execution test suite', () => { expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.noteHashCounter).toEqual(noteHashes[0].counter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); expect(encryptedLog.length).toEqual(new Fr(getEncryptedNoteSerializedLength(result))); }); @@ -462,18 +434,18 @@ describe('Private Execution test suite', () => { const result = await runSimulator({ args, artifact, msgSender: owner }); // The two notes were nullified - const newNullifiers = getNonEmptyItems(result.callStackItem.publicInputs.newNullifiers).map(n => n.value); - expect(newNullifiers).toHaveLength(consumedNotes.length); - expect(newNullifiers).toEqual(expect.arrayContaining(consumedNotes.map(n => n.innerNullifier))); + const nullifiers = getNonEmptyItems(result.callStackItem.publicInputs.nullifiers).map(n => n.value); + expect(nullifiers).toHaveLength(consumedNotes.length); + expect(nullifiers).toEqual(expect.arrayContaining(consumedNotes.map(n => n.innerNullifier))); expect(result.newNotes).toHaveLength(2); const [changeNote, recipientNote] = result.newNotes; expect(recipientNote.storageSlot).toEqual(recipientStorageSlot); expect(recipientNote.noteTypeId).toEqual(valueNoteTypeId); - const newNoteHashes = getNonEmptyItems(result.callStackItem.publicInputs.newNoteHashes); - expect(newNoteHashes).toHaveLength(2); - const [changeNoteHash, recipientNoteHash] = newNoteHashes; + const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashes).toHaveLength(2); + const [changeNoteHash, recipientNoteHash] = noteHashes; const [recipientInnerNoteHash, changeInnerNoteHash] = [ await acirSimulator.computeInnerNoteHash( contractAddress, @@ -538,8 +510,8 @@ describe('Private Execution test suite', () => { const args = [recipient, amountToTransfer]; const result = await runSimulator({ args, artifact, msgSender: owner }); - const newNullifiers = getNonEmptyItems(result.callStackItem.publicInputs.newNullifiers).map(n => n.value); - expect(newNullifiers).toEqual(consumedNotes.map(n => n.innerNullifier)); + const nullifiers = getNonEmptyItems(result.callStackItem.publicInputs.nullifiers).map(n => n.value); + expect(nullifiers).toEqual(consumedNotes.map(n => n.innerNullifier)); expect(result.newNotes).toHaveLength(2); const [changeNote, recipientNote] = result.newNotes; @@ -550,9 +522,9 @@ describe('Private Execution test suite', () => { expect(newEncryptedLogs).toHaveLength(2); const [encryptedChangeLog, encryptedRecipientLog] = newEncryptedLogs; expect(encryptedChangeLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); - expect(encryptedChangeLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.newNoteHashes[0].counter); + expect(encryptedChangeLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.noteHashes[0].counter); expect(encryptedRecipientLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[1].log.hash())); - expect(encryptedRecipientLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.newNoteHashes[1].counter); + expect(encryptedRecipientLog.noteHashCounter).toEqual(result.callStackItem.publicInputs.noteHashes[1].counter); expect(encryptedChangeLog.length.add(encryptedRecipientLog.length)).toEqual( new Fr(getEncryptedNoteSerializedLength(result)), ); @@ -706,8 +678,8 @@ describe('Private Execution test suite', () => { }); // Check a nullifier has been inserted - const newNullifiers = getNonEmptyItems(result.callStackItem.publicInputs.newNullifiers); - expect(newNullifiers).toHaveLength(1); + const nullifiers = getNonEmptyItems(result.callStackItem.publicInputs.nullifiers); + expect(nullifiers).toHaveLength(1); }); it('Invalid membership proof', async () => { @@ -869,8 +841,8 @@ describe('Private Execution test suite', () => { const result = await runSimulator({ artifact, args: [secret] }); // Check a nullifier has been inserted. - const newNullifiers = getNonEmptyItems(result.callStackItem.publicInputs.newNullifiers); - expect(newNullifiers).toHaveLength(1); + const nullifiers = getNonEmptyItems(result.callStackItem.publicInputs.nullifiers); + expect(nullifiers).toHaveLength(1); // Check the commitment read request was created successfully. const readRequests = getNonEmptyItems(result.callStackItem.publicInputs.noteHashReadRequests); @@ -952,7 +924,7 @@ describe('Private Execution test suite', () => { describe('setting fee payer', () => { it('should default to not being a fee payer', async () => { // arbitrary random function that doesn't set a fee payer - const entrypoint = getFunctionArtifact(TestContractArtifact, 'emit_msg_sender'); + const entrypoint = getFunctionArtifact(TestContractArtifact, 'get_this_address'); const contractAddress = AztecAddress.random(); const result = await runSimulator({ artifact: entrypoint, contractAddress }); expect(result.callStackItem.publicInputs.isFeePayer).toBe(false); @@ -1000,10 +972,10 @@ describe('Private Execution test suite', () => { expect(noteAndSlot.note.items[0]).toEqual(new Fr(amountToTransfer)); - const newNoteHashes = getNonEmptyItems(result.callStackItem.publicInputs.newNoteHashes); - expect(newNoteHashes).toHaveLength(1); + const noteHashes = getNonEmptyItems(result.callStackItem.publicInputs.noteHashes); + expect(noteHashes).toHaveLength(1); - const noteHash = newNoteHashes[0].value; + const noteHash = noteHashes[0].value; const storageSlot = computeSlotForMapping( PendingNoteHashesContractArtifact.storageLayout['balances'].slot, owner, @@ -1021,7 +993,7 @@ describe('Private Execution test suite', () => { expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.noteHashCounter).toEqual(noteHashes[0].counter); expect(encryptedLog.noteHashCounter).toEqual(result.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(result.noteEncryptedLogs[0].log.hash())); @@ -1031,7 +1003,7 @@ describe('Private Execution test suite', () => { expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); - const nullifier = result.callStackItem.publicInputs.newNullifiers[0]; + const nullifier = result.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2Hash([ innerNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress), @@ -1089,10 +1061,10 @@ describe('Private Execution test suite', () => { expect(noteAndSlot.note.items[0]).toEqual(new Fr(amountToTransfer)); - const newNoteHashes = getNonEmptyItems(execInsert.callStackItem.publicInputs.newNoteHashes); - expect(newNoteHashes).toHaveLength(1); + const noteHashes = getNonEmptyItems(execInsert.callStackItem.publicInputs.noteHashes); + expect(noteHashes).toHaveLength(1); - const noteHash = newNoteHashes[0].value; + const noteHash = noteHashes[0].value; const innerNoteHash = await acirSimulator.computeInnerNoteHash( contractAddress, noteAndSlot.storageSlot, @@ -1105,7 +1077,7 @@ describe('Private Execution test suite', () => { expect(newEncryptedLogs).toHaveLength(1); const [encryptedLog] = newEncryptedLogs; - expect(encryptedLog.noteHashCounter).toEqual(newNoteHashes[0].counter); + expect(encryptedLog.noteHashCounter).toEqual(noteHashes[0].counter); expect(encryptedLog.noteHashCounter).toEqual(execInsert.noteEncryptedLogs[0].noteHashCounter); expect(encryptedLog.value).toEqual(Fr.fromBuffer(execInsert.noteEncryptedLogs[0].log.hash())); @@ -1115,7 +1087,7 @@ describe('Private Execution test suite', () => { expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); - const nullifier = execGetThenNullify.callStackItem.publicInputs.newNullifiers[0]; + const nullifier = execGetThenNullify.callStackItem.publicInputs.nullifiers[0]; const expectedNullifier = poseidon2Hash([ innerNoteHash, computeAppNullifierSecretKey(ownerNskM, contractAddress), diff --git a/yarn-project/simulator/src/client/view_data_oracle.ts b/yarn-project/simulator/src/client/view_data_oracle.ts index fd1710205dcc..75e7f1802338 100644 --- a/yarn-project/simulator/src/client/view_data_oracle.ts +++ b/yarn-project/simulator/src/client/view_data_oracle.ts @@ -260,16 +260,25 @@ export class ViewDataOracle extends TypedOracle { /** * Read the public storage data. + * @param contractAddress - The address to read storage from. * @param startStorageSlot - The starting storage slot. + * @param blockNumber - The block number to read storage at. * @param numberOfElements - Number of elements to read from the starting storage slot. */ - public override async storageRead(startStorageSlot: Fr, numberOfElements: number) { + public override async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, + numberOfElements: number, + ) { const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = new Fr(startStorageSlot.value + i); - const value = await this.aztecNode.getPublicStorageAt(this.contractAddress, storageSlot); + const value = await this.aztecNode.getPublicStorageAt(contractAddress, storageSlot, blockNumber); - this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`); + this.log.debug( + `Oracle storage read: slot=${storageSlot.toString()} address-${contractAddress.toString()} value=${value}`, + ); values.push(value); } return values; diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index 7bbd49b1f7a5..2dd199084a15 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -14,10 +14,10 @@ import { makeAztecAddress, makeSelector } from '@aztec/circuits.js/testing'; import { FunctionType } from '@aztec/foundation/abi'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { type PublicExecution, type PublicExecutionResult } from '../public/execution.js'; +import { type PublicExecutionRequest, type PublicExecutionResult } from '../public/execution.js'; export class PublicExecutionResultBuilder { - private _execution: PublicExecution; + private _executionRequest: PublicExecutionRequest; private _nestedExecutions: PublicExecutionResult[] = []; private _contractStorageUpdateRequests: ContractStorageUpdateRequest[] = []; private _contractStorageReads: ContractStorageRead[] = []; @@ -25,8 +25,8 @@ export class PublicExecutionResultBuilder { private _reverted = false; private _revertReason: SimulationError | undefined = undefined; - constructor(execution: PublicExecution) { - this._execution = execution; + constructor(executionRequest: PublicExecutionRequest) { + this._executionRequest = executionRequest; } static fromPublicCallRequest({ @@ -120,7 +120,7 @@ export class PublicExecutionResultBuilder { build(overrides: Partial = {}): PublicExecutionResult { return { - execution: this._execution, + executionRequest: this._executionRequest, nestedExecutions: this._nestedExecutions, noteHashReadRequests: [], nullifierReadRequests: [], @@ -128,9 +128,9 @@ export class PublicExecutionResultBuilder { l1ToL2MsgReadRequests: [], contractStorageUpdateRequests: this._contractStorageUpdateRequests, returnValues: padArrayEnd(this._returnValues, Fr.ZERO, 4), // TODO(#5450) Need to use the proper return values here - newNoteHashes: [], - newNullifiers: [], - newL2ToL1Messages: [], + noteHashes: [], + nullifiers: [], + l2ToL1Messages: [], contractStorageReads: [], unencryptedLogsHashes: [], unencryptedLogs: UnencryptedFunctionL2Logs.empty(), diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.test.ts b/yarn-project/simulator/src/public/abstract_phase_manager.test.ts index 58a2881e5370..d17cd896a4e6 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.test.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.test.ts @@ -10,16 +10,16 @@ describe('AbstractPhaseManager utils', () => { const startingCounter = AbstractPhaseManager.getMaxSideEffectCounter(inputs); - inputs.endNonRevertibleData.newNoteHashes.at(-1)!.counter = startingCounter + 1; + inputs.endNonRevertibleData.noteHashes.at(-1)!.counter = startingCounter + 1; expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 1); inputs.endNonRevertibleData.publicCallStack.at(-1)!.startSideEffectCounter = new Fr(startingCounter + 2); expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 2); - inputs.end.newNoteHashes.at(-1)!.counter = startingCounter + 3; + inputs.end.noteHashes.at(-1)!.counter = startingCounter + 3; expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 3); - inputs.end.newNullifiers.at(-1)!.counter = startingCounter + 4; + inputs.end.nullifiers.at(-1)!.counter = startingCounter + 4; expect(AbstractPhaseManager.getMaxSideEffectCounter(inputs)).toBe(startingCounter + 4); }); }); diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index fecc49988d2f..ec278a3c9a55 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -25,10 +25,10 @@ import { L2ToL1Message, LogHash, MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - MAX_NEW_NOTE_HASHES_PER_CALL, - MAX_NEW_NULLIFIERS_PER_CALL, + MAX_L2_TO_L1_MSGS_PER_CALL, + MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, + MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, @@ -57,7 +57,7 @@ import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { - type PublicExecution, + type PublicExecutionRequest, type PublicExecutionResult, type PublicExecutor, accumulateReturnValues, @@ -176,12 +176,14 @@ export abstract class AbstractPhaseManager { call => revertibleCallStack.find(p => p.equals(call)) || nonRevertibleCallStack.find(p => p.equals(call)), ); + const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall]; + if (callRequestsStack.length === 0) { return { [PublicKernelType.NON_PUBLIC]: [], [PublicKernelType.SETUP]: [], [PublicKernelType.APP_LOGIC]: [], - [PublicKernelType.TEARDOWN]: [], + [PublicKernelType.TEARDOWN]: teardownCallStack, [PublicKernelType.TAIL]: [], }; } @@ -191,8 +193,6 @@ export abstract class AbstractPhaseManager { c => revertibleCallStack.findIndex(p => p.equals(c)) !== -1, ); - const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall]; - if (firstRevertibleCallIndex === 0) { return { [PublicKernelType.NON_PUBLIC]: [], @@ -256,7 +256,7 @@ export abstract class AbstractPhaseManager { const enqueuedCallResults = []; for (const enqueuedCall of enqueuedCalls) { - const executionStack: (PublicExecution | PublicExecutionResult)[] = [enqueuedCall]; + const executionStack: (PublicExecutionRequest | PublicExecutionResult)[] = [enqueuedCall]; // Keep track of which result is for the top/enqueued call let enqueuedExecutionResult: PublicExecutionResult | undefined; @@ -283,10 +283,10 @@ export abstract class AbstractPhaseManager { // Sanity check for a current upstream assumption. // Consumers of the result seem to expect "reverted <=> revertReason !== undefined". - const functionSelector = result.execution.functionSelector.toString(); + const functionSelector = result.executionRequest.functionSelector.toString(); if (result.reverted && !result.revertReason) { throw new Error( - `Simulation of ${result.execution.contractAddress.toString()}:${functionSelector}(${ + `Simulation of ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ result.functionName }) reverted with no reason.`, ); @@ -294,7 +294,7 @@ export abstract class AbstractPhaseManager { if (result.reverted && !PhaseIsRevertible[this.phase]) { this.log.debug( - `Simulation error on ${result.execution.contractAddress.toString()}:${functionSelector}(${ + `Simulation error on ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ result.functionName }) with reason: ${result.revertReason}`, ); @@ -308,7 +308,7 @@ export abstract class AbstractPhaseManager { // Simulate the public kernel circuit. this.log.debug( - `Running public kernel circuit for ${result.execution.contractAddress.toString()}:${functionSelector}(${ + `Running public kernel circuit for ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ result.functionName })`, ); @@ -331,7 +331,7 @@ export abstract class AbstractPhaseManager { // but the kernel carries the reverted flag forward. But if the simulator reverts, so should the kernel. if (result.reverted && kernelPublicOutput.revertCode.isOK()) { throw new Error( - `Public kernel circuit did not revert on ${result.execution.contractAddress.toString()}:${functionSelector}(${ + `Public kernel circuit did not revert on ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ result.functionName }), but simulator did.`, ); @@ -341,7 +341,7 @@ export abstract class AbstractPhaseManager { // So safely return the revert reason and the kernel output (which has had its revertible side effects dropped) if (result.reverted) { this.log.debug( - `Reverting on ${result.execution.contractAddress.toString()}:${functionSelector}(${ + `Reverting on ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${ result.functionName }) with reason: ${result.revertReason}`, ); @@ -375,7 +375,7 @@ export abstract class AbstractPhaseManager { /** Returns all pending private and public nullifiers. */ private getSiloedPendingNullifiers(ko: PublicKernelCircuitPublicInputs) { - return [...ko.end.newNullifiers, ...ko.endNonRevertibleData.newNullifiers].filter(n => !n.isEmpty()); + return [...ko.end.nullifiers, ...ko.endNonRevertibleData.nullifiers].filter(n => !n.isEmpty()); } protected getAvailableGas(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs) { @@ -430,12 +430,12 @@ export abstract class AbstractPhaseManager { ); const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({ - callContext: result.execution.callContext, + callContext: result.executionRequest.callContext, proverAddress: AztecAddress.ZERO, - argsHash: computeVarArgsHash(result.execution.args), - newNoteHashes: padArrayEnd(result.newNoteHashes, NoteHash.empty(), MAX_NEW_NOTE_HASHES_PER_CALL), - newNullifiers: padArrayEnd(result.newNullifiers, Nullifier.empty(), MAX_NEW_NULLIFIERS_PER_CALL), - newL2ToL1Msgs: padArrayEnd(result.newL2ToL1Messages, L2ToL1Message.empty(), MAX_NEW_L2_TO_L1_MSGS_PER_CALL), + argsHash: computeVarArgsHash(result.executionRequest.args), + noteHashes: padArrayEnd(result.noteHashes, NoteHash.empty(), MAX_NOTE_HASHES_PER_CALL), + nullifiers: padArrayEnd(result.nullifiers, Nullifier.empty(), MAX_NULLIFIERS_PER_CALL), + l2ToL1Msgs: padArrayEnd(result.l2ToL1Messages, L2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_CALL), startSideEffectCounter: result.startSideEffectCounter, endSideEffectCounter: result.endSideEffectCounter, returnsHash: computeVarArgsHash(result.returnValues), @@ -481,8 +481,8 @@ export abstract class AbstractPhaseManager { }); return new PublicCallStackItem( - result.execution.contractAddress, - new FunctionData(result.execution.functionSelector, false), + result.executionRequest.contractAddress, + new FunctionData(result.executionRequest.functionSelector, false), publicCircuitPublicInputs, isExecutionRequest, ); @@ -506,15 +506,15 @@ export abstract class AbstractPhaseManager { */ static getMaxSideEffectCounter(inputs: PublicKernelCircuitPublicInputs): number { const sideEffectCounters = [ - ...inputs.endNonRevertibleData.newNoteHashes, - ...inputs.endNonRevertibleData.newNullifiers, + ...inputs.endNonRevertibleData.noteHashes, + ...inputs.endNonRevertibleData.nullifiers, ...inputs.endNonRevertibleData.noteEncryptedLogsHashes, ...inputs.endNonRevertibleData.encryptedLogsHashes, ...inputs.endNonRevertibleData.unencryptedLogsHashes, ...inputs.endNonRevertibleData.publicCallStack, ...inputs.endNonRevertibleData.publicDataUpdateRequests, - ...inputs.end.newNoteHashes, - ...inputs.end.newNullifiers, + ...inputs.end.noteHashes, + ...inputs.end.nullifiers, ...inputs.end.noteEncryptedLogsHashes, ...inputs.end.encryptedLogsHashes, ...inputs.end.unencryptedLogsHashes, diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index e5ca2cecd53b..a95fee4bbb59 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -18,8 +18,8 @@ import { type Gas } from '../avm/avm_gas.js'; * The public function execution result. */ export interface PublicExecutionResult { - /** The execution that triggered this result. */ - execution: PublicExecution; + /** The execution request that triggered this result. */ + executionRequest: PublicExecutionRequest; /** The side effect counter at the start of the function call. */ startSideEffectCounter: Fr; @@ -48,11 +48,11 @@ export interface PublicExecutionResult { /** The contract storage update requests performed by the function. */ contractStorageUpdateRequests: ContractStorageUpdateRequest[]; /** The new note hashes to be inserted into the note hashes tree. */ - newNoteHashes: NoteHash[]; + noteHashes: NoteHash[]; /** The new l2 to l1 messages generated in this call. */ - newL2ToL1Messages: L2ToL1Message[]; + l2ToL1Messages: L2ToL1Message[]; /** The new nullifiers to be inserted into the nullifier tree. */ - newNullifiers: Nullifier[]; + nullifiers: Nullifier[]; /** The note hash read requests emitted in this call. */ noteHashReadRequests: ReadRequest[]; /** The nullifier read requests emitted in this call. */ @@ -90,9 +90,13 @@ export interface PublicExecutionResult { } /** - * The execution of a public function. + * The execution request of a public function. + * A subset of PublicCallRequest */ -export type PublicExecution = Pick; +export type PublicExecutionRequest = Pick< + PublicCallRequest, + 'contractAddress' | 'functionSelector' | 'callContext' | 'args' +>; /** * Returns if the input is a public execution result and not just a public execution. @@ -100,9 +104,9 @@ export type PublicExecution = Pick 0 || - newNoteHashes.length > 0 || - newNullifiers.length > 0 || - newL2ToL1Messages.length > 0 || + noteHashes.length > 0 || + nullifiers.length > 0 || + l2ToL1Messages.length > 0 || unencryptedLogs.logs.length > 0 ) { throw new Error('Static call cannot update the state, emit L2->L1 messages or generate logs'); diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 8486fb8d80e8..9a524c458c86 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -4,21 +4,21 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { AvmContext } from '../avm/avm_context.js'; +import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; import { AvmMachineState } from '../avm/avm_machine_state.js'; import { AvmSimulator } from '../avm/avm_simulator.js'; import { HostStorage } from '../avm/journal/host_storage.js'; import { AvmPersistableStateManager } from '../avm/journal/index.js'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js'; -import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js'; +import { type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; import { PublicSideEffectTrace } from './side_effect_trace.js'; -import { createAvmExecutionEnvironment } from './transitional_adaptors.js'; /** * Handles execution of public functions. */ export class PublicExecutor { constructor( - private readonly stateDb: PublicStateDB, + private readonly publicStorageDB: PublicStateDB, private readonly contractsDb: PublicContractsDB, private readonly commitmentsDb: CommitmentsDB, private readonly header: Header, @@ -38,10 +38,10 @@ export class PublicExecutor { * @returns The result of execution, including the results of all nested calls. */ public async simulate( - executionRequest: PublicExecution, + executionRequest: PublicExecutionRequest, globalVariables: GlobalVariables, availableGas: Gas, - txContext: TxContext, + _txContext: TxContext, pendingSiloedNullifiers: Nullifier[], transactionFee: Fr = Fr.ZERO, startSideEffectCounter: number = 0, @@ -53,7 +53,7 @@ export class PublicExecutor { PublicExecutor.log.verbose(`[AVM] Executing public external function ${fnName}.`); const timer = new Timer(); - const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb); + const hostStorage = new HostStorage(this.publicStorageDB, this.contractsDb, this.commitmentsDb); const trace = new PublicSideEffectTrace(startSideEffectCounter); const avmPersistableState = AvmPersistableStateManager.newWithPendingSiloedNullifiers( hostStorage, @@ -65,7 +65,6 @@ export class PublicExecutor { executionRequest, this.header, globalVariables, - txContext.gasSettings, transactionFee, ); @@ -75,7 +74,7 @@ export class PublicExecutor { const avmResult = await simulator.execute(); const bytecode = simulator.getBytecode()!; - // Commit the journals state to the DBs since this is a top-level execution. + // Commit the public storage state to the DBs since this is a top-level execution. // Observe that this will write all the state changes to the DBs, not only the latest for each slot. // However, the underlying DB keep a cache and will only write the latest state to disk. // TODO(dbanks12): this should be unnecessary here or should be exposed by state manager @@ -105,18 +104,34 @@ export class PublicExecutor { // (which counts the request itself) ); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5818): is this really needed? - // should already be handled in simulation. - if (executionRequest.callContext.isStaticCall) { - checkValidStaticCall( - publicExecutionResult.newNoteHashes, - publicExecutionResult.newNullifiers, - publicExecutionResult.contractStorageUpdateRequests, - publicExecutionResult.newL2ToL1Messages, - publicExecutionResult.unencryptedLogs, - ); - } - return publicExecutionResult; } } + +/** + * Convert a PublicExecutionRequest object to an AvmExecutionEnvironment + * + * @param executionRequest + * @param globalVariables + * @returns + */ +function createAvmExecutionEnvironment( + executionRequest: PublicExecutionRequest, + header: Header, + globalVariables: GlobalVariables, + transactionFee: Fr, +): AvmExecutionEnvironment { + return new AvmExecutionEnvironment( + executionRequest.contractAddress, + executionRequest.callContext.storageContractAddress, + executionRequest.callContext.msgSender, + executionRequest.functionSelector, + /*contractCallDepth=*/ Fr.zero(), + transactionFee, + header, + globalVariables, + executionRequest.callContext.isStaticCall, + executionRequest.callContext.isDelegateCall, + executionRequest.args, + ); +} diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index b7ee0e0506fd..7846f10f1525 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -1,7 +1,7 @@ import { MerkleTreeId } from '@aztec/circuit-types'; import { type Fr, - type MAX_NEW_NULLIFIERS_PER_TX, + type MAX_NULLIFIERS_PER_TX, type MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, type MAX_PUBLIC_DATA_HINTS, @@ -30,7 +30,7 @@ export class HintsBuilder { async getNullifierReadRequestHints( nullifierReadRequests: Tuple, - pendingNullifiers: Tuple, + pendingNullifiers: Tuple, ) { return ( await buildSiloedNullifierReadRequestHints( @@ -45,7 +45,7 @@ export class HintsBuilder { getNullifierNonExistentReadRequestHints( nullifierNonExistentReadRequests: Tuple, - pendingNullifiers: Tuple, + pendingNullifiers: Tuple, ) { return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers); } diff --git a/yarn-project/simulator/src/public/index.ts b/yarn-project/simulator/src/public/index.ts index 933b918f4c90..6bbddcb71e63 100644 --- a/yarn-project/simulator/src/public/index.ts +++ b/yarn-project/simulator/src/public/index.ts @@ -1,6 +1,6 @@ export * from './abstract_phase_manager.js'; export * from './db_interfaces.js'; -export { isPublicExecutionResult, type PublicExecution, type PublicExecutionResult } from './execution.js'; +export { isPublicExecutionResult, type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; export { PublicExecutor } from './executor.js'; export * from './fee_payment.js'; export { HintsBuilder } from './hints_builder.js'; diff --git a/yarn-project/simulator/src/public/public_kernel.ts b/yarn-project/simulator/src/public/public_kernel.ts index c48c9ed4512e..6910123b54e6 100644 --- a/yarn-project/simulator/src/public/public_kernel.ts +++ b/yarn-project/simulator/src/public/public_kernel.ts @@ -21,8 +21,9 @@ import { convertSimulatedPublicTeardownInputsToWitnessMap, convertSimulatedPublicTeardownOutputFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; -import { type SimulationProvider, WASMSimulator } from '@aztec/simulator'; +import { WASMSimulator } from '../providers/acvm_wasm.js'; +import { type SimulationProvider } from '../providers/simulation_provider.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; /** diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 362fd788e1db..70687522d83e 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -1017,6 +1017,79 @@ describe('public_processor', () => { expect(prover.addNewTx).toHaveBeenCalledWith(processed[0]); }); + it('runs a tx with only teardown', async function () { + const baseContractAddressSeed = 0x200; + const teardown = makePublicCallRequest(baseContractAddressSeed); + const tx = mockTxWithPartialState({ + numberOfNonRevertiblePublicCallRequests: 0, + numberOfRevertiblePublicCallRequests: 0, + publicCallRequests: [], + publicTeardownCallRequest: teardown, + }); + + const gasLimits = Gas.from({ l2Gas: 1e9, daGas: 1e9 }); + const teardownGas = Gas.from({ l2Gas: 1e7, daGas: 1e7 }); + tx.data.constants.txContext.gasSettings = GasSettings.from({ + gasLimits: gasLimits, + teardownGasLimits: teardownGas, + inclusionFee: new Fr(1e4), + maxFeesPerGas: { feePerDaGas: new Fr(10), feePerL2Gas: new Fr(10) }, + }); + + // Private kernel tail to public pushes teardown gas allocation into revertible gas used + tx.data.forPublic!.end = PublicAccumulatedDataBuilder.fromPublicAccumulatedData(tx.data.forPublic!.end) + .withGasUsed(teardownGas) + .build(); + tx.data.forPublic!.endNonRevertibleData = PublicAccumulatedDataBuilder.fromPublicAccumulatedData( + tx.data.forPublic!.endNonRevertibleData, + ) + .withGasUsed(Gas.empty()) + .build(); + + let simulatorCallCount = 0; + const txOverhead = 1e4; + const expectedTxFee = txOverhead + teardownGas.l2Gas * 1 + teardownGas.daGas * 1; + const transactionFee = new Fr(expectedTxFee); + const teardownGasUsed = Gas.from({ l2Gas: 1e6, daGas: 1e6 }); + + const simulatorResults: PublicExecutionResult[] = [ + // Teardown + PublicExecutionResultBuilder.fromPublicCallRequest({ + request: teardown, + nestedExecutions: [], + }).build({ + startGasLeft: teardownGas, + endGasLeft: teardownGas.sub(teardownGasUsed), + transactionFee, + }), + ]; + + publicExecutor.simulate.mockImplementation(execution => { + if (simulatorCallCount < simulatorResults.length) { + const result = simulatorResults[simulatorCallCount++]; + return Promise.resolve(result); + } else { + throw new Error(`Unexpected execution request: ${execution}, call count: ${simulatorCallCount}`); + } + }); + + const setupSpy = jest.spyOn(publicKernel, 'publicKernelCircuitSetup'); + const appLogicSpy = jest.spyOn(publicKernel, 'publicKernelCircuitAppLogic'); + const teardownSpy = jest.spyOn(publicKernel, 'publicKernelCircuitTeardown'); + const tailSpy = jest.spyOn(publicKernel, 'publicKernelCircuitTail'); + + const [processed, failed] = await processor.process([tx], 1, prover); + + expect(processed).toHaveLength(1); + expect(processed).toEqual([expectedTxByHash(tx)]); + expect(failed).toHaveLength(0); + + expect(setupSpy).toHaveBeenCalledTimes(0); + expect(appLogicSpy).toHaveBeenCalledTimes(0); + expect(teardownSpy).toHaveBeenCalledTimes(1); + expect(tailSpy).toHaveBeenCalledTimes(1); + }); + describe('with fee payer', () => { it('injects balance update with no public calls', async function () { const feePayer = AztecAddress.random(); diff --git a/yarn-project/simulator/src/public/side_effect_trace.test.ts b/yarn-project/simulator/src/public/side_effect_trace.test.ts index fbfb42b2e5f4..63337b137352 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.test.ts @@ -6,8 +6,7 @@ import { SerializableContractInstance } from '@aztec/types/contracts'; import { randomBytes, randomInt } from 'crypto'; -import { Selector } from '../../../foundation/src/abi/selector.js'; -import { AvmContractCallResults } from '../avm/avm_message_call_result.js'; +import { AvmContractCallResult } from '../avm/avm_contract_call_result.js'; import { initExecutionEnvironment } from '../avm/fixtures/index.js'; import { PublicSideEffectTrace, type TracedContractInstance } from './side_effect_trace.js'; @@ -25,7 +24,6 @@ describe('Side Effect Trace', () => { const value = Fr.random(); const recipient = Fr.random(); const content = Fr.random(); - const event = new Fr(randomBytes(Selector.SIZE).readUint32BE()); const log = [Fr.random(), Fr.random(), Fr.random()]; const startGasLeft = Gas.fromFields([new Fr(randomInt(10000)), new Fr(randomInt(10000))]); @@ -41,7 +39,7 @@ describe('Side Effect Trace', () => { transactionFee, }); const reverted = false; - const avmCallResults = new AvmContractCallResults(reverted, returnValues); + const avmCallResults = new AvmContractCallResult(reverted, returnValues); let startCounter: number; let startCounterFr: Fr; @@ -117,7 +115,7 @@ describe('Side Effect Trace', () => { expect(trace.getCounter()).toBe(startCounterPlus1); const pxResult = toPxResult(trace); - expect(pxResult.newNoteHashes).toEqual([ + expect(pxResult.noteHashes).toEqual([ { //storageAddress: contractAddress, value: utxo, @@ -165,7 +163,7 @@ describe('Side Effect Trace', () => { expect(trace.getCounter()).toBe(startCounterPlus1); const pxResult = toPxResult(trace); - expect(pxResult.newNullifiers).toEqual([ + expect(pxResult.nullifiers).toEqual([ { value: utxo, counter: startCounter, @@ -199,19 +197,19 @@ describe('Side Effect Trace', () => { expect(trace.getCounter()).toBe(startCounterPlus1); const pxResult = toPxResult(trace); - expect(pxResult.newL2ToL1Messages).toEqual([ + expect(pxResult.l2ToL1Messages).toEqual([ new L2ToL1Message(EthAddress.fromField(recipient), content, startCounter), ]); }); it('Should trace new unencrypted logs', () => { - trace.traceUnencryptedLog(address, event, log); + trace.traceUnencryptedLog(address, log); expect(trace.getCounter()).toBe(startCounterPlus1); const pxResult = toPxResult(trace); const expectLog = new UnencryptedL2Log( AztecAddress.fromField(address), - EventSelector.fromField(event), + EventSelector.fromField(new Fr(0)), Buffer.concat(log.map(f => f.toBuffer())), ); expect(pxResult.unencryptedLogs.logs).toEqual([expectLog]); @@ -266,7 +264,7 @@ describe('Side Effect Trace', () => { testCounter++; nestedTrace.traceNewL2ToL1Message(recipient, content); testCounter++; - nestedTrace.traceUnencryptedLog(address, event, log); + nestedTrace.traceUnencryptedLog(address, log); testCounter++; trace.traceNestedCall(nestedTrace, avmEnvironment, startGasLeft, endGasLeft, bytecode, avmCallResults); diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index 64e32718a599..c397db272ac7 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -18,17 +18,20 @@ import { } from '@aztec/circuits.js'; import { EventSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; +import { createDebugLogger } from '@aztec/foundation/log'; import { type ContractInstanceWithAddress } from '@aztec/types/contracts'; +import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { type AvmContractCallResults } from '../avm/avm_message_call_result.js'; import { createSimulationError } from '../common/errors.js'; -import { type PublicExecution, type PublicExecutionResult } from './execution.js'; +import { type PublicExecutionRequest, type PublicExecutionResult } from './execution.js'; import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js'; export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress; export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { + public logger = createDebugLogger('aztec:public_side_effect_trace'); + /** The side effect counter increments with every call to the trace. */ private sideEffectCounter: number; // kept as number until finalized for efficiency @@ -36,11 +39,11 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { private contractStorageUpdateRequests: ContractStorageUpdateRequest[] = []; private noteHashReadRequests: ReadRequest[] = []; - private newNoteHashes: NoteHash[] = []; + private noteHashes: NoteHash[] = []; private nullifierReadRequests: ReadRequest[] = []; private nullifierNonExistentReadRequests: ReadRequest[] = []; - private newNullifiers: Nullifier[] = []; + private nullifiers: Nullifier[] = []; private l1ToL2MsgReadRequests: ReadRequest[] = []; private newL2ToL1Messages: L2ToL1Message[] = []; @@ -85,6 +88,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.avmCircuitHints.storageValues.items.push( new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value), ); + this.logger.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); this.incrementSideEffectCounter(); } @@ -94,6 +98,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.contractStorageUpdateRequests.push( new ContractStorageUpdateRequest(slot, value, this.sideEffectCounter, storageAddress), ); + this.logger.debug(`SSTORE cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); this.incrementSideEffectCounter(); } @@ -106,6 +111,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.avmCircuitHints.noteHashExists.items.push( new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), ); + this.logger.debug(`NOTE_HASH_CHECK cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -116,7 +122,8 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // IS there, and the AVM circuit should accept THAT noteHash as a hint. The circuit will then compare // the noteHash against the one provided by the user code to determine what to return to the user (exists or not), // and will then propagate the actually-present noteHash to its public inputs. - this.newNoteHashes.push(new NoteHash(noteHash, this.sideEffectCounter)); + this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter)); + this.logger.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -133,13 +140,15 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.avmCircuitHints.nullifierExists.items.push( new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), ); + this.logger.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } public traceNewNullifier(_storageAddress: Fr, nullifier: Fr) { // TODO(4805): check if some threshold is reached for max new nullifier // NOTE: storageAddress is unused but will be important when an AVM circuit processes an entire enqueued call - this.newNullifiers.push(new Nullifier(nullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); + this.nullifiers.push(new Nullifier(nullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); + this.logger.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -152,6 +161,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.avmCircuitHints.l1ToL2MessageExists.items.push( new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), ); + this.logger.debug(`L1_TO_L2_MSG_CHECK cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -159,14 +169,16 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // TODO(4805): check if some threshold is reached for max messages const recipientAddress = EthAddress.fromField(recipient); this.newL2ToL1Messages.push(new L2ToL1Message(recipientAddress, content, this.sideEffectCounter)); + this.logger.debug(`NEW_L2_TO_L1_MSG cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } - public traceUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]) { + public traceUnencryptedLog(contractAddress: Fr, log: Fr[]) { // TODO(4805): check if some threshold is reached for max logs const ulog = new UnencryptedL2Log( AztecAddress.fromField(contractAddress), - EventSelector.fromField(event), + // TODO(#7198): Remove event selector from UnencryptedL2Log + EventSelector.fromField(new Fr(0)), Buffer.concat(log.map(f => f.toBuffer())), ); const basicLogHash = Fr.fromBuffer(ulog.hash()); @@ -174,6 +186,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.allUnencryptedLogs.push(ulog); // TODO(6578): explain magic number 4 here this.unencryptedLogsHashes.push(new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4))); + this.logger.debug(`NEW_UNENCRYPTED_LOG cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -191,6 +204,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { instance.publicKeysHash, ), ); + this.logger.debug(`CONTRACT_INSTANCE cnt: ${this.sideEffectCounter}`); this.incrementSideEffectCounter(); } @@ -210,7 +224,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { /** Bytecode used for this execution. */ bytecode: Buffer, /** The call's results */ - avmCallResults: AvmContractCallResults, + avmCallResults: AvmContractCallResult, /** Function name for logging */ functionName: string = 'unknown', ) { @@ -234,7 +248,12 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { result.startGasLeft.l2Gas - result.endGasLeft.l2Gas, ); this.avmCircuitHints.externalCalls.items.push( - new AvmExternalCallHint(/*success=*/ new Fr(result.reverted ? 0 : 1), result.returnValues, gasUsed), + new AvmExternalCallHint( + /*success=*/ new Fr(result.reverted ? 0 : 1), + result.returnValues, + gasUsed, + result.endSideEffectCounter, + ), ); } @@ -251,14 +270,14 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { /** Bytecode used for this execution. */ bytecode: Buffer, /** The call's results */ - avmCallResults: AvmContractCallResults, + avmCallResults: AvmContractCallResult, /** Function name for logging */ functionName: string = 'unknown', /** The side effect counter of the execution request itself */ requestSideEffectCounter: number = this.startSideEffectCounter, ): PublicExecutionResult { return { - execution: createPublicExecutionRequest(requestSideEffectCounter, avmEnvironment), + executionRequest: createPublicExecutionRequest(requestSideEffectCounter, avmEnvironment), startSideEffectCounter: new Fr(this.startSideEffectCounter), endSideEffectCounter: new Fr(this.sideEffectCounter), @@ -275,12 +294,12 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { contractStorageReads: this.contractStorageReads, contractStorageUpdateRequests: this.contractStorageUpdateRequests, noteHashReadRequests: this.noteHashReadRequests, - newNoteHashes: this.newNoteHashes, + noteHashes: this.noteHashes, nullifierReadRequests: this.nullifierReadRequests, nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests, - newNullifiers: this.newNullifiers, + nullifiers: this.nullifiers, l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests, - newL2ToL1Messages: this.newL2ToL1Messages, + l2ToL1Messages: this.newL2ToL1Messages, // correct the type on these now that they are finalized (lists won't grow) unencryptedLogs: new UnencryptedFunctionL2Logs(this.unencryptedLogs), allUnencryptedLogs: new UnencryptedFunctionL2Logs(this.allUnencryptedLogs), @@ -303,21 +322,20 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { function createPublicExecutionRequest( requestSideEffectCounter: number, avmEnvironment: AvmExecutionEnvironment, -): PublicExecution { +): PublicExecutionRequest { const callContext = CallContext.from({ msgSender: avmEnvironment.sender, storageContractAddress: avmEnvironment.storageAddress, - functionSelector: avmEnvironment.temporaryFunctionSelector, + functionSelector: avmEnvironment.functionSelector, isDelegateCall: avmEnvironment.isDelegateCall, isStaticCall: avmEnvironment.isStaticCall, sideEffectCounter: requestSideEffectCounter, }); - const execution: PublicExecution = { + return { contractAddress: avmEnvironment.address, - functionSelector: avmEnvironment.temporaryFunctionSelector, + functionSelector: avmEnvironment.functionSelector, callContext, // execution request does not contain AvmContextInputs prefix args: avmEnvironment.getCalldataWithoutPrefix(), }; - return execution; } diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts index 60dd0b1107d4..91326fb021b4 100644 --- a/yarn-project/simulator/src/public/side_effect_trace_interface.ts +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -1,8 +1,8 @@ import { type Gas } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; +import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { type AvmContractCallResults } from '../avm/avm_message_call_result.js'; import { type TracedContractInstance } from './side_effect_trace.js'; export interface PublicSideEffectTraceInterface { @@ -17,7 +17,7 @@ export interface PublicSideEffectTraceInterface { traceL1ToL2MessageCheck(contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr, exists: boolean): void; // TODO(dbanks12): should new message accept contract address as arg? traceNewL2ToL1Message(recipient: Fr, content: Fr): void; - traceUnencryptedLog(contractAddress: Fr, event: Fr, log: Fr[]): void; + traceUnencryptedLog(contractAddress: Fr, log: Fr[]): void; // TODO(dbanks12): odd that getContractInstance is a one-off in that it accepts an entire object instead of components traceGetContractInstance(instance: TracedContractInstance): void; traceNestedCall( @@ -34,7 +34,7 @@ export interface PublicSideEffectTraceInterface { /** Bytecode used for this execution. */ bytecode: Buffer, /** The call's results */ - avmCallResults: AvmContractCallResults, + avmCallResults: AvmContractCallResult, /** Function name */ functionName: string, ): void; diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index d0f547751d55..940c66218708 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -4,7 +4,7 @@ import { type GlobalVariables, type Header, type KernelCircuitPublicInputs, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, type PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, @@ -69,9 +69,9 @@ export class TailPhaseManager extends AbstractPhaseManager { const { validationRequests, endNonRevertibleData: nonRevertibleData, end: revertibleData } = previousOutput; const pendingNullifiers = mergeAccumulatedData( - nonRevertibleData.newNullifiers, - revertibleData.newNullifiers, - MAX_NEW_NULLIFIERS_PER_TX, + nonRevertibleData.nullifiers, + revertibleData.nullifiers, + MAX_NULLIFIERS_PER_TX, ); const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints( diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts deleted file mode 100644 index 9cea3c780753..000000000000 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ /dev/null @@ -1,70 +0,0 @@ -// All code in this file needs to die once the public executor is phased out in favor of the AVM. -import { type GasSettings, type GlobalVariables, type Header } from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; - -import { promisify } from 'util'; -import { gunzip } from 'zlib'; - -import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { Mov } from '../avm/opcodes/memory.js'; -import { type PublicExecution } from './execution.js'; - -/** - * Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment - * - * @param current - * @param globalVariables - * @returns - */ -export function createAvmExecutionEnvironment( - current: PublicExecution, - header: Header, - globalVariables: GlobalVariables, - gasSettings: GasSettings, - transactionFee: Fr, -): AvmExecutionEnvironment { - return new AvmExecutionEnvironment( - current.contractAddress, - current.callContext.storageContractAddress, - current.callContext.msgSender, - globalVariables.gasFees.feePerL2Gas, - globalVariables.gasFees.feePerDaGas, - /*contractCallDepth=*/ Fr.zero(), - header, - globalVariables, - current.callContext.isStaticCall, - current.callContext.isDelegateCall, - current.args, - gasSettings, - transactionFee, - current.functionSelector, - ); -} - -const AVM_MAGIC_SUFFIX = Buffer.from([ - Mov.opcode, // opcode - 0x00, // indirect - ...Buffer.from('000018ca', 'hex'), // srcOffset - ...Buffer.from('000018ca', 'hex'), // dstOffset -]); - -export function markBytecodeAsAvm(bytecode: Buffer): Buffer { - return Buffer.concat([bytecode, AVM_MAGIC_SUFFIX]); -} - -// This is just a helper function for the AVM circuit. -export async function decompressBytecodeIfCompressed(bytecode: Buffer): Promise { - try { - return await promisify(gunzip)(bytecode); - } catch { - // If the bytecode is not compressed, the gunzip call will throw an error - // In this case, we assume the bytecode is not compressed and continue. - return Promise.resolve(bytecode); - } -} - -export async function isAvmBytecode(bytecode: Buffer): Promise { - const decompressedBytecode = await decompressBytecodeIfCompressed(bytecode); - const magicSize = AVM_MAGIC_SUFFIX.length; - return decompressedBytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX); -} diff --git a/yarn-project/simulator/src/rollup/rollup.ts b/yarn-project/simulator/src/rollup/rollup.ts index 114873499a75..58c72653d8f8 100644 --- a/yarn-project/simulator/src/rollup/rollup.ts +++ b/yarn-project/simulator/src/rollup/rollup.ts @@ -28,7 +28,9 @@ import { convertSimulatedBaseRollupInputsToWitnessMap, convertSimulatedBaseRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; -import { type SimulationProvider, WASMSimulator } from '@aztec/simulator'; + +import { WASMSimulator } from '../providers/acvm_wasm.js'; +import { type SimulationProvider } from '../providers/simulation_provider.js'; /** * Circuit simulator for the rollup circuits. diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 52b02c625b21..68777079e4ac 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -16,7 +16,8 @@ "resolveJsonModule": true, "composite": true, "skipLibCheck": true, - "noImplicitOverride": true + "noImplicitOverride": true, + "allowArbitraryExtensions": true }, "references": [ { "path": "accounts/tsconfig.json" }, @@ -50,5 +51,5 @@ { "path": "cli/tsconfig.json" } ], "files": ["./@types/jest/index.d.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "**/node_modules", "**/.*/"] } diff --git a/yarn-project/txe/package.json b/yarn-project/txe/package.json index f77a47b7f62a..14f89c536216 100644 --- a/yarn-project/txe/package.json +++ b/yarn-project/txe/package.json @@ -18,7 +18,7 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "dev": "DEBUG='aztec:*' && node ./dest/bin/index.js", + "dev": "DEBUG='aztec:*' LOG_LEVEL=debug && node ./dest/bin/index.js", "start": "node ./dest/bin/index.js" }, "inherits": [ diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 567bf0a656dc..be9bc6390417 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -113,6 +113,10 @@ export class TXE implements TypedOracle { return this.msgSender; } + getFunctionSelector() { + return this.functionSelector; + } + setMsgSender(msgSender: Fr) { this.msgSender = msgSender; } @@ -185,11 +189,10 @@ export class TXE implements TypedOracle { getPublicContextInputs() { const inputs = { - functionSelector: FunctionSelector.fromField(new Fr(0)), argsHash: new Fr(0), isStaticCall: false, toFields: function () { - return [this.functionSelector.toField(), this.argsHash, new Fr(this.isStaticCall)]; + return [this.argsHash, new Fr(this.isStaticCall)]; }, }; return inputs; @@ -434,13 +437,45 @@ export class TXE implements TypedOracle { throw new Error('Method not implemented.'); } - async storageRead(startStorageSlot: Fr, numberOfElements: number): Promise { + async avmOpcodeStorageRead(slot: Fr, length: Fr) { const db = this.trees.asLatest(); + const result = []; + + for (let i = 0; i < length.toNumber(); i++) { + const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, slot.add(new Fr(i))).toBigInt(); + + const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); + if (!lowLeafResult || !lowLeafResult.alreadyPresent) { + result.push(Fr.ZERO); + continue; + } + + const preimage = (await db.getLeafPreimage( + MerkleTreeId.PUBLIC_DATA_TREE, + lowLeafResult.index, + )) as PublicDataTreeLeafPreimage; + + result.push(preimage.value); + } + return result; + } + + async storageRead( + contractAddress: Fr, + startStorageSlot: Fr, + blockNumber: number, + numberOfElements: number, + ): Promise { + const db = + blockNumber === (await this.getBlockNumber()) + ? this.trees.asLatest() + : new MerkleTreeSnapshotOperationsFacade(this.trees, blockNumber); + const values = []; for (let i = 0n; i < numberOfElements; i++) { const storageSlot = startStorageSlot.add(new Fr(i)); - const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, storageSlot).toBigInt(); + const leafSlot = computePublicDataTreeLeafSlot(contractAddress, storageSlot).toBigInt(); const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); @@ -582,12 +617,12 @@ export class TXE implements TypedOracle { await this.addNullifiers( targetContractAddress, - publicInputs.newNullifiers.filter(nullifier => !nullifier.isEmpty()).map(nullifier => nullifier.value), + publicInputs.nullifiers.filter(nullifier => !nullifier.isEmpty()).map(nullifier => nullifier.value), ); await this.addNoteHashes( targetContractAddress, - publicInputs.newNoteHashes.filter(noteHash => !noteHash.isEmpty()).map(noteHash => noteHash.value), + publicInputs.noteHashes.filter(noteHash => !noteHash.isEmpty()).map(noteHash => noteHash.value), ); return callStackItem; @@ -685,7 +720,7 @@ export class TXE implements TypedOracle { Gas.test(), TxContext.empty(), /* pendingNullifiers */ [], - /* transactionFee */ Fr.ZERO, + /* transactionFee */ Fr.ONE, callContext.sideEffectCounter, ); } @@ -830,14 +865,23 @@ export class TXE implements TypedOracle { } setPublicTeardownFunctionCall( - _targetContractAddress: AztecAddress, - _functionSelector: FunctionSelector, - _argsHash: Fr, - _sideEffectCounter: number, - _isStaticCall: boolean, - _isDelegateCall: boolean, + targetContractAddress: AztecAddress, + functionSelector: FunctionSelector, + argsHash: Fr, + sideEffectCounter: number, + isStaticCall: boolean, + isDelegateCall: boolean, ): Promise { - throw new Error('Method not implemented.'); + // Definitely not right, in that the teardown should always be last. + // But useful for executing flows. + return this.enqueuePublicFunctionCall( + targetContractAddress, + functionSelector, + argsHash, + sideEffectCounter, + isStaticCall, + isDelegateCall, + ); } aes128Encrypt(input: Buffer, initializationVector: Buffer, key: Buffer): Buffer { diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index de25cc812997..ca36fb812281 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -251,6 +251,16 @@ export class TXEService { return toForeignCallResult([]); } + setFunctionSelector(functionSelector: ForeignCallSingle) { + (this.typedOracle as TXE).setFunctionSelector(FunctionSelector.fromField(fromSingle(functionSelector))); + return toForeignCallResult([]); + } + + getFunctionSelector() { + const functionSelector = (this.typedOracle as TXE).getFunctionSelector(); + return toForeignCallResult([toSingle(functionSelector.toField())]); + } + // PXE oracles getRandomField() { @@ -277,6 +287,11 @@ export class TXEService { return toForeignCallResult([toSingle(new Fr(blockNumber))]); } + avmOpcodeFunctionSelector() { + const functionSelector = (this.typedOracle as TXE).getFunctionSelector(); + return toForeignCallResult([toSingle(functionSelector.toField())]); + } + async packArgumentsArray(args: ForeignCallArray) { const packed = await this.typedOracle.packArgumentsArray(fromArray(args)); return toForeignCallResult([toSingle(packed)]); @@ -308,9 +323,16 @@ export class TXEService { return toForeignCallResult([]); } - async storageRead(startStorageSlot: ForeignCallSingle, numberOfElements: ForeignCallSingle) { + async storageRead( + contractAddress: ForeignCallSingle, + startStorageSlot: ForeignCallSingle, + blockNumber: ForeignCallSingle, + numberOfElements: ForeignCallSingle, + ) { const values = await this.typedOracle.storageRead( + fromSingle(contractAddress), fromSingle(startStorageSlot), + fromSingle(blockNumber).toNumber(), fromSingle(numberOfElements).toNumber(), ); return toForeignCallResult([toArray(values)]); @@ -499,13 +521,41 @@ export class TXEService { fromSingle(address), FunctionSelector.fromField(fromSingle(functionSelector)), fromArray(args), - false, - false, + /* isStaticCall */ false, + /* isDelegateCall */ false, ); return toForeignCallResult([toArray(result.returnValues), toSingle(new Fr(1))]); } + async avmOpcodeStaticCall( + _gas: ForeignCallArray, + address: ForeignCallSingle, + _length: ForeignCallSingle, + args: ForeignCallArray, + functionSelector: ForeignCallSingle, + ) { + const result = await (this.typedOracle as TXE).avmOpcodeCall( + fromSingle(address), + FunctionSelector.fromField(fromSingle(functionSelector)), + fromArray(args), + /* isStaticCall */ true, + /* isDelegateCall */ false, + ); + + return toForeignCallResult([toArray(result.returnValues), toSingle(new Fr(1))]); + } + + async avmOpcodeStorageRead(slot: ForeignCallSingle, length: ForeignCallSingle) { + const values = await (this.typedOracle as TXE).avmOpcodeStorageRead(fromSingle(slot), fromSingle(length)); + return toForeignCallResult([toArray(values)]); + } + + async avmOpcodeStorageWrite(startStorageSlot: ForeignCallSingle, values: ForeignCallArray) { + await this.typedOracle.storageWrite(fromSingle(startStorageSlot), fromArray(values)); + return toForeignCallResult([]); + } + async getPublicKeysAndPartialAddress(address: ForeignCallSingle) { const parsedAddress = AztecAddress.fromField(fromSingle(address)); const { publicKeys, partialAddress } = await this.typedOracle.getCompleteAddress(parsedAddress); @@ -564,6 +614,10 @@ export class TXEService { return toForeignCallResult([]); } + emitEncryptedEventLog(_contractAddress: AztecAddress, _randomness: Fr, _encryptedEvent: Buffer, _counter: number) { + return toForeignCallResult([]); + } + async callPrivateFunction( targetContractAddress: ForeignCallSingle, functionSelector: ForeignCallSingle, @@ -626,6 +680,33 @@ export class TXEService { return toForeignCallResult([toArray(fields)]); } + public async setPublicTeardownFunctionCall( + targetContractAddress: ForeignCallSingle, + functionSelector: ForeignCallSingle, + argsHash: ForeignCallSingle, + sideEffectCounter: ForeignCallSingle, + isStaticCall: ForeignCallSingle, + isDelegateCall: ForeignCallSingle, + ) { + const publicTeardownCallRequest = await this.typedOracle.setPublicTeardownFunctionCall( + fromSingle(targetContractAddress), + FunctionSelector.fromField(fromSingle(functionSelector)), + fromSingle(argsHash), + fromSingle(sideEffectCounter).toNumber(), + fromSingle(isStaticCall).toBool(), + fromSingle(isDelegateCall).toBool(), + ); + + const fields = [ + publicTeardownCallRequest.contractAddress.toField(), + publicTeardownCallRequest.functionSelector.toField(), + ...publicTeardownCallRequest.callContext.toFields(), + publicTeardownCallRequest.getArgsHash(), + ]; + + return toForeignCallResult([toArray(fields)]); + } + async getChainId() { return toForeignCallResult([toSingle(await this.typedOracle.getChainId())]); } diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index 91b0eb30ba88..861eb227206e 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -231,7 +231,7 @@ function getStorageLayout(input: NoirCompiledContract) { const name = field.name; const slot = field.value.fields[0].value as IntegerValue; acc[name] = { - slot: new Fr(BigInt(slot.value)), + slot: Fr.fromString(slot.value), }; return acc; }, {}); diff --git a/yarn-project/types/src/noir/index.ts b/yarn-project/types/src/noir/index.ts index 7361d6687dbe..41b860a3719a 100644 --- a/yarn-project/types/src/noir/index.ts +++ b/yarn-project/types/src/noir/index.ts @@ -18,6 +18,8 @@ export const AZTEC_VIEW_ATTRIBUTE = 'aztec(view)'; export interface NoirFunctionAbi { /** The parameters of the function. */ parameters: ABIParameter[]; + /** TODO */ + error_types: Record; /** The return type of the function. */ return_type: { /** diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_db.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_db.ts index 1e485b439e24..4cee2af4522d 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_db.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_db.ts @@ -1,5 +1,5 @@ import { type MerkleTreeId } from '@aztec/circuit-types'; -import { type Fr, MAX_NEW_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '@aztec/circuits.js'; +import { type Fr, MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX } from '@aztec/circuits.js'; import { type IndexedTreeSnapshot, type TreeSnapshot } from '@aztec/merkle-tree'; import { type MerkleTreeOperations } from './merkle_tree_operations.js'; @@ -19,7 +19,7 @@ import { type MerkleTreeOperations } from './merkle_tree_operations.js'; * 1024 leaves for the first block, because there's only neat space for 1023 leaves after 0. By padding with 1023 * more leaves, we can then insert the first block of 1024 leaves into indices 1024:2047. */ -export const INITIAL_NULLIFIER_TREE_SIZE = 2 * MAX_NEW_NULLIFIERS_PER_TX; +export const INITIAL_NULLIFIER_TREE_SIZE = 2 * MAX_NULLIFIERS_PER_TX; export const INITIAL_PUBLIC_DATA_TREE_SIZE = 2 * MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index be41f087fdcd..5d8be02b4dd2 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -7,8 +7,8 @@ import { GlobalVariables, Header, L1_TO_L2_MSG_TREE_HEIGHT, - MAX_NEW_NOTE_HASHES_PER_TX, - MAX_NEW_NULLIFIERS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NOTE_HASH_TREE_HEIGHT, NULLIFIER_SUBTREE_HEIGHT, @@ -592,7 +592,7 @@ export class MerkleTrees implements MerkleTreeDb { // Sync the append only trees { const noteHashesPadded = paddedTxEffects.flatMap(txEffect => - padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NEW_NOTE_HASHES_PER_TX), + padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX), ); await this.#appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded); @@ -603,7 +603,7 @@ export class MerkleTrees implements MerkleTreeDb { // Sync the indexed trees { const nullifiersPadded = paddedTxEffects.flatMap(txEffect => - padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NEW_NULLIFIERS_PER_TX), + padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX), ); await (this.trees[MerkleTreeId.NULLIFIER_TREE] as StandardIndexedTree).batchInsert( nullifiersPadded.map(nullifier => nullifier.toBuffer()), diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 1b9ed2231ace..4d4c0a11fb8a 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -3000,7 +3000,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noir_codegen@portal:../noir/packages/noir_codegen::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/types": 0.30.0 + "@noir-lang/types": 0.31.0 glob: ^10.3.10 ts-command-line-args: ^2.5.1 bin: @@ -3009,13 +3009,13 @@ __metadata: linkType: soft "@noir-lang/noir_js@file:../noir/packages/noir_js::locator=%40aztec%2Faztec3-packages%40workspace%3A.": - version: 0.30.0 - resolution: "@noir-lang/noir_js@file:../noir/packages/noir_js#../noir/packages/noir_js::hash=17d6ef&locator=%40aztec%2Faztec3-packages%40workspace%3A." + version: 0.31.0 + resolution: "@noir-lang/noir_js@file:../noir/packages/noir_js#../noir/packages/noir_js::hash=1adb3c&locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/acvm_js": 0.46.0 - "@noir-lang/noirc_abi": 0.30.0 - "@noir-lang/types": 0.30.0 - checksum: 112f68952038ae06e9e8f3f063be73bf6a527dff4cc352874b1d35d7d6b98845a8979e49cbd092e830f76a0c00fa78c411101ceaf01990cc077acb42c41c3193 + "@noir-lang/acvm_js": 0.47.0 + "@noir-lang/noirc_abi": 0.31.0 + "@noir-lang/types": 0.31.0 + checksum: 98132370d4f4e1ac1b5f6c5b461f451d9df79d051fcc6136572030e3cb7b4472f9f9c2b93e899ddf753901108d1ec45ed4f6fee435058297cd90d5ff985b5b6d languageName: node linkType: hard @@ -3023,7 +3023,7 @@ __metadata: version: 0.0.0-use.local resolution: "@noir-lang/noirc_abi@portal:../noir/packages/noirc_abi::locator=%40aztec%2Faztec3-packages%40workspace%3A." dependencies: - "@noir-lang/types": 0.30.0 + "@noir-lang/types": 0.31.0 languageName: node linkType: soft From 56c52f9f98169a81b8087a0ed512cb97c2a09fe4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 12:00:51 +0100 Subject: [PATCH 39/94] fix: init terraform in all cases (#7304) --- .github/workflows/devnet-deploys.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index df3af6699911..75df1925cc8d 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -117,11 +117,15 @@ jobs: terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/p2p-bootstrap" terraform apply -input=false -auto-approve + - name: Init Aztec Node Terraform + working-directory: ./yarn-project/aztec/terraform/node + run: | + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" + - name: Taint node filesystem if L1 contracts are redeployed if: steps.check_changes_release.outputs.result == 'true' working-directory: ./yarn-project/aztec/terraform/node run: | - terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" terraform state list | grep 'aws_efs_file_system.node_data_store' | xargs -n1 terraform taint - name: Deploy Aztec Nodes @@ -134,9 +138,3 @@ jobs: run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/prover" terraform apply -input=false -auto-approve - - - name: Deploy Provers - working-directory: ./yarn-project/aztec/terraform/prover - run: | - terraform init -input=false -backend-config="key=devnet/prover" - terraform apply -input=false -auto-approve From b26dd729d704c8b87fa80f3f2853ae77273ca9b4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 12:41:19 +0000 Subject: [PATCH 40/94] merge with master --- .github/workflows/devnet-deploys.yml | 6 + .noir-sync-commit | 2 +- .../barretenberg/vm/generated/avm_flavor.hpp | 2131 ++--------------- .../barretenberg/vm/generated/avm_prover.cpp | 761 +----- .../vm/generated/avm_verifier.cpp | 534 +---- .../bb-pil-backend/src/flavor_builder.rs | 128 +- .../bb-pil-backend/src/prover_builder.rs | 31 +- .../bb-pil-backend/src/verifier_builder.rs | 8 +- bb-pilcom/bb-pil-backend/src/vm_builder.rs | 10 +- noir/Earthfile | 2 +- noir/noir-repo/Cargo.lock | 7 + .../compiler/noirc_frontend/Cargo.toml | 1 + .../src/elaborator/expressions.rs | 9 +- .../noirc_frontend/src/elaborator/mod.rs | 103 +- .../noirc_frontend/src/elaborator/patterns.rs | 26 +- .../src/elaborator/statements.rs | 7 + .../noirc_frontend/src/elaborator/types.rs | 46 +- .../noirc_frontend/src/hir/comptime/errors.rs | 16 +- .../src/hir/comptime/interpreter.rs | 129 +- .../src/hir/comptime/interpreter/builtin.rs | 130 +- .../src/hir/def_collector/dc_crate.rs | 30 +- .../src/hir/def_collector/dc_mod.rs | 8 +- .../src/hir/resolution/resolver.rs | 2 +- .../src/hir/type_check/errors.rs | 75 +- .../noirc_frontend/src/hir/type_check/expr.rs | 25 +- .../noirc_frontend/src/hir/type_check/mod.rs | 2 +- .../noirc_frontend/src/hir_def/traits.rs | 2 +- .../compiler/noirc_frontend/src/lib.rs | 1 + .../compiler/noirc_frontend/src/locations.rs | 122 + .../src/monomorphization/mod.rs | 191 +- .../noirc_frontend/src/node_interner.rs | 74 +- noir/noir-repo/cspell.json | 4 + .../cryptographic_primitives/ec_primitives.md | 4 +- .../cryptographic_primitives/hashes.mdx | 12 +- .../{collections.nr => collections/mod.nr} | 0 .../src/ec/{consts.nr => consts/mod.nr} | 0 .../noir_stdlib/src/{ec.nr => ec/mod.nr} | 0 .../src/{field.nr => field/mod.nr} | 0 .../noir_stdlib/src/{hash.nr => hash/mod.nr} | 0 .../src/hash/{poseidon.nr => poseidon/mod.nr} | 0 .../noir_stdlib/src/{meta.nr => meta/mod.nr} | 0 .../noir_stdlib/src/{ops.nr => ops/mod.nr} | 0 .../comptime_traits/Nargo.toml | 7 + .../comptime_traits/src/main.nr | 15 + noir/noir-repo/tooling/lsp/src/lib.rs | 14 +- .../lsp/src/requests/goto_definition.rs | 57 +- .../noir-repo/tooling/lsp/src/requests/mod.rs | 12 +- .../tooling/lsp/src/requests/rename.rs | 249 ++ noir/noir-repo/tooling/lsp/src/test_utils.rs | 39 + noir/noir-repo/tooling/lsp/src/types.rs | 7 +- .../test_programs/go_to_definition/Nargo.toml | 6 + .../go_to_definition/src/main.nr | 11 + .../lsp/test_programs/rename/Nargo.toml | 6 + .../lsp/test_programs/rename/src/main.nr | 22 + .../test_programs/rename_qualified/Nargo.toml | 6 + .../rename_qualified/src/main.nr | 9 + noir/noir-repo/tooling/nargo_cli/build.rs | 3 +- noir/scripts/sync-in-fixup.sh | 3 +- noir/verify_honk_proof/Prover.toml | 2 +- .../accounts/src/artifacts/EcdsaAccount.json | 1 - .../src/artifacts/SchnorrAccount.json | 1 - .../artifacts/SchnorrSingleKeyAccount.json | 1 - yarn-project/cli/Earthfile | 22 - .../src/artifacts/AuthRegistry.json | 1 - .../artifacts/ContractClassRegisterer.json | 1 - .../artifacts/ContractInstanceDeployer.json | 1 - .../src/artifacts/GasToken.json | 1 - .../src/artifacts/KeyRegistry.json | 1 - .../src/artifacts/MultiCallEntrypoint.json | 1 - 69 files changed, 1494 insertions(+), 3644 deletions(-) create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/locations.rs rename noir/noir-repo/noir_stdlib/src/{collections.nr => collections/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/ec/{consts.nr => consts/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{ec.nr => ec/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{field.nr => field/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{hash.nr => hash/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/hash/{poseidon.nr => poseidon/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{meta.nr => meta/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{ops.nr => ops/mod.nr} (100%) create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/src/requests/rename.rs create mode 100644 noir/noir-repo/tooling/lsp/src/test_utils.rs create mode 100644 noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr delete mode 100644 yarn-project/accounts/src/artifacts/EcdsaAccount.json delete mode 100644 yarn-project/accounts/src/artifacts/SchnorrAccount.json delete mode 100644 yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json delete mode 100644 yarn-project/cli/Earthfile delete mode 100644 yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json delete mode 100644 yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json delete mode 100644 yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json delete mode 100644 yarn-project/protocol-contracts/src/artifacts/GasToken.json delete mode 100644 yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json delete mode 100644 yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 75df1925cc8d..2f28ecacf8e7 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -138,3 +138,9 @@ jobs: run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/prover" terraform apply -input=false -auto-approve + + - name: Deploy Provers + working-directory: ./yarn-project/aztec/terraform/prover + run: | + terraform init -input=false -backend-config="key=devnet/prover" + terraform apply -input=false -auto-approve diff --git a/.noir-sync-commit b/.noir-sync-commit index 7f0f18023f8f..c288f5b3cd9b 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -7b77bbfc19c51829814149e623257a3424d8e8c2 +32029f91f6aae4d2f6b08b4ea40481f5837e50bc diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp index c29a3b0212a6..066bf7e1a316 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_flavor.hpp @@ -106,61 +106,6 @@ class AvmFlavor { // the unshifted and one for the shifted static constexpr size_t NUM_ALL_ENTITIES = 452; - using GrandProductRelations = std::tuple, - perm_main_bin_relation, - perm_main_conv_relation, - perm_main_pos2_perm_relation, - perm_main_pedersen_relation, - perm_main_mem_a_relation, - perm_main_mem_b_relation, - perm_main_mem_c_relation, - perm_main_mem_d_relation, - perm_main_mem_ind_addr_a_relation, - perm_main_mem_ind_addr_b_relation, - perm_main_mem_ind_addr_c_relation, - perm_main_mem_ind_addr_d_relation, - lookup_byte_lengths_relation, - lookup_byte_operations_relation, - lookup_opcode_gas_relation, - range_check_l2_gas_hi_relation, - range_check_l2_gas_lo_relation, - range_check_da_gas_hi_relation, - range_check_da_gas_lo_relation, - kernel_output_lookup_relation, - lookup_into_kernel_relation, - incl_main_tag_err_relation, - incl_mem_tag_err_relation, - lookup_mem_rng_chk_lo_relation, - lookup_mem_rng_chk_mid_relation, - lookup_mem_rng_chk_hi_relation, - lookup_pow_2_0_relation, - lookup_pow_2_1_relation, - lookup_u8_0_relation, - lookup_u8_1_relation, - lookup_u16_0_relation, - lookup_u16_1_relation, - lookup_u16_2_relation, - lookup_u16_3_relation, - lookup_u16_4_relation, - lookup_u16_5_relation, - lookup_u16_6_relation, - lookup_u16_7_relation, - lookup_u16_8_relation, - lookup_u16_9_relation, - lookup_u16_10_relation, - lookup_u16_11_relation, - lookup_u16_12_relation, - lookup_u16_13_relation, - lookup_u16_14_relation, - lookup_div_u16_0_relation, - lookup_div_u16_1_relation, - lookup_div_u16_2_relation, - lookup_div_u16_3_relation, - lookup_div_u16_4_relation, - lookup_div_u16_5_relation, - lookup_div_u16_6_relation, - lookup_div_u16_7_relation>; - using Relations = std::tuple, Avm_vm::binary, Avm_vm::conversion, @@ -257,7 +202,7 @@ class AvmFlavor { RefVector get_table_polynomials() { return {}; }; }; - template class WitnessEntities { + template class WireEntities { public: DEFINE_FLAVOR_MEMBERS(DataType, kernel_kernel_inputs, @@ -550,6 +495,51 @@ class AvmFlavor { sha256_output, sha256_sel_sha256_compression, sha256_state, + lookup_byte_lengths_counts, + lookup_byte_operations_counts, + lookup_opcode_gas_counts, + range_check_l2_gas_hi_counts, + range_check_l2_gas_lo_counts, + range_check_da_gas_hi_counts, + range_check_da_gas_lo_counts, + kernel_output_lookup_counts, + lookup_into_kernel_counts, + incl_main_tag_err_counts, + incl_mem_tag_err_counts, + lookup_mem_rng_chk_lo_counts, + lookup_mem_rng_chk_mid_counts, + lookup_mem_rng_chk_hi_counts, + lookup_pow_2_0_counts, + lookup_pow_2_1_counts, + lookup_u8_0_counts, + lookup_u8_1_counts, + lookup_u16_0_counts, + lookup_u16_1_counts, + lookup_u16_2_counts, + lookup_u16_3_counts, + lookup_u16_4_counts, + lookup_u16_5_counts, + lookup_u16_6_counts, + lookup_u16_7_counts, + lookup_u16_8_counts, + lookup_u16_9_counts, + lookup_u16_10_counts, + lookup_u16_11_counts, + lookup_u16_12_counts, + lookup_u16_13_counts, + lookup_u16_14_counts, + lookup_div_u16_0_counts, + lookup_div_u16_1_counts, + lookup_div_u16_2_counts, + lookup_div_u16_3_counts, + lookup_div_u16_4_counts, + lookup_div_u16_5_counts, + lookup_div_u16_6_counts, + lookup_div_u16_7_counts) + }; + + template struct DerivedWitnessEntities { + DEFINE_FLAVOR_MEMBERS(DataType, perm_main_alu, perm_main_bin, perm_main_conv, @@ -603,1876 +593,179 @@ class AvmFlavor { lookup_div_u16_4, lookup_div_u16_5, lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts) + lookup_div_u16_7) + }; - RefVector get_wires() - { - return { kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_rng_16, - main_sel_rng_8, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts }; + template class ShiftedEntities { + public: + DEFINE_FLAVOR_MEMBERS(DataType, + alu_a_hi_shift, + alu_a_lo_shift, + alu_b_hi_shift, + alu_b_lo_shift, + alu_cmp_rng_ctr_shift, + alu_div_u16_r0_shift, + alu_div_u16_r1_shift, + alu_div_u16_r2_shift, + alu_div_u16_r3_shift, + alu_div_u16_r4_shift, + alu_div_u16_r5_shift, + alu_div_u16_r6_shift, + alu_div_u16_r7_shift, + alu_op_add_shift, + alu_op_cast_prev_shift, + alu_op_cast_shift, + alu_op_div_shift, + alu_op_mul_shift, + alu_op_shl_shift, + alu_op_shr_shift, + alu_op_sub_shift, + alu_p_sub_a_hi_shift, + alu_p_sub_a_lo_shift, + alu_p_sub_b_hi_shift, + alu_p_sub_b_lo_shift, + alu_sel_alu_shift, + alu_sel_cmp_shift, + alu_sel_div_rng_chk_shift, + alu_sel_rng_chk_lookup_shift, + alu_sel_rng_chk_shift, + alu_u16_r0_shift, + alu_u16_r1_shift, + alu_u16_r2_shift, + alu_u16_r3_shift, + alu_u16_r4_shift, + alu_u16_r5_shift, + alu_u16_r6_shift, + alu_u8_r0_shift, + alu_u8_r1_shift, + binary_acc_ia_shift, + binary_acc_ib_shift, + binary_acc_ic_shift, + binary_mem_tag_ctr_shift, + binary_op_id_shift, + kernel_emit_l2_to_l1_msg_write_offset_shift, + kernel_emit_note_hash_write_offset_shift, + kernel_emit_nullifier_write_offset_shift, + kernel_emit_unencrypted_log_write_offset_shift, + kernel_l1_to_l2_msg_exists_write_offset_shift, + kernel_note_hash_exist_write_offset_shift, + kernel_nullifier_exists_write_offset_shift, + kernel_nullifier_non_exists_write_offset_shift, + kernel_side_effect_counter_shift, + kernel_sload_write_offset_shift, + kernel_sstore_write_offset_shift, + main_da_gas_remaining_shift, + main_internal_return_ptr_shift, + main_l2_gas_remaining_shift, + main_pc_shift, + mem_glob_addr_shift, + mem_rw_shift, + mem_sel_mem_shift, + mem_tag_shift, + mem_tsp_shift, + mem_val_shift) + }; + + template + static auto get_to_be_shifted(PrecomputedAndWitnessEntitiesSuperset& entities) + { + return RefArray{ + + entities.alu_a_hi, + entities.alu_a_lo, + entities.alu_b_hi, + entities.alu_b_lo, + entities.alu_cmp_rng_ctr, + entities.alu_div_u16_r0, + entities.alu_div_u16_r1, + entities.alu_div_u16_r2, + entities.alu_div_u16_r3, + entities.alu_div_u16_r4, + entities.alu_div_u16_r5, + entities.alu_div_u16_r6, + entities.alu_div_u16_r7, + entities.alu_op_add, + entities.alu_op_cast_prev, + entities.alu_op_cast, + entities.alu_op_div, + entities.alu_op_mul, + entities.alu_op_shl, + entities.alu_op_shr, + entities.alu_op_sub, + entities.alu_p_sub_a_hi, + entities.alu_p_sub_a_lo, + entities.alu_p_sub_b_hi, + entities.alu_p_sub_b_lo, + entities.alu_sel_alu, + entities.alu_sel_cmp, + entities.alu_sel_div_rng_chk, + entities.alu_sel_rng_chk_lookup, + entities.alu_sel_rng_chk, + entities.alu_u16_r0, + entities.alu_u16_r1, + entities.alu_u16_r2, + entities.alu_u16_r3, + entities.alu_u16_r4, + entities.alu_u16_r5, + entities.alu_u16_r6, + entities.alu_u8_r0, + entities.alu_u8_r1, + entities.binary_acc_ia, + entities.binary_acc_ib, + entities.binary_acc_ic, + entities.binary_mem_tag_ctr, + entities.binary_op_id, + entities.kernel_emit_l2_to_l1_msg_write_offset, + entities.kernel_emit_note_hash_write_offset, + entities.kernel_emit_nullifier_write_offset, + entities.kernel_emit_unencrypted_log_write_offset, + entities.kernel_l1_to_l2_msg_exists_write_offset, + entities.kernel_note_hash_exist_write_offset, + entities.kernel_nullifier_exists_write_offset, + entities.kernel_nullifier_non_exists_write_offset, + entities.kernel_side_effect_counter, + entities.kernel_sload_write_offset, + entities.kernel_sstore_write_offset, + entities.main_da_gas_remaining, + entities.main_internal_return_ptr, + entities.main_l2_gas_remaining, + entities.main_pc, + entities.mem_glob_addr, + entities.mem_rw, + entities.mem_sel_mem, + entities.mem_tag, + entities.mem_tsp, + entities.mem_val, }; + } + + template + class WitnessEntities : public WireEntities, public DerivedWitnessEntities { + public: + DEFINE_COMPOUND_GET_ALL(WireEntities, DerivedWitnessEntities) + auto get_wires() { return WireEntities::get_all(); }; }; - template class AllEntities { + template + class AllEntities : public PrecomputedEntities, + public WitnessEntities, + public ShiftedEntities { public: - DEFINE_FLAVOR_MEMBERS(DataType, - main_clk, - main_sel_first, - kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_rng_16, - main_sel_rng_8, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts, - alu_a_hi_shift, - alu_a_lo_shift, - alu_b_hi_shift, - alu_b_lo_shift, - alu_cmp_rng_ctr_shift, - alu_div_u16_r0_shift, - alu_div_u16_r1_shift, - alu_div_u16_r2_shift, - alu_div_u16_r3_shift, - alu_div_u16_r4_shift, - alu_div_u16_r5_shift, - alu_div_u16_r6_shift, - alu_div_u16_r7_shift, - alu_op_add_shift, - alu_op_cast_prev_shift, - alu_op_cast_shift, - alu_op_div_shift, - alu_op_mul_shift, - alu_op_shl_shift, - alu_op_shr_shift, - alu_op_sub_shift, - alu_p_sub_a_hi_shift, - alu_p_sub_a_lo_shift, - alu_p_sub_b_hi_shift, - alu_p_sub_b_lo_shift, - alu_sel_alu_shift, - alu_sel_cmp_shift, - alu_sel_div_rng_chk_shift, - alu_sel_rng_chk_lookup_shift, - alu_sel_rng_chk_shift, - alu_u16_r0_shift, - alu_u16_r1_shift, - alu_u16_r2_shift, - alu_u16_r3_shift, - alu_u16_r4_shift, - alu_u16_r5_shift, - alu_u16_r6_shift, - alu_u8_r0_shift, - alu_u8_r1_shift, - binary_acc_ia_shift, - binary_acc_ib_shift, - binary_acc_ic_shift, - binary_mem_tag_ctr_shift, - binary_op_id_shift, - kernel_emit_l2_to_l1_msg_write_offset_shift, - kernel_emit_note_hash_write_offset_shift, - kernel_emit_nullifier_write_offset_shift, - kernel_emit_unencrypted_log_write_offset_shift, - kernel_l1_to_l2_msg_exists_write_offset_shift, - kernel_note_hash_exist_write_offset_shift, - kernel_nullifier_exists_write_offset_shift, - kernel_nullifier_non_exists_write_offset_shift, - kernel_side_effect_counter_shift, - kernel_sload_write_offset_shift, - kernel_sstore_write_offset_shift, - main_da_gas_remaining_shift, - main_internal_return_ptr_shift, - main_l2_gas_remaining_shift, - main_pc_shift, - mem_glob_addr_shift, - mem_rw_shift, - mem_sel_mem_shift, - mem_tag_shift, - mem_tsp_shift, - mem_val_shift) + AllEntities() + : PrecomputedEntities{} + , WitnessEntities{} + , ShiftedEntities{} + {} - RefVector get_wires() - { - return { main_clk, - main_sel_first, - kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_rng_16, - main_sel_rng_8, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts, - alu_a_hi_shift, - alu_a_lo_shift, - alu_b_hi_shift, - alu_b_lo_shift, - alu_cmp_rng_ctr_shift, - alu_div_u16_r0_shift, - alu_div_u16_r1_shift, - alu_div_u16_r2_shift, - alu_div_u16_r3_shift, - alu_div_u16_r4_shift, - alu_div_u16_r5_shift, - alu_div_u16_r6_shift, - alu_div_u16_r7_shift, - alu_op_add_shift, - alu_op_cast_prev_shift, - alu_op_cast_shift, - alu_op_div_shift, - alu_op_mul_shift, - alu_op_shl_shift, - alu_op_shr_shift, - alu_op_sub_shift, - alu_p_sub_a_hi_shift, - alu_p_sub_a_lo_shift, - alu_p_sub_b_hi_shift, - alu_p_sub_b_lo_shift, - alu_sel_alu_shift, - alu_sel_cmp_shift, - alu_sel_div_rng_chk_shift, - alu_sel_rng_chk_lookup_shift, - alu_sel_rng_chk_shift, - alu_u16_r0_shift, - alu_u16_r1_shift, - alu_u16_r2_shift, - alu_u16_r3_shift, - alu_u16_r4_shift, - alu_u16_r5_shift, - alu_u16_r6_shift, - alu_u8_r0_shift, - alu_u8_r1_shift, - binary_acc_ia_shift, - binary_acc_ib_shift, - binary_acc_ic_shift, - binary_mem_tag_ctr_shift, - binary_op_id_shift, - kernel_emit_l2_to_l1_msg_write_offset_shift, - kernel_emit_note_hash_write_offset_shift, - kernel_emit_nullifier_write_offset_shift, - kernel_emit_unencrypted_log_write_offset_shift, - kernel_l1_to_l2_msg_exists_write_offset_shift, - kernel_note_hash_exist_write_offset_shift, - kernel_nullifier_exists_write_offset_shift, - kernel_nullifier_non_exists_write_offset_shift, - kernel_side_effect_counter_shift, - kernel_sload_write_offset_shift, - kernel_sstore_write_offset_shift, - main_da_gas_remaining_shift, - main_internal_return_ptr_shift, - main_l2_gas_remaining_shift, - main_pc_shift, - mem_glob_addr_shift, - mem_rw_shift, - mem_sel_mem_shift, - mem_tag_shift, - mem_tsp_shift, - mem_val_shift }; - }; - RefVector get_unshifted() - { - return { main_clk, - main_sel_first, - kernel_kernel_inputs, - kernel_kernel_value_out, - kernel_kernel_side_effect_out, - kernel_kernel_metadata_out, - main_calldata, - alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_borrow, - alu_cf, - alu_clk, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_divisor_hi, - alu_divisor_lo, - alu_ff_tag, - alu_ia, - alu_ib, - alu_ic, - alu_in_tag, - alu_op_add, - alu_op_cast, - alu_op_cast_prev, - alu_op_div, - alu_op_div_a_lt_b, - alu_op_div_std, - alu_op_eq, - alu_op_eq_diff_inv, - alu_op_lt, - alu_op_lte, - alu_op_mul, - alu_op_not, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_a_borrow, - alu_p_b_borrow, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_partial_prod_hi, - alu_partial_prod_lo, - alu_quotient_hi, - alu_quotient_lo, - alu_remainder, - alu_res_hi, - alu_res_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_shift_which, - alu_shift_lt_bit_len, - alu_t_sub_s_bits, - alu_two_pow_s, - alu_two_pow_t_sub_s, - alu_u128_tag, - alu_u16_r0, - alu_u16_r1, - alu_u16_r10, - alu_u16_r11, - alu_u16_r12, - alu_u16_r13, - alu_u16_r14, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u16_r7, - alu_u16_r8, - alu_u16_r9, - alu_u16_tag, - alu_u32_tag, - alu_u64_tag, - alu_u8_r0, - alu_u8_r1, - alu_u8_tag, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_clk, - binary_ia_bytes, - binary_ib_bytes, - binary_ic_bytes, - binary_in_tag, - binary_mem_tag_ctr, - binary_mem_tag_ctr_inv, - binary_op_id, - binary_sel_bin, - binary_start, - byte_lookup_sel_bin, - byte_lookup_table_byte_lengths, - byte_lookup_table_in_tags, - byte_lookup_table_input_a, - byte_lookup_table_input_b, - byte_lookup_table_op_id, - byte_lookup_table_output, - conversion_clk, - conversion_input, - conversion_num_limbs, - conversion_radix, - conversion_sel_to_radix_le, - gas_da_gas_fixed_table, - gas_l2_gas_fixed_table, - gas_sel_gas_cost, - keccakf1600_clk, - keccakf1600_input, - keccakf1600_output, - keccakf1600_sel_keccakf1600, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_kernel_in_offset, - kernel_kernel_out_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_q_public_input_kernel_add_to_table, - kernel_q_public_input_kernel_out_add_to_table, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_abs_da_rem_gas_hi, - main_abs_da_rem_gas_lo, - main_abs_l2_rem_gas_hi, - main_abs_l2_rem_gas_lo, - main_alu_in_tag, - main_bin_op_id, - main_call_ptr, - main_da_gas_op_cost, - main_da_gas_remaining, - main_da_out_of_gas, - main_ia, - main_ib, - main_ic, - main_id, - main_id_zero, - main_ind_addr_a, - main_ind_addr_b, - main_ind_addr_c, - main_ind_addr_d, - main_internal_return_ptr, - main_inv, - main_l2_gas_op_cost, - main_l2_gas_remaining, - main_l2_out_of_gas, - main_mem_addr_a, - main_mem_addr_b, - main_mem_addr_c, - main_mem_addr_d, - main_op_err, - main_opcode_val, - main_pc, - main_r_in_tag, - main_rwa, - main_rwb, - main_rwc, - main_rwd, - main_sel_alu, - main_sel_bin, - main_sel_gas_accounting_active, - main_sel_last, - main_sel_mem_op_a, - main_sel_mem_op_activate_gas, - main_sel_mem_op_b, - main_sel_mem_op_c, - main_sel_mem_op_d, - main_sel_mov_ia_to_ic, - main_sel_mov_ib_to_ic, - main_sel_op_add, - main_sel_op_address, - main_sel_op_and, - main_sel_op_block_number, - main_sel_op_cast, - main_sel_op_chain_id, - main_sel_op_cmov, - main_sel_op_coinbase, - main_sel_op_dagasleft, - main_sel_op_div, - main_sel_op_emit_l2_to_l1_msg, - main_sel_op_emit_note_hash, - main_sel_op_emit_nullifier, - main_sel_op_emit_unencrypted_log, - main_sel_op_eq, - main_sel_op_external_call, - main_sel_op_fdiv, - main_sel_op_fee_per_da_gas, - main_sel_op_fee_per_l2_gas, - main_sel_op_function_selector, - main_sel_op_get_contract_instance, - main_sel_op_halt, - main_sel_op_internal_call, - main_sel_op_internal_return, - main_sel_op_jump, - main_sel_op_jumpi, - main_sel_op_keccak, - main_sel_op_l1_to_l2_msg_exists, - main_sel_op_l2gasleft, - main_sel_op_lt, - main_sel_op_lte, - main_sel_op_mov, - main_sel_op_mul, - main_sel_op_not, - main_sel_op_note_hash_exists, - main_sel_op_nullifier_exists, - main_sel_op_or, - main_sel_op_pedersen, - main_sel_op_poseidon2, - main_sel_op_radix_le, - main_sel_op_sender, - main_sel_op_sha256, - main_sel_op_shl, - main_sel_op_shr, - main_sel_op_sload, - main_sel_op_sstore, - main_sel_op_storage_address, - main_sel_op_sub, - main_sel_op_timestamp, - main_sel_op_transaction_fee, - main_sel_op_version, - main_sel_op_xor, - main_sel_q_kernel_lookup, - main_sel_q_kernel_output_lookup, - main_sel_resolve_ind_addr_a, - main_sel_resolve_ind_addr_b, - main_sel_resolve_ind_addr_c, - main_sel_resolve_ind_addr_d, - main_sel_rng_16, - main_sel_rng_8, - main_space_id, - main_tag_err, - main_w_in_tag, - mem_addr, - mem_clk, - mem_diff_hi, - mem_diff_lo, - mem_diff_mid, - mem_glob_addr, - mem_last, - mem_lastAccess, - mem_one_min_inv, - mem_r_in_tag, - mem_rw, - mem_sel_mem, - mem_sel_mov_ia_to_ic, - mem_sel_mov_ib_to_ic, - mem_sel_op_a, - mem_sel_op_b, - mem_sel_op_c, - mem_sel_op_cmov, - mem_sel_op_d, - mem_sel_resolve_ind_addr_a, - mem_sel_resolve_ind_addr_b, - mem_sel_resolve_ind_addr_c, - mem_sel_resolve_ind_addr_d, - mem_sel_rng_chk, - mem_skip_check_tag, - mem_space_id, - mem_tag, - mem_tag_err, - mem_tsp, - mem_val, - mem_w_in_tag, - pedersen_clk, - pedersen_input, - pedersen_output, - pedersen_sel_pedersen, - poseidon2_clk, - poseidon2_input, - poseidon2_output, - poseidon2_sel_poseidon_perm, - powers_power_of_2, - sha256_clk, - sha256_input, - sha256_output, - sha256_sel_sha256_compression, - sha256_state, - perm_main_alu, - perm_main_bin, - perm_main_conv, - perm_main_pos2_perm, - perm_main_pedersen, - perm_main_mem_a, - perm_main_mem_b, - perm_main_mem_c, - perm_main_mem_d, - perm_main_mem_ind_addr_a, - perm_main_mem_ind_addr_b, - perm_main_mem_ind_addr_c, - perm_main_mem_ind_addr_d, - lookup_byte_lengths, - lookup_byte_operations, - lookup_opcode_gas, - range_check_l2_gas_hi, - range_check_l2_gas_lo, - range_check_da_gas_hi, - range_check_da_gas_lo, - kernel_output_lookup, - lookup_into_kernel, - incl_main_tag_err, - incl_mem_tag_err, - lookup_mem_rng_chk_lo, - lookup_mem_rng_chk_mid, - lookup_mem_rng_chk_hi, - lookup_pow_2_0, - lookup_pow_2_1, - lookup_u8_0, - lookup_u8_1, - lookup_u16_0, - lookup_u16_1, - lookup_u16_2, - lookup_u16_3, - lookup_u16_4, - lookup_u16_5, - lookup_u16_6, - lookup_u16_7, - lookup_u16_8, - lookup_u16_9, - lookup_u16_10, - lookup_u16_11, - lookup_u16_12, - lookup_u16_13, - lookup_u16_14, - lookup_div_u16_0, - lookup_div_u16_1, - lookup_div_u16_2, - lookup_div_u16_3, - lookup_div_u16_4, - lookup_div_u16_5, - lookup_div_u16_6, - lookup_div_u16_7, - lookup_byte_lengths_counts, - lookup_byte_operations_counts, - lookup_opcode_gas_counts, - range_check_l2_gas_hi_counts, - range_check_l2_gas_lo_counts, - range_check_da_gas_hi_counts, - range_check_da_gas_lo_counts, - kernel_output_lookup_counts, - lookup_into_kernel_counts, - incl_main_tag_err_counts, - incl_mem_tag_err_counts, - lookup_mem_rng_chk_lo_counts, - lookup_mem_rng_chk_mid_counts, - lookup_mem_rng_chk_hi_counts, - lookup_pow_2_0_counts, - lookup_pow_2_1_counts, - lookup_u8_0_counts, - lookup_u8_1_counts, - lookup_u16_0_counts, - lookup_u16_1_counts, - lookup_u16_2_counts, - lookup_u16_3_counts, - lookup_u16_4_counts, - lookup_u16_5_counts, - lookup_u16_6_counts, - lookup_u16_7_counts, - lookup_u16_8_counts, - lookup_u16_9_counts, - lookup_u16_10_counts, - lookup_u16_11_counts, - lookup_u16_12_counts, - lookup_u16_13_counts, - lookup_u16_14_counts, - lookup_div_u16_0_counts, - lookup_div_u16_1_counts, - lookup_div_u16_2_counts, - lookup_div_u16_3_counts, - lookup_div_u16_4_counts, - lookup_div_u16_5_counts, - lookup_div_u16_6_counts, - lookup_div_u16_7_counts }; - }; - RefVector get_to_be_shifted() - { - return { alu_a_hi, - alu_a_lo, - alu_b_hi, - alu_b_lo, - alu_cmp_rng_ctr, - alu_div_u16_r0, - alu_div_u16_r1, - alu_div_u16_r2, - alu_div_u16_r3, - alu_div_u16_r4, - alu_div_u16_r5, - alu_div_u16_r6, - alu_div_u16_r7, - alu_op_add, - alu_op_cast_prev, - alu_op_cast, - alu_op_div, - alu_op_mul, - alu_op_shl, - alu_op_shr, - alu_op_sub, - alu_p_sub_a_hi, - alu_p_sub_a_lo, - alu_p_sub_b_hi, - alu_p_sub_b_lo, - alu_sel_alu, - alu_sel_cmp, - alu_sel_div_rng_chk, - alu_sel_rng_chk_lookup, - alu_sel_rng_chk, - alu_u16_r0, - alu_u16_r1, - alu_u16_r2, - alu_u16_r3, - alu_u16_r4, - alu_u16_r5, - alu_u16_r6, - alu_u8_r0, - alu_u8_r1, - binary_acc_ia, - binary_acc_ib, - binary_acc_ic, - binary_mem_tag_ctr, - binary_op_id, - kernel_emit_l2_to_l1_msg_write_offset, - kernel_emit_note_hash_write_offset, - kernel_emit_nullifier_write_offset, - kernel_emit_unencrypted_log_write_offset, - kernel_l1_to_l2_msg_exists_write_offset, - kernel_note_hash_exist_write_offset, - kernel_nullifier_exists_write_offset, - kernel_nullifier_non_exists_write_offset, - kernel_side_effect_counter, - kernel_sload_write_offset, - kernel_sstore_write_offset, - main_da_gas_remaining, - main_internal_return_ptr, - main_l2_gas_remaining, - main_pc, - mem_glob_addr, - mem_rw, - mem_sel_mem, - mem_tag, - mem_tsp, - mem_val }; - }; - RefVector get_shifted() + DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) + + auto get_unshifted() { - return { alu_a_hi_shift, - alu_a_lo_shift, - alu_b_hi_shift, - alu_b_lo_shift, - alu_cmp_rng_ctr_shift, - alu_div_u16_r0_shift, - alu_div_u16_r1_shift, - alu_div_u16_r2_shift, - alu_div_u16_r3_shift, - alu_div_u16_r4_shift, - alu_div_u16_r5_shift, - alu_div_u16_r6_shift, - alu_div_u16_r7_shift, - alu_op_add_shift, - alu_op_cast_prev_shift, - alu_op_cast_shift, - alu_op_div_shift, - alu_op_mul_shift, - alu_op_shl_shift, - alu_op_shr_shift, - alu_op_sub_shift, - alu_p_sub_a_hi_shift, - alu_p_sub_a_lo_shift, - alu_p_sub_b_hi_shift, - alu_p_sub_b_lo_shift, - alu_sel_alu_shift, - alu_sel_cmp_shift, - alu_sel_div_rng_chk_shift, - alu_sel_rng_chk_lookup_shift, - alu_sel_rng_chk_shift, - alu_u16_r0_shift, - alu_u16_r1_shift, - alu_u16_r2_shift, - alu_u16_r3_shift, - alu_u16_r4_shift, - alu_u16_r5_shift, - alu_u16_r6_shift, - alu_u8_r0_shift, - alu_u8_r1_shift, - binary_acc_ia_shift, - binary_acc_ib_shift, - binary_acc_ic_shift, - binary_mem_tag_ctr_shift, - binary_op_id_shift, - kernel_emit_l2_to_l1_msg_write_offset_shift, - kernel_emit_note_hash_write_offset_shift, - kernel_emit_nullifier_write_offset_shift, - kernel_emit_unencrypted_log_write_offset_shift, - kernel_l1_to_l2_msg_exists_write_offset_shift, - kernel_note_hash_exist_write_offset_shift, - kernel_nullifier_exists_write_offset_shift, - kernel_nullifier_non_exists_write_offset_shift, - kernel_side_effect_counter_shift, - kernel_sload_write_offset_shift, - kernel_sstore_write_offset_shift, - main_da_gas_remaining_shift, - main_internal_return_ptr_shift, - main_l2_gas_remaining_shift, - main_pc_shift, - mem_glob_addr_shift, - mem_rw_shift, - mem_sel_mem_shift, - mem_tag_shift, - mem_tsp_shift, - mem_val_shift }; - }; + return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_all()); + } + auto get_to_be_shifted() { return AvmFlavor::get_to_be_shifted(*this); } + auto get_shifted() { return ShiftedEntities::get_all(); } + auto get_precomputed() { return PrecomputedEntities::get_all(); } }; public: diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 93ff4ac5989f..c4926193ce65 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -58,762 +58,11 @@ void AvmProver::execute_wire_commitments_round() // Commit to all polynomials (apart from logderivative inverse polynomials, which are committed to in the later // logderivative phase) - witness_commitments.kernel_kernel_inputs = commitment_key->commit(key->kernel_kernel_inputs); - witness_commitments.kernel_kernel_value_out = commitment_key->commit(key->kernel_kernel_value_out); - witness_commitments.kernel_kernel_side_effect_out = commitment_key->commit(key->kernel_kernel_side_effect_out); - witness_commitments.kernel_kernel_metadata_out = commitment_key->commit(key->kernel_kernel_metadata_out); - witness_commitments.main_calldata = commitment_key->commit(key->main_calldata); - witness_commitments.alu_a_hi = commitment_key->commit(key->alu_a_hi); - witness_commitments.alu_a_lo = commitment_key->commit(key->alu_a_lo); - witness_commitments.alu_b_hi = commitment_key->commit(key->alu_b_hi); - witness_commitments.alu_b_lo = commitment_key->commit(key->alu_b_lo); - witness_commitments.alu_borrow = commitment_key->commit(key->alu_borrow); - witness_commitments.alu_cf = commitment_key->commit(key->alu_cf); - witness_commitments.alu_clk = commitment_key->commit(key->alu_clk); - witness_commitments.alu_cmp_rng_ctr = commitment_key->commit(key->alu_cmp_rng_ctr); - witness_commitments.alu_div_u16_r0 = commitment_key->commit(key->alu_div_u16_r0); - witness_commitments.alu_div_u16_r1 = commitment_key->commit(key->alu_div_u16_r1); - witness_commitments.alu_div_u16_r2 = commitment_key->commit(key->alu_div_u16_r2); - witness_commitments.alu_div_u16_r3 = commitment_key->commit(key->alu_div_u16_r3); - witness_commitments.alu_div_u16_r4 = commitment_key->commit(key->alu_div_u16_r4); - witness_commitments.alu_div_u16_r5 = commitment_key->commit(key->alu_div_u16_r5); - witness_commitments.alu_div_u16_r6 = commitment_key->commit(key->alu_div_u16_r6); - witness_commitments.alu_div_u16_r7 = commitment_key->commit(key->alu_div_u16_r7); - witness_commitments.alu_divisor_hi = commitment_key->commit(key->alu_divisor_hi); - witness_commitments.alu_divisor_lo = commitment_key->commit(key->alu_divisor_lo); - witness_commitments.alu_ff_tag = commitment_key->commit(key->alu_ff_tag); - witness_commitments.alu_ia = commitment_key->commit(key->alu_ia); - witness_commitments.alu_ib = commitment_key->commit(key->alu_ib); - witness_commitments.alu_ic = commitment_key->commit(key->alu_ic); - witness_commitments.alu_in_tag = commitment_key->commit(key->alu_in_tag); - witness_commitments.alu_op_add = commitment_key->commit(key->alu_op_add); - witness_commitments.alu_op_cast = commitment_key->commit(key->alu_op_cast); - witness_commitments.alu_op_cast_prev = commitment_key->commit(key->alu_op_cast_prev); - witness_commitments.alu_op_div = commitment_key->commit(key->alu_op_div); - witness_commitments.alu_op_div_a_lt_b = commitment_key->commit(key->alu_op_div_a_lt_b); - witness_commitments.alu_op_div_std = commitment_key->commit(key->alu_op_div_std); - witness_commitments.alu_op_eq = commitment_key->commit(key->alu_op_eq); - witness_commitments.alu_op_eq_diff_inv = commitment_key->commit(key->alu_op_eq_diff_inv); - witness_commitments.alu_op_lt = commitment_key->commit(key->alu_op_lt); - witness_commitments.alu_op_lte = commitment_key->commit(key->alu_op_lte); - witness_commitments.alu_op_mul = commitment_key->commit(key->alu_op_mul); - witness_commitments.alu_op_not = commitment_key->commit(key->alu_op_not); - witness_commitments.alu_op_shl = commitment_key->commit(key->alu_op_shl); - witness_commitments.alu_op_shr = commitment_key->commit(key->alu_op_shr); - witness_commitments.alu_op_sub = commitment_key->commit(key->alu_op_sub); - witness_commitments.alu_p_a_borrow = commitment_key->commit(key->alu_p_a_borrow); - witness_commitments.alu_p_b_borrow = commitment_key->commit(key->alu_p_b_borrow); - witness_commitments.alu_p_sub_a_hi = commitment_key->commit(key->alu_p_sub_a_hi); - witness_commitments.alu_p_sub_a_lo = commitment_key->commit(key->alu_p_sub_a_lo); - witness_commitments.alu_p_sub_b_hi = commitment_key->commit(key->alu_p_sub_b_hi); - witness_commitments.alu_p_sub_b_lo = commitment_key->commit(key->alu_p_sub_b_lo); - witness_commitments.alu_partial_prod_hi = commitment_key->commit(key->alu_partial_prod_hi); - witness_commitments.alu_partial_prod_lo = commitment_key->commit(key->alu_partial_prod_lo); - witness_commitments.alu_quotient_hi = commitment_key->commit(key->alu_quotient_hi); - witness_commitments.alu_quotient_lo = commitment_key->commit(key->alu_quotient_lo); - witness_commitments.alu_remainder = commitment_key->commit(key->alu_remainder); - witness_commitments.alu_res_hi = commitment_key->commit(key->alu_res_hi); - witness_commitments.alu_res_lo = commitment_key->commit(key->alu_res_lo); - witness_commitments.alu_sel_alu = commitment_key->commit(key->alu_sel_alu); - witness_commitments.alu_sel_cmp = commitment_key->commit(key->alu_sel_cmp); - witness_commitments.alu_sel_div_rng_chk = commitment_key->commit(key->alu_sel_div_rng_chk); - witness_commitments.alu_sel_rng_chk = commitment_key->commit(key->alu_sel_rng_chk); - witness_commitments.alu_sel_rng_chk_lookup = commitment_key->commit(key->alu_sel_rng_chk_lookup); - witness_commitments.alu_sel_shift_which = commitment_key->commit(key->alu_sel_shift_which); - witness_commitments.alu_shift_lt_bit_len = commitment_key->commit(key->alu_shift_lt_bit_len); - witness_commitments.alu_t_sub_s_bits = commitment_key->commit(key->alu_t_sub_s_bits); - witness_commitments.alu_two_pow_s = commitment_key->commit(key->alu_two_pow_s); - witness_commitments.alu_two_pow_t_sub_s = commitment_key->commit(key->alu_two_pow_t_sub_s); - witness_commitments.alu_u128_tag = commitment_key->commit(key->alu_u128_tag); - witness_commitments.alu_u16_r0 = commitment_key->commit(key->alu_u16_r0); - witness_commitments.alu_u16_r1 = commitment_key->commit(key->alu_u16_r1); - witness_commitments.alu_u16_r10 = commitment_key->commit(key->alu_u16_r10); - witness_commitments.alu_u16_r11 = commitment_key->commit(key->alu_u16_r11); - witness_commitments.alu_u16_r12 = commitment_key->commit(key->alu_u16_r12); - witness_commitments.alu_u16_r13 = commitment_key->commit(key->alu_u16_r13); - witness_commitments.alu_u16_r14 = commitment_key->commit(key->alu_u16_r14); - witness_commitments.alu_u16_r2 = commitment_key->commit(key->alu_u16_r2); - witness_commitments.alu_u16_r3 = commitment_key->commit(key->alu_u16_r3); - witness_commitments.alu_u16_r4 = commitment_key->commit(key->alu_u16_r4); - witness_commitments.alu_u16_r5 = commitment_key->commit(key->alu_u16_r5); - witness_commitments.alu_u16_r6 = commitment_key->commit(key->alu_u16_r6); - witness_commitments.alu_u16_r7 = commitment_key->commit(key->alu_u16_r7); - witness_commitments.alu_u16_r8 = commitment_key->commit(key->alu_u16_r8); - witness_commitments.alu_u16_r9 = commitment_key->commit(key->alu_u16_r9); - witness_commitments.alu_u16_tag = commitment_key->commit(key->alu_u16_tag); - witness_commitments.alu_u32_tag = commitment_key->commit(key->alu_u32_tag); - witness_commitments.alu_u64_tag = commitment_key->commit(key->alu_u64_tag); - witness_commitments.alu_u8_r0 = commitment_key->commit(key->alu_u8_r0); - witness_commitments.alu_u8_r1 = commitment_key->commit(key->alu_u8_r1); - witness_commitments.alu_u8_tag = commitment_key->commit(key->alu_u8_tag); - witness_commitments.binary_acc_ia = commitment_key->commit(key->binary_acc_ia); - witness_commitments.binary_acc_ib = commitment_key->commit(key->binary_acc_ib); - witness_commitments.binary_acc_ic = commitment_key->commit(key->binary_acc_ic); - witness_commitments.binary_clk = commitment_key->commit(key->binary_clk); - witness_commitments.binary_ia_bytes = commitment_key->commit(key->binary_ia_bytes); - witness_commitments.binary_ib_bytes = commitment_key->commit(key->binary_ib_bytes); - witness_commitments.binary_ic_bytes = commitment_key->commit(key->binary_ic_bytes); - witness_commitments.binary_in_tag = commitment_key->commit(key->binary_in_tag); - witness_commitments.binary_mem_tag_ctr = commitment_key->commit(key->binary_mem_tag_ctr); - witness_commitments.binary_mem_tag_ctr_inv = commitment_key->commit(key->binary_mem_tag_ctr_inv); - witness_commitments.binary_op_id = commitment_key->commit(key->binary_op_id); - witness_commitments.binary_sel_bin = commitment_key->commit(key->binary_sel_bin); - witness_commitments.binary_start = commitment_key->commit(key->binary_start); - witness_commitments.byte_lookup_sel_bin = commitment_key->commit(key->byte_lookup_sel_bin); - witness_commitments.byte_lookup_table_byte_lengths = commitment_key->commit(key->byte_lookup_table_byte_lengths); - witness_commitments.byte_lookup_table_in_tags = commitment_key->commit(key->byte_lookup_table_in_tags); - witness_commitments.byte_lookup_table_input_a = commitment_key->commit(key->byte_lookup_table_input_a); - witness_commitments.byte_lookup_table_input_b = commitment_key->commit(key->byte_lookup_table_input_b); - witness_commitments.byte_lookup_table_op_id = commitment_key->commit(key->byte_lookup_table_op_id); - witness_commitments.byte_lookup_table_output = commitment_key->commit(key->byte_lookup_table_output); - witness_commitments.conversion_clk = commitment_key->commit(key->conversion_clk); - witness_commitments.conversion_input = commitment_key->commit(key->conversion_input); - witness_commitments.conversion_num_limbs = commitment_key->commit(key->conversion_num_limbs); - witness_commitments.conversion_radix = commitment_key->commit(key->conversion_radix); - witness_commitments.conversion_sel_to_radix_le = commitment_key->commit(key->conversion_sel_to_radix_le); - witness_commitments.gas_da_gas_fixed_table = commitment_key->commit(key->gas_da_gas_fixed_table); - witness_commitments.gas_l2_gas_fixed_table = commitment_key->commit(key->gas_l2_gas_fixed_table); - witness_commitments.gas_sel_gas_cost = commitment_key->commit(key->gas_sel_gas_cost); - witness_commitments.keccakf1600_clk = commitment_key->commit(key->keccakf1600_clk); - witness_commitments.keccakf1600_input = commitment_key->commit(key->keccakf1600_input); - witness_commitments.keccakf1600_output = commitment_key->commit(key->keccakf1600_output); - witness_commitments.keccakf1600_sel_keccakf1600 = commitment_key->commit(key->keccakf1600_sel_keccakf1600); - witness_commitments.kernel_emit_l2_to_l1_msg_write_offset = - commitment_key->commit(key->kernel_emit_l2_to_l1_msg_write_offset); - witness_commitments.kernel_emit_note_hash_write_offset = - commitment_key->commit(key->kernel_emit_note_hash_write_offset); - witness_commitments.kernel_emit_nullifier_write_offset = - commitment_key->commit(key->kernel_emit_nullifier_write_offset); - witness_commitments.kernel_emit_unencrypted_log_write_offset = - commitment_key->commit(key->kernel_emit_unencrypted_log_write_offset); - witness_commitments.kernel_kernel_in_offset = commitment_key->commit(key->kernel_kernel_in_offset); - witness_commitments.kernel_kernel_out_offset = commitment_key->commit(key->kernel_kernel_out_offset); - witness_commitments.kernel_l1_to_l2_msg_exists_write_offset = - commitment_key->commit(key->kernel_l1_to_l2_msg_exists_write_offset); - witness_commitments.kernel_note_hash_exist_write_offset = - commitment_key->commit(key->kernel_note_hash_exist_write_offset); - witness_commitments.kernel_nullifier_exists_write_offset = - commitment_key->commit(key->kernel_nullifier_exists_write_offset); - witness_commitments.kernel_nullifier_non_exists_write_offset = - commitment_key->commit(key->kernel_nullifier_non_exists_write_offset); - witness_commitments.kernel_q_public_input_kernel_add_to_table = - commitment_key->commit(key->kernel_q_public_input_kernel_add_to_table); - witness_commitments.kernel_q_public_input_kernel_out_add_to_table = - commitment_key->commit(key->kernel_q_public_input_kernel_out_add_to_table); - witness_commitments.kernel_side_effect_counter = commitment_key->commit(key->kernel_side_effect_counter); - witness_commitments.kernel_sload_write_offset = commitment_key->commit(key->kernel_sload_write_offset); - witness_commitments.kernel_sstore_write_offset = commitment_key->commit(key->kernel_sstore_write_offset); - witness_commitments.main_abs_da_rem_gas_hi = commitment_key->commit(key->main_abs_da_rem_gas_hi); - witness_commitments.main_abs_da_rem_gas_lo = commitment_key->commit(key->main_abs_da_rem_gas_lo); - witness_commitments.main_abs_l2_rem_gas_hi = commitment_key->commit(key->main_abs_l2_rem_gas_hi); - witness_commitments.main_abs_l2_rem_gas_lo = commitment_key->commit(key->main_abs_l2_rem_gas_lo); - witness_commitments.main_alu_in_tag = commitment_key->commit(key->main_alu_in_tag); - witness_commitments.main_bin_op_id = commitment_key->commit(key->main_bin_op_id); - witness_commitments.main_call_ptr = commitment_key->commit(key->main_call_ptr); - witness_commitments.main_da_gas_op_cost = commitment_key->commit(key->main_da_gas_op_cost); - witness_commitments.main_da_gas_remaining = commitment_key->commit(key->main_da_gas_remaining); - witness_commitments.main_da_out_of_gas = commitment_key->commit(key->main_da_out_of_gas); - witness_commitments.main_ia = commitment_key->commit(key->main_ia); - witness_commitments.main_ib = commitment_key->commit(key->main_ib); - witness_commitments.main_ic = commitment_key->commit(key->main_ic); - witness_commitments.main_id = commitment_key->commit(key->main_id); - witness_commitments.main_id_zero = commitment_key->commit(key->main_id_zero); - witness_commitments.main_ind_addr_a = commitment_key->commit(key->main_ind_addr_a); - witness_commitments.main_ind_addr_b = commitment_key->commit(key->main_ind_addr_b); - witness_commitments.main_ind_addr_c = commitment_key->commit(key->main_ind_addr_c); - witness_commitments.main_ind_addr_d = commitment_key->commit(key->main_ind_addr_d); - witness_commitments.main_internal_return_ptr = commitment_key->commit(key->main_internal_return_ptr); - witness_commitments.main_inv = commitment_key->commit(key->main_inv); - witness_commitments.main_l2_gas_op_cost = commitment_key->commit(key->main_l2_gas_op_cost); - witness_commitments.main_l2_gas_remaining = commitment_key->commit(key->main_l2_gas_remaining); - witness_commitments.main_l2_out_of_gas = commitment_key->commit(key->main_l2_out_of_gas); - witness_commitments.main_mem_addr_a = commitment_key->commit(key->main_mem_addr_a); - witness_commitments.main_mem_addr_b = commitment_key->commit(key->main_mem_addr_b); - witness_commitments.main_mem_addr_c = commitment_key->commit(key->main_mem_addr_c); - witness_commitments.main_mem_addr_d = commitment_key->commit(key->main_mem_addr_d); - witness_commitments.main_op_err = commitment_key->commit(key->main_op_err); - witness_commitments.main_opcode_val = commitment_key->commit(key->main_opcode_val); - witness_commitments.main_pc = commitment_key->commit(key->main_pc); - witness_commitments.main_r_in_tag = commitment_key->commit(key->main_r_in_tag); - witness_commitments.main_rwa = commitment_key->commit(key->main_rwa); - witness_commitments.main_rwb = commitment_key->commit(key->main_rwb); - witness_commitments.main_rwc = commitment_key->commit(key->main_rwc); - witness_commitments.main_rwd = commitment_key->commit(key->main_rwd); - witness_commitments.main_sel_alu = commitment_key->commit(key->main_sel_alu); - witness_commitments.main_sel_bin = commitment_key->commit(key->main_sel_bin); - witness_commitments.main_sel_gas_accounting_active = commitment_key->commit(key->main_sel_gas_accounting_active); - witness_commitments.main_sel_last = commitment_key->commit(key->main_sel_last); - witness_commitments.main_sel_mem_op_a = commitment_key->commit(key->main_sel_mem_op_a); - witness_commitments.main_sel_mem_op_activate_gas = commitment_key->commit(key->main_sel_mem_op_activate_gas); - witness_commitments.main_sel_mem_op_b = commitment_key->commit(key->main_sel_mem_op_b); - witness_commitments.main_sel_mem_op_c = commitment_key->commit(key->main_sel_mem_op_c); - witness_commitments.main_sel_mem_op_d = commitment_key->commit(key->main_sel_mem_op_d); - witness_commitments.main_sel_mov_ia_to_ic = commitment_key->commit(key->main_sel_mov_ia_to_ic); - witness_commitments.main_sel_mov_ib_to_ic = commitment_key->commit(key->main_sel_mov_ib_to_ic); - witness_commitments.main_sel_op_add = commitment_key->commit(key->main_sel_op_add); - witness_commitments.main_sel_op_address = commitment_key->commit(key->main_sel_op_address); - witness_commitments.main_sel_op_and = commitment_key->commit(key->main_sel_op_and); - witness_commitments.main_sel_op_block_number = commitment_key->commit(key->main_sel_op_block_number); - witness_commitments.main_sel_op_cast = commitment_key->commit(key->main_sel_op_cast); - witness_commitments.main_sel_op_chain_id = commitment_key->commit(key->main_sel_op_chain_id); - witness_commitments.main_sel_op_cmov = commitment_key->commit(key->main_sel_op_cmov); - witness_commitments.main_sel_op_coinbase = commitment_key->commit(key->main_sel_op_coinbase); - witness_commitments.main_sel_op_dagasleft = commitment_key->commit(key->main_sel_op_dagasleft); - witness_commitments.main_sel_op_div = commitment_key->commit(key->main_sel_op_div); - witness_commitments.main_sel_op_emit_l2_to_l1_msg = commitment_key->commit(key->main_sel_op_emit_l2_to_l1_msg); - witness_commitments.main_sel_op_emit_note_hash = commitment_key->commit(key->main_sel_op_emit_note_hash); - witness_commitments.main_sel_op_emit_nullifier = commitment_key->commit(key->main_sel_op_emit_nullifier); - witness_commitments.main_sel_op_emit_unencrypted_log = - commitment_key->commit(key->main_sel_op_emit_unencrypted_log); - witness_commitments.main_sel_op_eq = commitment_key->commit(key->main_sel_op_eq); - witness_commitments.main_sel_op_external_call = commitment_key->commit(key->main_sel_op_external_call); - witness_commitments.main_sel_op_fdiv = commitment_key->commit(key->main_sel_op_fdiv); - witness_commitments.main_sel_op_fee_per_da_gas = commitment_key->commit(key->main_sel_op_fee_per_da_gas); - witness_commitments.main_sel_op_fee_per_l2_gas = commitment_key->commit(key->main_sel_op_fee_per_l2_gas); - witness_commitments.main_sel_op_function_selector = commitment_key->commit(key->main_sel_op_function_selector); - witness_commitments.main_sel_op_get_contract_instance = - commitment_key->commit(key->main_sel_op_get_contract_instance); - witness_commitments.main_sel_op_halt = commitment_key->commit(key->main_sel_op_halt); - witness_commitments.main_sel_op_internal_call = commitment_key->commit(key->main_sel_op_internal_call); - witness_commitments.main_sel_op_internal_return = commitment_key->commit(key->main_sel_op_internal_return); - witness_commitments.main_sel_op_jump = commitment_key->commit(key->main_sel_op_jump); - witness_commitments.main_sel_op_jumpi = commitment_key->commit(key->main_sel_op_jumpi); - witness_commitments.main_sel_op_keccak = commitment_key->commit(key->main_sel_op_keccak); - witness_commitments.main_sel_op_l1_to_l2_msg_exists = commitment_key->commit(key->main_sel_op_l1_to_l2_msg_exists); - witness_commitments.main_sel_op_l2gasleft = commitment_key->commit(key->main_sel_op_l2gasleft); - witness_commitments.main_sel_op_lt = commitment_key->commit(key->main_sel_op_lt); - witness_commitments.main_sel_op_lte = commitment_key->commit(key->main_sel_op_lte); - witness_commitments.main_sel_op_mov = commitment_key->commit(key->main_sel_op_mov); - witness_commitments.main_sel_op_mul = commitment_key->commit(key->main_sel_op_mul); - witness_commitments.main_sel_op_not = commitment_key->commit(key->main_sel_op_not); - witness_commitments.main_sel_op_note_hash_exists = commitment_key->commit(key->main_sel_op_note_hash_exists); - witness_commitments.main_sel_op_nullifier_exists = commitment_key->commit(key->main_sel_op_nullifier_exists); - witness_commitments.main_sel_op_or = commitment_key->commit(key->main_sel_op_or); - witness_commitments.main_sel_op_pedersen = commitment_key->commit(key->main_sel_op_pedersen); - witness_commitments.main_sel_op_poseidon2 = commitment_key->commit(key->main_sel_op_poseidon2); - witness_commitments.main_sel_op_radix_le = commitment_key->commit(key->main_sel_op_radix_le); - witness_commitments.main_sel_op_sender = commitment_key->commit(key->main_sel_op_sender); - witness_commitments.main_sel_op_sha256 = commitment_key->commit(key->main_sel_op_sha256); - witness_commitments.main_sel_op_shl = commitment_key->commit(key->main_sel_op_shl); - witness_commitments.main_sel_op_shr = commitment_key->commit(key->main_sel_op_shr); - witness_commitments.main_sel_op_sload = commitment_key->commit(key->main_sel_op_sload); - witness_commitments.main_sel_op_sstore = commitment_key->commit(key->main_sel_op_sstore); - witness_commitments.main_sel_op_storage_address = commitment_key->commit(key->main_sel_op_storage_address); - witness_commitments.main_sel_op_sub = commitment_key->commit(key->main_sel_op_sub); - witness_commitments.main_sel_op_timestamp = commitment_key->commit(key->main_sel_op_timestamp); - witness_commitments.main_sel_op_transaction_fee = commitment_key->commit(key->main_sel_op_transaction_fee); - witness_commitments.main_sel_op_version = commitment_key->commit(key->main_sel_op_version); - witness_commitments.main_sel_op_xor = commitment_key->commit(key->main_sel_op_xor); - witness_commitments.main_sel_q_kernel_lookup = commitment_key->commit(key->main_sel_q_kernel_lookup); - witness_commitments.main_sel_q_kernel_output_lookup = commitment_key->commit(key->main_sel_q_kernel_output_lookup); - witness_commitments.main_sel_resolve_ind_addr_a = commitment_key->commit(key->main_sel_resolve_ind_addr_a); - witness_commitments.main_sel_resolve_ind_addr_b = commitment_key->commit(key->main_sel_resolve_ind_addr_b); - witness_commitments.main_sel_resolve_ind_addr_c = commitment_key->commit(key->main_sel_resolve_ind_addr_c); - witness_commitments.main_sel_resolve_ind_addr_d = commitment_key->commit(key->main_sel_resolve_ind_addr_d); - witness_commitments.main_sel_rng_16 = commitment_key->commit(key->main_sel_rng_16); - witness_commitments.main_sel_rng_8 = commitment_key->commit(key->main_sel_rng_8); - witness_commitments.main_space_id = commitment_key->commit(key->main_space_id); - witness_commitments.main_tag_err = commitment_key->commit(key->main_tag_err); - witness_commitments.main_w_in_tag = commitment_key->commit(key->main_w_in_tag); - witness_commitments.mem_addr = commitment_key->commit(key->mem_addr); - witness_commitments.mem_clk = commitment_key->commit(key->mem_clk); - witness_commitments.mem_diff_hi = commitment_key->commit(key->mem_diff_hi); - witness_commitments.mem_diff_lo = commitment_key->commit(key->mem_diff_lo); - witness_commitments.mem_diff_mid = commitment_key->commit(key->mem_diff_mid); - witness_commitments.mem_glob_addr = commitment_key->commit(key->mem_glob_addr); - witness_commitments.mem_last = commitment_key->commit(key->mem_last); - witness_commitments.mem_lastAccess = commitment_key->commit(key->mem_lastAccess); - witness_commitments.mem_one_min_inv = commitment_key->commit(key->mem_one_min_inv); - witness_commitments.mem_r_in_tag = commitment_key->commit(key->mem_r_in_tag); - witness_commitments.mem_rw = commitment_key->commit(key->mem_rw); - witness_commitments.mem_sel_mem = commitment_key->commit(key->mem_sel_mem); - witness_commitments.mem_sel_mov_ia_to_ic = commitment_key->commit(key->mem_sel_mov_ia_to_ic); - witness_commitments.mem_sel_mov_ib_to_ic = commitment_key->commit(key->mem_sel_mov_ib_to_ic); - witness_commitments.mem_sel_op_a = commitment_key->commit(key->mem_sel_op_a); - witness_commitments.mem_sel_op_b = commitment_key->commit(key->mem_sel_op_b); - witness_commitments.mem_sel_op_c = commitment_key->commit(key->mem_sel_op_c); - witness_commitments.mem_sel_op_cmov = commitment_key->commit(key->mem_sel_op_cmov); - witness_commitments.mem_sel_op_d = commitment_key->commit(key->mem_sel_op_d); - witness_commitments.mem_sel_resolve_ind_addr_a = commitment_key->commit(key->mem_sel_resolve_ind_addr_a); - witness_commitments.mem_sel_resolve_ind_addr_b = commitment_key->commit(key->mem_sel_resolve_ind_addr_b); - witness_commitments.mem_sel_resolve_ind_addr_c = commitment_key->commit(key->mem_sel_resolve_ind_addr_c); - witness_commitments.mem_sel_resolve_ind_addr_d = commitment_key->commit(key->mem_sel_resolve_ind_addr_d); - witness_commitments.mem_sel_rng_chk = commitment_key->commit(key->mem_sel_rng_chk); - witness_commitments.mem_skip_check_tag = commitment_key->commit(key->mem_skip_check_tag); - witness_commitments.mem_space_id = commitment_key->commit(key->mem_space_id); - witness_commitments.mem_tag = commitment_key->commit(key->mem_tag); - witness_commitments.mem_tag_err = commitment_key->commit(key->mem_tag_err); - witness_commitments.mem_tsp = commitment_key->commit(key->mem_tsp); - witness_commitments.mem_val = commitment_key->commit(key->mem_val); - witness_commitments.mem_w_in_tag = commitment_key->commit(key->mem_w_in_tag); - witness_commitments.pedersen_clk = commitment_key->commit(key->pedersen_clk); - witness_commitments.pedersen_input = commitment_key->commit(key->pedersen_input); - witness_commitments.pedersen_output = commitment_key->commit(key->pedersen_output); - witness_commitments.pedersen_sel_pedersen = commitment_key->commit(key->pedersen_sel_pedersen); - witness_commitments.poseidon2_clk = commitment_key->commit(key->poseidon2_clk); - witness_commitments.poseidon2_input = commitment_key->commit(key->poseidon2_input); - witness_commitments.poseidon2_output = commitment_key->commit(key->poseidon2_output); - witness_commitments.poseidon2_sel_poseidon_perm = commitment_key->commit(key->poseidon2_sel_poseidon_perm); - witness_commitments.powers_power_of_2 = commitment_key->commit(key->powers_power_of_2); - witness_commitments.sha256_clk = commitment_key->commit(key->sha256_clk); - witness_commitments.sha256_input = commitment_key->commit(key->sha256_input); - witness_commitments.sha256_output = commitment_key->commit(key->sha256_output); - witness_commitments.sha256_sel_sha256_compression = commitment_key->commit(key->sha256_sel_sha256_compression); - witness_commitments.sha256_state = commitment_key->commit(key->sha256_state); - witness_commitments.lookup_byte_lengths_counts = commitment_key->commit(key->lookup_byte_lengths_counts); - witness_commitments.lookup_byte_operations_counts = commitment_key->commit(key->lookup_byte_operations_counts); - witness_commitments.lookup_opcode_gas_counts = commitment_key->commit(key->lookup_opcode_gas_counts); - witness_commitments.range_check_l2_gas_hi_counts = commitment_key->commit(key->range_check_l2_gas_hi_counts); - witness_commitments.range_check_l2_gas_lo_counts = commitment_key->commit(key->range_check_l2_gas_lo_counts); - witness_commitments.range_check_da_gas_hi_counts = commitment_key->commit(key->range_check_da_gas_hi_counts); - witness_commitments.range_check_da_gas_lo_counts = commitment_key->commit(key->range_check_da_gas_lo_counts); - witness_commitments.kernel_output_lookup_counts = commitment_key->commit(key->kernel_output_lookup_counts); - witness_commitments.lookup_into_kernel_counts = commitment_key->commit(key->lookup_into_kernel_counts); - witness_commitments.incl_main_tag_err_counts = commitment_key->commit(key->incl_main_tag_err_counts); - witness_commitments.incl_mem_tag_err_counts = commitment_key->commit(key->incl_mem_tag_err_counts); - witness_commitments.lookup_mem_rng_chk_lo_counts = commitment_key->commit(key->lookup_mem_rng_chk_lo_counts); - witness_commitments.lookup_mem_rng_chk_mid_counts = commitment_key->commit(key->lookup_mem_rng_chk_mid_counts); - witness_commitments.lookup_mem_rng_chk_hi_counts = commitment_key->commit(key->lookup_mem_rng_chk_hi_counts); - witness_commitments.lookup_pow_2_0_counts = commitment_key->commit(key->lookup_pow_2_0_counts); - witness_commitments.lookup_pow_2_1_counts = commitment_key->commit(key->lookup_pow_2_1_counts); - witness_commitments.lookup_u8_0_counts = commitment_key->commit(key->lookup_u8_0_counts); - witness_commitments.lookup_u8_1_counts = commitment_key->commit(key->lookup_u8_1_counts); - witness_commitments.lookup_u16_0_counts = commitment_key->commit(key->lookup_u16_0_counts); - witness_commitments.lookup_u16_1_counts = commitment_key->commit(key->lookup_u16_1_counts); - witness_commitments.lookup_u16_2_counts = commitment_key->commit(key->lookup_u16_2_counts); - witness_commitments.lookup_u16_3_counts = commitment_key->commit(key->lookup_u16_3_counts); - witness_commitments.lookup_u16_4_counts = commitment_key->commit(key->lookup_u16_4_counts); - witness_commitments.lookup_u16_5_counts = commitment_key->commit(key->lookup_u16_5_counts); - witness_commitments.lookup_u16_6_counts = commitment_key->commit(key->lookup_u16_6_counts); - witness_commitments.lookup_u16_7_counts = commitment_key->commit(key->lookup_u16_7_counts); - witness_commitments.lookup_u16_8_counts = commitment_key->commit(key->lookup_u16_8_counts); - witness_commitments.lookup_u16_9_counts = commitment_key->commit(key->lookup_u16_9_counts); - witness_commitments.lookup_u16_10_counts = commitment_key->commit(key->lookup_u16_10_counts); - witness_commitments.lookup_u16_11_counts = commitment_key->commit(key->lookup_u16_11_counts); - witness_commitments.lookup_u16_12_counts = commitment_key->commit(key->lookup_u16_12_counts); - witness_commitments.lookup_u16_13_counts = commitment_key->commit(key->lookup_u16_13_counts); - witness_commitments.lookup_u16_14_counts = commitment_key->commit(key->lookup_u16_14_counts); - witness_commitments.lookup_div_u16_0_counts = commitment_key->commit(key->lookup_div_u16_0_counts); - witness_commitments.lookup_div_u16_1_counts = commitment_key->commit(key->lookup_div_u16_1_counts); - witness_commitments.lookup_div_u16_2_counts = commitment_key->commit(key->lookup_div_u16_2_counts); - witness_commitments.lookup_div_u16_3_counts = commitment_key->commit(key->lookup_div_u16_3_counts); - witness_commitments.lookup_div_u16_4_counts = commitment_key->commit(key->lookup_div_u16_4_counts); - witness_commitments.lookup_div_u16_5_counts = commitment_key->commit(key->lookup_div_u16_5_counts); - witness_commitments.lookup_div_u16_6_counts = commitment_key->commit(key->lookup_div_u16_6_counts); - witness_commitments.lookup_div_u16_7_counts = commitment_key->commit(key->lookup_div_u16_7_counts); - - // Send all commitments to the verifier - transcript->send_to_verifier(commitment_labels.kernel_kernel_inputs, witness_commitments.kernel_kernel_inputs); - transcript->send_to_verifier(commitment_labels.kernel_kernel_value_out, - witness_commitments.kernel_kernel_value_out); - transcript->send_to_verifier(commitment_labels.kernel_kernel_side_effect_out, - witness_commitments.kernel_kernel_side_effect_out); - transcript->send_to_verifier(commitment_labels.kernel_kernel_metadata_out, - witness_commitments.kernel_kernel_metadata_out); - transcript->send_to_verifier(commitment_labels.main_calldata, witness_commitments.main_calldata); - transcript->send_to_verifier(commitment_labels.alu_a_hi, witness_commitments.alu_a_hi); - transcript->send_to_verifier(commitment_labels.alu_a_lo, witness_commitments.alu_a_lo); - transcript->send_to_verifier(commitment_labels.alu_b_hi, witness_commitments.alu_b_hi); - transcript->send_to_verifier(commitment_labels.alu_b_lo, witness_commitments.alu_b_lo); - transcript->send_to_verifier(commitment_labels.alu_borrow, witness_commitments.alu_borrow); - transcript->send_to_verifier(commitment_labels.alu_cf, witness_commitments.alu_cf); - transcript->send_to_verifier(commitment_labels.alu_clk, witness_commitments.alu_clk); - transcript->send_to_verifier(commitment_labels.alu_cmp_rng_ctr, witness_commitments.alu_cmp_rng_ctr); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r0, witness_commitments.alu_div_u16_r0); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r1, witness_commitments.alu_div_u16_r1); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r2, witness_commitments.alu_div_u16_r2); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r3, witness_commitments.alu_div_u16_r3); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r4, witness_commitments.alu_div_u16_r4); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r5, witness_commitments.alu_div_u16_r5); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r6, witness_commitments.alu_div_u16_r6); - transcript->send_to_verifier(commitment_labels.alu_div_u16_r7, witness_commitments.alu_div_u16_r7); - transcript->send_to_verifier(commitment_labels.alu_divisor_hi, witness_commitments.alu_divisor_hi); - transcript->send_to_verifier(commitment_labels.alu_divisor_lo, witness_commitments.alu_divisor_lo); - transcript->send_to_verifier(commitment_labels.alu_ff_tag, witness_commitments.alu_ff_tag); - transcript->send_to_verifier(commitment_labels.alu_ia, witness_commitments.alu_ia); - transcript->send_to_verifier(commitment_labels.alu_ib, witness_commitments.alu_ib); - transcript->send_to_verifier(commitment_labels.alu_ic, witness_commitments.alu_ic); - transcript->send_to_verifier(commitment_labels.alu_in_tag, witness_commitments.alu_in_tag); - transcript->send_to_verifier(commitment_labels.alu_op_add, witness_commitments.alu_op_add); - transcript->send_to_verifier(commitment_labels.alu_op_cast, witness_commitments.alu_op_cast); - transcript->send_to_verifier(commitment_labels.alu_op_cast_prev, witness_commitments.alu_op_cast_prev); - transcript->send_to_verifier(commitment_labels.alu_op_div, witness_commitments.alu_op_div); - transcript->send_to_verifier(commitment_labels.alu_op_div_a_lt_b, witness_commitments.alu_op_div_a_lt_b); - transcript->send_to_verifier(commitment_labels.alu_op_div_std, witness_commitments.alu_op_div_std); - transcript->send_to_verifier(commitment_labels.alu_op_eq, witness_commitments.alu_op_eq); - transcript->send_to_verifier(commitment_labels.alu_op_eq_diff_inv, witness_commitments.alu_op_eq_diff_inv); - transcript->send_to_verifier(commitment_labels.alu_op_lt, witness_commitments.alu_op_lt); - transcript->send_to_verifier(commitment_labels.alu_op_lte, witness_commitments.alu_op_lte); - transcript->send_to_verifier(commitment_labels.alu_op_mul, witness_commitments.alu_op_mul); - transcript->send_to_verifier(commitment_labels.alu_op_not, witness_commitments.alu_op_not); - transcript->send_to_verifier(commitment_labels.alu_op_shl, witness_commitments.alu_op_shl); - transcript->send_to_verifier(commitment_labels.alu_op_shr, witness_commitments.alu_op_shr); - transcript->send_to_verifier(commitment_labels.alu_op_sub, witness_commitments.alu_op_sub); - transcript->send_to_verifier(commitment_labels.alu_p_a_borrow, witness_commitments.alu_p_a_borrow); - transcript->send_to_verifier(commitment_labels.alu_p_b_borrow, witness_commitments.alu_p_b_borrow); - transcript->send_to_verifier(commitment_labels.alu_p_sub_a_hi, witness_commitments.alu_p_sub_a_hi); - transcript->send_to_verifier(commitment_labels.alu_p_sub_a_lo, witness_commitments.alu_p_sub_a_lo); - transcript->send_to_verifier(commitment_labels.alu_p_sub_b_hi, witness_commitments.alu_p_sub_b_hi); - transcript->send_to_verifier(commitment_labels.alu_p_sub_b_lo, witness_commitments.alu_p_sub_b_lo); - transcript->send_to_verifier(commitment_labels.alu_partial_prod_hi, witness_commitments.alu_partial_prod_hi); - transcript->send_to_verifier(commitment_labels.alu_partial_prod_lo, witness_commitments.alu_partial_prod_lo); - transcript->send_to_verifier(commitment_labels.alu_quotient_hi, witness_commitments.alu_quotient_hi); - transcript->send_to_verifier(commitment_labels.alu_quotient_lo, witness_commitments.alu_quotient_lo); - transcript->send_to_verifier(commitment_labels.alu_remainder, witness_commitments.alu_remainder); - transcript->send_to_verifier(commitment_labels.alu_res_hi, witness_commitments.alu_res_hi); - transcript->send_to_verifier(commitment_labels.alu_res_lo, witness_commitments.alu_res_lo); - transcript->send_to_verifier(commitment_labels.alu_sel_alu, witness_commitments.alu_sel_alu); - transcript->send_to_verifier(commitment_labels.alu_sel_cmp, witness_commitments.alu_sel_cmp); - transcript->send_to_verifier(commitment_labels.alu_sel_div_rng_chk, witness_commitments.alu_sel_div_rng_chk); - transcript->send_to_verifier(commitment_labels.alu_sel_rng_chk, witness_commitments.alu_sel_rng_chk); - transcript->send_to_verifier(commitment_labels.alu_sel_rng_chk_lookup, witness_commitments.alu_sel_rng_chk_lookup); - transcript->send_to_verifier(commitment_labels.alu_sel_shift_which, witness_commitments.alu_sel_shift_which); - transcript->send_to_verifier(commitment_labels.alu_shift_lt_bit_len, witness_commitments.alu_shift_lt_bit_len); - transcript->send_to_verifier(commitment_labels.alu_t_sub_s_bits, witness_commitments.alu_t_sub_s_bits); - transcript->send_to_verifier(commitment_labels.alu_two_pow_s, witness_commitments.alu_two_pow_s); - transcript->send_to_verifier(commitment_labels.alu_two_pow_t_sub_s, witness_commitments.alu_two_pow_t_sub_s); - transcript->send_to_verifier(commitment_labels.alu_u128_tag, witness_commitments.alu_u128_tag); - transcript->send_to_verifier(commitment_labels.alu_u16_r0, witness_commitments.alu_u16_r0); - transcript->send_to_verifier(commitment_labels.alu_u16_r1, witness_commitments.alu_u16_r1); - transcript->send_to_verifier(commitment_labels.alu_u16_r10, witness_commitments.alu_u16_r10); - transcript->send_to_verifier(commitment_labels.alu_u16_r11, witness_commitments.alu_u16_r11); - transcript->send_to_verifier(commitment_labels.alu_u16_r12, witness_commitments.alu_u16_r12); - transcript->send_to_verifier(commitment_labels.alu_u16_r13, witness_commitments.alu_u16_r13); - transcript->send_to_verifier(commitment_labels.alu_u16_r14, witness_commitments.alu_u16_r14); - transcript->send_to_verifier(commitment_labels.alu_u16_r2, witness_commitments.alu_u16_r2); - transcript->send_to_verifier(commitment_labels.alu_u16_r3, witness_commitments.alu_u16_r3); - transcript->send_to_verifier(commitment_labels.alu_u16_r4, witness_commitments.alu_u16_r4); - transcript->send_to_verifier(commitment_labels.alu_u16_r5, witness_commitments.alu_u16_r5); - transcript->send_to_verifier(commitment_labels.alu_u16_r6, witness_commitments.alu_u16_r6); - transcript->send_to_verifier(commitment_labels.alu_u16_r7, witness_commitments.alu_u16_r7); - transcript->send_to_verifier(commitment_labels.alu_u16_r8, witness_commitments.alu_u16_r8); - transcript->send_to_verifier(commitment_labels.alu_u16_r9, witness_commitments.alu_u16_r9); - transcript->send_to_verifier(commitment_labels.alu_u16_tag, witness_commitments.alu_u16_tag); - transcript->send_to_verifier(commitment_labels.alu_u32_tag, witness_commitments.alu_u32_tag); - transcript->send_to_verifier(commitment_labels.alu_u64_tag, witness_commitments.alu_u64_tag); - transcript->send_to_verifier(commitment_labels.alu_u8_r0, witness_commitments.alu_u8_r0); - transcript->send_to_verifier(commitment_labels.alu_u8_r1, witness_commitments.alu_u8_r1); - transcript->send_to_verifier(commitment_labels.alu_u8_tag, witness_commitments.alu_u8_tag); - transcript->send_to_verifier(commitment_labels.binary_acc_ia, witness_commitments.binary_acc_ia); - transcript->send_to_verifier(commitment_labels.binary_acc_ib, witness_commitments.binary_acc_ib); - transcript->send_to_verifier(commitment_labels.binary_acc_ic, witness_commitments.binary_acc_ic); - transcript->send_to_verifier(commitment_labels.binary_clk, witness_commitments.binary_clk); - transcript->send_to_verifier(commitment_labels.binary_ia_bytes, witness_commitments.binary_ia_bytes); - transcript->send_to_verifier(commitment_labels.binary_ib_bytes, witness_commitments.binary_ib_bytes); - transcript->send_to_verifier(commitment_labels.binary_ic_bytes, witness_commitments.binary_ic_bytes); - transcript->send_to_verifier(commitment_labels.binary_in_tag, witness_commitments.binary_in_tag); - transcript->send_to_verifier(commitment_labels.binary_mem_tag_ctr, witness_commitments.binary_mem_tag_ctr); - transcript->send_to_verifier(commitment_labels.binary_mem_tag_ctr_inv, witness_commitments.binary_mem_tag_ctr_inv); - transcript->send_to_verifier(commitment_labels.binary_op_id, witness_commitments.binary_op_id); - transcript->send_to_verifier(commitment_labels.binary_sel_bin, witness_commitments.binary_sel_bin); - transcript->send_to_verifier(commitment_labels.binary_start, witness_commitments.binary_start); - transcript->send_to_verifier(commitment_labels.byte_lookup_sel_bin, witness_commitments.byte_lookup_sel_bin); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_byte_lengths, - witness_commitments.byte_lookup_table_byte_lengths); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_in_tags, - witness_commitments.byte_lookup_table_in_tags); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_input_a, - witness_commitments.byte_lookup_table_input_a); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_input_b, - witness_commitments.byte_lookup_table_input_b); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_op_id, - witness_commitments.byte_lookup_table_op_id); - transcript->send_to_verifier(commitment_labels.byte_lookup_table_output, - witness_commitments.byte_lookup_table_output); - transcript->send_to_verifier(commitment_labels.conversion_clk, witness_commitments.conversion_clk); - transcript->send_to_verifier(commitment_labels.conversion_input, witness_commitments.conversion_input); - transcript->send_to_verifier(commitment_labels.conversion_num_limbs, witness_commitments.conversion_num_limbs); - transcript->send_to_verifier(commitment_labels.conversion_radix, witness_commitments.conversion_radix); - transcript->send_to_verifier(commitment_labels.conversion_sel_to_radix_le, - witness_commitments.conversion_sel_to_radix_le); - transcript->send_to_verifier(commitment_labels.gas_da_gas_fixed_table, witness_commitments.gas_da_gas_fixed_table); - transcript->send_to_verifier(commitment_labels.gas_l2_gas_fixed_table, witness_commitments.gas_l2_gas_fixed_table); - transcript->send_to_verifier(commitment_labels.gas_sel_gas_cost, witness_commitments.gas_sel_gas_cost); - transcript->send_to_verifier(commitment_labels.keccakf1600_clk, witness_commitments.keccakf1600_clk); - transcript->send_to_verifier(commitment_labels.keccakf1600_input, witness_commitments.keccakf1600_input); - transcript->send_to_verifier(commitment_labels.keccakf1600_output, witness_commitments.keccakf1600_output); - transcript->send_to_verifier(commitment_labels.keccakf1600_sel_keccakf1600, - witness_commitments.keccakf1600_sel_keccakf1600); - transcript->send_to_verifier(commitment_labels.kernel_emit_l2_to_l1_msg_write_offset, - witness_commitments.kernel_emit_l2_to_l1_msg_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_emit_note_hash_write_offset, - witness_commitments.kernel_emit_note_hash_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_emit_nullifier_write_offset, - witness_commitments.kernel_emit_nullifier_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_emit_unencrypted_log_write_offset, - witness_commitments.kernel_emit_unencrypted_log_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_kernel_in_offset, - witness_commitments.kernel_kernel_in_offset); - transcript->send_to_verifier(commitment_labels.kernel_kernel_out_offset, - witness_commitments.kernel_kernel_out_offset); - transcript->send_to_verifier(commitment_labels.kernel_l1_to_l2_msg_exists_write_offset, - witness_commitments.kernel_l1_to_l2_msg_exists_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_note_hash_exist_write_offset, - witness_commitments.kernel_note_hash_exist_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_nullifier_exists_write_offset, - witness_commitments.kernel_nullifier_exists_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_nullifier_non_exists_write_offset, - witness_commitments.kernel_nullifier_non_exists_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_q_public_input_kernel_add_to_table, - witness_commitments.kernel_q_public_input_kernel_add_to_table); - transcript->send_to_verifier(commitment_labels.kernel_q_public_input_kernel_out_add_to_table, - witness_commitments.kernel_q_public_input_kernel_out_add_to_table); - transcript->send_to_verifier(commitment_labels.kernel_side_effect_counter, - witness_commitments.kernel_side_effect_counter); - transcript->send_to_verifier(commitment_labels.kernel_sload_write_offset, - witness_commitments.kernel_sload_write_offset); - transcript->send_to_verifier(commitment_labels.kernel_sstore_write_offset, - witness_commitments.kernel_sstore_write_offset); - transcript->send_to_verifier(commitment_labels.main_abs_da_rem_gas_hi, witness_commitments.main_abs_da_rem_gas_hi); - transcript->send_to_verifier(commitment_labels.main_abs_da_rem_gas_lo, witness_commitments.main_abs_da_rem_gas_lo); - transcript->send_to_verifier(commitment_labels.main_abs_l2_rem_gas_hi, witness_commitments.main_abs_l2_rem_gas_hi); - transcript->send_to_verifier(commitment_labels.main_abs_l2_rem_gas_lo, witness_commitments.main_abs_l2_rem_gas_lo); - transcript->send_to_verifier(commitment_labels.main_alu_in_tag, witness_commitments.main_alu_in_tag); - transcript->send_to_verifier(commitment_labels.main_bin_op_id, witness_commitments.main_bin_op_id); - transcript->send_to_verifier(commitment_labels.main_call_ptr, witness_commitments.main_call_ptr); - transcript->send_to_verifier(commitment_labels.main_da_gas_op_cost, witness_commitments.main_da_gas_op_cost); - transcript->send_to_verifier(commitment_labels.main_da_gas_remaining, witness_commitments.main_da_gas_remaining); - transcript->send_to_verifier(commitment_labels.main_da_out_of_gas, witness_commitments.main_da_out_of_gas); - transcript->send_to_verifier(commitment_labels.main_ia, witness_commitments.main_ia); - transcript->send_to_verifier(commitment_labels.main_ib, witness_commitments.main_ib); - transcript->send_to_verifier(commitment_labels.main_ic, witness_commitments.main_ic); - transcript->send_to_verifier(commitment_labels.main_id, witness_commitments.main_id); - transcript->send_to_verifier(commitment_labels.main_id_zero, witness_commitments.main_id_zero); - transcript->send_to_verifier(commitment_labels.main_ind_addr_a, witness_commitments.main_ind_addr_a); - transcript->send_to_verifier(commitment_labels.main_ind_addr_b, witness_commitments.main_ind_addr_b); - transcript->send_to_verifier(commitment_labels.main_ind_addr_c, witness_commitments.main_ind_addr_c); - transcript->send_to_verifier(commitment_labels.main_ind_addr_d, witness_commitments.main_ind_addr_d); - transcript->send_to_verifier(commitment_labels.main_internal_return_ptr, - witness_commitments.main_internal_return_ptr); - transcript->send_to_verifier(commitment_labels.main_inv, witness_commitments.main_inv); - transcript->send_to_verifier(commitment_labels.main_l2_gas_op_cost, witness_commitments.main_l2_gas_op_cost); - transcript->send_to_verifier(commitment_labels.main_l2_gas_remaining, witness_commitments.main_l2_gas_remaining); - transcript->send_to_verifier(commitment_labels.main_l2_out_of_gas, witness_commitments.main_l2_out_of_gas); - transcript->send_to_verifier(commitment_labels.main_mem_addr_a, witness_commitments.main_mem_addr_a); - transcript->send_to_verifier(commitment_labels.main_mem_addr_b, witness_commitments.main_mem_addr_b); - transcript->send_to_verifier(commitment_labels.main_mem_addr_c, witness_commitments.main_mem_addr_c); - transcript->send_to_verifier(commitment_labels.main_mem_addr_d, witness_commitments.main_mem_addr_d); - transcript->send_to_verifier(commitment_labels.main_op_err, witness_commitments.main_op_err); - transcript->send_to_verifier(commitment_labels.main_opcode_val, witness_commitments.main_opcode_val); - transcript->send_to_verifier(commitment_labels.main_pc, witness_commitments.main_pc); - transcript->send_to_verifier(commitment_labels.main_r_in_tag, witness_commitments.main_r_in_tag); - transcript->send_to_verifier(commitment_labels.main_rwa, witness_commitments.main_rwa); - transcript->send_to_verifier(commitment_labels.main_rwb, witness_commitments.main_rwb); - transcript->send_to_verifier(commitment_labels.main_rwc, witness_commitments.main_rwc); - transcript->send_to_verifier(commitment_labels.main_rwd, witness_commitments.main_rwd); - transcript->send_to_verifier(commitment_labels.main_sel_alu, witness_commitments.main_sel_alu); - transcript->send_to_verifier(commitment_labels.main_sel_bin, witness_commitments.main_sel_bin); - transcript->send_to_verifier(commitment_labels.main_sel_gas_accounting_active, - witness_commitments.main_sel_gas_accounting_active); - transcript->send_to_verifier(commitment_labels.main_sel_last, witness_commitments.main_sel_last); - transcript->send_to_verifier(commitment_labels.main_sel_mem_op_a, witness_commitments.main_sel_mem_op_a); - transcript->send_to_verifier(commitment_labels.main_sel_mem_op_activate_gas, - witness_commitments.main_sel_mem_op_activate_gas); - transcript->send_to_verifier(commitment_labels.main_sel_mem_op_b, witness_commitments.main_sel_mem_op_b); - transcript->send_to_verifier(commitment_labels.main_sel_mem_op_c, witness_commitments.main_sel_mem_op_c); - transcript->send_to_verifier(commitment_labels.main_sel_mem_op_d, witness_commitments.main_sel_mem_op_d); - transcript->send_to_verifier(commitment_labels.main_sel_mov_ia_to_ic, witness_commitments.main_sel_mov_ia_to_ic); - transcript->send_to_verifier(commitment_labels.main_sel_mov_ib_to_ic, witness_commitments.main_sel_mov_ib_to_ic); - transcript->send_to_verifier(commitment_labels.main_sel_op_add, witness_commitments.main_sel_op_add); - transcript->send_to_verifier(commitment_labels.main_sel_op_address, witness_commitments.main_sel_op_address); - transcript->send_to_verifier(commitment_labels.main_sel_op_and, witness_commitments.main_sel_op_and); - transcript->send_to_verifier(commitment_labels.main_sel_op_block_number, - witness_commitments.main_sel_op_block_number); - transcript->send_to_verifier(commitment_labels.main_sel_op_cast, witness_commitments.main_sel_op_cast); - transcript->send_to_verifier(commitment_labels.main_sel_op_chain_id, witness_commitments.main_sel_op_chain_id); - transcript->send_to_verifier(commitment_labels.main_sel_op_cmov, witness_commitments.main_sel_op_cmov); - transcript->send_to_verifier(commitment_labels.main_sel_op_coinbase, witness_commitments.main_sel_op_coinbase); - transcript->send_to_verifier(commitment_labels.main_sel_op_dagasleft, witness_commitments.main_sel_op_dagasleft); - transcript->send_to_verifier(commitment_labels.main_sel_op_div, witness_commitments.main_sel_op_div); - transcript->send_to_verifier(commitment_labels.main_sel_op_emit_l2_to_l1_msg, - witness_commitments.main_sel_op_emit_l2_to_l1_msg); - transcript->send_to_verifier(commitment_labels.main_sel_op_emit_note_hash, - witness_commitments.main_sel_op_emit_note_hash); - transcript->send_to_verifier(commitment_labels.main_sel_op_emit_nullifier, - witness_commitments.main_sel_op_emit_nullifier); - transcript->send_to_verifier(commitment_labels.main_sel_op_emit_unencrypted_log, - witness_commitments.main_sel_op_emit_unencrypted_log); - transcript->send_to_verifier(commitment_labels.main_sel_op_eq, witness_commitments.main_sel_op_eq); - transcript->send_to_verifier(commitment_labels.main_sel_op_external_call, - witness_commitments.main_sel_op_external_call); - transcript->send_to_verifier(commitment_labels.main_sel_op_fdiv, witness_commitments.main_sel_op_fdiv); - transcript->send_to_verifier(commitment_labels.main_sel_op_fee_per_da_gas, - witness_commitments.main_sel_op_fee_per_da_gas); - transcript->send_to_verifier(commitment_labels.main_sel_op_fee_per_l2_gas, - witness_commitments.main_sel_op_fee_per_l2_gas); - transcript->send_to_verifier(commitment_labels.main_sel_op_function_selector, - witness_commitments.main_sel_op_function_selector); - transcript->send_to_verifier(commitment_labels.main_sel_op_get_contract_instance, - witness_commitments.main_sel_op_get_contract_instance); - transcript->send_to_verifier(commitment_labels.main_sel_op_halt, witness_commitments.main_sel_op_halt); - transcript->send_to_verifier(commitment_labels.main_sel_op_internal_call, - witness_commitments.main_sel_op_internal_call); - transcript->send_to_verifier(commitment_labels.main_sel_op_internal_return, - witness_commitments.main_sel_op_internal_return); - transcript->send_to_verifier(commitment_labels.main_sel_op_jump, witness_commitments.main_sel_op_jump); - transcript->send_to_verifier(commitment_labels.main_sel_op_jumpi, witness_commitments.main_sel_op_jumpi); - transcript->send_to_verifier(commitment_labels.main_sel_op_keccak, witness_commitments.main_sel_op_keccak); - transcript->send_to_verifier(commitment_labels.main_sel_op_l1_to_l2_msg_exists, - witness_commitments.main_sel_op_l1_to_l2_msg_exists); - transcript->send_to_verifier(commitment_labels.main_sel_op_l2gasleft, witness_commitments.main_sel_op_l2gasleft); - transcript->send_to_verifier(commitment_labels.main_sel_op_lt, witness_commitments.main_sel_op_lt); - transcript->send_to_verifier(commitment_labels.main_sel_op_lte, witness_commitments.main_sel_op_lte); - transcript->send_to_verifier(commitment_labels.main_sel_op_mov, witness_commitments.main_sel_op_mov); - transcript->send_to_verifier(commitment_labels.main_sel_op_mul, witness_commitments.main_sel_op_mul); - transcript->send_to_verifier(commitment_labels.main_sel_op_not, witness_commitments.main_sel_op_not); - transcript->send_to_verifier(commitment_labels.main_sel_op_note_hash_exists, - witness_commitments.main_sel_op_note_hash_exists); - transcript->send_to_verifier(commitment_labels.main_sel_op_nullifier_exists, - witness_commitments.main_sel_op_nullifier_exists); - transcript->send_to_verifier(commitment_labels.main_sel_op_or, witness_commitments.main_sel_op_or); - transcript->send_to_verifier(commitment_labels.main_sel_op_pedersen, witness_commitments.main_sel_op_pedersen); - transcript->send_to_verifier(commitment_labels.main_sel_op_poseidon2, witness_commitments.main_sel_op_poseidon2); - transcript->send_to_verifier(commitment_labels.main_sel_op_radix_le, witness_commitments.main_sel_op_radix_le); - transcript->send_to_verifier(commitment_labels.main_sel_op_sender, witness_commitments.main_sel_op_sender); - transcript->send_to_verifier(commitment_labels.main_sel_op_sha256, witness_commitments.main_sel_op_sha256); - transcript->send_to_verifier(commitment_labels.main_sel_op_shl, witness_commitments.main_sel_op_shl); - transcript->send_to_verifier(commitment_labels.main_sel_op_shr, witness_commitments.main_sel_op_shr); - transcript->send_to_verifier(commitment_labels.main_sel_op_sload, witness_commitments.main_sel_op_sload); - transcript->send_to_verifier(commitment_labels.main_sel_op_sstore, witness_commitments.main_sel_op_sstore); - transcript->send_to_verifier(commitment_labels.main_sel_op_storage_address, - witness_commitments.main_sel_op_storage_address); - transcript->send_to_verifier(commitment_labels.main_sel_op_sub, witness_commitments.main_sel_op_sub); - transcript->send_to_verifier(commitment_labels.main_sel_op_timestamp, witness_commitments.main_sel_op_timestamp); - transcript->send_to_verifier(commitment_labels.main_sel_op_transaction_fee, - witness_commitments.main_sel_op_transaction_fee); - transcript->send_to_verifier(commitment_labels.main_sel_op_version, witness_commitments.main_sel_op_version); - transcript->send_to_verifier(commitment_labels.main_sel_op_xor, witness_commitments.main_sel_op_xor); - transcript->send_to_verifier(commitment_labels.main_sel_q_kernel_lookup, - witness_commitments.main_sel_q_kernel_lookup); - transcript->send_to_verifier(commitment_labels.main_sel_q_kernel_output_lookup, - witness_commitments.main_sel_q_kernel_output_lookup); - transcript->send_to_verifier(commitment_labels.main_sel_resolve_ind_addr_a, - witness_commitments.main_sel_resolve_ind_addr_a); - transcript->send_to_verifier(commitment_labels.main_sel_resolve_ind_addr_b, - witness_commitments.main_sel_resolve_ind_addr_b); - transcript->send_to_verifier(commitment_labels.main_sel_resolve_ind_addr_c, - witness_commitments.main_sel_resolve_ind_addr_c); - transcript->send_to_verifier(commitment_labels.main_sel_resolve_ind_addr_d, - witness_commitments.main_sel_resolve_ind_addr_d); - transcript->send_to_verifier(commitment_labels.main_sel_rng_16, witness_commitments.main_sel_rng_16); - transcript->send_to_verifier(commitment_labels.main_sel_rng_8, witness_commitments.main_sel_rng_8); - transcript->send_to_verifier(commitment_labels.main_space_id, witness_commitments.main_space_id); - transcript->send_to_verifier(commitment_labels.main_tag_err, witness_commitments.main_tag_err); - transcript->send_to_verifier(commitment_labels.main_w_in_tag, witness_commitments.main_w_in_tag); - transcript->send_to_verifier(commitment_labels.mem_addr, witness_commitments.mem_addr); - transcript->send_to_verifier(commitment_labels.mem_clk, witness_commitments.mem_clk); - transcript->send_to_verifier(commitment_labels.mem_diff_hi, witness_commitments.mem_diff_hi); - transcript->send_to_verifier(commitment_labels.mem_diff_lo, witness_commitments.mem_diff_lo); - transcript->send_to_verifier(commitment_labels.mem_diff_mid, witness_commitments.mem_diff_mid); - transcript->send_to_verifier(commitment_labels.mem_glob_addr, witness_commitments.mem_glob_addr); - transcript->send_to_verifier(commitment_labels.mem_last, witness_commitments.mem_last); - transcript->send_to_verifier(commitment_labels.mem_lastAccess, witness_commitments.mem_lastAccess); - transcript->send_to_verifier(commitment_labels.mem_one_min_inv, witness_commitments.mem_one_min_inv); - transcript->send_to_verifier(commitment_labels.mem_r_in_tag, witness_commitments.mem_r_in_tag); - transcript->send_to_verifier(commitment_labels.mem_rw, witness_commitments.mem_rw); - transcript->send_to_verifier(commitment_labels.mem_sel_mem, witness_commitments.mem_sel_mem); - transcript->send_to_verifier(commitment_labels.mem_sel_mov_ia_to_ic, witness_commitments.mem_sel_mov_ia_to_ic); - transcript->send_to_verifier(commitment_labels.mem_sel_mov_ib_to_ic, witness_commitments.mem_sel_mov_ib_to_ic); - transcript->send_to_verifier(commitment_labels.mem_sel_op_a, witness_commitments.mem_sel_op_a); - transcript->send_to_verifier(commitment_labels.mem_sel_op_b, witness_commitments.mem_sel_op_b); - transcript->send_to_verifier(commitment_labels.mem_sel_op_c, witness_commitments.mem_sel_op_c); - transcript->send_to_verifier(commitment_labels.mem_sel_op_cmov, witness_commitments.mem_sel_op_cmov); - transcript->send_to_verifier(commitment_labels.mem_sel_op_d, witness_commitments.mem_sel_op_d); - transcript->send_to_verifier(commitment_labels.mem_sel_resolve_ind_addr_a, - witness_commitments.mem_sel_resolve_ind_addr_a); - transcript->send_to_verifier(commitment_labels.mem_sel_resolve_ind_addr_b, - witness_commitments.mem_sel_resolve_ind_addr_b); - transcript->send_to_verifier(commitment_labels.mem_sel_resolve_ind_addr_c, - witness_commitments.mem_sel_resolve_ind_addr_c); - transcript->send_to_verifier(commitment_labels.mem_sel_resolve_ind_addr_d, - witness_commitments.mem_sel_resolve_ind_addr_d); - transcript->send_to_verifier(commitment_labels.mem_sel_rng_chk, witness_commitments.mem_sel_rng_chk); - transcript->send_to_verifier(commitment_labels.mem_skip_check_tag, witness_commitments.mem_skip_check_tag); - transcript->send_to_verifier(commitment_labels.mem_space_id, witness_commitments.mem_space_id); - transcript->send_to_verifier(commitment_labels.mem_tag, witness_commitments.mem_tag); - transcript->send_to_verifier(commitment_labels.mem_tag_err, witness_commitments.mem_tag_err); - transcript->send_to_verifier(commitment_labels.mem_tsp, witness_commitments.mem_tsp); - transcript->send_to_verifier(commitment_labels.mem_val, witness_commitments.mem_val); - transcript->send_to_verifier(commitment_labels.mem_w_in_tag, witness_commitments.mem_w_in_tag); - transcript->send_to_verifier(commitment_labels.pedersen_clk, witness_commitments.pedersen_clk); - transcript->send_to_verifier(commitment_labels.pedersen_input, witness_commitments.pedersen_input); - transcript->send_to_verifier(commitment_labels.pedersen_output, witness_commitments.pedersen_output); - transcript->send_to_verifier(commitment_labels.pedersen_sel_pedersen, witness_commitments.pedersen_sel_pedersen); - transcript->send_to_verifier(commitment_labels.poseidon2_clk, witness_commitments.poseidon2_clk); - transcript->send_to_verifier(commitment_labels.poseidon2_input, witness_commitments.poseidon2_input); - transcript->send_to_verifier(commitment_labels.poseidon2_output, witness_commitments.poseidon2_output); - transcript->send_to_verifier(commitment_labels.poseidon2_sel_poseidon_perm, - witness_commitments.poseidon2_sel_poseidon_perm); - transcript->send_to_verifier(commitment_labels.powers_power_of_2, witness_commitments.powers_power_of_2); - transcript->send_to_verifier(commitment_labels.sha256_clk, witness_commitments.sha256_clk); - transcript->send_to_verifier(commitment_labels.sha256_input, witness_commitments.sha256_input); - transcript->send_to_verifier(commitment_labels.sha256_output, witness_commitments.sha256_output); - transcript->send_to_verifier(commitment_labels.sha256_sel_sha256_compression, - witness_commitments.sha256_sel_sha256_compression); - transcript->send_to_verifier(commitment_labels.sha256_state, witness_commitments.sha256_state); - transcript->send_to_verifier(commitment_labels.lookup_byte_lengths_counts, - witness_commitments.lookup_byte_lengths_counts); - transcript->send_to_verifier(commitment_labels.lookup_byte_operations_counts, - witness_commitments.lookup_byte_operations_counts); - transcript->send_to_verifier(commitment_labels.lookup_opcode_gas_counts, - witness_commitments.lookup_opcode_gas_counts); - transcript->send_to_verifier(commitment_labels.range_check_l2_gas_hi_counts, - witness_commitments.range_check_l2_gas_hi_counts); - transcript->send_to_verifier(commitment_labels.range_check_l2_gas_lo_counts, - witness_commitments.range_check_l2_gas_lo_counts); - transcript->send_to_verifier(commitment_labels.range_check_da_gas_hi_counts, - witness_commitments.range_check_da_gas_hi_counts); - transcript->send_to_verifier(commitment_labels.range_check_da_gas_lo_counts, - witness_commitments.range_check_da_gas_lo_counts); - transcript->send_to_verifier(commitment_labels.kernel_output_lookup_counts, - witness_commitments.kernel_output_lookup_counts); - transcript->send_to_verifier(commitment_labels.lookup_into_kernel_counts, - witness_commitments.lookup_into_kernel_counts); - transcript->send_to_verifier(commitment_labels.incl_main_tag_err_counts, - witness_commitments.incl_main_tag_err_counts); - transcript->send_to_verifier(commitment_labels.incl_mem_tag_err_counts, - witness_commitments.incl_mem_tag_err_counts); - transcript->send_to_verifier(commitment_labels.lookup_mem_rng_chk_lo_counts, - witness_commitments.lookup_mem_rng_chk_lo_counts); - transcript->send_to_verifier(commitment_labels.lookup_mem_rng_chk_mid_counts, - witness_commitments.lookup_mem_rng_chk_mid_counts); - transcript->send_to_verifier(commitment_labels.lookup_mem_rng_chk_hi_counts, - witness_commitments.lookup_mem_rng_chk_hi_counts); - transcript->send_to_verifier(commitment_labels.lookup_pow_2_0_counts, witness_commitments.lookup_pow_2_0_counts); - transcript->send_to_verifier(commitment_labels.lookup_pow_2_1_counts, witness_commitments.lookup_pow_2_1_counts); - transcript->send_to_verifier(commitment_labels.lookup_u8_0_counts, witness_commitments.lookup_u8_0_counts); - transcript->send_to_verifier(commitment_labels.lookup_u8_1_counts, witness_commitments.lookup_u8_1_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_0_counts, witness_commitments.lookup_u16_0_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_1_counts, witness_commitments.lookup_u16_1_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_2_counts, witness_commitments.lookup_u16_2_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_3_counts, witness_commitments.lookup_u16_3_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_4_counts, witness_commitments.lookup_u16_4_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_5_counts, witness_commitments.lookup_u16_5_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_6_counts, witness_commitments.lookup_u16_6_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_7_counts, witness_commitments.lookup_u16_7_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_8_counts, witness_commitments.lookup_u16_8_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_9_counts, witness_commitments.lookup_u16_9_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_10_counts, witness_commitments.lookup_u16_10_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_11_counts, witness_commitments.lookup_u16_11_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_12_counts, witness_commitments.lookup_u16_12_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_13_counts, witness_commitments.lookup_u16_13_counts); - transcript->send_to_verifier(commitment_labels.lookup_u16_14_counts, witness_commitments.lookup_u16_14_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_0_counts, - witness_commitments.lookup_div_u16_0_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_1_counts, - witness_commitments.lookup_div_u16_1_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_2_counts, - witness_commitments.lookup_div_u16_2_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_3_counts, - witness_commitments.lookup_div_u16_3_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_4_counts, - witness_commitments.lookup_div_u16_4_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_5_counts, - witness_commitments.lookup_div_u16_5_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_6_counts, - witness_commitments.lookup_div_u16_6_counts); - transcript->send_to_verifier(commitment_labels.lookup_div_u16_7_counts, - witness_commitments.lookup_div_u16_7_counts); + auto wire_polys = prover_polynomials.get_wires(); + auto labels = commitment_labels.get_wires(); + for (size_t idx = 0; idx < wire_polys.size(); ++idx) { + transcript->send_to_verifier(labels[idx], commitment_key->commit(wire_polys[idx])); + } } void AvmProver::execute_log_derivative_inverse_round() diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp index d15ad4f2fcaf..71f078ae5605 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_verifier.cpp @@ -71,537 +71,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate receive_from_prover(commitment_labels.kernel_kernel_inputs); - commitments.kernel_kernel_value_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_value_out); - commitments.kernel_kernel_side_effect_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_side_effect_out); - commitments.kernel_kernel_metadata_out = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_metadata_out); - commitments.main_calldata = transcript->template receive_from_prover(commitment_labels.main_calldata); - commitments.alu_a_hi = transcript->template receive_from_prover(commitment_labels.alu_a_hi); - commitments.alu_a_lo = transcript->template receive_from_prover(commitment_labels.alu_a_lo); - commitments.alu_b_hi = transcript->template receive_from_prover(commitment_labels.alu_b_hi); - commitments.alu_b_lo = transcript->template receive_from_prover(commitment_labels.alu_b_lo); - commitments.alu_borrow = transcript->template receive_from_prover(commitment_labels.alu_borrow); - commitments.alu_cf = transcript->template receive_from_prover(commitment_labels.alu_cf); - commitments.alu_clk = transcript->template receive_from_prover(commitment_labels.alu_clk); - commitments.alu_cmp_rng_ctr = - transcript->template receive_from_prover(commitment_labels.alu_cmp_rng_ctr); - commitments.alu_div_u16_r0 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r0); - commitments.alu_div_u16_r1 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r1); - commitments.alu_div_u16_r2 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r2); - commitments.alu_div_u16_r3 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r3); - commitments.alu_div_u16_r4 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r4); - commitments.alu_div_u16_r5 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r5); - commitments.alu_div_u16_r6 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r6); - commitments.alu_div_u16_r7 = transcript->template receive_from_prover(commitment_labels.alu_div_u16_r7); - commitments.alu_divisor_hi = transcript->template receive_from_prover(commitment_labels.alu_divisor_hi); - commitments.alu_divisor_lo = transcript->template receive_from_prover(commitment_labels.alu_divisor_lo); - commitments.alu_ff_tag = transcript->template receive_from_prover(commitment_labels.alu_ff_tag); - commitments.alu_ia = transcript->template receive_from_prover(commitment_labels.alu_ia); - commitments.alu_ib = transcript->template receive_from_prover(commitment_labels.alu_ib); - commitments.alu_ic = transcript->template receive_from_prover(commitment_labels.alu_ic); - commitments.alu_in_tag = transcript->template receive_from_prover(commitment_labels.alu_in_tag); - commitments.alu_op_add = transcript->template receive_from_prover(commitment_labels.alu_op_add); - commitments.alu_op_cast = transcript->template receive_from_prover(commitment_labels.alu_op_cast); - commitments.alu_op_cast_prev = - transcript->template receive_from_prover(commitment_labels.alu_op_cast_prev); - commitments.alu_op_div = transcript->template receive_from_prover(commitment_labels.alu_op_div); - commitments.alu_op_div_a_lt_b = - transcript->template receive_from_prover(commitment_labels.alu_op_div_a_lt_b); - commitments.alu_op_div_std = transcript->template receive_from_prover(commitment_labels.alu_op_div_std); - commitments.alu_op_eq = transcript->template receive_from_prover(commitment_labels.alu_op_eq); - commitments.alu_op_eq_diff_inv = - transcript->template receive_from_prover(commitment_labels.alu_op_eq_diff_inv); - commitments.alu_op_lt = transcript->template receive_from_prover(commitment_labels.alu_op_lt); - commitments.alu_op_lte = transcript->template receive_from_prover(commitment_labels.alu_op_lte); - commitments.alu_op_mul = transcript->template receive_from_prover(commitment_labels.alu_op_mul); - commitments.alu_op_not = transcript->template receive_from_prover(commitment_labels.alu_op_not); - commitments.alu_op_shl = transcript->template receive_from_prover(commitment_labels.alu_op_shl); - commitments.alu_op_shr = transcript->template receive_from_prover(commitment_labels.alu_op_shr); - commitments.alu_op_sub = transcript->template receive_from_prover(commitment_labels.alu_op_sub); - commitments.alu_p_a_borrow = transcript->template receive_from_prover(commitment_labels.alu_p_a_borrow); - commitments.alu_p_b_borrow = transcript->template receive_from_prover(commitment_labels.alu_p_b_borrow); - commitments.alu_p_sub_a_hi = transcript->template receive_from_prover(commitment_labels.alu_p_sub_a_hi); - commitments.alu_p_sub_a_lo = transcript->template receive_from_prover(commitment_labels.alu_p_sub_a_lo); - commitments.alu_p_sub_b_hi = transcript->template receive_from_prover(commitment_labels.alu_p_sub_b_hi); - commitments.alu_p_sub_b_lo = transcript->template receive_from_prover(commitment_labels.alu_p_sub_b_lo); - commitments.alu_partial_prod_hi = - transcript->template receive_from_prover(commitment_labels.alu_partial_prod_hi); - commitments.alu_partial_prod_lo = - transcript->template receive_from_prover(commitment_labels.alu_partial_prod_lo); - commitments.alu_quotient_hi = - transcript->template receive_from_prover(commitment_labels.alu_quotient_hi); - commitments.alu_quotient_lo = - transcript->template receive_from_prover(commitment_labels.alu_quotient_lo); - commitments.alu_remainder = transcript->template receive_from_prover(commitment_labels.alu_remainder); - commitments.alu_res_hi = transcript->template receive_from_prover(commitment_labels.alu_res_hi); - commitments.alu_res_lo = transcript->template receive_from_prover(commitment_labels.alu_res_lo); - commitments.alu_sel_alu = transcript->template receive_from_prover(commitment_labels.alu_sel_alu); - commitments.alu_sel_cmp = transcript->template receive_from_prover(commitment_labels.alu_sel_cmp); - commitments.alu_sel_div_rng_chk = - transcript->template receive_from_prover(commitment_labels.alu_sel_div_rng_chk); - commitments.alu_sel_rng_chk = - transcript->template receive_from_prover(commitment_labels.alu_sel_rng_chk); - commitments.alu_sel_rng_chk_lookup = - transcript->template receive_from_prover(commitment_labels.alu_sel_rng_chk_lookup); - commitments.alu_sel_shift_which = - transcript->template receive_from_prover(commitment_labels.alu_sel_shift_which); - commitments.alu_shift_lt_bit_len = - transcript->template receive_from_prover(commitment_labels.alu_shift_lt_bit_len); - commitments.alu_t_sub_s_bits = - transcript->template receive_from_prover(commitment_labels.alu_t_sub_s_bits); - commitments.alu_two_pow_s = transcript->template receive_from_prover(commitment_labels.alu_two_pow_s); - commitments.alu_two_pow_t_sub_s = - transcript->template receive_from_prover(commitment_labels.alu_two_pow_t_sub_s); - commitments.alu_u128_tag = transcript->template receive_from_prover(commitment_labels.alu_u128_tag); - commitments.alu_u16_r0 = transcript->template receive_from_prover(commitment_labels.alu_u16_r0); - commitments.alu_u16_r1 = transcript->template receive_from_prover(commitment_labels.alu_u16_r1); - commitments.alu_u16_r10 = transcript->template receive_from_prover(commitment_labels.alu_u16_r10); - commitments.alu_u16_r11 = transcript->template receive_from_prover(commitment_labels.alu_u16_r11); - commitments.alu_u16_r12 = transcript->template receive_from_prover(commitment_labels.alu_u16_r12); - commitments.alu_u16_r13 = transcript->template receive_from_prover(commitment_labels.alu_u16_r13); - commitments.alu_u16_r14 = transcript->template receive_from_prover(commitment_labels.alu_u16_r14); - commitments.alu_u16_r2 = transcript->template receive_from_prover(commitment_labels.alu_u16_r2); - commitments.alu_u16_r3 = transcript->template receive_from_prover(commitment_labels.alu_u16_r3); - commitments.alu_u16_r4 = transcript->template receive_from_prover(commitment_labels.alu_u16_r4); - commitments.alu_u16_r5 = transcript->template receive_from_prover(commitment_labels.alu_u16_r5); - commitments.alu_u16_r6 = transcript->template receive_from_prover(commitment_labels.alu_u16_r6); - commitments.alu_u16_r7 = transcript->template receive_from_prover(commitment_labels.alu_u16_r7); - commitments.alu_u16_r8 = transcript->template receive_from_prover(commitment_labels.alu_u16_r8); - commitments.alu_u16_r9 = transcript->template receive_from_prover(commitment_labels.alu_u16_r9); - commitments.alu_u16_tag = transcript->template receive_from_prover(commitment_labels.alu_u16_tag); - commitments.alu_u32_tag = transcript->template receive_from_prover(commitment_labels.alu_u32_tag); - commitments.alu_u64_tag = transcript->template receive_from_prover(commitment_labels.alu_u64_tag); - commitments.alu_u8_r0 = transcript->template receive_from_prover(commitment_labels.alu_u8_r0); - commitments.alu_u8_r1 = transcript->template receive_from_prover(commitment_labels.alu_u8_r1); - commitments.alu_u8_tag = transcript->template receive_from_prover(commitment_labels.alu_u8_tag); - commitments.binary_acc_ia = transcript->template receive_from_prover(commitment_labels.binary_acc_ia); - commitments.binary_acc_ib = transcript->template receive_from_prover(commitment_labels.binary_acc_ib); - commitments.binary_acc_ic = transcript->template receive_from_prover(commitment_labels.binary_acc_ic); - commitments.binary_clk = transcript->template receive_from_prover(commitment_labels.binary_clk); - commitments.binary_ia_bytes = - transcript->template receive_from_prover(commitment_labels.binary_ia_bytes); - commitments.binary_ib_bytes = - transcript->template receive_from_prover(commitment_labels.binary_ib_bytes); - commitments.binary_ic_bytes = - transcript->template receive_from_prover(commitment_labels.binary_ic_bytes); - commitments.binary_in_tag = transcript->template receive_from_prover(commitment_labels.binary_in_tag); - commitments.binary_mem_tag_ctr = - transcript->template receive_from_prover(commitment_labels.binary_mem_tag_ctr); - commitments.binary_mem_tag_ctr_inv = - transcript->template receive_from_prover(commitment_labels.binary_mem_tag_ctr_inv); - commitments.binary_op_id = transcript->template receive_from_prover(commitment_labels.binary_op_id); - commitments.binary_sel_bin = transcript->template receive_from_prover(commitment_labels.binary_sel_bin); - commitments.binary_start = transcript->template receive_from_prover(commitment_labels.binary_start); - commitments.byte_lookup_sel_bin = - transcript->template receive_from_prover(commitment_labels.byte_lookup_sel_bin); - commitments.byte_lookup_table_byte_lengths = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_byte_lengths); - commitments.byte_lookup_table_in_tags = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_in_tags); - commitments.byte_lookup_table_input_a = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_input_a); - commitments.byte_lookup_table_input_b = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_input_b); - commitments.byte_lookup_table_op_id = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_op_id); - commitments.byte_lookup_table_output = - transcript->template receive_from_prover(commitment_labels.byte_lookup_table_output); - commitments.conversion_clk = transcript->template receive_from_prover(commitment_labels.conversion_clk); - commitments.conversion_input = - transcript->template receive_from_prover(commitment_labels.conversion_input); - commitments.conversion_num_limbs = - transcript->template receive_from_prover(commitment_labels.conversion_num_limbs); - commitments.conversion_radix = - transcript->template receive_from_prover(commitment_labels.conversion_radix); - commitments.conversion_sel_to_radix_le = - transcript->template receive_from_prover(commitment_labels.conversion_sel_to_radix_le); - commitments.gas_da_gas_fixed_table = - transcript->template receive_from_prover(commitment_labels.gas_da_gas_fixed_table); - commitments.gas_l2_gas_fixed_table = - transcript->template receive_from_prover(commitment_labels.gas_l2_gas_fixed_table); - commitments.gas_sel_gas_cost = - transcript->template receive_from_prover(commitment_labels.gas_sel_gas_cost); - commitments.keccakf1600_clk = - transcript->template receive_from_prover(commitment_labels.keccakf1600_clk); - commitments.keccakf1600_input = - transcript->template receive_from_prover(commitment_labels.keccakf1600_input); - commitments.keccakf1600_output = - transcript->template receive_from_prover(commitment_labels.keccakf1600_output); - commitments.keccakf1600_sel_keccakf1600 = - transcript->template receive_from_prover(commitment_labels.keccakf1600_sel_keccakf1600); - commitments.kernel_emit_l2_to_l1_msg_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_emit_l2_to_l1_msg_write_offset); - commitments.kernel_emit_note_hash_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_emit_note_hash_write_offset); - commitments.kernel_emit_nullifier_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_emit_nullifier_write_offset); - commitments.kernel_emit_unencrypted_log_write_offset = transcript->template receive_from_prover( - commitment_labels.kernel_emit_unencrypted_log_write_offset); - commitments.kernel_kernel_in_offset = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_in_offset); - commitments.kernel_kernel_out_offset = - transcript->template receive_from_prover(commitment_labels.kernel_kernel_out_offset); - commitments.kernel_l1_to_l2_msg_exists_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_l1_to_l2_msg_exists_write_offset); - commitments.kernel_note_hash_exist_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_note_hash_exist_write_offset); - commitments.kernel_nullifier_exists_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_nullifier_exists_write_offset); - commitments.kernel_nullifier_non_exists_write_offset = transcript->template receive_from_prover( - commitment_labels.kernel_nullifier_non_exists_write_offset); - commitments.kernel_q_public_input_kernel_add_to_table = transcript->template receive_from_prover( - commitment_labels.kernel_q_public_input_kernel_add_to_table); - commitments.kernel_q_public_input_kernel_out_add_to_table = transcript->template receive_from_prover( - commitment_labels.kernel_q_public_input_kernel_out_add_to_table); - commitments.kernel_side_effect_counter = - transcript->template receive_from_prover(commitment_labels.kernel_side_effect_counter); - commitments.kernel_sload_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_sload_write_offset); - commitments.kernel_sstore_write_offset = - transcript->template receive_from_prover(commitment_labels.kernel_sstore_write_offset); - commitments.main_abs_da_rem_gas_hi = - transcript->template receive_from_prover(commitment_labels.main_abs_da_rem_gas_hi); - commitments.main_abs_da_rem_gas_lo = - transcript->template receive_from_prover(commitment_labels.main_abs_da_rem_gas_lo); - commitments.main_abs_l2_rem_gas_hi = - transcript->template receive_from_prover(commitment_labels.main_abs_l2_rem_gas_hi); - commitments.main_abs_l2_rem_gas_lo = - transcript->template receive_from_prover(commitment_labels.main_abs_l2_rem_gas_lo); - commitments.main_alu_in_tag = - transcript->template receive_from_prover(commitment_labels.main_alu_in_tag); - commitments.main_bin_op_id = transcript->template receive_from_prover(commitment_labels.main_bin_op_id); - commitments.main_call_ptr = transcript->template receive_from_prover(commitment_labels.main_call_ptr); - commitments.main_da_gas_op_cost = - transcript->template receive_from_prover(commitment_labels.main_da_gas_op_cost); - commitments.main_da_gas_remaining = - transcript->template receive_from_prover(commitment_labels.main_da_gas_remaining); - commitments.main_da_out_of_gas = - transcript->template receive_from_prover(commitment_labels.main_da_out_of_gas); - commitments.main_ia = transcript->template receive_from_prover(commitment_labels.main_ia); - commitments.main_ib = transcript->template receive_from_prover(commitment_labels.main_ib); - commitments.main_ic = transcript->template receive_from_prover(commitment_labels.main_ic); - commitments.main_id = transcript->template receive_from_prover(commitment_labels.main_id); - commitments.main_id_zero = transcript->template receive_from_prover(commitment_labels.main_id_zero); - commitments.main_ind_addr_a = - transcript->template receive_from_prover(commitment_labels.main_ind_addr_a); - commitments.main_ind_addr_b = - transcript->template receive_from_prover(commitment_labels.main_ind_addr_b); - commitments.main_ind_addr_c = - transcript->template receive_from_prover(commitment_labels.main_ind_addr_c); - commitments.main_ind_addr_d = - transcript->template receive_from_prover(commitment_labels.main_ind_addr_d); - commitments.main_internal_return_ptr = - transcript->template receive_from_prover(commitment_labels.main_internal_return_ptr); - commitments.main_inv = transcript->template receive_from_prover(commitment_labels.main_inv); - commitments.main_l2_gas_op_cost = - transcript->template receive_from_prover(commitment_labels.main_l2_gas_op_cost); - commitments.main_l2_gas_remaining = - transcript->template receive_from_prover(commitment_labels.main_l2_gas_remaining); - commitments.main_l2_out_of_gas = - transcript->template receive_from_prover(commitment_labels.main_l2_out_of_gas); - commitments.main_mem_addr_a = - transcript->template receive_from_prover(commitment_labels.main_mem_addr_a); - commitments.main_mem_addr_b = - transcript->template receive_from_prover(commitment_labels.main_mem_addr_b); - commitments.main_mem_addr_c = - transcript->template receive_from_prover(commitment_labels.main_mem_addr_c); - commitments.main_mem_addr_d = - transcript->template receive_from_prover(commitment_labels.main_mem_addr_d); - commitments.main_op_err = transcript->template receive_from_prover(commitment_labels.main_op_err); - commitments.main_opcode_val = - transcript->template receive_from_prover(commitment_labels.main_opcode_val); - commitments.main_pc = transcript->template receive_from_prover(commitment_labels.main_pc); - commitments.main_r_in_tag = transcript->template receive_from_prover(commitment_labels.main_r_in_tag); - commitments.main_rwa = transcript->template receive_from_prover(commitment_labels.main_rwa); - commitments.main_rwb = transcript->template receive_from_prover(commitment_labels.main_rwb); - commitments.main_rwc = transcript->template receive_from_prover(commitment_labels.main_rwc); - commitments.main_rwd = transcript->template receive_from_prover(commitment_labels.main_rwd); - commitments.main_sel_alu = transcript->template receive_from_prover(commitment_labels.main_sel_alu); - commitments.main_sel_bin = transcript->template receive_from_prover(commitment_labels.main_sel_bin); - commitments.main_sel_gas_accounting_active = - transcript->template receive_from_prover(commitment_labels.main_sel_gas_accounting_active); - commitments.main_sel_last = transcript->template receive_from_prover(commitment_labels.main_sel_last); - commitments.main_sel_mem_op_a = - transcript->template receive_from_prover(commitment_labels.main_sel_mem_op_a); - commitments.main_sel_mem_op_activate_gas = - transcript->template receive_from_prover(commitment_labels.main_sel_mem_op_activate_gas); - commitments.main_sel_mem_op_b = - transcript->template receive_from_prover(commitment_labels.main_sel_mem_op_b); - commitments.main_sel_mem_op_c = - transcript->template receive_from_prover(commitment_labels.main_sel_mem_op_c); - commitments.main_sel_mem_op_d = - transcript->template receive_from_prover(commitment_labels.main_sel_mem_op_d); - commitments.main_sel_mov_ia_to_ic = - transcript->template receive_from_prover(commitment_labels.main_sel_mov_ia_to_ic); - commitments.main_sel_mov_ib_to_ic = - transcript->template receive_from_prover(commitment_labels.main_sel_mov_ib_to_ic); - commitments.main_sel_op_add = - transcript->template receive_from_prover(commitment_labels.main_sel_op_add); - commitments.main_sel_op_address = - transcript->template receive_from_prover(commitment_labels.main_sel_op_address); - commitments.main_sel_op_and = - transcript->template receive_from_prover(commitment_labels.main_sel_op_and); - commitments.main_sel_op_block_number = - transcript->template receive_from_prover(commitment_labels.main_sel_op_block_number); - commitments.main_sel_op_cast = - transcript->template receive_from_prover(commitment_labels.main_sel_op_cast); - commitments.main_sel_op_chain_id = - transcript->template receive_from_prover(commitment_labels.main_sel_op_chain_id); - commitments.main_sel_op_cmov = - transcript->template receive_from_prover(commitment_labels.main_sel_op_cmov); - commitments.main_sel_op_coinbase = - transcript->template receive_from_prover(commitment_labels.main_sel_op_coinbase); - commitments.main_sel_op_dagasleft = - transcript->template receive_from_prover(commitment_labels.main_sel_op_dagasleft); - commitments.main_sel_op_div = - transcript->template receive_from_prover(commitment_labels.main_sel_op_div); - commitments.main_sel_op_emit_l2_to_l1_msg = - transcript->template receive_from_prover(commitment_labels.main_sel_op_emit_l2_to_l1_msg); - commitments.main_sel_op_emit_note_hash = - transcript->template receive_from_prover(commitment_labels.main_sel_op_emit_note_hash); - commitments.main_sel_op_emit_nullifier = - transcript->template receive_from_prover(commitment_labels.main_sel_op_emit_nullifier); - commitments.main_sel_op_emit_unencrypted_log = - transcript->template receive_from_prover(commitment_labels.main_sel_op_emit_unencrypted_log); - commitments.main_sel_op_eq = transcript->template receive_from_prover(commitment_labels.main_sel_op_eq); - commitments.main_sel_op_external_call = - transcript->template receive_from_prover(commitment_labels.main_sel_op_external_call); - commitments.main_sel_op_fdiv = - transcript->template receive_from_prover(commitment_labels.main_sel_op_fdiv); - commitments.main_sel_op_fee_per_da_gas = - transcript->template receive_from_prover(commitment_labels.main_sel_op_fee_per_da_gas); - commitments.main_sel_op_fee_per_l2_gas = - transcript->template receive_from_prover(commitment_labels.main_sel_op_fee_per_l2_gas); - commitments.main_sel_op_function_selector = - transcript->template receive_from_prover(commitment_labels.main_sel_op_function_selector); - commitments.main_sel_op_get_contract_instance = - transcript->template receive_from_prover(commitment_labels.main_sel_op_get_contract_instance); - commitments.main_sel_op_halt = - transcript->template receive_from_prover(commitment_labels.main_sel_op_halt); - commitments.main_sel_op_internal_call = - transcript->template receive_from_prover(commitment_labels.main_sel_op_internal_call); - commitments.main_sel_op_internal_return = - transcript->template receive_from_prover(commitment_labels.main_sel_op_internal_return); - commitments.main_sel_op_jump = - transcript->template receive_from_prover(commitment_labels.main_sel_op_jump); - commitments.main_sel_op_jumpi = - transcript->template receive_from_prover(commitment_labels.main_sel_op_jumpi); - commitments.main_sel_op_keccak = - transcript->template receive_from_prover(commitment_labels.main_sel_op_keccak); - commitments.main_sel_op_l1_to_l2_msg_exists = - transcript->template receive_from_prover(commitment_labels.main_sel_op_l1_to_l2_msg_exists); - commitments.main_sel_op_l2gasleft = - transcript->template receive_from_prover(commitment_labels.main_sel_op_l2gasleft); - commitments.main_sel_op_lt = transcript->template receive_from_prover(commitment_labels.main_sel_op_lt); - commitments.main_sel_op_lte = - transcript->template receive_from_prover(commitment_labels.main_sel_op_lte); - commitments.main_sel_op_mov = - transcript->template receive_from_prover(commitment_labels.main_sel_op_mov); - commitments.main_sel_op_mul = - transcript->template receive_from_prover(commitment_labels.main_sel_op_mul); - commitments.main_sel_op_not = - transcript->template receive_from_prover(commitment_labels.main_sel_op_not); - commitments.main_sel_op_note_hash_exists = - transcript->template receive_from_prover(commitment_labels.main_sel_op_note_hash_exists); - commitments.main_sel_op_nullifier_exists = - transcript->template receive_from_prover(commitment_labels.main_sel_op_nullifier_exists); - commitments.main_sel_op_or = transcript->template receive_from_prover(commitment_labels.main_sel_op_or); - commitments.main_sel_op_pedersen = - transcript->template receive_from_prover(commitment_labels.main_sel_op_pedersen); - commitments.main_sel_op_poseidon2 = - transcript->template receive_from_prover(commitment_labels.main_sel_op_poseidon2); - commitments.main_sel_op_radix_le = - transcript->template receive_from_prover(commitment_labels.main_sel_op_radix_le); - commitments.main_sel_op_sender = - transcript->template receive_from_prover(commitment_labels.main_sel_op_sender); - commitments.main_sel_op_sha256 = - transcript->template receive_from_prover(commitment_labels.main_sel_op_sha256); - commitments.main_sel_op_shl = - transcript->template receive_from_prover(commitment_labels.main_sel_op_shl); - commitments.main_sel_op_shr = - transcript->template receive_from_prover(commitment_labels.main_sel_op_shr); - commitments.main_sel_op_sload = - transcript->template receive_from_prover(commitment_labels.main_sel_op_sload); - commitments.main_sel_op_sstore = - transcript->template receive_from_prover(commitment_labels.main_sel_op_sstore); - commitments.main_sel_op_storage_address = - transcript->template receive_from_prover(commitment_labels.main_sel_op_storage_address); - commitments.main_sel_op_sub = - transcript->template receive_from_prover(commitment_labels.main_sel_op_sub); - commitments.main_sel_op_timestamp = - transcript->template receive_from_prover(commitment_labels.main_sel_op_timestamp); - commitments.main_sel_op_transaction_fee = - transcript->template receive_from_prover(commitment_labels.main_sel_op_transaction_fee); - commitments.main_sel_op_version = - transcript->template receive_from_prover(commitment_labels.main_sel_op_version); - commitments.main_sel_op_xor = - transcript->template receive_from_prover(commitment_labels.main_sel_op_xor); - commitments.main_sel_q_kernel_lookup = - transcript->template receive_from_prover(commitment_labels.main_sel_q_kernel_lookup); - commitments.main_sel_q_kernel_output_lookup = - transcript->template receive_from_prover(commitment_labels.main_sel_q_kernel_output_lookup); - commitments.main_sel_resolve_ind_addr_a = - transcript->template receive_from_prover(commitment_labels.main_sel_resolve_ind_addr_a); - commitments.main_sel_resolve_ind_addr_b = - transcript->template receive_from_prover(commitment_labels.main_sel_resolve_ind_addr_b); - commitments.main_sel_resolve_ind_addr_c = - transcript->template receive_from_prover(commitment_labels.main_sel_resolve_ind_addr_c); - commitments.main_sel_resolve_ind_addr_d = - transcript->template receive_from_prover(commitment_labels.main_sel_resolve_ind_addr_d); - commitments.main_sel_rng_16 = - transcript->template receive_from_prover(commitment_labels.main_sel_rng_16); - commitments.main_sel_rng_8 = transcript->template receive_from_prover(commitment_labels.main_sel_rng_8); - commitments.main_space_id = transcript->template receive_from_prover(commitment_labels.main_space_id); - commitments.main_tag_err = transcript->template receive_from_prover(commitment_labels.main_tag_err); - commitments.main_w_in_tag = transcript->template receive_from_prover(commitment_labels.main_w_in_tag); - commitments.mem_addr = transcript->template receive_from_prover(commitment_labels.mem_addr); - commitments.mem_clk = transcript->template receive_from_prover(commitment_labels.mem_clk); - commitments.mem_diff_hi = transcript->template receive_from_prover(commitment_labels.mem_diff_hi); - commitments.mem_diff_lo = transcript->template receive_from_prover(commitment_labels.mem_diff_lo); - commitments.mem_diff_mid = transcript->template receive_from_prover(commitment_labels.mem_diff_mid); - commitments.mem_glob_addr = transcript->template receive_from_prover(commitment_labels.mem_glob_addr); - commitments.mem_last = transcript->template receive_from_prover(commitment_labels.mem_last); - commitments.mem_lastAccess = transcript->template receive_from_prover(commitment_labels.mem_lastAccess); - commitments.mem_one_min_inv = - transcript->template receive_from_prover(commitment_labels.mem_one_min_inv); - commitments.mem_r_in_tag = transcript->template receive_from_prover(commitment_labels.mem_r_in_tag); - commitments.mem_rw = transcript->template receive_from_prover(commitment_labels.mem_rw); - commitments.mem_sel_mem = transcript->template receive_from_prover(commitment_labels.mem_sel_mem); - commitments.mem_sel_mov_ia_to_ic = - transcript->template receive_from_prover(commitment_labels.mem_sel_mov_ia_to_ic); - commitments.mem_sel_mov_ib_to_ic = - transcript->template receive_from_prover(commitment_labels.mem_sel_mov_ib_to_ic); - commitments.mem_sel_op_a = transcript->template receive_from_prover(commitment_labels.mem_sel_op_a); - commitments.mem_sel_op_b = transcript->template receive_from_prover(commitment_labels.mem_sel_op_b); - commitments.mem_sel_op_c = transcript->template receive_from_prover(commitment_labels.mem_sel_op_c); - commitments.mem_sel_op_cmov = - transcript->template receive_from_prover(commitment_labels.mem_sel_op_cmov); - commitments.mem_sel_op_d = transcript->template receive_from_prover(commitment_labels.mem_sel_op_d); - commitments.mem_sel_resolve_ind_addr_a = - transcript->template receive_from_prover(commitment_labels.mem_sel_resolve_ind_addr_a); - commitments.mem_sel_resolve_ind_addr_b = - transcript->template receive_from_prover(commitment_labels.mem_sel_resolve_ind_addr_b); - commitments.mem_sel_resolve_ind_addr_c = - transcript->template receive_from_prover(commitment_labels.mem_sel_resolve_ind_addr_c); - commitments.mem_sel_resolve_ind_addr_d = - transcript->template receive_from_prover(commitment_labels.mem_sel_resolve_ind_addr_d); - commitments.mem_sel_rng_chk = - transcript->template receive_from_prover(commitment_labels.mem_sel_rng_chk); - commitments.mem_skip_check_tag = - transcript->template receive_from_prover(commitment_labels.mem_skip_check_tag); - commitments.mem_space_id = transcript->template receive_from_prover(commitment_labels.mem_space_id); - commitments.mem_tag = transcript->template receive_from_prover(commitment_labels.mem_tag); - commitments.mem_tag_err = transcript->template receive_from_prover(commitment_labels.mem_tag_err); - commitments.mem_tsp = transcript->template receive_from_prover(commitment_labels.mem_tsp); - commitments.mem_val = transcript->template receive_from_prover(commitment_labels.mem_val); - commitments.mem_w_in_tag = transcript->template receive_from_prover(commitment_labels.mem_w_in_tag); - commitments.pedersen_clk = transcript->template receive_from_prover(commitment_labels.pedersen_clk); - commitments.pedersen_input = transcript->template receive_from_prover(commitment_labels.pedersen_input); - commitments.pedersen_output = - transcript->template receive_from_prover(commitment_labels.pedersen_output); - commitments.pedersen_sel_pedersen = - transcript->template receive_from_prover(commitment_labels.pedersen_sel_pedersen); - commitments.poseidon2_clk = transcript->template receive_from_prover(commitment_labels.poseidon2_clk); - commitments.poseidon2_input = - transcript->template receive_from_prover(commitment_labels.poseidon2_input); - commitments.poseidon2_output = - transcript->template receive_from_prover(commitment_labels.poseidon2_output); - commitments.poseidon2_sel_poseidon_perm = - transcript->template receive_from_prover(commitment_labels.poseidon2_sel_poseidon_perm); - commitments.powers_power_of_2 = - transcript->template receive_from_prover(commitment_labels.powers_power_of_2); - commitments.sha256_clk = transcript->template receive_from_prover(commitment_labels.sha256_clk); - commitments.sha256_input = transcript->template receive_from_prover(commitment_labels.sha256_input); - commitments.sha256_output = transcript->template receive_from_prover(commitment_labels.sha256_output); - commitments.sha256_sel_sha256_compression = - transcript->template receive_from_prover(commitment_labels.sha256_sel_sha256_compression); - commitments.sha256_state = transcript->template receive_from_prover(commitment_labels.sha256_state); - commitments.lookup_byte_lengths_counts = - transcript->template receive_from_prover(commitment_labels.lookup_byte_lengths_counts); - commitments.lookup_byte_operations_counts = - transcript->template receive_from_prover(commitment_labels.lookup_byte_operations_counts); - commitments.lookup_opcode_gas_counts = - transcript->template receive_from_prover(commitment_labels.lookup_opcode_gas_counts); - commitments.range_check_l2_gas_hi_counts = - transcript->template receive_from_prover(commitment_labels.range_check_l2_gas_hi_counts); - commitments.range_check_l2_gas_lo_counts = - transcript->template receive_from_prover(commitment_labels.range_check_l2_gas_lo_counts); - commitments.range_check_da_gas_hi_counts = - transcript->template receive_from_prover(commitment_labels.range_check_da_gas_hi_counts); - commitments.range_check_da_gas_lo_counts = - transcript->template receive_from_prover(commitment_labels.range_check_da_gas_lo_counts); - commitments.kernel_output_lookup_counts = - transcript->template receive_from_prover(commitment_labels.kernel_output_lookup_counts); - commitments.lookup_into_kernel_counts = - transcript->template receive_from_prover(commitment_labels.lookup_into_kernel_counts); - commitments.incl_main_tag_err_counts = - transcript->template receive_from_prover(commitment_labels.incl_main_tag_err_counts); - commitments.incl_mem_tag_err_counts = - transcript->template receive_from_prover(commitment_labels.incl_mem_tag_err_counts); - commitments.lookup_mem_rng_chk_lo_counts = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_lo_counts); - commitments.lookup_mem_rng_chk_mid_counts = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_mid_counts); - commitments.lookup_mem_rng_chk_hi_counts = - transcript->template receive_from_prover(commitment_labels.lookup_mem_rng_chk_hi_counts); - commitments.lookup_pow_2_0_counts = - transcript->template receive_from_prover(commitment_labels.lookup_pow_2_0_counts); - commitments.lookup_pow_2_1_counts = - transcript->template receive_from_prover(commitment_labels.lookup_pow_2_1_counts); - commitments.lookup_u8_0_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u8_0_counts); - commitments.lookup_u8_1_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u8_1_counts); - commitments.lookup_u16_0_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_0_counts); - commitments.lookup_u16_1_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_1_counts); - commitments.lookup_u16_2_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_2_counts); - commitments.lookup_u16_3_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_3_counts); - commitments.lookup_u16_4_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_4_counts); - commitments.lookup_u16_5_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_5_counts); - commitments.lookup_u16_6_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_6_counts); - commitments.lookup_u16_7_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_7_counts); - commitments.lookup_u16_8_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_8_counts); - commitments.lookup_u16_9_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_9_counts); - commitments.lookup_u16_10_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_10_counts); - commitments.lookup_u16_11_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_11_counts); - commitments.lookup_u16_12_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_12_counts); - commitments.lookup_u16_13_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_13_counts); - commitments.lookup_u16_14_counts = - transcript->template receive_from_prover(commitment_labels.lookup_u16_14_counts); - commitments.lookup_div_u16_0_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_0_counts); - commitments.lookup_div_u16_1_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_1_counts); - commitments.lookup_div_u16_2_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_2_counts); - commitments.lookup_div_u16_3_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_3_counts); - commitments.lookup_div_u16_4_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_4_counts); - commitments.lookup_div_u16_5_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_5_counts); - commitments.lookup_div_u16_6_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_6_counts); - commitments.lookup_div_u16_7_counts = - transcript->template receive_from_prover(commitment_labels.lookup_div_u16_7_counts); + for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) { + comm = transcript->template receive_from_prover(label); + } auto [beta, gamm] = transcript->template get_challenges("beta", "gamma"); relation_parameters.beta = beta; diff --git a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs index dab4058bdfe2..2c139e505c1c 100644 --- a/bb-pilcom/bb-pil-backend/src/flavor_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/flavor_builder.rs @@ -12,6 +12,7 @@ pub trait FlavorBuilder { lookups: &[String], fixed: &[String], witness: &[String], + witness_without_inverses: &[String], all_cols: &[String], to_be_shifted: &[String], shifted: &[String], @@ -28,6 +29,7 @@ impl FlavorBuilder for BBFiles { lookups: &[String], fixed: &[String], witness: &[String], + witness_without_inverses: &[String], all_cols: &[String], to_be_shifted: &[String], shifted: &[String], @@ -47,9 +49,9 @@ impl FlavorBuilder for BBFiles { // Entities classes let precomputed_entities = create_precomputed_entities(fixed); - let witness_entities = create_witness_entities(witness); - let all_entities = - create_all_entities(all_cols, to_be_shifted, shifted, all_cols_and_shifts); + let witness_entities = + create_witness_entities(witness_without_inverses, lookups, shifted, to_be_shifted); + let all_entities = create_all_entities(); let proving_and_verification_key = create_proving_and_verification_key(name, lookups, to_be_shifted); @@ -197,16 +199,12 @@ fn create_relation_definitions( let comma_sep_lookups: Option = create_lookups_tuple(lookups); // We only include the grand product relations if we are given lookups - let mut grand_product_relations = String::new(); let mut all_relations = comma_sep_relations.to_string(); if let Some(lookups) = comma_sep_lookups { all_relations = all_relations + &format!(", {lookups}"); - grand_product_relations = format!("using GrandProductRelations = std::tuple<{lookups}>;"); } format!(" - {grand_product_relations} - using Relations = std::tuple<{all_relations}>; static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); @@ -286,52 +284,120 @@ fn create_precomputed_entities(fixed: &[String]) -> String { ) } -fn create_witness_entities(witness: &[String]) -> String { - let pointer_view = create_flavor_members(witness); - - let wires = return_ref_vector("get_wires", witness); +// Note(md): this is witnesses WITHOUT inverses or shifts +fn create_wire_entities(witness: &[String]) -> String { + let flavor_members = create_flavor_members(witness); format!( " template - class WitnessEntities {{ + class WireEntities {{ public: + {flavor_members} + }}; + " + ) +} - {pointer_view} +// Note(md): this is witnesses and in future grand products +fn create_derived_witnesses(inverses: &[String]) -> String { + let flavor_members = create_flavor_members(inverses); - {wires} + format!( + " + template + struct DerivedWitnessEntities {{ + {flavor_members} }}; " ) } -/// Creates container of all witness entities and shifts -fn create_all_entities( - all_cols: &[String], - to_be_shifted: &[String], +fn create_shifted_entities(shifted: &[String]) -> String { + let flavor_members = create_flavor_members(shifted); + + format!( + " + template + class ShiftedEntities {{ + public: + {flavor_members} + }}; + " + ) +} + +fn create_to_be_shifted(to_be_shifted: &[String]) -> String { + let entities_transformation = |name: &String| format!("entities.{name},"); + let entities_list = map_with_newline(to_be_shifted, entities_transformation); + + format!( + " + template + static auto get_to_be_shifted(PrecomputedAndWitnessEntitiesSuperset& entities) {{ + return RefArray{{ + + {entities_list} + }}; + }} + " + ) +} + +fn create_witness_entities( + witness: &[String], + inverses: &[String], shifted: &[String], - all_cols_and_shifts: &[String], + to_be_shifted: &[String], ) -> String { - let all_entities_flavor_members = create_flavor_members(all_cols_and_shifts); - - let wires = return_ref_vector("get_wires", all_cols_and_shifts); - let get_unshifted = return_ref_vector("get_unshifted", all_cols); - let get_to_be_shifted = return_ref_vector("get_to_be_shifted", to_be_shifted); - let get_shifted = return_ref_vector("get_shifted", shifted); + let wire_entities = create_wire_entities(witness); + let derived_witnesses = create_derived_witnesses(inverses); + let shifted_entities = create_shifted_entities(shifted); + let to_be_shifted = create_to_be_shifted(to_be_shifted); format!( " + {wire_entities} + + {derived_witnesses} + + {shifted_entities} + + {to_be_shifted} + template - class AllEntities {{ + class WitnessEntities: public WireEntities, public DerivedWitnessEntities {{ public: + DEFINE_COMPOUND_GET_ALL(WireEntities, DerivedWitnessEntities) + auto get_wires() {{ return WireEntities::get_all(); }}; + }}; + " + ) +} - {all_entities_flavor_members} +/// Creates container of all witness entities and shifts +fn create_all_entities() -> String { + format!( + " + template + class AllEntities: public PrecomputedEntities, + public WitnessEntities, + public ShiftedEntities {{ + public: + AllEntities() + : PrecomputedEntities{{}} + , WitnessEntities{{}} + , ShiftedEntities{{}} + {{}} + DEFINE_COMPOUND_GET_ALL(PrecomputedEntities, WitnessEntities, ShiftedEntities) - {wires} - {get_unshifted} - {get_to_be_shifted} - {get_shifted} + auto get_unshifted(){{ + return concatenate(PrecomputedEntities::get_all(), WitnessEntities::get_all()); + }} + auto get_to_be_shifted(){{ return AvmFlavor::get_to_be_shifted(*this); }} + auto get_shifted() {{ return ShiftedEntities::get_all(); }} + auto get_precomputed() {{ return PrecomputedEntities::get_all(); }} }}; " ) diff --git a/bb-pilcom/bb-pil-backend/src/prover_builder.rs b/bb-pilcom/bb-pil-backend/src/prover_builder.rs index c0ea19709a52..faa2d81df987 100644 --- a/bb-pilcom/bb-pil-backend/src/prover_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/prover_builder.rs @@ -4,12 +4,7 @@ use crate::utils::{map_with_newline, snake_case}; pub trait ProverBuilder { fn create_prover_hpp(&mut self, name: &str); - fn create_prover_cpp( - &mut self, - name: &str, - commitment_polys: &[String], - lookup_names: &[String], - ); + fn create_prover_cpp(&mut self, name: &str, lookup_names: &[String]); } impl ProverBuilder for BBFiles { @@ -83,15 +78,10 @@ impl ProverBuilder for BBFiles { /// Create the prover cpp file /// /// Committed polys are included as we manually unroll all commitments, as we do not commit to everything - fn create_prover_cpp( - &mut self, - name: &str, - commitment_polys: &[String], - lookup_names: &[String], - ) { + fn create_prover_cpp(&mut self, name: &str, lookup_names: &[String]) { let include_str = includes_cpp(&snake_case(name)); - let polynomial_commitment_phase = create_commitments_phase(commitment_polys); + let polynomial_commitment_phase = create_commitments_phase(); let (call_log_derivative_phase, log_derivative_inverse_phase): (String, String) = if lookup_names.is_empty() { @@ -292,18 +282,15 @@ fn send_to_verifier_transform(name: &String) -> String { format!("transcript->send_to_verifier(commitment_labels.{name}, witness_commitments.{name});") } -fn create_commitments_phase(polys_to_commit_to: &[String]) -> String { - let all_commit_operations = map_with_newline(polys_to_commit_to, commitment_transform); - let send_to_verifier_operations = - map_with_newline(polys_to_commit_to, send_to_verifier_transform); - +fn create_commitments_phase() -> String { format!( " // Commit to all polynomials (apart from logderivative inverse polynomials, which are committed to in the later logderivative phase) - {all_commit_operations} - - // Send all commitments to the verifier - {send_to_verifier_operations} + auto wire_polys = prover_polynomials.get_wires(); + auto labels = commitment_labels.get_wires(); + for (size_t idx = 0; idx < wire_polys.size(); ++idx) {{ + transcript->send_to_verifier(labels[idx], commitment_key->commit(wire_polys[idx])); + }} " ) } diff --git a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs index a10a7bea021f..588574de2ca3 100644 --- a/bb-pilcom/bb-pil-backend/src/verifier_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/verifier_builder.rs @@ -7,7 +7,6 @@ pub trait VerifierBuilder { fn create_verifier_cpp( &mut self, name: &str, - witness: &[String], inverses: &[String], public_cols: &[(String, usize)], ); @@ -19,7 +18,6 @@ impl VerifierBuilder for BBFiles { fn create_verifier_cpp( &mut self, name: &str, - witness: &[String], inverses: &[String], public_cols: &[(String, usize)], ) { @@ -30,8 +28,6 @@ impl VerifierBuilder for BBFiles { "commitments.{n} = transcript->template receive_from_prover(commitment_labels.{n});" ) }; - let wire_commitments = map_with_newline(witness, wire_transformation); - let has_public_input_columns = !public_cols.is_empty(); let has_inverses = !inverses.is_empty(); @@ -151,7 +147,9 @@ impl VerifierBuilder for BBFiles { }} // Get commitments to VM wires - {wire_commitments} + for (auto [comm, label] : zip_view(commitments.get_wires(), commitment_labels.get_wires())) {{ + comm = transcript->template receive_from_prover(label); + }} {get_inverse_challenges} diff --git a/bb-pilcom/bb-pil-backend/src/vm_builder.rs b/bb-pilcom/bb-pil-backend/src/vm_builder.rs index 8707ef40a45b..1410a317dc53 100644 --- a/bb-pilcom/bb-pil-backend/src/vm_builder.rs +++ b/bb-pilcom/bb-pil-backend/src/vm_builder.rs @@ -136,6 +136,7 @@ pub fn analyzed_to_cpp( &inverses, &fixed, &witness, + &witnesses_without_inverses, &all_cols, &to_be_shifted, &shifted, @@ -147,16 +148,11 @@ pub fn analyzed_to_cpp( bb_files.create_composer_hpp(file_name); // ----------------------- Create the Verifier files ----------------------- - bb_files.create_verifier_cpp( - file_name, - &witnesses_without_inverses, - &inverses, - &public_inputs, - ); + bb_files.create_verifier_cpp(file_name, &inverses, &public_inputs); bb_files.create_verifier_hpp(file_name, &public_inputs); // ----------------------- Create the Prover files ----------------------- - bb_files.create_prover_cpp(file_name, &witnesses_without_inverses, &inverses); + bb_files.create_prover_cpp(file_name, &inverses); bb_files.create_prover_hpp(file_name); } diff --git a/noir/Earthfile b/noir/Earthfile index 718321420eb1..6cee66f45c78 100644 --- a/noir/Earthfile +++ b/noir/Earthfile @@ -259,4 +259,4 @@ bench-publish-acir-bb: RUN mkdir -p ./log RUN docker run -v "$(pwd)/log":/log -e LOG_FILE=/log/bench-acir.jsonl --rm aztecprotocol/barretenberg-acir-benches:$AZTEC_DOCKER_TAG ./bench_acir_tests.sh - DO ../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH + DO ../+UPLOAD_LOGS --PULL_REQUEST=$PULL_REQUEST --BRANCH=$BRANCH --COMMIT_HASH=$COMMIT_HASH \ No newline at end of file diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 589c3d179d8f..17778d09d370 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -2917,6 +2917,7 @@ dependencies = [ "num-bigint", "num-traits", "petgraph", + "rangemap", "regex", "rustc-hash", "serde", @@ -3564,6 +3565,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rangemap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" + [[package]] name = "rayon" version = "1.8.0" diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index cc5a9b1e652a..052d2c5f4844 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -29,6 +29,7 @@ regex = "1.9.1" cfg-if = "1.0.0" tracing.workspace = true petgraph = "0.6" +rangemap = "1.4.0" lalrpop-util = { version = "0.20.2", features = ["lexer"] } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index 7d304990dd81..9c72529e11ad 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -547,7 +547,7 @@ impl<'context> Elaborator<'context> { trait_id: trait_id.trait_id, trait_generics: Vec::new(), }; - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); self.type_check_operator_method(expr_id, trait_id, &lhs_type, span); } typ @@ -663,7 +663,14 @@ impl<'context> Elaborator<'context> { } fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { + // We have to push a new FunctionContext so that we can resolve any constraints + // in this comptime block early before the function as a whole finishes elaborating. + // Otherwise the interpreter below may find expressions for which the underlying trait + // call is not yet solved for. + self.function_context.push(Default::default()); let (block, _typ) = self.elaborate_block_expression(block); + self.check_and_pop_function_context(); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_block(block); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index e0671d6f7ffa..4b4cf33aa2a7 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -138,16 +138,14 @@ pub struct Elaborator<'context> { current_function: Option, - /// All type variables created in the current function. - /// This map is used to default any integer type variables at the end of - /// a function (before checking trait constraints) if a type wasn't already chosen. - type_variables: Vec, - - /// Trait constraints are collected during type checking until they are - /// verified at the end of a function. This is because constraints arise - /// on each variable, but it is only until function calls when the types - /// needed for the trait constraint may become known. - trait_constraints: Vec<(TraitConstraint, ExprId)>, + /// This is a stack of function contexts. Most of the time, for each function we + /// expect this to be of length one, containing each type variable and trait constraint + /// used in the function. This is also pushed to when a `comptime {}` block is used within + /// the function. Since it can force us to resolve that block's trait constraints earlier + /// so that they are resolved when the interpreter is run before the enclosing function + /// is finished elaborating. When this happens, we need to resolve any type variables + /// that were made within this block as well so that we can solve these traits. + function_context: Vec, /// The current module this elaborator is in. /// Initially empty, it is set whenever a new top-level item is resolved. @@ -166,6 +164,20 @@ pub struct Elaborator<'context> { unresolved_globals: BTreeMap, } +#[derive(Default)] +struct FunctionContext { + /// All type variables created in the current function. + /// This map is used to default any integer type variables at the end of + /// a function (before checking trait constraints) if a type wasn't already chosen. + type_variables: Vec, + + /// Trait constraints are collected during type checking until they are + /// verified at the end of a function. This is because constraints arise + /// on each variable, but it is only until function calls when the types + /// needed for the trait constraint may become known. + trait_constraints: Vec<(TraitConstraint, ExprId)>, +} + impl<'context> Elaborator<'context> { pub fn new(context: &'context mut Context, crate_id: CrateId) -> Self { Self { @@ -185,8 +197,7 @@ impl<'context> Elaborator<'context> { resolving_ids: BTreeSet::new(), trait_bounds: Vec::new(), current_function: None, - type_variables: Vec::new(), - trait_constraints: Vec::new(), + function_context: vec![FunctionContext::default()], current_trait_impl: None, comptime_scopes: vec![HashMap::default()], unresolved_globals: BTreeMap::new(), @@ -326,6 +337,7 @@ impl<'context> Elaborator<'context> { let func_meta = func_meta.clone(); self.trait_bounds = func_meta.trait_constraints.clone(); + self.function_context.push(FunctionContext::default()); // Introduce all numeric generics into scope for generic in &func_meta.all_generics { @@ -367,34 +379,11 @@ impl<'context> Elaborator<'context> { self.type_check_function_body(body_type, &func_meta, hir_func.as_expr()); } - // Default any type variables that still need defaulting. + // Default any type variables that still need defaulting and + // verify any remaining trait constraints arising from the function body. // This is done before trait impl search since leaving them bindable can lead to errors // when multiple impls are available. Instead we default first to choose the Field or u64 impl. - for typ in &self.type_variables { - if let Type::TypeVariable(variable, kind) = typ.follow_bindings() { - let msg = "TypeChecker should only track defaultable type vars"; - variable.bind(kind.default_type().expect(msg)); - } - } - - // Verify any remaining trait constraints arising from the function body - for (mut constraint, expr_id) in std::mem::take(&mut self.trait_constraints) { - let span = self.interner.expr_span(&expr_id); - - if matches!(&constraint.typ, Type::MutableReference(_)) { - let (_, dereferenced_typ) = - self.insert_auto_dereferences(expr_id, constraint.typ.clone()); - constraint.typ = dereferenced_typ; - } - - self.verify_trait_constraint( - &constraint.typ, - constraint.trait_id, - &constraint.trait_generics, - expr_id, - span, - ); - } + self.check_and_pop_function_context(); // Now remove all the `where` clause constraints we added for constraint in &func_meta.trait_constraints { @@ -417,12 +406,42 @@ impl<'context> Elaborator<'context> { meta.function_body = FunctionBody::Resolved; self.trait_bounds.clear(); - self.type_variables.clear(); self.interner.update_fn(id, hir_func); self.current_function = old_function; self.current_item = old_item; } + /// Defaults all type variables used in this function context then solves + /// all still-unsolved trait constraints in this context. + fn check_and_pop_function_context(&mut self) { + let context = self.function_context.pop().expect("Imbalanced function_context pushes"); + + for typ in context.type_variables { + if let Type::TypeVariable(variable, kind) = typ.follow_bindings() { + let msg = "TypeChecker should only track defaultable type vars"; + variable.bind(kind.default_type().expect(msg)); + } + } + + for (mut constraint, expr_id) in context.trait_constraints { + let span = self.interner.expr_span(&expr_id); + + if matches!(&constraint.typ, Type::MutableReference(_)) { + let (_, dereferenced_typ) = + self.insert_auto_dereferences(expr_id, constraint.typ.clone()); + constraint.typ = dereferenced_typ; + } + + self.verify_trait_constraint( + &constraint.typ, + constraint.trait_id, + &constraint.trait_generics, + expr_id, + span, + ); + } + } + /// This turns function parameters of the form: /// `fn foo(x: impl Bar)` /// @@ -1339,10 +1358,6 @@ impl<'context> Elaborator<'context> { self.elaborate_comptime_global(global_id); } - // Avoid defaulting the types of globals here since they may be used in any function. - // Otherwise we may prematurely default to a Field inside the next function if this - // global was unused there, even if it is consistently used as a u8 everywhere else. - self.type_variables.clear(); self.local_module = old_module; self.file = old_file; self.current_item = old_item; @@ -1494,7 +1509,7 @@ impl<'context> Elaborator<'context> { traits: BTreeMap::new(), trait_impls: Vec::new(), globals: Vec::new(), - impls: std::collections::HashMap::new(), + impls: rustc_hash::FxHashMap::default(), }; items.functions = function_sets; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index 4f04f5c523c2..5b128d8ce1d6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -14,7 +14,7 @@ use crate::{ stmt::HirPattern, }, macros_api::{HirExpression, Ident, Path, Pattern}, - node_interner::{DefinitionId, DefinitionKind, ExprId, GlobalId, TraitImplKind}, + node_interner::{DefinitionId, DefinitionKind, DependencyId, ExprId, GlobalId, TraitImplKind}, Shared, StructType, Type, TypeBindings, }; @@ -396,6 +396,7 @@ impl<'context> Elaborator<'context> { let expr = self.resolve_variable(variable); let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone())); + self.interner.push_expr_location(id, span, self.file); let typ = self.type_check_variable(expr, id, generics); self.interner.push_expr_type(id, typ.clone()); @@ -418,10 +419,14 @@ impl<'context> Elaborator<'context> { if hir_ident.id != DefinitionId::dummy_id() { match self.interner.definition(hir_ident.id).kind { - DefinitionKind::Function(id) => { + DefinitionKind::Function(func_id) => { if let Some(current_item) = self.current_item { - self.interner.add_function_dependency(current_item, id); + self.interner.add_function_dependency(current_item, func_id); } + + let variable = DependencyId::Variable(hir_ident.location); + let function = DependencyId::Function(func_id); + self.interner.add_reference(function, variable); } DefinitionKind::Global(global_id) => { if let Some(global) = self.unresolved_globals.remove(&global_id) { @@ -430,6 +435,10 @@ impl<'context> Elaborator<'context> { if let Some(current_item) = self.current_item { self.interner.add_global_dependency(current_item, global_id); } + + let variable = DependencyId::Variable(hir_ident.location); + let global = DependencyId::Global(global_id); + self.interner.add_reference(global, variable); } DefinitionKind::GenericType(_) => { // Initialize numeric generics to a polymorphic integer type in case @@ -516,7 +525,7 @@ impl<'context> Elaborator<'context> { for mut constraint in function.trait_constraints.clone() { constraint.apply_bindings(&bindings); - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); } } } @@ -533,7 +542,7 @@ impl<'context> Elaborator<'context> { // Currently only one impl can be selected per expr_id, so this // constraint needs to be pushed after any other constraints so // that monomorphization can resolve this trait method to the correct impl. - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); } } @@ -575,7 +584,10 @@ impl<'context> Elaborator<'context> { } pub fn get_ident_from_path(&mut self, path: Path) -> (HirIdent, usize) { - let location = Location::new(path.span(), self.file); + let location = Location::new( + path.segments.last().expect("ice: path without segments").span(), + self.file, + ); let error = match path.as_ident().map(|ident| self.use_variable(ident)) { Some(Ok(found)) => return found, @@ -593,4 +605,4 @@ impl<'context> Elaborator<'context> { let id = DefinitionId::dummy_id(); (HirIdent::non_trait_method(id, location), 0) } -} +} \ No newline at end of file diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index 0d67c9ed3e3d..e2d44919c5ef 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -433,8 +433,15 @@ impl<'context> Elaborator<'context> { } fn elaborate_comptime_statement(&mut self, statement: Statement) -> (HirStatement, Type) { + // We have to push a new FunctionContext so that we can resolve any constraints + // in this comptime block early before the function as a whole finishes elaborating. + // Otherwise the interpreter below may find expressions for which the underlying trait + // call is not yet solved for. + self.function_context.push(Default::default()); let span = statement.span; let (hir_statement, _typ) = self.elaborate_statement(statement); + self.check_and_pop_function_context(); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_statement(hir_statement); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 63cab40f9d3b..7f07e2a95386 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -16,7 +16,7 @@ use crate::{ errors::ResolverError, resolver::{verify_mutable_reference, SELF_TYPE_NAME, WILDCARD_TYPE}, }, - type_check::{Source, TypeCheckError}, + type_check::{NoMatchingImplFoundError, Source, TypeCheckError}, }, hir_def::{ expr::{ @@ -615,7 +615,7 @@ impl<'context> Elaborator<'context> { /// in self.type_variables to default it later. pub(super) fn polymorphic_integer_or_field(&mut self) -> Type { let typ = Type::polymorphic_integer_or_field(self.interner); - self.type_variables.push(typ.clone()); + self.push_type_variable(typ.clone()); typ } @@ -623,7 +623,7 @@ impl<'context> Elaborator<'context> { /// in self.type_variables to default it later. pub(super) fn polymorphic_integer(&mut self) -> Type { let typ = Type::polymorphic_integer(self.interner); - self.type_variables.push(typ.clone()); + self.push_type_variable(typ.clone()); typ } @@ -1410,26 +1410,10 @@ impl<'context> Elaborator<'context> { Err(erroring_constraints) => { if erroring_constraints.is_empty() { self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); - } else { - // Don't show any errors where try_get_trait returns None. - // This can happen if a trait is used that was never declared. - let constraints = erroring_constraints - .into_iter() - .map(|constraint| { - let r#trait = self.interner.try_get_trait(constraint.trait_id)?; - let mut name = r#trait.name.to_string(); - if !constraint.trait_generics.is_empty() { - let generics = - vecmap(&constraint.trait_generics, ToString::to_string); - name += &format!("<{}>", generics.join(", ")); - } - Some((constraint.typ, name)) - }) - .collect::>>(); - - if let Some(constraints) = constraints { - self.push_err(TypeCheckError::NoMatchingImplFound { constraints, span }); - } + } else if let Some(error) = + NoMatchingImplFoundError::new(self.interner, erroring_constraints, span) + { + self.push_err(TypeCheckError::NoMatchingImplFound(error)); } } } @@ -1557,4 +1541,20 @@ impl<'context> Elaborator<'context> { } } } + + /// Push a type variable into the current FunctionContext to be defaulted if needed + /// at the end of the earlier of either the current function or the current comptime scope. + fn push_type_variable(&mut self, typ: Type) { + let context = self.function_context.last_mut(); + let context = context.expect("The function_context stack should always be non-empty"); + context.type_variables.push(typ); + } + + /// Push a trait constraint into the current FunctionContext to be solved if needed + /// at the end of the earlier of either the current function or the current comptime scope. + pub fn push_trait_constraint(&mut self, constraint: TraitConstraint, expr_id: ExprId) { + let context = self.function_context.last_mut(); + let context = context.expect("The function_context stack should always be non-empty"); + context.trait_constraints.push((constraint, expr_id)); + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs index d2c7acee2a33..9bc54cf0e04f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -1,7 +1,10 @@ use std::rc::Rc; use crate::{ - hir::def_collector::dc_crate::CompilationError, parser::ParserError, token::Tokens, Type, + hir::{def_collector::dc_crate::CompilationError, type_check::NoMatchingImplFoundError}, + parser::ParserError, + token::Tokens, + Type, }; use acvm::{acir::AcirField, FieldElement}; use fm::FileId; @@ -44,6 +47,8 @@ pub enum InterpreterError { FailedToParseMacro { error: ParserError, tokens: Rc, rule: &'static str, file: FileId }, UnsupportedTopLevelItemUnquote { item: String, location: Location }, NonComptimeFnCallInSameCrate { function: String, location: Location }, + NoImpl { location: Location }, + NoMatchingImplFound { error: NoMatchingImplFoundError, file: FileId }, Unimplemented { item: String, location: Location }, @@ -106,11 +111,15 @@ impl InterpreterError { | InterpreterError::UnsupportedTopLevelItemUnquote { location, .. } | InterpreterError::NonComptimeFnCallInSameCrate { location, .. } | InterpreterError::Unimplemented { location, .. } + | InterpreterError::NoImpl { location, .. } | InterpreterError::BreakNotInLoop { location, .. } | InterpreterError::ContinueNotInLoop { location, .. } => *location, InterpreterError::FailedToParseMacro { error, file, .. } => { Location::new(error.span(), *file) } + InterpreterError::NoMatchingImplFound { error, file } => { + Location::new(error.span, *file) + } InterpreterError::Break | InterpreterError::Continue => { panic!("Tried to get the location of Break/Continue error!") } @@ -324,6 +333,11 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let msg = "There is no loop to continue!".into(); CustomDiagnostic::simple_error(msg, String::new(), location.span) } + InterpreterError::NoImpl { location } => { + let msg = "No impl found due to prior type error".into(); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NoMatchingImplFound { error, .. } => error.into(), InterpreterError::Break => unreachable!("Uncaught InterpreterError::Break"), InterpreterError::Continue => unreachable!("Uncaught InterpreterError::Continue"), } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index d2b98569bbb0..1b168e400433 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -8,7 +8,12 @@ use rustc_hash::FxHashMap as HashMap; use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; use crate::graph::CrateId; -use crate::monomorphization::{perform_instantiation_bindings, undo_instantiation_bindings}; +use crate::hir_def::expr::ImplKind; +use crate::macros_api::UnaryOp; +use crate::monomorphization::{ + perform_impl_bindings, perform_instantiation_bindings, resolve_trait_method, + undo_instantiation_bindings, +}; use crate::token::Tokens; use crate::{ hir_def::{ @@ -66,8 +71,12 @@ impl<'a> Interpreter<'a> { instantiation_bindings: TypeBindings, location: Location, ) -> IResult { + let trait_method = self.interner.get_trait_method_id(function); + perform_instantiation_bindings(&instantiation_bindings); + let impl_bindings = perform_impl_bindings(self.interner, trait_method, function); let result = self.call_function_inner(function, arguments, location); + undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(instantiation_bindings); result } @@ -347,6 +356,13 @@ impl<'a> Interpreter<'a> { pub(super) fn evaluate_ident(&mut self, ident: HirIdent, id: ExprId) -> IResult { let definition = self.interner.definition(ident.id); + if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { + let method_id = resolve_trait_method(self.interner, method, id)?; + let typ = self.interner.id_type(id).follow_bindings(); + let bindings = self.interner.get_instantiation_bindings(id).clone(); + return Ok(Value::Function(method_id, typ, Rc::new(bindings))); + } + match &definition.kind { DefinitionKind::Function(function_id) => { let typ = self.interner.id_type(id).follow_bindings(); @@ -556,8 +572,17 @@ impl<'a> Interpreter<'a> { fn evaluate_prefix(&mut self, prefix: HirPrefixExpression, id: ExprId) -> IResult { let rhs = self.evaluate(prefix.rhs)?; - match prefix.operator { - crate::ast::UnaryOp::Minus => match rhs { + self.evaluate_prefix_with_value(rhs, prefix.operator, id) + } + + fn evaluate_prefix_with_value( + &mut self, + rhs: Value, + operator: UnaryOp, + id: ExprId, + ) -> IResult { + match operator { + UnaryOp::Minus => match rhs { Value::Field(value) => Ok(Value::Field(FieldElement::zero() - value)), Value::I8(value) => Ok(Value::I8(-value)), Value::I16(value) => Ok(Value::I16(-value)), @@ -573,7 +598,7 @@ impl<'a> Interpreter<'a> { Err(InterpreterError::InvalidValueForUnary { value, location, operator }) } }, - crate::ast::UnaryOp::Not => match rhs { + UnaryOp::Not => match rhs { Value::Bool(value) => Ok(Value::Bool(!value)), Value::I8(value) => Ok(Value::I8(!value)), Value::I16(value) => Ok(Value::I16(!value)), @@ -588,8 +613,8 @@ impl<'a> Interpreter<'a> { Err(InterpreterError::InvalidValueForUnary { value, location, operator: "not" }) } }, - crate::ast::UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), - crate::ast::UnaryOp::Dereference { implicitly_added: _ } => match rhs { + UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), + UnaryOp::Dereference { implicitly_added: _ } => match rhs { Value::Pointer(element) => Ok(element.borrow().clone()), value => { let location = self.interner.expr_location(&id); @@ -603,13 +628,8 @@ impl<'a> Interpreter<'a> { let lhs = self.evaluate(infix.lhs)?; let rhs = self.evaluate(infix.rhs)?; - // TODO: Need to account for operator overloading - // See https://github.com/noir-lang/noir/issues/4925 if self.interner.get_selected_impl_for_expression(id).is_some() { - return Err(InterpreterError::Unimplemented { - item: "Operator overloading in the interpreter".to_string(), - location: infix.operator.location, - }); + return self.evaluate_overloaded_infix(infix, lhs, rhs, id); } use InterpreterError::InvalidValuesForBinary; @@ -854,6 +874,64 @@ impl<'a> Interpreter<'a> { } } + fn evaluate_overloaded_infix( + &mut self, + infix: HirInfixExpression, + lhs: Value, + rhs: Value, + id: ExprId, + ) -> IResult { + let method = infix.trait_method_id; + let operator = infix.operator.kind; + + let method_id = resolve_trait_method(self.interner, method, id)?; + let type_bindings = self.interner.get_instantiation_bindings(id).clone(); + + let lhs = (lhs, self.interner.expr_location(&infix.lhs)); + let rhs = (rhs, self.interner.expr_location(&infix.rhs)); + + let location = self.interner.expr_location(&id); + let value = self.call_function(method_id, vec![lhs, rhs], type_bindings, location)?; + + // Certain operators add additional operations after the trait call: + // - `!=`: Reverse the result of Eq + // - Comparator operators: Convert the returned `Ordering` to a boolean. + use BinaryOpKind::*; + match operator { + NotEqual => self.evaluate_prefix_with_value(value, UnaryOp::Not, id), + Less | LessEqual | Greater | GreaterEqual => self.evaluate_ordering(value, operator), + _ => Ok(value), + } + } + + /// Given the result of a `cmp` operation, convert it into the boolean result of the given operator. + /// - `<`: `ordering == Ordering::Less` + /// - `<=`: `ordering != Ordering::Greater` + /// - `>`: `ordering == Ordering::Greater` + /// - `<=`: `ordering != Ordering::Less` + fn evaluate_ordering(&self, ordering: Value, operator: BinaryOpKind) -> IResult { + let ordering = match ordering { + Value::Struct(fields, _) => match fields.into_iter().next().unwrap().1 { + Value::Field(ordering) => ordering, + _ => unreachable!("`cmp` should always return an Ordering value"), + }, + _ => unreachable!("`cmp` should always return an Ordering value"), + }; + + use BinaryOpKind::*; + let less_or_greater = if matches!(operator, Less | GreaterEqual) { + FieldElement::zero() // Ordering::Less + } else { + 2u128.into() // Ordering::Greater + }; + + if matches!(operator, Less | Greater) { + Ok(Value::Bool(ordering == less_or_greater)) + } else { + Ok(Value::Bool(ordering != less_or_greater)) + } + } + fn evaluate_index(&mut self, index: HirIndexExpression, id: ExprId) -> IResult { let array = self.evaluate(index.collection)?; let index = self.evaluate(index.index)?; @@ -882,7 +960,10 @@ impl<'a> Interpreter<'a> { let index = match index { Value::Field(value) => { - value.try_to_u64().expect("index could not fit into u64") as usize + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or_else(|| { + let typ = Type::default_int_type(); + InterpreterError::IntegerOutOfRangeForType { value, typ, location } + })? } Value::I8(value) => value as usize, Value::I16(value) => value as usize, @@ -1209,8 +1290,15 @@ impl<'a> Interpreter<'a> { } } HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { - let index = field_index.expect("The field index should be set after type checking"); - match self.evaluate_lvalue(&object)? { + let object_value = self.evaluate_lvalue(&object)?; + + let index = field_index.ok_or_else(|| { + let value = object_value.clone(); + let field_name = field_name.to_string(); + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + })?; + + match object_value { Value::Tuple(mut fields) => { fields[index] = rhs; self.store_lvalue(*object, Value::Tuple(fields)) @@ -1254,9 +1342,16 @@ impl<'a> Interpreter<'a> { } } HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { - let index = field_index.expect("The field index should be set after type checking"); + let object_value = self.evaluate_lvalue(object)?; + + let index = field_index.ok_or_else(|| { + let value = object_value.clone(); + let field_name = field_name.to_string(); + let location = *location; + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + })?; - match self.evaluate_lvalue(object)? { + match object_value { Value::Tuple(mut values) => Ok(values.swap_remove(index)), Value::Struct(fields, _) => Ok(fields[&field_name.0.contents].clone()), value => Err(InterpreterError::NonTupleOrStructInMemberAccess { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 8523e13aeea4..89c0b1d438e6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -16,12 +16,12 @@ pub(super) fn call_builtin( location: Location, ) -> IResult { match name { - "array_len" => array_len(&arguments), - "as_slice" => as_slice(arguments), - "slice_push_back" => slice_push_back(arguments), - "struct_def_as_type" => struct_def_as_type(interner, arguments), - "struct_def_generics" => struct_def_generics(interner, arguments), - "struct_def_fields" => struct_def_fields(interner, arguments), + "array_len" => array_len(interner, arguments, location), + "as_slice" => as_slice(interner, arguments, location), + "slice_push_back" => slice_push_back(interner, arguments, location), + "struct_def_as_type" => struct_def_as_type(interner, arguments, location), + "struct_def_generics" => struct_def_generics(interner, arguments, location), + "struct_def_fields" => struct_def_fields(interner, arguments, location), _ => { let item = format!("Comptime evaluation for builtin function {name}"); Err(InterpreterError::Unimplemented { item, location }) @@ -29,27 +29,61 @@ pub(super) fn call_builtin( } } -fn array_len(arguments: &[(Value, Location)]) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument"); - match &arguments[0].0 { +fn check_argument_count( + expected: usize, + arguments: &[(Value, Location)], + location: Location, +) -> IResult<()> { + if arguments.len() == expected { + Ok(()) + } else { + let actual = arguments.len(); + Err(InterpreterError::ArgumentCountMismatch { expected, actual, location }) + } +} + +fn array_len( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(1, &arguments, location)?; + + match arguments.pop().unwrap().0 { Value::Array(values, _) | Value::Slice(values, _) => Ok(Value::U32(values.len() as u32)), - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: Cannot query length of types other than arrays or slices"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Array(type_var.clone(), type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } -fn as_slice(mut arguments: Vec<(Value, Location)>) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `as_slice` should only receive a single argument"); +fn as_slice( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(1, &arguments, location)?; + let (array, _) = arguments.pop().unwrap(); match array { Value::Array(values, Type::Array(_, typ)) => Ok(Value::Slice(values, Type::Slice(typ))), - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: Cannot convert types other than arrays into slices"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Array(type_var.clone(), type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } -fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { - assert_eq!(arguments.len(), 2, "ICE: `slice_push_back` should only receive two arguments"); +fn slice_push_back( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(2, &arguments, location)?; + let (element, _) = arguments.pop().unwrap(); let (slice, _) = arguments.pop().unwrap(); match slice { @@ -57,8 +91,11 @@ fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { values.push_back(element); Ok(Value::Slice(values, typ)) } - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: `slice_push_back` expects a slice as its first argument"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Slice(type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } @@ -66,12 +103,15 @@ fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { fn struct_def_as_type( interner: &NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; @@ -95,29 +135,28 @@ fn struct_def_as_type( fn struct_def_generics( interner: &NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; let struct_def = interner.get_struct(struct_def); + let struct_def = struct_def.borrow(); - let generics = struct_def - .borrow() - .generics - .iter() - .map(|generic| { - let name = SpannedToken::new(Token::Ident(generic.type_var.borrow().to_string()), span); - Value::Code(Rc::new(Tokens(vec![name]))) - }) - .collect(); + let generics = struct_def.generics.iter().map(|generic| { + let name = SpannedToken::new(Token::Ident(generic.type_var.borrow().to_string()), span); + Value::Code(Rc::new(Tokens(vec![name]))) + }); let typ = Type::Slice(Box::new(Type::Quoted(QuotedType::Quoted))); - Ok(Value::Slice(generics, typ)) + Ok(Value::Slice(generics.collect(), typ)) } /// fn fields(self) -> [(Quoted, Quoted)] @@ -125,12 +164,15 @@ fn struct_def_generics( fn struct_def_fields( interner: &mut NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 37ece01c8050..6858e10a1752 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -20,18 +20,20 @@ use crate::hir::Context; use crate::macros_api::{MacroError, MacroProcessor}; use crate::node_interner::{ - FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId, + DependencyId, FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId, }; use crate::ast::{ ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, NoirTypeAlias, Path, PathKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; + use crate::parser::{ParserError, SortedModule}; use fm::FileId; use iter_extended::vecmap; -use noirc_errors::{CustomDiagnostic, Span}; -use std::collections::{BTreeMap, HashMap}; +use noirc_errors::{CustomDiagnostic, Location, Span}; +use rustc_hash::FxHashMap as HashMap; +use std::collections::BTreeMap; use std::vec; @@ -253,7 +255,7 @@ impl DefCollector { types: BTreeMap::new(), type_aliases: BTreeMap::new(), traits: BTreeMap::new(), - impls: HashMap::new(), + impls: HashMap::default(), globals: vec![], trait_impls: vec![], }, @@ -327,6 +329,7 @@ impl DefCollector { // Resolve unresolved imports collected from the crate, one by one. for collected_import in std::mem::take(&mut def_collector.imports) { + let module_id = collected_import.module_id; match resolve_import(crate_id, &collected_import, &context.def_maps) { Ok(resolved_import) => { if let Some(error) = resolved_import.error { @@ -344,6 +347,9 @@ impl DefCollector { let result = current_def_map.modules[resolved_import.module_scope.0] .import(name.clone(), ns, resolved_import.is_prelude); + let file_id = current_def_map.file_id(module_id); + add_import_reference(ns, &name, &mut context.def_interner, file_id); + if let Err((first_def, second_def)) = result { let err = DefCollectorErrorKind::Duplicate { typ: DuplicateType::Import, @@ -467,6 +473,22 @@ impl DefCollector { } } +fn add_import_reference( + def_id: crate::macros_api::ModuleDefId, + name: &Ident, + interner: &mut NodeInterner, + file_id: FileId, +) { + if name.span() == Span::empty(0) { + // We ignore empty spans at 0 location, this must be Stdlib + return; + } + if let crate::macros_api::ModuleDefId::FunctionId(func_id) = def_id { + let variable = DependencyId::Variable(Location::new(name.span(), file_id)); + interner.add_reference_for(DependencyId::Function(func_id), variable); + } +} + fn inject_prelude( crate_id: CrateId, context: &Context, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index c9198a1d04c8..aebc649b7b28 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,11 +1,12 @@ use std::path::Path; -use std::{collections::HashMap, vec}; +use std::vec; use acvm::{AcirField, FieldElement}; use fm::{FileId, FileManager, FILE_EXTENSION}; use noirc_errors::Location; use num_bigint::BigUint; use num_traits::Num; +use rustc_hash::FxHashMap as HashMap; use crate::ast::{ FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, @@ -400,7 +401,7 @@ impl<'a> ModCollector<'a> { self_type: None, }; - let mut method_ids = HashMap::new(); + let mut method_ids = HashMap::default(); for trait_item in &trait_definition.items { match trait_item { TraitItem::Function { @@ -414,6 +415,7 @@ impl<'a> ModCollector<'a> { let func_id = context.def_interner.push_empty_fn(); method_ids.insert(name.to_string(), func_id); + let location = Location::new(name.span(), self.file_id); let modifiers = FunctionModifiers { name: name.to_string(), visibility: ItemVisibility::Public, @@ -422,9 +424,9 @@ impl<'a> ModCollector<'a> { is_unconstrained: false, generic_count: generics.len(), is_comptime: false, + name_location: location, }; - let location = Location::new(name.span(), self.file_id); context .def_interner .push_function_definition(func_id, modifiers, trait_id.0, location); 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 6d547aaf0b71..2eb33f7603fe 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 @@ -1512,7 +1512,7 @@ impl<'a> Resolver<'a> { // Otherwise, then it is referring to an Identifier // This lookup allows support of such statements: let x = foo::bar::SOME_GLOBAL + 10; // If the expression is a singular indent, we search the resolver's current scope as normal. - let (hir_ident, var_scope_index) = self.get_ident_from_path(path); + let (hir_ident, var_scope_index) = self.get_ident_from_path(path.clone()); if hir_ident.id != DefinitionId::dummy_id() { match self.interner.definition(hir_ident.id).kind { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index f18e8a9e843e..470bf52677c0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -1,4 +1,5 @@ use acvm::FieldElement; +use iter_extended::vecmap; use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::Span; use thiserror::Error; @@ -6,7 +7,9 @@ use thiserror::Error; use crate::ast::{BinaryOpKind, FunctionReturnType, IntegerBitSize, Signedness}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; +use crate::hir_def::traits::TraitConstraint; use crate::hir_def::types::Type; +use crate::macros_api::NodeInterner; #[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum Source { @@ -114,7 +117,7 @@ pub enum TypeCheckError { parameter_index: usize, }, #[error("No matching impl found")] - NoMatchingImplFound { constraints: Vec<(Type, String)>, span: Span }, + NoMatchingImplFound(NoMatchingImplFoundError), #[error("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope")] UnneededTraitConstraint { trait_name: String, typ: Type, span: Span }, #[error( @@ -149,6 +152,12 @@ pub enum TypeCheckError { MacroReturningNonExpr { typ: Type, span: Span }, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NoMatchingImplFoundError { + constraints: Vec<(Type, String)>, + pub span: Span, +} + impl TypeCheckError { pub fn add_context(self, ctx: &'static str) -> Self { TypeCheckError::Context { err: Box::new(self), ctx } @@ -307,20 +316,7 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Unused expression result of type {expr_type}"); Diagnostic::simple_warning(msg, String::new(), *expr_span) } - TypeCheckError::NoMatchingImplFound { constraints, span } => { - assert!(!constraints.is_empty()); - let msg = format!("No matching impl found for `{}: {}`", constraints[0].0, constraints[0].1); - let mut diagnostic = Diagnostic::from_message(&msg); - - diagnostic.add_secondary(format!("No impl for `{}: {}`", constraints[0].0, constraints[0].1), *span); - - // These must be notes since secondaries are unordered - for (typ, trait_name) in &constraints[1..] { - diagnostic.add_note(format!("Required by `{typ}: {trait_name}`")); - } - - diagnostic - } + TypeCheckError::NoMatchingImplFound(error) => error.into(), TypeCheckError::UnneededTraitConstraint { trait_name, typ, span } => { let msg = format!("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope"); Diagnostic::simple_warning(msg, "Unnecessary trait constraint in where clause".into(), *span) @@ -350,7 +346,54 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { format!("Expected macro call to return a `Quoted` but found a(n) `{typ}`"), "Macro calls must return quoted values, otherwise there is no code to insert".into(), *span, - ), + ), } } } + +impl<'a> From<&'a NoMatchingImplFoundError> for Diagnostic { + fn from(error: &'a NoMatchingImplFoundError) -> Self { + let constraints = &error.constraints; + let span = error.span; + + assert!(!constraints.is_empty()); + let msg = + format!("No matching impl found for `{}: {}`", constraints[0].0, constraints[0].1); + let mut diagnostic = Diagnostic::from_message(&msg); + + let secondary = format!("No impl for `{}: {}`", constraints[0].0, constraints[0].1); + diagnostic.add_secondary(secondary, span); + + // These must be notes since secondaries are unordered + for (typ, trait_name) in &constraints[1..] { + diagnostic.add_note(format!("Required by `{typ}: {trait_name}`")); + } + + diagnostic + } +} + +impl NoMatchingImplFoundError { + pub fn new( + interner: &NodeInterner, + failing_constraints: Vec, + span: Span, + ) -> Option { + // Don't show any errors where try_get_trait returns None. + // This can happen if a trait is used that was never declared. + let constraints = failing_constraints + .into_iter() + .map(|constraint| { + let r#trait = interner.try_get_trait(constraint.trait_id)?; + let mut name = r#trait.name.to_string(); + if !constraint.trait_generics.is_empty() { + let generics = vecmap(&constraint.trait_generics, ToString::to_string); + name += &format!("<{}>", generics.join(", ")); + } + Some((constraint.typ, name)) + }) + .collect::>>()?; + + Some(Self { constraints, span }) + } +} \ No newline at end of file diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 77861a6d8f88..1f3e9103cde6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -17,6 +17,7 @@ use crate::{ TypeBinding, TypeBindings, TypeVariableKind, }; +use super::NoMatchingImplFoundError; use super::{errors::TypeCheckError, TypeChecker}; impl<'interner> TypeChecker<'interner> { @@ -518,26 +519,10 @@ impl<'interner> TypeChecker<'interner> { Err(erroring_constraints) => { if erroring_constraints.is_empty() { self.errors.push(TypeCheckError::TypeAnnotationsNeeded { span }); - } else { - // Don't show any errors where try_get_trait returns None. - // This can happen if a trait is used that was never declared. - let constraints = erroring_constraints - .into_iter() - .map(|constraint| { - let r#trait = self.interner.try_get_trait(constraint.trait_id)?; - let mut name = r#trait.name.to_string(); - if !constraint.trait_generics.is_empty() { - let generics = - vecmap(&constraint.trait_generics, ToString::to_string); - name += &format!("<{}>", generics.join(", ")); - } - Some((constraint.typ, name)) - }) - .collect::>>(); - - if let Some(constraints) = constraints { - self.errors.push(TypeCheckError::NoMatchingImplFound { constraints, span }); - } + } else if let Some(error) = + NoMatchingImplFoundError::new(self.interner, erroring_constraints, span) + { + self.errors.push(TypeCheckError::NoMatchingImplFound(error)); } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 1d3c7fcda9b6..b8fd59e015b0 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -11,7 +11,7 @@ mod errors; mod expr; mod stmt; -pub use errors::TypeCheckError; +pub use errors::{NoMatchingImplFoundError, TypeCheckError}; use noirc_errors::Span; use crate::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs index e4959cb3dd93..0600706922b9 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap as HashMap; use crate::ast::{Ident, NoirFunction}; use crate::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs index b05c635f4364..b14f65a3e353 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs @@ -15,6 +15,7 @@ pub mod debug; pub mod elaborator; pub mod graph; pub mod lexer; +pub mod locations; pub mod monomorphization; pub mod node_interner; pub mod parser; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs new file mode 100644 index 000000000000..dd6a3412a406 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -0,0 +1,122 @@ +use fm::FileId; +use noirc_errors::Location; +use rangemap::RangeMap; +use rustc_hash::FxHashMap; + +use crate::{macros_api::NodeInterner, node_interner::DependencyId}; +use petgraph::prelude::NodeIndex as PetGraphIndex; + +#[derive(Debug, Default)] +pub(crate) struct LocationIndices { + map_file_to_range: FxHashMap>, +} + +impl LocationIndices { + pub(crate) fn add_location(&mut self, location: Location, node_index: PetGraphIndex) { + // Some location spans are empty: maybe they are from ficticious nodes? + if location.span.start() == location.span.end() { + return; + } + + let range_map = self.map_file_to_range.entry(location.file).or_default(); + range_map.insert(location.span.start()..location.span.end(), node_index); + } + + pub(crate) fn get_node_from_location(&self, location: Location) -> Option { + let range_map = self.map_file_to_range.get(&location.file)?; + Some(*range_map.get(&location.span.start())?) + } +} + +impl NodeInterner { + pub fn dependency_location(&self, dependency: DependencyId) -> Location { + match dependency { + DependencyId::Function(id) => self.function_modifiers(&id).name_location, + DependencyId::Struct(id) => self.get_struct(id).borrow().location, + DependencyId::Global(id) => self.get_global(id).location, + DependencyId::Alias(id) => self.get_type_alias(id).borrow().location, + DependencyId::Variable(location) => location, + } + } + + pub(crate) fn add_reference(&mut self, referenced: DependencyId, reference: DependencyId) { + let referenced_index = self.get_or_insert_reference(referenced); + let reference_index = self.reference_graph.add_node(reference); + + let referenced_location = self.dependency_location(referenced); + let reference_location = self.dependency_location(reference); + + self.reference_graph.add_edge(referenced_index, reference_index, ()); + self.location_indices.add_location(referenced_location, referenced_index); + self.location_indices.add_location(reference_location, reference_index); + } + + pub(crate) fn add_reference_for( + &mut self, + referenced_id: DependencyId, + reference: DependencyId, + ) { + let Some(referenced_index) = self.reference_graph_indices.get(&referenced_id) else { + panic!("Compiler Error: Referenced index not found") + }; + + let reference_location = self.dependency_location(reference); + let reference_index = self.reference_graph.add_node(reference); + self.reference_graph.add_edge(*referenced_index, reference_index, ()); + self.location_indices.add_location(reference_location, reference_index); + } + + pub(crate) fn add_definition_location(&mut self, referenced: DependencyId) { + let referenced_index = self.get_or_insert_reference(referenced); + let referenced_location = self.dependency_location(referenced); + self.location_indices.add_location(referenced_location, referenced_index); + } + + #[tracing::instrument(skip(self), ret)] + pub(crate) fn get_or_insert_reference(&mut self, id: DependencyId) -> PetGraphIndex { + if let Some(index) = self.reference_graph_indices.get(&id) { + return *index; + } + + let index = self.reference_graph.add_node(id); + self.reference_graph_indices.insert(id, index); + index + } + + pub fn check_rename_possible(&self, location: Location) -> bool { + self.location_indices.get_node_from_location(location).is_some() + } + + pub fn find_rename_symbols_at(&self, location: Location) -> Option> { + let node_index = self.location_indices.get_node_from_location(location)?; + + let reference_node = self.reference_graph[node_index]; + let found_locations: Vec = match reference_node { + DependencyId::Alias(_) | DependencyId::Struct(_) | DependencyId::Global(_) => todo!(), + DependencyId::Function(_) => self.get_edit_locations(node_index), + + DependencyId::Variable(_) => { + let referenced_node_index = self + .reference_graph + .neighbors_directed(node_index, petgraph::Direction::Incoming) + .next()?; + + self.get_edit_locations(referenced_node_index) + } + }; + Some(found_locations) + } + + fn get_edit_locations(&self, referenced_node_index: PetGraphIndex) -> Vec { + let id = self.reference_graph[referenced_node_index]; + let mut edit_locations = vec![self.dependency_location(id)]; + + self.reference_graph + .neighbors_directed(referenced_node_index, petgraph::Direction::Outgoing) + .for_each(|reference_node_index| { + let id = self.reference_graph[reference_node_index]; + edit_locations.push(self.dependency_location(id)); + }); + edit_locations + } +} 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 ebf0503963e0..071ca95b114c 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -9,6 +9,9 @@ //! The entry point to this pass is the `monomorphize` function which, starting from a given //! function, will monomorphize the entire reachable program. use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility}; +use crate::hir::comptime::InterpreterError; +use crate::hir::type_check::NoMatchingImplFoundError; +use crate::node_interner::ExprId; use crate::{ debug::DebugInstrumenter, hir_def::{ @@ -125,7 +128,7 @@ pub fn monomorphize_debug( monomorphizer.locals.clear(); perform_instantiation_bindings(&bindings); - let impl_bindings = monomorphizer.perform_impl_bindings(trait_method, next_fn_id); + let impl_bindings = perform_impl_bindings(monomorphizer.interner, trait_method, next_fn_id); monomorphizer.function(next_fn_id, new_id)?; undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(bindings); @@ -467,23 +470,11 @@ impl<'interner> Monomorphizer<'interner> { if self.interner.get_selected_impl_for_expression(expr).is_some() { // If an impl was selected for this infix operator, replace it // with a method call to the appropriate trait impl method. - let lhs_type = self.interner.id_type(infix.lhs); - let args = vec![lhs_type.clone(), lhs_type]; - - // If this is a comparison operator, the result is a boolean but - // the actual method call returns an Ordering - use crate::ast::BinaryOpKind::*; - let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { - self.interner.ordering_type() - } else { - self.interner.id_type(expr) - }; - - let env = Box::new(Type::Unit); - let function_type = Type::Function(args, Box::new(ret.clone()), env); + let (function_type, ret) = + self.interner.get_operator_type(infix.lhs, operator, expr); let method = infix.trait_method_id; - let func = self.resolve_trait_method_reference(expr, function_type, method)?; + let func = self.resolve_trait_method_expr(expr, function_type, method)?; self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location)? } else { let lhs = Box::new(lhs); @@ -843,7 +834,7 @@ impl<'interner> Monomorphizer<'interner> { let typ = self.interner.id_type(expr_id); if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { - return self.resolve_trait_method_reference(expr_id, typ, method); + return self.resolve_trait_method_expr(expr_id, typ, method); } let definition = self.interner.definition(ident.id); @@ -1046,53 +1037,14 @@ impl<'interner> Monomorphizer<'interner> { } } - fn resolve_trait_method_reference( + fn resolve_trait_method_expr( &mut self, expr_id: node_interner::ExprId, function_type: HirType, method: TraitMethodId, ) -> Result { - let trait_impl = self - .interner - .get_selected_impl_for_expression(expr_id) - .expect("ICE: missing trait impl - should be caught during type checking"); - - let func_id = match trait_impl { - node_interner::TraitImplKind::Normal(impl_id) => { - self.interner.get_trait_implementation(impl_id).borrow().methods - [method.method_index] - } - node_interner::TraitImplKind::Assumed { object_type, trait_generics } => { - match self.interner.lookup_trait_implementation( - &object_type, - method.trait_id, - &trait_generics, - ) { - Ok(TraitImplKind::Normal(impl_id)) => { - self.interner.get_trait_implementation(impl_id).borrow().methods - [method.method_index] - } - Ok(TraitImplKind::Assumed { .. }) => unreachable!( - "There should be no remaining Assumed impls during monomorphization" - ), - Err(constraints) => { - let failed_constraints = vecmap(constraints, |constraint| { - let id = constraint.trait_id; - let mut name = self.interner.get_trait(id).name.to_string(); - if !constraint.trait_generics.is_empty() { - let types = - vecmap(&constraint.trait_generics, |t| format!("{t:?}")); - name += &format!("<{}>", types.join(", ")); - } - format!(" {}: {name}", constraint.typ) - }) - .join("\n"); - - unreachable!("Failed to find trait impl during monomorphization. The failed constraint(s) are:\n{failed_constraints}") - } - } - } - }; + let func_id = resolve_trait_method(self.interner, method, expr_id) + .map_err(MonomorphizationError::InterpreterError)?; let func_id = match self.lookup_function(func_id, expr_id, &function_type, vec![], Some(method)) { @@ -1763,46 +1715,6 @@ impl<'interner> Monomorphizer<'interner> { Ok(result) } - - /// Call sites are instantiated against the trait method, but when an impl is later selected, - /// the corresponding method in the impl will have a different set of generics. `perform_impl_bindings` - /// is needed to apply the generics from the trait method to the impl method. Without this, - /// static method references to generic impls (e.g. `Eq::eq` for `[T; N]`) will fail to re-apply - /// the correct type bindings during monomorphization. - fn perform_impl_bindings( - &self, - trait_method: Option, - impl_method: node_interner::FuncId, - ) -> TypeBindings { - let mut bindings = TypeBindings::new(); - - if let Some(trait_method) = trait_method { - let the_trait = self.interner.get_trait(trait_method.trait_id); - - let trait_method_type = the_trait.methods[trait_method.method_index].typ.as_monotype(); - - // Make each NamedGeneric in this type bindable by replacing it with a TypeVariable - // with the same internal id and binding. - let (generics, impl_method_type) = - self.interner.function_meta(&impl_method).typ.unwrap_forall(); - - let replace_type_variable = |var: &TypeVariable| { - (var.id(), (var.clone(), Type::TypeVariable(var.clone(), TypeVariableKind::Normal))) - }; - - // Replace each NamedGeneric with a TypeVariable containing the same internal type variable - let type_bindings = generics.iter().map(replace_type_variable).collect(); - let impl_method_type = impl_method_type.force_substitute(&type_bindings); - - trait_method_type.try_unify(&impl_method_type, &mut bindings).unwrap_or_else(|_| { - unreachable!("Impl method type {} does not unify with trait method type {} during monomorphization", impl_method_type, trait_method_type) - }); - - perform_instantiation_bindings(&bindings); - } - - bindings - } } fn unwrap_tuple_type(typ: &HirType) -> Vec { @@ -1830,3 +1742,84 @@ pub fn undo_instantiation_bindings(bindings: TypeBindings) { var.unbind(id); } } + +/// Call sites are instantiated against the trait method, but when an impl is later selected, +/// the corresponding method in the impl will have a different set of generics. `perform_impl_bindings` +/// is needed to apply the generics from the trait method to the impl method. Without this, +/// static method references to generic impls (e.g. `Eq::eq` for `[T; N]`) will fail to re-apply +/// the correct type bindings during monomorphization. +pub fn perform_impl_bindings( + interner: &NodeInterner, + trait_method: Option, + impl_method: node_interner::FuncId, +) -> TypeBindings { + let mut bindings = TypeBindings::new(); + + if let Some(trait_method) = trait_method { + let the_trait = interner.get_trait(trait_method.trait_id); + + let trait_method_type = the_trait.methods[trait_method.method_index].typ.as_monotype(); + + // Make each NamedGeneric in this type bindable by replacing it with a TypeVariable + // with the same internal id and binding. + let (generics, impl_method_type) = interner.function_meta(&impl_method).typ.unwrap_forall(); + + let replace_type_variable = |var: &TypeVariable| { + (var.id(), (var.clone(), Type::TypeVariable(var.clone(), TypeVariableKind::Normal))) + }; + + // Replace each NamedGeneric with a TypeVariable containing the same internal type variable + let type_bindings = generics.iter().map(replace_type_variable).collect(); + let impl_method_type = impl_method_type.force_substitute(&type_bindings); + + trait_method_type.try_unify(&impl_method_type, &mut bindings).unwrap_or_else(|_| { + unreachable!("Impl method type {} does not unify with trait method type {} during monomorphization", impl_method_type, trait_method_type) + }); + + perform_instantiation_bindings(&bindings); + } + + bindings +} + +pub fn resolve_trait_method( + interner: &NodeInterner, + method: TraitMethodId, + expr_id: ExprId, +) -> Result { + let trait_impl = interner.get_selected_impl_for_expression(expr_id).ok_or_else(|| { + let location = interner.expr_location(&expr_id); + InterpreterError::NoImpl { location } + })?; + + let impl_id = match trait_impl { + TraitImplKind::Normal(impl_id) => impl_id, + TraitImplKind::Assumed { object_type, trait_generics } => { + match interner.lookup_trait_implementation( + &object_type, + method.trait_id, + &trait_generics, + ) { + Ok(TraitImplKind::Normal(impl_id)) => impl_id, + Ok(TraitImplKind::Assumed { .. }) => { + let location = interner.expr_location(&expr_id); + return Err(InterpreterError::NoImpl { location }); + } + Err(constraints) => { + let location = interner.expr_location(&expr_id); + if let Some(error) = + NoMatchingImplFoundError::new(interner, constraints, location.span) + { + let file = location.file; + return Err(InterpreterError::NoMatchingImplFound { error, file }); + } else { + let location = interner.expr_location(&expr_id); + return Err(InterpreterError::NoImpl { location }); + } + } + } + } + }; + + Ok(interner.get_trait_implementation(impl_id).borrow().methods[method.method_index]) +} 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 17531d09eaca..2cb18a71d7af 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -31,6 +31,7 @@ use crate::hir_def::{ function::{FuncMeta, HirFunction}, stmt::HirStatement, }; +use crate::locations::LocationIndices; use crate::token::{Attributes, SecondaryAttribute}; use crate::GenericTypeVars; use crate::Generics; @@ -64,7 +65,7 @@ pub struct NodeInterner { function_modules: HashMap, /// This graph tracks dependencies between different global definitions. - /// This is used to ensure the absense of dependency cycles for globals and types. + /// This is used to ensure the absence of dependency cycles for globals and types. dependency_graph: DiGraph, /// To keep track of where each DependencyId is in `dependency_graph`, we need @@ -182,6 +183,15 @@ pub struct NodeInterner { /// and creating a `Token::QuotedType(id)` from this id. We cannot create a token holding /// the actual type since types do not implement Send or Sync. quoted_types: noirc_arena::Arena, + + /// Store the location of the references in the graph + pub(crate) reference_graph: DiGraph, + + /// Tracks the index of the references in the graph + pub(crate) reference_graph_indices: HashMap, + + /// Store the location of the references in the graph + pub(crate) location_indices: LocationIndices, } /// A dependency in the dependency graph may be a type or a definition. @@ -200,6 +210,7 @@ pub enum DependencyId { Global(GlobalId), Function(FuncId), Alias(TypeAliasId), + Variable(Location), } /// A trait implementation is either a normal implementation that is present in the source @@ -258,6 +269,9 @@ pub struct FunctionModifiers { pub generic_count: usize, pub is_comptime: bool, + + /// The location of the function's name rather than the entire function + pub name_location: Location, } impl FunctionModifiers { @@ -272,6 +286,7 @@ impl FunctionModifiers { is_unconstrained: false, generic_count: 0, is_comptime: false, + name_location: Location::dummy(), } } } @@ -516,6 +531,9 @@ impl Default for NodeInterner { type_alias_ref: Vec::new(), type_ref_locations: Vec::new(), quoted_types: Default::default(), + location_indices: LocationIndices::default(), + reference_graph: petgraph::graph::DiGraph::new(), + reference_graph_indices: HashMap::new(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -804,8 +822,14 @@ impl NodeInterner { is_unconstrained: function.is_unconstrained, generic_count: function.generics.len(), is_comptime: function.is_comptime, + name_location: Location::new(function.name.span(), location.file), }; - self.push_function_definition(id, modifiers, module, location) + let definition_id = self.push_function_definition(id, modifiers, module, location); + + // This needs to be done after pushing the definition since it will reference the + // location that was stored + self.add_definition_location(DependencyId::Function(id)); + definition_id } pub fn push_function_definition( @@ -1194,6 +1218,17 @@ impl NodeInterner { self.trait_implementations[&id].clone() } + /// If the given function belongs to a trait impl, return its trait method id. + /// Otherwise, return None. + pub fn get_trait_method_id(&self, function: FuncId) -> Option { + let impl_id = self.function_meta(&function).trait_impl?; + let trait_impl = self.get_trait_implementation(impl_id); + let trait_impl = trait_impl.borrow(); + + let method_index = trait_impl.methods.iter().position(|id| *id == function)?; + Some(TraitMethodId { trait_id: trait_impl.trait_id, method_index }) + } + /// Given a `ObjectType: TraitId` pair, try to find an existing impl that satisfies the /// constraint. If an impl cannot be found, this will return a vector of each constraint /// in the path to get to the failing constraint. Usually this is just the single failing @@ -1664,13 +1699,13 @@ impl NodeInterner { self.add_dependency(dependent, DependencyId::Alias(dependency)); } - fn add_dependency(&mut self, dependent: DependencyId, dependency: DependencyId) { + pub fn add_dependency(&mut self, dependent: DependencyId, dependency: DependencyId) { let dependent_index = self.get_or_insert_dependency(dependent); let dependency_index = self.get_or_insert_dependency(dependency); self.dependency_graph.update_edge(dependent_index, dependency_index, ()); } - fn get_or_insert_dependency(&mut self, id: DependencyId) -> PetGraphIndex { + pub fn get_or_insert_dependency(&mut self, id: DependencyId) -> PetGraphIndex { if let Some(index) = self.dependency_graph_indices.get(&id) { return *index; } @@ -1721,6 +1756,11 @@ impl NodeInterner { } // Mutually recursive functions are allowed DependencyId::Function(_) => (), + // Local variables should never be in a dependency cycle, scoping rules + // prevents referring to them before they're defined + DependencyId::Variable(loc) => unreachable!( + "Variable used at location {loc:?} caught in a dependency cycle" + ), } } } @@ -1742,6 +1782,9 @@ impl NodeInterner { DependencyId::Global(id) => { Cow::Borrowed(self.get_global(id).ident.0.contents.as_ref()) } + DependencyId::Variable(loc) => { + unreachable!("Variable used at location {loc:?} caught in a dependency cycle") + } }; let mut cycle = index_to_string(scc[start_index]).to_string(); @@ -1762,6 +1805,29 @@ impl NodeInterner { pub fn get_quoted_type(&self, id: QuotedTypeId) -> &Type { &self.quoted_types[id.0] } + + /// Returns the type of an operator (which is always a function), along with its return type. + pub fn get_operator_type( + &self, + lhs: ExprId, + operator: BinaryOpKind, + operator_expr: ExprId, + ) -> (Type, Type) { + let lhs_type = self.id_type(lhs); + let args = vec![lhs_type.clone(), lhs_type]; + + // If this is a comparison operator, the result is a boolean but + // the actual method call returns an Ordering + use crate::ast::BinaryOpKind::*; + let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { + self.ordering_type() + } else { + self.id_type(operator_expr) + }; + + let env = Box::new(Type::Unit); + (Type::Function(args, Box::new(ret.clone()), env), ret) + } } impl Methods { diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 2fb20ae2ba49..b3a39108f246 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -150,6 +150,7 @@ "nouner", "pedersen", "peekable", + "petgraph", "plonkc", "PLONKish", "pprof", @@ -161,6 +162,7 @@ "pseudocode", "pubkey", "quantile", + "rangemap", "repr", "reqwest", "rfind", @@ -185,6 +187,7 @@ "subtyping", "swcurve", "Taiko", + "tarjan", "tecurve", "tempdir", "tempfile", @@ -203,6 +206,7 @@ "urem", "USERPROFILE", "vecmap", + "vitkov", "wasi", "wasmer", "Weierstraß", diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md index f839b4a228ec..f262d8160d60 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -18,7 +18,7 @@ curve you want to use, which would be specified using any one of the methods `std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the defining equation together with a generator point as parameters. You can find more detail in the comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +[`noir_stdlib/src/ec/mod.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr), but the gist of it is that the elliptic curves of interest are usually expressed in one of the standard forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly @@ -67,7 +67,7 @@ does indeed lie on `c` by calling `c.contains(p1)`. the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr)). ## Examples diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index efa52b2c3f20..05a2bb983a15 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -15,7 +15,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; Given an array of bytes, returns the resulting sha256 hash. Specify a message_size to hash only the first `message_size` bytes of the input. -#include_code sha256 noir_stdlib/src/hash.nr rust +#include_code sha256 noir_stdlib/src/hash/mod.nr rust example: #include_code sha256_var test_programs/execution_success/sha256/src/main.nr rust @@ -34,7 +34,7 @@ fn main() { Given an array of bytes, returns an array with the Blake2 hash -#include_code blake2s noir_stdlib/src/hash.nr rust +#include_code blake2s noir_stdlib/src/hash/mod.nr rust example: @@ -51,7 +51,7 @@ fn main() { Given an array of bytes, returns an array with the Blake3 hash -#include_code blake3 noir_stdlib/src/hash.nr rust +#include_code blake3 noir_stdlib/src/hash/mod.nr rust example: @@ -68,7 +68,7 @@ fn main() { Given an array of Fields, returns the Pedersen hash. -#include_code pedersen_hash noir_stdlib/src/hash.nr rust +#include_code pedersen_hash noir_stdlib/src/hash/mod.nr rust example: @@ -80,7 +80,7 @@ example: Given an array of Fields, returns the Pedersen commitment. -#include_code pedersen_commitment noir_stdlib/src/hash.nr rust +#include_code pedersen_commitment noir_stdlib/src/hash/mod.nr rust example: @@ -94,7 +94,7 @@ Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes (`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes of the input. -#include_code keccak256 noir_stdlib/src/hash.nr rust +#include_code keccak256 noir_stdlib/src/hash/mod.nr rust example: diff --git a/noir/noir-repo/noir_stdlib/src/collections.nr b/noir/noir-repo/noir_stdlib/src/collections/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/collections.nr rename to noir/noir-repo/noir_stdlib/src/collections/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ec/consts.nr b/noir/noir-repo/noir_stdlib/src/ec/consts/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ec/consts.nr rename to noir/noir-repo/noir_stdlib/src/ec/consts/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ec.nr b/noir/noir-repo/noir_stdlib/src/ec/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ec.nr rename to noir/noir-repo/noir_stdlib/src/ec/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/field.nr b/noir/noir-repo/noir_stdlib/src/field/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/field.nr rename to noir/noir-repo/noir_stdlib/src/field/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/hash.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/hash.nr rename to noir/noir-repo/noir_stdlib/src/hash/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/hash/poseidon.nr rename to noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/meta.nr b/noir/noir-repo/noir_stdlib/src/meta/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/meta.nr rename to noir/noir-repo/noir_stdlib/src/meta/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ops.nr b/noir/noir-repo/noir_stdlib/src/ops/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ops.nr rename to noir/noir-repo/noir_stdlib/src/ops/mod.nr diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml new file mode 100644 index 000000000000..75df4dc5c20d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_traits" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr new file mode 100644 index 000000000000..143c9cda2744 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr @@ -0,0 +1,15 @@ +fn main() { + comptime + { + // impl Eq for Field + assert(3 == 3); + + // impl Default for [T; N] where T: Default + // impl Default for Field + let array = Default::default(); + + // impl Eq for [T; N] where T: Eq + // impl Eq for Field + assert([1, 2] != array); + } +} diff --git a/noir/noir-repo/tooling/lsp/src/lib.rs b/noir/noir-repo/tooling/lsp/src/lib.rs index 304a2d34e471..92924e701a61 100644 --- a/noir/noir-repo/tooling/lsp/src/lib.rs +++ b/noir/noir-repo/tooling/lsp/src/lib.rs @@ -20,7 +20,10 @@ use async_lsp::{ }; use fm::{codespan_files as files, FileManager}; use fxhash::FxHashSet; -use lsp_types::CodeLens; +use lsp_types::{ + request::{PrepareRenameRequest, Rename}, + CodeLens, +}; use nargo::{ package::{Package, PackageType}, parse_all, @@ -43,8 +46,8 @@ use notifications::{ }; use requests::{ on_code_lens_request, on_formatting, on_goto_declaration_request, on_goto_definition_request, - on_goto_type_definition_request, on_initialize, on_profile_run_request, on_shutdown, - on_test_run_request, on_tests_request, + on_goto_type_definition_request, on_initialize, on_prepare_rename_request, + on_profile_run_request, on_rename_request, on_shutdown, on_test_run_request, on_tests_request, }; use serde_json::Value as JsonValue; use thiserror::Error; @@ -55,6 +58,9 @@ mod requests; mod solver; mod types; +#[cfg(test)] +mod test_utils; + use solver::WrapperSolver; use types::{notification, request, NargoTest, NargoTestId, Position, Range, Url}; @@ -119,6 +125,8 @@ impl NargoLspService { .request::(on_goto_definition_request) .request::(on_goto_declaration_request) .request::(on_goto_type_definition_request) + .request::(on_prepare_rename_request) + .request::(on_rename_request) .notification::(on_initialized) .notification::(on_did_change_configuration) .notification::(on_did_open_text_document) diff --git a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs index 3a92e28cc112..4985c565e06a 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs @@ -76,59 +76,42 @@ fn on_goto_definition_inner( #[cfg(test)] mod goto_definition_tests { + use std::panic; - use acvm::blackbox_solver::StubbedBlackBoxSolver; - use async_lsp::ClientSocket; - use lsp_types::{Position, Url}; + use crate::test_utils; + use lsp_types::{Position, Range}; use tokio::test; use super::*; #[test] async fn test_on_goto_definition() { - let client = ClientSocket::new_closed(); - let mut state = LspState::new(&client, StubbedBlackBoxSolver); - - let root_path = std::env::current_dir() - .unwrap() - .join("../../test_programs/execution_success/7_function") - .canonicalize() - .expect("Could not resolve root path"); - let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) - .expect("Could not convert text document path to URI"); - let root_uri = Some( - Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI"), - ); - - #[allow(deprecated)] - let initialize_params = lsp_types::InitializeParams { - process_id: Default::default(), - root_path: None, - root_uri, - initialization_options: None, - capabilities: Default::default(), - trace: Some(lsp_types::TraceValue::Verbose), - workspace_folders: None, - client_info: None, - locale: None, - }; - let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) - .await - .expect("Could not initialize LSP server"); + let (mut state, noir_text_document) = test_utils::init_lsp_server("go_to_definition").await; let params = GotoDefinitionParams { text_document_position_params: lsp_types::TextDocumentPositionParams { text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, - position: Position { line: 95, character: 5 }, + position: Position { line: 9, character: 12 }, // Right at the beginning of "another_function" }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), }; - let response = on_goto_definition_request(&mut state, params) + let response: GotoDefinitionResponse = on_goto_definition_request(&mut state, params) .await - .expect("Could execute on_goto_definition_request"); - - assert!(&response.is_some()); + .expect("Could execute on_goto_definition_request") + .expect("Didn't get a goto definition response"); + + if let GotoDefinitionResponse::Scalar(location) = response { + assert_eq!( + location.range, + Range { + start: Position { line: 4, character: 3 }, + end: Position { line: 4, character: 19 }, + } + ); + } else { + panic!("Expected a scalar response"); + }; } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index 769e9ba17ce7..545b5fef3d24 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -5,7 +5,7 @@ use async_lsp::{ErrorCode, ResponseError}; use fm::{codespan_files::Error, FileMap, PathString}; use lsp_types::{ DeclarationCapability, Location, Position, TextDocumentSyncCapability, TextDocumentSyncKind, - TypeDefinitionProviderCapability, Url, + TypeDefinitionProviderCapability, Url, WorkDoneProgressOptions, }; use nargo_fmt::Config; use serde::{Deserialize, Serialize}; @@ -29,6 +29,7 @@ mod code_lens_request; mod goto_declaration; mod goto_definition; mod profile_run; +mod rename; mod test_run; mod tests; @@ -36,7 +37,8 @@ pub(crate) use { code_lens_request::collect_lenses_for_package, code_lens_request::on_code_lens_request, goto_declaration::on_goto_declaration_request, goto_definition::on_goto_definition_request, goto_definition::on_goto_type_definition_request, profile_run::on_profile_run_request, - test_run::on_test_run_request, tests::on_tests_request, + rename::on_prepare_rename_request, rename::on_rename_request, test_run::on_test_run_request, + tests::on_tests_request, }; /// LSP client will send initialization request after the server has started. @@ -106,6 +108,12 @@ pub(crate) fn on_initialize( definition_provider: Some(lsp_types::OneOf::Left(true)), declaration_provider: Some(DeclarationCapability::Simple(true)), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), + rename_provider: Some(lsp_types::OneOf::Right(lsp_types::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + })), }, server_info: None, }) diff --git a/noir/noir-repo/tooling/lsp/src/requests/rename.rs b/noir/noir-repo/tooling/lsp/src/requests/rename.rs new file mode 100644 index 000000000000..9f6416a2c63b --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/requests/rename.rs @@ -0,0 +1,249 @@ +use std::{ + collections::HashMap, + future::{self, Future}, +}; + +use async_lsp::{ErrorCode, ResponseError}; +use fm::FileMap; +use lsp_types::{ + PrepareRenameResponse, RenameParams, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit, +}; +use nargo::insert_all_files_for_workspace_into_file_manager; +use noirc_driver::file_manager_with_stdlib; +use noirc_errors::Location; +use noirc_frontend::macros_api::NodeInterner; + +use crate::{parse_diff, resolve_workspace_for_source_path, LspState}; + +use super::{position_to_byte_index, to_lsp_location}; + +pub(crate) fn on_prepare_rename_request( + state: &mut LspState, + params: TextDocumentPositionParams, +) -> impl Future, ResponseError>> { + let result = process_rename_request(state, params, |search_for_location, interner, _| { + let rename_possible = interner.check_rename_possible(search_for_location); + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: rename_possible }) + }); + future::ready(result) +} + +pub(crate) fn on_rename_request( + state: &mut LspState, + params: RenameParams, +) -> impl Future, ResponseError>> { + let result = process_rename_request( + state, + params.text_document_position, + |search_for_location, interner, files| { + let rename_changes = + interner.find_rename_symbols_at(search_for_location).map(|locations| { + let rs = locations.iter().fold( + HashMap::new(), + |mut acc: HashMap>, location| { + let file_id = location.file; + let span = location.span; + + let Some(lsp_location) = to_lsp_location(files, file_id, span) else { + return acc; + }; + + let edit = TextEdit { + range: lsp_location.range, + new_text: params.new_name.clone(), + }; + + acc.entry(lsp_location.uri).or_default().push(edit); + + acc + }, + ); + rs + }); + + let response = WorkspaceEdit { + changes: rename_changes, + document_changes: None, + change_annotations: None, + }; + + Some(response) + }, + ); + future::ready(result) +} + +fn process_rename_request( + state: &mut LspState, + text_document_position_params: TextDocumentPositionParams, + callback: F, +) -> Result +where + F: FnOnce(Location, &NodeInterner, &FileMap) -> T, +{ + let file_path = + text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = workspace.members.first().unwrap(); + + let package_root_path: String = package.root_dir.as_os_str().to_string_lossy().into(); + + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let parsed_files = parse_diff(&workspace_file_manager, state); + + let (mut context, crate_id) = + nargo::prepare_package(&workspace_file_manager, &parsed_files, package); + + let interner; + if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { + interner = def_interner; + } else { + // We ignore the warnings and errors produced by compilation while resolving the definition + let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, false); + interner = &context.def_interner; + } + + let files = context.file_manager.as_file_map(); + let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not find file in file manager. File path: {:?}", file_path), + ))?; + let byte_index = + position_to_byte_index(files, file_id, &text_document_position_params.position).map_err( + |err| { + ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not convert position to byte index. Error: {:?}", err), + ) + }, + )?; + + let search_for_location = noirc_errors::Location { + file: file_id, + span: noirc_errors::Span::single_char(byte_index as u32), + }; + + Ok(callback(search_for_location, interner, files)) +} + +#[cfg(test)] +mod rename_tests { + use super::*; + use crate::test_utils; + use lsp_types::{Position, Range, WorkDoneProgressParams}; + use tokio::test; + + async fn check_rename_succeeds(directory: &str, name: &str, ranges: &[Range]) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + let main_path = noir_text_document.path(); + + // As we process the rename requests we'll check that the request position actually + // includes the target name. + let file_contents = std::fs::read_to_string(main_path) + .unwrap_or_else(|_| panic!("Couldn't read file {}", main_path)); + + let file_lines: Vec<&str> = file_contents.lines().collect(); + + // Test renaming works on any instance of the symbol. + for target_range in ranges { + assert_eq!(target_range.start.line, target_range.end.line); + + // Check that the range includes the target name + let line = file_lines[target_range.start.line as usize]; + let chunk = + &line[target_range.start.character as usize..target_range.end.character as usize]; + assert_eq!(chunk, name); + + let target_position = target_range.start; + + let params = RenameParams { + text_document_position: TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position: target_position, + }, + new_name: "renamed_function".to_string(), + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + }; + + let response = on_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request") + .unwrap(); + + let changes = response.changes.expect("Expected to find rename changes"); + let mut changes: Vec = + changes.values().flatten().map(|edit| edit.range).collect(); + changes.sort_by_key(|range| range.start.line); + assert_eq!(changes, ranges); + } + } + + #[test] + async fn test_on_prepare_rename_request_cannot_be_applied() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("rename").await; + + let params = TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, + position: lsp_types::Position { line: 0, character: 0 }, // This is at the "f" of an "fn" keyword + }; + + let response = on_prepare_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request"); + + assert_eq!( + response, + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: false }) + ); + } + + #[test] + async fn test_on_rename_request() { + const ANOTHER_FUNCTION_REFERENCE: Range = Range { + start: Position { line: 9, character: 12 }, + end: Position { line: 9, character: 28 }, + }; + const ANOTHER_FUNCTION_DECLARATION: Range = Range { + start: Position { line: 4, character: 3 }, + end: Position { line: 4, character: 19 }, + }; + // The ranges of positions which represent the usage of the `another_function` symbol. + const ANOTHER_FUNCTION_RANGES: &[Range] = &[ + ANOTHER_FUNCTION_DECLARATION, + ANOTHER_FUNCTION_REFERENCE, + Range { + start: Position { line: 13, character: 12 }, + end: Position { line: 13, character: 28 }, + }, + Range { + start: Position { line: 19, character: 15 }, + end: Position { line: 19, character: 31 }, + }, + ]; + + check_rename_succeeds("rename", "another_function", ANOTHER_FUNCTION_RANGES).await; + } + + #[test] + async fn test_on_rename_request_works_with_qualified_path() { + const BAR_FUNCTION_REFERENCE: Range = Range { + start: Position { line: 1, character: 9 }, + end: Position { line: 1, character: 12 }, + }; + const BAR_FUNCTION_DECLARATION: Range = Range { + start: Position { line: 5, character: 11 }, + end: Position { line: 5, character: 14 }, + }; + // The ranges of positions which represent the usage of the `bar` symbol. + const BAR_FUNCTION_RANGES: &[Range] = &[BAR_FUNCTION_REFERENCE, BAR_FUNCTION_DECLARATION]; + + check_rename_succeeds("rename_qualified", "bar", BAR_FUNCTION_RANGES).await; + } +} diff --git a/noir/noir-repo/tooling/lsp/src/test_utils.rs b/noir/noir-repo/tooling/lsp/src/test_utils.rs new file mode 100644 index 000000000000..dcaec2fd615a --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/test_utils.rs @@ -0,0 +1,39 @@ +use crate::LspState; +use acvm::blackbox_solver::StubbedBlackBoxSolver; +use async_lsp::ClientSocket; +use lsp_types::Url; + +pub(crate) async fn init_lsp_server(directory: &str) -> (LspState, Url) { + let client = ClientSocket::new_closed(); + let mut state = LspState::new(&client, StubbedBlackBoxSolver); + + let root_path = std::env::current_dir() + .unwrap() + .join("test_programs") + .join(directory) + .canonicalize() + .expect("Could not resolve root path"); + let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) + .expect("Could not convert text document path to URI"); + let root_uri = + Some(Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI")); + + #[allow(deprecated)] + let initialize_params = lsp_types::InitializeParams { + process_id: Default::default(), + root_path: None, + root_uri, + initialization_options: None, + capabilities: Default::default(), + trace: Some(lsp_types::TraceValue::Verbose), + workspace_folders: None, + client_info: None, + locale: None, + }; + + let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) + .await + .expect("Could not initialize LSP server"); + + (state, noir_text_document) +} diff --git a/noir/noir-repo/tooling/lsp/src/types.rs b/noir/noir-repo/tooling/lsp/src/types.rs index e3492f21346d..7239b1db6857 100644 --- a/noir/noir-repo/tooling/lsp/src/types.rs +++ b/noir/noir-repo/tooling/lsp/src/types.rs @@ -1,6 +1,7 @@ use fm::FileId; use lsp_types::{ - DeclarationCapability, DefinitionOptions, OneOf, TypeDefinitionProviderCapability, + DeclarationCapability, DefinitionOptions, OneOf, RenameOptions, + TypeDefinitionProviderCapability, }; use noirc_driver::DebugFile; use noirc_errors::{debug_info::OpCodesCount, Location}; @@ -135,6 +136,10 @@ pub(crate) struct ServerCapabilities { /// The server handles and provides custom nargo messages. #[serde(skip_serializing_if = "Option::is_none")] pub(crate) nargo: Option, + + /// The server provides rename support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) rename_provider: Option>, } #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] diff --git a/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml new file mode 100644 index 000000000000..c894a050c407 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "go_to_definition" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr new file mode 100644 index 000000000000..c27f8fed868f --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr @@ -0,0 +1,11 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); +} diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml new file mode 100644 index 000000000000..2d5b6415dc92 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr new file mode 100644 index 000000000000..4c28249582e0 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr @@ -0,0 +1,22 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); + + let _ = 1; + + let _ = another_function(); +} + + +mod foo { + fn yet_another_function() -> Field { + crate::another_function() + } +} \ No newline at end of file diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml new file mode 100644 index 000000000000..7de13ef6b349 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_qualified" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr new file mode 100644 index 000000000000..f1b777962109 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr @@ -0,0 +1,9 @@ +fn main() -> pub Field { + foo::bar() +} + +mod foo { + pub fn bar() -> Field { + 1 + } +} diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index a6873910524d..0fbdaaba0b4e 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -61,12 +61,13 @@ const IGNORED_BRILLIG_TESTS: [&str; 11] = [ /// Certain features are only available in the elaborator. /// We skip these tests for non-elaborator code since they are not /// expected to work there. This can be removed once the old code is removed. -const IGNORED_NEW_FEATURE_TESTS: [&str; 5] = [ +const IGNORED_NEW_FEATURE_TESTS: [&str; 6] = [ "macros", "wildcard_type", "type_definition_annotation", "numeric_generics_explicit", "derive_impl", + "comptime_traits", ]; fn read_test_cases( diff --git a/noir/scripts/sync-in-fixup.sh b/noir/scripts/sync-in-fixup.sh index fce52060fa7e..6820e62a8006 100755 --- a/noir/scripts/sync-in-fixup.sh +++ b/noir/scripts/sync-in-fixup.sh @@ -18,4 +18,5 @@ sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./tooling/noirc_ sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./acvm-repo/acvm_js/build.sh # Replace `verify_honk_proof` test -cp -r ../verify_honk_proof ./test_programs/execution_success/verify_honk_proof +cp -r ../verify_honk_proof ./test_programs/execution_success/ +git add ./test_programs/execution_success/verify_honk_proof diff --git a/noir/verify_honk_proof/Prover.toml b/noir/verify_honk_proof/Prover.toml index af4e99197a5b..921b69e100ac 100644 --- a/noir/verify_honk_proof/Prover.toml +++ b/noir/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"]" +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"] diff --git a/yarn-project/accounts/src/artifacts/EcdsaAccount.json b/yarn-project/accounts/src/artifacts/EcdsaAccount.json deleted file mode 100644 index a1a1f0d2a1a6..000000000000 --- a/yarn-project/accounts/src/artifacts/EcdsaAccount.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"EcdsaAccount","functions":[{"name":"constructor","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(initializer)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"signing_pub_key_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"},{"name":"signing_pub_key_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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CxAmm0BuswCh0AlBJ+x0QqUTGp3Q6QRumwUIg07gtlngEAS3zQKEQicEncBtswCh0gmNTuh0wkEnDDqB/uaE3WYxj4Q2ixNi3GYBe98btmHve8M27H1v2IZ9tbb3vWEb9r43bMPe94Zt2PvesA173zaL0964zQL21rPWuM0C9taz1rjNAvbWs9a4zQL21rPWuM0C9lJtFqeQVpsFhHxv2Ia97w3bsPe9YRv21dre94Zt2PvesA173xu2Ye97wzbsfW/YPu2N2yxgbz1rjdssYG89a43bLGBvPWuN2yxgbz1rjdssYG89a7XaLCAk1WYBIak2CwhJtVlASGVuXUJSbRYQkmqzgJBUmwWEpNosICTVZnEKabVZQCh52X933T+UxNosoCR2gR6Oa4m1WUBJrM0CSmJtFlASa7OAklibBZTE2iygJNZmcSqptVlASazNAkpibRZQEmuzgFLVUxJrs4CSWJsFlMTaLKAk1mYBJbE2i1NJrc0CSmJtFlASa7OAklibBZSqnpJYmwWUxNosoCTWZgElsTYLKIm1Wawok1ibxXISa7NYTmJtFstJ7Lb45STWZrGcxNoslpPeyzi5NovlJNZmsZzE2iyWUxV00tqfjq3y88GA+OaDl71tZmnZ22aWlr1tZmnZV2t728zSsrfNLC1728zSsrfNLC1723ww7H3zwcveetb65oOXvfWs9c0HL3vrWeubD1721rPWNx+87JXywRCSygcvIdvM0rK3zSwte9vM0rKv1va2maVlb5tZWva2maVlb5tZWva2mSXY++aDl731rPXNBy9761nrmw9e9taz1jcfvOytZ61vPnjZW89aqXzwElLKBy8hpXzwElLKBy8hlbl1CSnlg5eQUj54CSnlg5eQUj54CSnlgyEklQ9eQsnL/psA5VLSygcvJa0jieu4llY+eClp5YOXklY+eClp5YOXklY+eClp5YOXklY+GEpi+eClpJUPXkpa+eClpJUPXkpVT0krH7yUtPLBS0krH7yUtPLBS0krHwwlsXzwUtLKBy8lrXzwUtLKBy+lqqeklQ9eSlr54KWklQ9eSlr54KWklQ/+ijJp5YO/nLTywV9OWvngLye9/J1aPvjLSSsf/OWk9zJOLR/85aSVD/5y0soHfzlVQSex/anEf97tca7bQ6fGNzbj2sDnVn99abzw6fgpPlzFp6t42WzN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KHQCt80ChE4ncO9kPAnkNgsQ6N8lcpsFCINOmGwCuc0ChEInBJ2w0wmVTmh0QqcTuG0WIAw6gdtmgY+zuG0WIBQ6IegEbpsFCJVOaHRCpxMOOoHbZgHCZBPIbRYgFDoh6ISdTqh0QqMTOp3AbbMAYdAJ3DYLHILgtlmAUOiEoBO4bRYgVDqh0QmdTjjohEEn0N+csNss9khoszghxm0WsPe9YRv2vjdsw973hm3YV2t73xu2Ye97wzbsfW/Yhr3vDduw922zOO2N2yxgbz1rjdssYG89a43bLGBvPWuN2yxgbz1rjdssYC/VZnEKabVZQMj3hm3Y+96wDXvfG7ZhX63tfW/Yhr3vDduw971hG/a+N2zD3veG7dPeuM0C9taz1rjNAvbWs9a4zQL21rPWuM0C9taz1rjNAvbWs1arzQJCUm0WEJJqs4CQVJsFhFTm1iUk1WYBIak2CwhJtVlASKrNAkJSbRankFabBYSSl/131/1DSazNAkpiF+jhuJZYmwWUxNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFqeSWpsFlMTaLKAk1mYBJbE2CyhVPSWxNgsoibVZQEmszQJKYm0WUBJrsziV1NosoCTWZgElsTYLKIm1WUCp6imJtVlASazNAkpibRZQEmuzgJJYm8WKMom1WSwnsTaL5STWZrGcxG6LX05ibRbLSazNYjnpvYyTa7NYTmJtFstJrM1iOVVBJ7X9aWbkg6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pniq5YOnWj54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6daPniq5YOnWj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnXD64Pz3af5QH5Dh+fTZdov167njxufHi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EzqdMOiEk07gtlmAsNgEcpsFCIVOCDqh0gmNTuh0wqATuG0WIEw6gdtmgUMQ3DYLEAqdEHQCt80ChEYndDph0AknnTDpBPqbE3abxSgJbRYPiHGbBex9b9iGve8N27D3vWEb9s3a3veGbdj73rANe98btmHve8M27H3bLB72xm0WsLeetcZtFrC3nrXGbRawt561xm0WsLeetcZtFrCXarN4CGm1WUDI94Zt2PvesA173xu2Yd+s7X1v2Ia97w3bsPe9YRv2vjdsw973hu2HvXGbBeytZ61xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXsrWetVpsFhKTaLCAk1WYBIak2CwipzK1LSKrNAkJSbRYQkmqzgJBUmwWEpNosHkJabRYQSl72X133DyWxNgsoiV2gh+NaYm0WUBJrs4CSWJsFlMTaLKAk1mYBJbE2CyiJtVk8lNTaLKAk1mYBJbE2CyiJtVlAqekpibVZQEmszQJKYm0WUBJrs4CSWJvFQ0mtzQJKYm0WUBJrs4CSWJsFlJqeklibBZTE2iygJNZmASWxNgsoibVZ7CiTWJvFdhJrs9hOYm0W20nstvjtJNZmsZ3E2iy2k97LOLk2i+0k1maxncTaLLZTE3RS259mRj54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp1o+eKrlg6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pniq5YOnWj54quWDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dgPngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eOrlg8/xn3d7nNvx1Gnxhc28NvB1tJ9fGt/4dPwhPl3Fl6t4OWzNi6152JpXW/Nma95tzYetue0ELbYjtNjO0LCdoWE7Q8N2hobtDA3bGRq2MzRoM/QinHTC2zOpP0/qtN5uCYtNqAedUOiEoBPe3tvmc/G0WW8JjU7odMKgE95d0/04//nSfsxbwqQTFpvQDjqh0Anv/rb2eH5pj3vCoBPe/UmP+jzqNnrcEfpBJ9C/S/3tNd2u36V+3hImnbDYhHHQCYVOCDqh0gmNTuh0wqATPrimx7glTDrh/TV97XznLeF8e01fu/crQqETgk54d02PKw8xjnVLaHRCpxMGnXDSCW+v6fW8/HmU45aw2IR50AmFTgg6odIJjU7odMKgE84PEm7X9Jx0wvtr+nmiZcQtYb29pq/Xoa8IhU4IOuHtOf3V/0VXoxM6nTDohJNOmHQC/c3Ji6PTH0PMkdBmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzOHcZjGHc5vFHM5tFnM4t1nM4dxmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzCHWZjGHWJvFHM5tFnM4t1nM4dxmMYdzm8Uczm0Wczi3Wczh3GYxh3ObxRzObRZzOLdZzOHcZgF761lr3GYBe+tZa9xmMYdzmwXsrWetcZvFHM5tFnOItVlASKrNAkJSbRYQkmqzgJDK3LqEpNos5hBrs5hDrM1iDrE2iznE2izmEGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos55Nos5pBrs5hDrs1iDrk2iznk2izmkGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos55Nos5pBrs5hDrs1iDrk2iznk2izmkGuzmEOuzWIOuTaLOeTaLOaQa7OYQ67NYg65Nos59NostpNYm8V2Emuz2E5it8VvJ7E2i+0k1maxnfRexsm1WWwnsTaL7STWZrGdmqCT2P60qmmbxUPc8yruh7jnTdwPcdM2C5h73sQNc8+buGHueRM3zJutuedN3DD3bLOAue0ENW2zgLntDDVts4C57Qw1bbOAue0MNW2zgLntDCW3WYBw0gncNgsQFptAbrMAodAJQSdw2yxAaHRCpxMGncBtswBh0gmLTSC3WYBQ6ARumwUIg07g3sn4IJDbLECgf5fIbRYgTDphsQnkNgsQCp0QdEKlExqd0OmEQSdw2yxAmHQCt80CH2dx2yxAKHRC0AncNgsQGp3Q6YRBJ5x0ArfNAoTFJpDbLEAodELQCZVOaHRCpxMGncBtswBh0gncNgscguC2WYBQ6ISgE7htFiA0OqHTCYNOOOmESSfQ35yQ2yzmEfw2C0B82yy2ve0N29ve9obtbW97w/a2b9b2tjdsb3vbG7a3ve0N29ve9obtbW/bZgF73zaLbW89a33bLLa99az1bbPY9taz1rfNYttbz1rfNottr9RmASGpNostZHvD9ra3vWF729vesL3tm7W97Q3b2972hu1tb3vD9ra3vWF729vesA173zaLbW89a33bLLa99az1bbPY9taz1rfNYttbz1rfNottbz1rpdostpBSm8UWUmqz2EJKbRZbSGVuXUJKbRZbSKnNYgsptVlsIaU2iy2k1GYBIak2iy2UvOy/uO5/K2m1WWwlrQv09nEtrTaLraTVZrGVtNostpJWm8VW0mqz2EpabRZbSavNAkpibRZbSavNYitptVlsJa02i63U9JS02iy2klabxVbSarPYSlptFltJq80CSmJtFltJq81iK2m1WWwlrTaLrdT0lLTaLLaSVpvFVtJqs9hKWm0WW0mrzeJHlEmrzeKHk1abxQ8nrTaLH05at8X/cNJqs/jhpNVm8cNJ72WcWpvFDyetNosfTlptFj+cmqCT2v60MvLByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvNTywUstH7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88HLOh+8rPPByzofvKzzwcs6H7ys88FLLR+81PLBSy0fvNTywUstH7zU8sFLLR+81PLBSy0fvNTywUstH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7z08sFLLx+89PLBSy8fvPTywUsvH7wE88FLMB+8BPPBSzAfvATzwUswH7wE88FLMB+8BPPBSzAfvATzwUstHzzKy6P9Z3lCzvPnZ9Ml+s/nzm8+N7/53Prec/fnvf/gufLN5+Kbz90uoXn9vTLjxXPtm8/1bz43vvnc+c3n5jefW9977v6A45zP9/9zxf1z5ZvPxTefq998rn3zuf7N58Y3n7v9ffnlg89y3D83v/nc+t5z94d0/uC58s3n4pvP1W8+d/v7suK5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G/bN2t73hm3Y+96wDXvfG7Zh73vDNux9b9h+2Bu3WcDeetYat1nA3nrWGrdZwN561hq3WcDeetYat1nA3nrWarVZQEiqzQJCUm0WEJJqs4CQyty6hKTaLCAk1WYBIak2CwhJtVlASKrN4iGk1WYBoeRl/9V1/1ASa7OAktgFejiuJdZmASWxNgsoibVZQEmszQJKYm0WUBJrs4CSWJvFQ0mtzQJKYm0WUBJrs4CSWJsFlJqeklibBZTE2iygJNZmASWxNgsoibVZPJTU2iygJNZmASWxNgsoibVZQKnpKYm1WUBJrM0CSmJtFlASa7OAklibxY4yibVZbCexNovtJNZmsZ3EbovfTmJtFttJrM1iO+m9jJNrs9hOYm0W20mszWI7NUEntf1pZuSDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eKrlg6daPnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OndT54WueDp3U+eFrng6d1Pnha54OnWj54quWDp1o+eKrlg6daPniq5YOnWj54quWDp1o+eKrlg6daPnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePnjq5YOnXj546uWDp14+eOrlg6dePngK5oOnYD54CuaDp2A+eArmg6dgPngK5oOnYD54CuaDp2A+eArmg6dePriN/7zb49yOp06LL2zmtYGvo/380vjGp+MP8ekqvlzFy2FrXmzNw9a82po3W/Nuaz5szW0naLEdocV2hobtDA3bGRq2MzRsZ2jYztCwnaFBm6EX4aQT3p5J/XlSp/V2S1hsQj3ohEInBJ3w9t42n4unzXpLaHRCpxMGnfDumu7H+c+X9mPeEiadsNiEdtAJhU5497e1x/NLe9wTBp3w7k961OdRt9HjjtAPOoH+Xepvr+l2/S7185Yw6YTFJoyDTih0QtAJlU5odEKnEwad8ME1PcYtYdIJ76/pa+c7bwnn22v62r1fEQqdEHTCu2t6XHmIcaxbQqMTOp0w6ISTTnh7Ta/n5c+jHLeExSbMg04odELQCZVOaHRCpxMGnXB+kHC7puekE95f088TLSNuCevtNX29Dn1FKHRC0Alvz+mv/i+6Gp3Q6YRBJ5x0wqQT6G9OXhyd/hiij4Q2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog/nNos+nNss+nBus+jDuc2iD+c2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog+xNos+xNos+nBus+jDuc2iD+c2iz6c2yz6cG6z6MO5zaIP5zaLPpzbLPpwbrPow7nNog/nNgvYW89a4zYL2FvPWuM2iz6c2yxgbz1rjdss+nBus+hDrM0CQlJtFhCSarOAkFSbBYRU5tYlJNVm0YdYm0UfYm0WfYi1WfQh1mbRh1ibRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0Iddm0Ydcm0Ufcm0Wfci1WfQh12bRh1ybRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0Iddm0Ydcm0Ufcm0Wfci1WfQh12bRh1ybRR9ybRZ9yLVZ9CHXZtGHXJtFH3JtFn3ItVn0oddmsZ3E2iy2k1ibxXYSuy1+O4m1WWwnsTaL7aT3Mk6uzWI7ibVZbCexNovt1ASdxPanUU3bLB7inldxP8Q9b+J+iJu2WcDc8yZumHvexA1zz5u4Yd5szT1v4oa5Z5sFzG0nqGmbBcxtZ6hpmwXMbWeoaZsFzG1nqGmbBcxtZyi5zQKEk07gtlmAsNgEcpsFCIVOCDqB22YBQqMTOp0w6ARumwUIk05YbAK5zQKEQidw2yxAGHQC907GB4HcZgEC/btEbrMAYdIJi00gt1mAUOiEoBMqndDohE4nDDqB22YBwqQTuG0W+DiL22YBQqETgk7gtlmA0OiETicMOuGkE7htFiAsNoHcZgFCoROCTqh0QqMTOp0w6ARumwUIk07gtlngEAS3zQKEQicEncBtswCh0QmdThh0wkknTDqB/uaE3WZxRkKbxQNi3GYBe98btmHve8M27H1v2IZ9s7b3vWEb9r43bMPe94Zt2PvesA173zaLh71xmwXsrWetcZsF7K1nrXGbBeytZ61xmwXsrWetcZsF7KXaLB5CWm0WEPK9YRv2vjdsw973hm3YN2t73xu2Ye97wzbsfW/Yhr3vDduw971h+2Fv3GYBe+tZa9xmAXvrWWvcZgF761lr3GYBe+tZa9xmAXvrWavVZgEhqTYLCEm1WUBIqs0CQipz6xKSarOAkFSbBYSk2iwgJNVmASGpNouHkFabBYSSl/1X1/1DSazNAkpiF+jhuJZYmwWUxNosoCTWZgElsTYLKIm1WUBJrM0CSmJtFg8ltTYLKIm1WUBJrM0CSmJtFlBqekpibRZQEmuzgJJYmwWUxNosoCTWZvFQUmuzgJJYmwWUxNosoCTWZgGlpqck1mYBJbE2CyiJtVlASazNAkpibRY7yiTWZrGdxNostpNYm8V2ErstfjuJtVlsJ7E2i+2k9zJOrs1iO4m1WWwnsTaL7dQEndT2p5WRD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eCllg9eavngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXtb54GWdD17W+eBlnQ9e1vngZZ0PXmr54KWWD15q+eCllg9eavngpZYPXmr54KWWD15q+eCllg9eavngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngpZcPXnr54KWXD156+eCllw9eevngJZgPXoL54CWYD16C+eAlmA9egvngJZgPXoL54CWYD16C+eAlmA9ecvng/vJo/1mekPP8+dl0if7zufObz81vPre+99z9ee8/eK5887n45nO3S2hef6/MePFc++Zz/ZvPjW8+d37zufnN59b3nrs/4Djn8/3/XHH/XPnmc/HN5+o3n2vffK5/87nxzeduf19++eCzHPfPzW8+t7733P0hnT94rnzzufjmc/Wbz93+vqx4rqNV79fR/TmPP3hufPO585vPzW8+t7733P1RgT94rnzxXLv/+Y345nP1m8/d/77053pf43693x8P+IPnxjefO7/53Pzmc+t7z53HN5+7/32Zx/WquM//efD//ZsvviiRQqkplJZC6SmUkUI5UygzhbIyKPef7H+ckrL2Z8ranylrf6as/Zmy9mfK2p8pa3+mrP2ZsvZXytpfKWt/paz9lbL2V8raXylrf6Ws/ZWy9lfK2l8pa//Fp4qfx5QcTORgag6m5WB6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1WaxlbTaLLaSVpvFVmp6SlptFltJq81iK2m1WWwlrTaLraTVZgElsTaLraTVZrGVtNostpJWm8VWanpKWm0WW0mrzWIrabVZbCWtNoutpNVm8SPKpNVm8cNJq83ih5NWm8UPJ63b4n84abVZ/HDSarP44aT3Mk6tzeKHk1abxQ8nrTaLH05N0Eltf5oZ+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+eavngqZYPntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54GmdD57W+eBpnQ+e1vngaZ0Pntb54KmWD55q+eCplg+eavngqZYPnmr54KmWD55q+eCplg+eavngqZYPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnnr54KmXD556+eCplw+eevngqZcPnoL54CmYD56C+eApmA+egvngKZgPnoL54CmYD56C+eApmA+egvngqZcPLuM/7/Y4t+Op0+ILm3lt4OtoP780vvHp+EN8uoovV/Fy2JoXW/OwNa+25s3WvNuaD1tz2wlabEdosZ2hYTtDw3aGhu0MDdsZGrYzNGxnaNBm6EU46YS3Z1J/ntRpvd0SFptQDzqh0AlBJ7y9t83n4mmz3hIandDphEEnvLum+3H+86X9mLeESScsNqEddEKhE979be3x/NIe94RBJ7z7kx71edRt9Lgj9INOoH+X+ttrul2/S/28JUw6YbEJ46ATCp0QdEKlExqd0OmEQSd8cE2PcUuYdML7a/ra+c5bwvn2mr5271eEQicEnfDumh5XHmIc65bQ6IROJww64aQT3l7T63n58yjHLWGxCfOgEwqdEHRCpRMandDphEEnnB8k3K7pOemE99f080TLiFvCentNX69DXxEKnRB0wttz+qv/i65GJ3Q6YdAJJ50w6QT6m5MXR6c/hoiR0GYRw7nNIoZzm0UM5zaLGM5tFjGc2yxiOLdZxHBus4jh3GYRw7nNIoZzm0UM5zaLGM5tFjGc2yxiOLdZxHBus4jh3GYRw7nNIoZzm0UM5zaLGGJtFjHE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YuvfCCcndGLr3wgntv6NcGLr3wgntv6NcGLr37g50fVvhBNb/0Y4sfVvhBNb/0Y4OaETW/9GOLH1b4QTW/9GOLH1b4QTW//Gzkax9W9sKbb+jS3F1r+xpdjutd9SbP0bW4qtf2NLEX5cx9e/saXY+je2FFv/xpZyRim6ObVS0sdLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO3286NLHiy59vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx4sufbzo0seLLn286NLHiy59vOjSx4sufbzo0seLLn286NLHiy59vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vBjTx4sxfbwY08eLMX28GNPHizF9vBjTx4sxfbwY08eLMX28GNPHizB97OVF+rj5uD/Y+vh7yjfPnt+EJpvQYhN6EeX+k0aFzsjojCqdkdMZNTqjTmdEN7EL3cgudDPb6Ga20c1so5vZRjezjW5mG93MNuDMfkJGBuT6ZP3mQdYwWmxG9aAzKnRGRmdU6YyczqjRGXU6o0FnRDezK93MdrqZ7XQz2+lmttPNbKeb2U43s51uZjtwZj8hMwOyEiDtyICUDIhlQGoGxDMgLQPSMyAZb3y//iP8NgwQGMvBXP/D/8mv//pK+a8ZRw4m50dg+Bcwb47kB6blYHoOZuRgZg7mG+/Nm9O88cvwIwdTcjCWg6k5GM/BtBxMz8GMHMzMwXxhCrw7nxonUI4cTMnBWA6m5mA8B9NyMD0HM3IwX5gC784fB2alYF6dUv8+p6b806McnsRpSZyexFk5nC+cM/wZpyRxLImT8f7U85O74/HcGG8+qvXjfpLY7c1B4vmYGuvwf//2me4nHwDX8yO+EuZL1vz8ZdZQL7rqpqteddVdV73pqndddd1dWnSXadHdpqa7TU13m5ruNjXdbWq629R0t6nBtukTMfCIy9up3X8b683PEQuOqAceUfAIwyMuT7l5f4l81nOE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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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WLN9ijXbp1izfYY122dYs32GNdtnWLN9tkBVZcOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtM6zZPsOa7TOs2T7Dmu0zrNk+w5rtc6zZPsea7XOs2T7Hmu3zBaoqO9Zsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51myfY832OdZsn2PN9jnWbJ9jzfY51mxfxZrtq1izfRVrtq9izfbVBaoqV6zZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYs32VazZvoo121exZvsq1mxfxZrtq1izfRVrtq9izfZVrNm+ijXbV7Fm+yrWbF/Fmu2rWLN9FWu2r2LN9lWs2b6KNdtXsWb7KtZsX8Wa7atYs30Va7avYc32NazZvoY129ewZvvaAlWVG9ZsX8Oa7WtYs30Na7avYc32NazZvoY129ewZvsa1mxfw5rta1izfQ1rtq9hzfY1rNm+hjXb17Bm+xrWbF/Dmu1rWLN9DWu2r2HN9jWs2b6GNdvXsGb7GtZsX8Oa7WtYs30Na7avYc32NazZvoY129ewZvsa1mxfw5rta1izfQ1rtq9hzfY1rNm+hjXb17Bm+xrWbF/Dmu1rWLN9DWu2r2HN9rXBs33l/sFlEdn54FZvH5yWdP/k/OyTU2k3oUnKl4v/qTMF0ZmD6CxBdEoQnRpEpwXR6UF01iA6WwydFsQPWRA/ZEH8kAXxQ4Mnlz+nM4gfsiB+yIL4IQvihyyIH/IgfsiD+CEP4oc8iB8azAz4nM4gfsiD+CEP4oc8iB/yIH6oBvFDNYgfqkH8UA3ihwbTOj6nM4gfqkH8UA3ih2oQP1SD+KEWxA+1IH6oBfFDLYgfGszJ+ZzOIH6oBfFDLYgfakH8UBvth7ZoSirpywev4aRlMOWoJFtu8WQtT+IZ7C+y3+Npy5N4OviAluQWj+7EkzzfPji5+v3iZ5+bLOntYiv34HNNf4IvzMELc/A6NviatumGpe4En6VIvl0tam27vN2iN+TotaUteitfon/yD1zKTWsR1+3iVPzJ1d78z8V1uX9wqvVPXnzm5Wle6szL07y0mZdneekB8bpkXtLMy9O85JmXp3kpMy9P8yIzL0/zAu1KP5iXC/ld9dvKpFhqe3nxLS+PzzVseRbIUreoU75/ck7LLzJ+ISdNkvELeXSSjF/I/XNkPF9oXUGS8QutWEgyfqG1EEnGL7TKIsm4zIwPzviFVoYkGZ9rzgMZX1+0bRmv+UvG/87iXEf2yOJcG/bI4lzvdchimWu4Hlmc67IeWZxrrR5ZnOunHlmUmcUOWZzrnB5ZnGuXA1lc14i3OPLjRuAti3Pt0iOLc+3SI4tz7dIhizLXLj2yONcuPbI41y49sjjXLj2yKDOLHbI41y49sjjXLkeyaFs68vrG6nsW59qlRxbn2qVHFufapUMWda5demRxrl16ZHGuXXpkca5demRRZhY7ZHGuXXpkEXrtYtK2LFZb3mcxm28kkFX2kh8v/1ss9BKjt1jolUBvsdCGvbNYg/bVPxRb84PYJ+AQg7a/vcVCu9TeYqHNZG+xEkkstDXrLfZKDmpX7JUcVN0YfNnaM7FXclC7Yq/koPbE+qUc1J7YSzmoPbGXclB7Yi/loPbEyoXEtnp7hpN9yfW72Cs5qF2xV3JQu2Iv5KA8adnE5py+i72Qg/Jctsu9PFCAN7EXclC7YuuFHNS+2As5qH2xF3JQ3tK9Grcm38VeyEHti5XriK1L2VpPfSQnbGIv5KD2xV7IQe2LhXZQtW1hSMv2PXpoS7QbPbTHaX5/6d5qfv9Dq+32zr3l+28y2bNX7imXDc6f2+NrdHkmUPN2WoRWvV9d2t9ZbNDm6UdZbOUeRtvJYl30FkdNRR6ymH+VRWhX9qMsers9dv/rnIcvafxb6lhPtv6s72Xg4R/H84Mrqtv2j2OtH9+LRivU0Qt19EodvVFH79TRV+roG3H0aVmoo0/U0TP32rQw99q0MPfatDD32rQw99q0MPfatDD32rRQ99pE3WsTda9N1L02UffawSca9Y6eutcm6l6bqHttou61ibrXZupem6l7babutZm61w4+faJ39NS9NlP32kzdazN1r83UvbZQ99pC3WsLda8t1L12MNW8d/TUvbZQ99pC3WsLda8t1L1WqHutUPdaoe61Qt1rB1N4e0dP3WuFutcKda8V6l4r1L1WqXutUvdape61St1rB1Mje0dP3WuVutcqda9V6l6r1L3WqHutUfdao+61Rt1rB9P6ekdP3WuNutcada816l5r1L3WqXutU/dap+61Tt1rB3PdekdP3Wudutc6da916l7r1L22UvfaSt1rK3WvrdS9djABrHf01L22UvfaSt1rK3WvrdS9tlH32kbda6m5UYmaG5WouVGJmhuVqLlRiZoblai5UYmaG5WpuVGZmhuVqblRmZoblRfmXpupuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZoblam5UZmaG5WpuVGZmhuVqblRmZob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Y8vZGVvOzthydsaWszO2nJ2x5eyMLWdnbDk7Y8vZGVvOzthydsaWszO2nJ2x5eyMLWdnbDk7Y8vZGVuVnbFV2RlblZ2xVdkZW3Uh78SVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsVXZGVuVnbFV2RlblZ2xVdkZW5WdsdXYGVuNnbHV2BlbjZ2x1RbyTtzYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW42dsdXYGVuNnbHV2BlbjZ2x1dgZW2uk5K34r0jpFZA34zVS8m68RkrejtdIyfvxGil5Q14jJe/Ia6TkLXmNlL4ns+O2VgX0PZkduLUqoO/J7MitVQF9T2aHbq0K6HsyO3ZrVUDfk9nBW6sC+p7Mjt5aFdD3ZHb41qqAviez47dWBfQ9mR3AtSqg78nsCK5VAX1PZodwrQroezI7hmtVQN+T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A77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Tv8Trhe7xO+B6vE77H63ygv5NP+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8brge7wu+B6vC77H64Lv8boe6O/kC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wMvsfL4Hu8DL7Hy+B7vOyB/k42+B4vg+/x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nit4V/4KxXSeK3iv/QrFdJ4reAf9CsV0nouuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQN7oe+kbXQ9/oeugbXQ99exidYjbP1eh66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dB3uh76TtdD3+l66DtdD31/GJ1iNs/V6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+Z+ooH+18fXH7+3d+05vobTylN9FzevT++uLRPulN9JSe0pvoGT2lN9ETekpvokw8ozdTY/WU3kzv3xm9md6/M3oTZeEpvUaml8xfZWqpntIL66/eNMB6pjcNsX3Q1b7+Kdl4uCTz4D3SKxTH9kIrFMd2QysUx/ZDKxQbneLYnmiF4tiuaIXi2L5oheLYLmqFYjrPFbxHeoViOs8VvEd6hWI6zxW8R3qFYjrPFbxHeoViOs8VvEd6hWI2zzWC90ivUMzmuUbwHukVitk813gYnWI2zzWC90ivUMzmuUbwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxX8B7pFYrpPFfwHukViuk8V/Ae6RWK6TxXpfNcwbvCVyim81yVznNVo1NM57mCt8KvUEznuYI3w69QTOe5grfDr1BM57mCN8SvUEznuYK3xK9QTOe5gjfFr1BM57mCN8uvUEznueh66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH2w99NeDrYf+qZjMcz0Vk3mup2Iyz/VUbHSKyTzXUzGZ53oqJvNcT8VknuupmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGb5zroeugPuh76g66H/qDroX/qoVPM5rkOuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/oeugPuh76g66H/qDroT/o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MOsu9rfEHLAPs+6Qf0vMAfuwgH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCffg7op58D+unngH76OaCf/hnQT/8M6Kd/BvTTPwP66Z9HCRhzvD7sDOinfwb00z8D+umfAf30z4B++mdAP/0zoJ/+GdBP/wzop38G9NM/A/rpnwH99M+AfvpnQD/9M6Cf/mnJT//tqQx1Sm9PZaiXeXuqYvKpDPUDb09l6MR+eypDZ+rbUxk69d6eytC59PVUlhzA357KZG235KL99lQma7slJ+q3pzJZ2y25Ob89lcnabskR+e2pTNZ2S67Cb09lsrZbcuZ9eyqTtd2Su+3bU5ms7ZYcYt+eymRtt+Sy+vZUJmu7JafSt6cyWdstuX2+PZXJ2m7JMfPtqW6u7W/f1LZ9U9/2TWPbN81d33S3Q+DbN6Vt35S3fdO57ZvKtm/aViPathrRttWItq1GtG01om+rEX1bjejbakTfViP6thrRt9WIvq1G9G01om+rEX1bjRjbasTYViPGthoxttWIsa1GjG01YmyrEWNbjRjbasTYViPmthoxt9WIua1GzG01Ym6rEXNbjZjbasTcViPmthoxd9WIIvJGau7l9U1j/vVNv7wlV0TeGr3jubLR5zqNPlcx+lzV6HM1o8/VjT7XMPpc0+ZzJaP1Phmt98lovU9G630yWu+T0XqfjNb7ZLTeJ6P1Phmt99lovc9G6302Wu+z0Xqfjdb7bLTeZ6P1Phut99lovc9G6/1ptN6fRuv9abTen0br/Wm03p9G6/1ptN6fRuv9abTen0brfTFa74vRel+M1vtitN4Xo/W+GK33xWi9L0brfTFa74vRel+N1vtqtN5Xo/W+Gq331Wi9r0brfTVa76vRel+N1vtqtN43o/W+Ga33zWi9b0brfTNa75vRet+M1vtmtN43o/W+Ga333Wi970brfTda77vRet+N1vtutN53o/W+G6333Wi970br/TBa74fRej+M1vthtN4Po/V+GK33w2i9H0br/TBa74fRej+N1vtptN5Po/V+Gq3302i9n0br/TRa76fRej+N1vtps95Xo+/XVqPv11aj79dWo+/X1sNmva9G36+tRt+vrUbfr61G36+tRt+vrUbfr61G36+tRt+vrUbfr61G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vRwGK3o5DFb0clis6MliRU8WK3qyWNGTxYqeLFb0ZLGiJ4sVPVms6MliRU8WK3q2WNGzxYqeLVb0bLGiZ4sVPVus6NliRc8WK3q2WNGzxYp+Wqzop8WKflqs6KfFin5arOinxYp+Wqzop8WKflqs6KfFil4sVvRisaIXixW9WKzoxWJFLxYrerFY0YvFil4sVvRisaJXixW9Wqzo1WJFrxYrerVY0avFil4tVvRqsaJXixW9WqzozWJFbxYrerNY0ZvFit4sVvRmsaI3ixW9WazozWJFt/jOaLH4zmix+M5osfjOaLH4zmjZ/85oTvn88+lcU/rr01+PVW0+VrP5WN3mYw2bjzVNPtb+90fXHivZfKxs87FOm49ls8oPm1V+2Kzyw2aVHzar/LBZ5afNKj9tVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9NVvl6mKzy9TBZ5ethssrXw2SVr4fJKl8Pk1W+HiarfD1MVvl6mKzy9bBZ5ZPNKp9sVvlks8onm1U+2azyyWaVTzarfLJZ5ZPNKp9sVvlss8pnm1U+26zy2WaVzzarfLZZ5bPNKp9tVvlss8pnm1X+tFnlT5tV/rRZ5U+bVf60WeVPm1X+tFnlT5tV/rRZ5U+bVb7YrPLFZpUvNqt8sVnli80qX2xW+WKzyhebVb7YrPLFZpWvNqt8tVnlq80qX21W+WqzylebVb7arPLVZpWvNqt8tVnlm80q32xW+WazyjebVb7ZrPLNZpVvNqt8s1nlm80q32xW+W6zynebVb7brPLdZpW3+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7X57mu1+e5rtfnua7P57muz+e5rs/nua7P57ms7TFb5ZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd12bz3ddm893XZvPd13b3u69fX1R3fZFEJe51vL6o9Ysv6ru+aOz6ornpi0Te81z6orTri7LwF/Vy8UXnri8qu75IojKM/PqicV7lqO36or7ri8auL5qbvkjk3cClL5L472jU9vqicV58Udn1RQK/deXREPz5dGllXHzR2PVFc9MXSbyrtPZFadcXLZxH5a8v+vqn5+//afn9P62//6ft9/+0//6fjt//0/nrf7ryvsXVP02//6e//21qv/9tar//bWq//21qv/9tar//bWq//21qv/9t6r//beq//23qv/9t6r//beq//23qv/9t6r//beq//23qv/9t6r//bRq//20av/9tGr//bRq//20av/9tGr//bRq//20av/9tGr//bRq//22av/9tmr//bZq//22av/9tmr//bZq//22av/9tmr//bZq//22av/5t6sfx+3+afv9P8+//6fn7f1p+/0/r7/9p+/0/7b//p+P3//T3v03p979N6fe/Ten3v03p979N6fe/Ten3v03p979N6fe/Ten3v03p979N+fe/Tfn3v00Lfyer5//7eRSx8iemvvCXL6EvKru+qO76ova/f1Fvz/WjvdfXZ//6lr7lW8aWb5k7vkXEcmnM/pzpznT8+xdAwhaopP78opKPcfFF564vKru+qO76orbri/quLxq7vmhu+iIJm5q1L5IY8Kdavv+ivOuLzl1fVHZ9Ud31RRKVIZ9fX1TPiy/qu75o7PqiuemLJKxN1r4o7foiicqQ5/NP6OVMV1907vqisuuL6q4varu+SKQyzPT1ReXii8auL5qbvmgcu74o7fqivOuLTuEvyhcCeZRdX1R3fZFEZSjjeV2o1OPqi/quLxq7vmhu+iIJC4VSav36ovzXF/33p+t4DovqeJ/nnW8PlSw+VLb4UKfFhyoWH6pafKhm8aG6xYcaFh9q2nuocRis6OMwWNHHYbCij8NgRR+HwYo+DoMVfRwGK/o4DFb0cRis6OOwWNGTxYqeLFb0ZLGiJ4sVPVms6MliRU8WK3qyWNGTxYqeLFb0bLGiZ4sVPVus6NliRc/7S0Kdz4fqXz85P8bBXw81DD7UqfCLnl/pGxcPlS0+1GnxoYrFh6oWH+rm1uXri/quL5KoJ/V8/e2q9vMbzPk4np9+/N+vxzpLe3usafKxJBwI7nisZPOxss3HOm0+VrH5WNXmYzWbj9VtPpbNKl9sVvlqs8pXm1W+2qzy1WaVrzarfLVZ5avNKl9tVvlqs8pXm1W+2azyzWaVbzarfLNZ5ZvNKt9sVvlms8o3m1W+2azyzWaV7zarfLdZ5bvNKt9tVvlus8p3m1W+26zy3WaV7zarfLdZ5YfNKj9sVvlhs8oPm1V+2Kzyw2aVHzar/LBZ5YfNKj9sVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9tVvlps8pPk1V+Hiar/DxMVvl5mKzy8zBZ5edhssrPw2SVn4fJKj8Pk1V+Hiar/DxsVvlks8onm1U+2azyyWaVTzarfLJZ5ZPNKp9sVvlks8onm1U+26zy2WaVzzarfLZZ5bPNKp9tVvlss8pnm1U+26zy2WaVP21W+dNmlT9tVvnTZpU/bVb502aVP21W+dNmlbf57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu67T57uu0+e7rtPnu69R497Ucr8d6+9l/P1ay+VjZ5mOdNh+r2HysavOxms3H6jYfa9h8rGnysabNKj9tVvlps8pPm1V+2qzy02aVnzar/LRZ5afNKj9NVvl0HCbL/OO5TNb5x3OZLPSP5zJZ6R/PZbLUP57LZK1/PJfJYv94LpPV/vFcJsv947mM1vtktN4no/U+Ga33yWi9T0brfTJa75PRep+M1vtktN4no/U+G6332Wi9z0brfTZa77PRep+N1vtstN5no/U+G6332Wi9P43W+9NovT+N1vvTaL0/jdb702i9P43W+9NovT+N1vvTaL0vRut9MVrvi9F6X4zW+2K03hej9b4YrffFaL0vRut9MVrvq9F6X43W+2q03lej9b4arffVaL2vRut9NVrvq9F6X43W+2a03jej9b4ZrffNaL1vRut9M1rvm9F634zW+2a03jej9b4brffdaL3vRut9N1rvu9F6343W+2603nej9b4brffdaL23+TLt47mM1nubr9M+nstovbf5Qu3juYzWe5uv1D6ey2i9t/lS7eO5jNZ7m6/VPp7LaL23+WLt47mM1nubr9Y+nstovbf5cu3juYzWe5uv1z6ey2a9T0bfr01G369NRt+vTUbfr02HzXqfjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fm4y+X5uMvl+bjL5fmzTer+1fzzXG1XNlo891Gn2uYvS5qtHnakafqxt9rqH5XA/5+tdz/fen53j+6P94nrw+nP/1HOmc7fnhcv714beAZ7CANd4I1g04RQs4Rwv4jBZwiRZwjRZwixZwjxZwtE7rjNZplWidVonWaZVonVaJ1mlp+B3oBhyt0yrROq0SrdMq0TqtEq3TqtE6rRqt06rROq0ardPScBrRDThap1WjdVo1WqdVo3VaNVqn1aJ1Wi1ap9WidVotWqel4fGjG3C0TqtF67RatE6rReu0mqlO6+u5uqmG6O259p9qKbfXc+WrC4YKhkNrz7W/gjx+2V/PVfrVcw2jzzVtPpeCgc7acyWjz7W/3U/z+emcj3n1XKfR5ypGn6safa5m9Lm60ecaRp9rqj5XrrsbTgVnHuWAU7SAc7SAz2gBl2gB12gBt2gB92gBj2gBB+u08hGs08pHsE4rH8E6rXwE67TyUaIFHKzTykewTisfwTqtfATrtPIRrdNK0TqtFK3TStE6rRSt01Jw/FMOOFqnlaJ1Wilap5WidVopWqeVo3VaOVqnlaN1Wjlap6XgtakccLROK0frtHK0TitH67RytE7rVO60Li7M5TMZfa5s9LlOo89VjD5XNfpczehzdaPPNYw+17T5XMVovVcwP0zj6wWPK0f3rOBRuPZcp9HnKkafqxp9rmb0ubrR5xpGn2vafC4Fb7e15zJa76vRel+N1vtqtN5Xo/W+Gq331Wi9r0brfTVa75vRet+M1vtmtN43o/W+Ga33zWi9b0brfTNa75vRet+M1vtutN53o/W+G6333Wi970brfd9f7x8a7DXH7OnquZrR5+pGn2sYfa5p87kUDJrWnisZfa6s+lzjb+OoDX/QV3B+Ug64RAu4Rgu4RQu4Rwt4RAt4Bgt4HtECTtECjtZpzWidloIfmHLA0TqtGa3TmtE6rRmt05rBOq3zCNZpnUewTus8gnVa5xGs0zqPEi3gYJ3WeQTrtM4jWKd1HsE6rfOI1mmlaJ1WitZppWidVorWaSn4gSkHHK3TStE6rRSt00rROq0UrdPK0TqtHK3TytE6rWyq03p7rmL0ufYX+YeifT7XQ/pcPde0+VwKRjXn16bY8zyunus0+lzF6HNVo8/VjD7X/u737OX1XDNfPdcw+lzT5nMpGNWsPVcy+lzZ6HOdRp+raD5XOcbuhlPBAUc54BYt4B4t4BEt4Bks4HpECzhFCzhHC/iMFnCJFnC0TqtG67RqtE6rRuu0arROq0XrtFq0TqtF67RatE5LwZxNOeBonVaL1mm1aJ1Wi9ZptWidVo/WafVonVaP1mn1aJ2Wgi2icsDROq0erdPq0TqtHq3T6tE6rRGt0xrROq0RrdMa0TotBXtP5YB1O610dWFuNKPP1Y0+1zD6XNPmc83D6HMlo8+VjT7XafS5itHnMlrvFbwAH3/eeD7XeeXofipY9q091zD6XNPkcxUFn7q150pGnysbfa7T6HMVo89VjT6XzXpfDpv1vhw26305jNb7ZLTeJ6P1Phmt98lovU9G630yWu+T0XqfjNb7ZLTeJ6P1Phut99lovc9G6302Wu+z0Xqfjdb7bLTeZ6P1Phut99lovT+N1vvTaL0/jdb702i9P43W+9NovT+N1vvTaL0/jdb702i9L0brfTFa74vRel+M1vtitN4Xo/W+GK33xWi9L0brfTFa76vRel+N1vtqtN4r+M+Ulp/PVcZx9VzF6HNVo8/VjD5XN/pcw+hzTZvPdbchyNs3pW3flLd907ntm8q2b6rbvqlt+6a+7ZvGtm+au76pb6sRfVuN6NtqRN9WI/q2GtG31Yi+rUb0bTWib6sRfVuNGNtqxNhWI8a2GjG21YixrUbIvOE2+vObWjq+6XgfjV95fbqMq+dqRp+rG32uYfS5ps3nknnD7YbnSkafKxt9rtPocxWjz2W03k+j9X4arffTaL2fNut9PWzW+3rYrPf1sFnv62Gz3tfDZr2vh816Xw+b9b4eNut9PW6u92/fNHd9Uzq2fVPa9k152zdJVMJWXzOC1qbIb6rIu193PFc1+lzN6HN1o881jD7XtPlcIu9+3fFc6d7nevumvO2bzm3fVLZ9k0jdXPqNaNu+qW/7prHtm+aubxJ5u2jtm9K2b8rbvunc9k1l2zdtqxHnthpxbqsR57YacW6rEWVbjSjbakTZViPKthpRttWIsq1GlG01omyrEWVbjSjbakTdViPqthpRt9WIuq1G1G01om6rEXVbjajbakTdViPqthrRttWItq1GtG01om2rEW1bjWjbakTbViPathrRttWItq1G9G01om+rEX1bjejbakTfViP6thrRt9WIvq1G9G01om+rEWNbjRjbasTYViPGthoxttWIsa1GjG01YmyrEWNbjRjbasTcViPmthoxt9WIua1GzG01Ym6rEXNbjZjbasTcViPmrhrRjmPbN6Vt35S3fdO57ZvKtm+q276pbfumvu2bxrZvmru+KW2rEWlbjUjbakTaViPSthqRttWItK1GpG01Im2rEWlbjcjbakTeViPythqRt9WIvK1GbLtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7lm2bfcs27Z7lm3bPcu27Z5l23bPsm27Z9m23bNs2+5Ztm33LNu2e5Zt2z3Ltu2eZdt2z7Jtu2fZtt2zbNvuWbZt9yzbtnuWbds9y7btnmXbds+ybbtn2bbds2zb7ln2bfcs+7Z7ln3bPcu+7Z5lP8q2b6rbvqlt+6a+7ZvGtm/aViO23bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7ln2bfcs+7Z7ln3bPcu+7Z5l33bPsm+7Z9m33bPs2+5Z9m33LPu2e5Z92z3Lvu2eZd92z7Jvu2fZt92z7NvuWfZt9yz7tnuWfds9y77tnmXfds+yb7tn2bfds+zb7lmObfcsx7Z7lmPbPcux7Z7lOMq2b6rbvqlt+6a+7ZvGtm/aViO23bMc2+5Zjm33LMe2e5Zj2z3Lse2e5dh2+3Fsu/04tt1+HNtuP45ttx+HyE3Ber42X9d+/vVN//3pfB7zz6fz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ju6x1dE9tjq6x1ZH99jqB/hJ3NE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tju6x1dE9tjq6x1ZH99jq6B5bHd1jq6N7bHV0j62O7rHV0T22OrrHVkf32OroHlsd3WOro3tsdXSPrY7usdXRPbY6usdWR/fY6ugeWx3dY6uje2x1dI+tge6xNdA9tga6x9ZA99gaB/hJPNA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tge6xNdA9tga6x9ZA99ga6B5bA91ja6B7bA10j62B7rE10D22BrrH1kD32BroHlsD3WNroHtsDXSPrYHusTXQPbYGusfWQPfYGugeWwPdY2uge2wNdI+tie6xNdE9tia6x9ZE99iaB/hJPNE9tia6x9ZE99ia6B5bE91ja6J7bE10j62J7rE10T22JrrH1kT32JroHlsT3WNrontsTXSPrYnusTXRPbYmusfWRPfYmugeWxPdY2uie2xNdI+tie6xNdE9tia6x9ZE99ia6B5bE91ja6J7bE10j62J7rE10T22JrrH1kT32JroHlsT3WNrontsTXSPrYnusTXRPbYmusfWRPfY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C64habb6iaaykCdNZSFPmspCkzTHV7Isj0/JMvolVzCaykKeNJWFPGkqC3nSVBbypKks5EizKAvN0Sz25TeLfUqWue4Nb6epLORJU1nIk6aJpiNNZSFPmspCnjSVhX5Os3zayDHfpV5AU1nIkSbzzeuZ3iLmm9dTfJRX7vkogdzzMfG55aOUcM9Hvv+eTyonP/prvTvGpyaYXJeepxSncsQzinNdTZ5SnMqHTilO5SynFKfyilOKjU5xKj83pTiVQ5tSTOe5cl2ZnVJM57lyXWydUkznuXJdP51STOe5cl0SnVJM57lyXeWcUkznuXJduJxSTOe5cl2LnFJM57lyXV6cUkznuXJdMZxSTOe5cl0EnFJM57lyXdebUszmuc4Hm+c6H2ye63ywea4z1/3FKcVGp5jNc50PNs915rpXOaWYzXOduW4/zijOdaFxSjGd58p17XBKMZ3nynU5cEoxnefKdYVvSjGd58p10W5KMZ3nynUdbkoxnefKdWltSjGd58p1tWxKMZ3nynUBbEoxnefKdUlrSjGd58p1kWpKMZ3nynXZaUoxnefKdSFpSjGd58p1aWhKMZ3nynWxZ0oxnefKdflmSjGd58p1QWZKMZ3nynWJZUoxnefKddFkSjGd58p1GWRKMZ3nynVhY0oxnefKdaliSjGd58p18WFKMZ3nynU5YUoxnefKdYFgSjGd58rV5D+lmM5z5Wrbn1JM57lyNeJPKabzXLla66cU03kuuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peuhPuh76k66H/qTroT/peugvuh76i66H/qLrob/oeuivh9EpZvNcF10P/UXXQ3/R9dBfdD30F10P/UXXQ3/l6ih/fu7H15ef45vv3vr4+iTnN19b7Pz1tcWuTyxTvek3s0zlITazTOVONrNM5Xs2s0zlqPayzNVfv5llKhe4mWWqnd5mlqm2hZtZmli6sVTumWPZX9+4jPKJpXKPH0vlHj+Wyj1+LJV75li23yzrB5a5bkhsZqnc48dSucePpXKPH0sTSzeWyj1zLMvr55Clfvo5ZK77IptZKvf4sVTu8WOp3OPGMtcdl80slXv8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+D2XFYrZPFcNftNlhWI2z1WD33VZoZjNc9WH0Slm81w1+N2YFYrZPFcNfuNlhWI6zxX8HssKxXSeK/jtlBWK6TxX8DsnKxTTea7gN0lWKKbzXMHvh6xQTOe5gt/6WKGYznMFv8uxQjGd5wp+Q2OFYjrPFfzexQrFdJ4r+G2KFYrpPFfwOxIrFNN5ruA3H1YopvNcwe8zrFBM57kuOs8V/LLGCsV0nuui81xG57mCXzpZoZjOcwW/SrJCsdEppvNcwe+CrFBM57mC3/BYoZjOcwW/t7FCMZ3nCn4bY4ViOs8V/I7FCsV0niv4zYkViuk8V/D7ECsU03mu4LccViim81zB7y6sUEznuYLfSFihmM5zBb9nsEIxnecKfntghWI6zxX8TsAKxXSeK3in/wrFdJ4reP/+CsV0nit4V/4KxXSeK3iv/QrFdJ4reAf9CsV0nouuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQN7oe+kbXQ9/oeugbXQ99exidYjbP1eh66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dB3uh76TtdD3+l66DtdD31/GJ1iNs/V6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfT/H3tvlB65rivpzqi/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x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerx2+x2uH7/Ha4Xu8dvgerwO+x+uA7/E64Hu8Dvger+OB/k4+4Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x+uA7/E64Hu8DvgerwO+x8vge7wMvsfL4Hu8DL7Hyx7o72SD7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvgeL4Pv8TL4Hi+D7/Ey+B4vg+/xMvge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9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+l66DtdD32n66HvdD30/WF0itk8V6froe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+p6po3y08+OL2+/f+UVvorfxlN5Ez+nR+8cXj/ZOb6Kn9JTeRM/oKb2JntBTehNl4hm9mRqrp/Rmev/O6M30/p3RmygLT+k1Mr1k/ipTS/WUXlh/9aIB1jO9aIjtg672+U/JxsMlmQfvkV6hOLYXWqE4thtaoTi2H1qh2OgUx/ZEKxTHdkUrFMf2RSsUx3ZRKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isUs3muEbxHeoViNs81gvdIr1DM5rnGw+gUs3muEbxHeoViNs81gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUEznuSqd5wreFb5CMZ3nqnSeqxqdYjrPFbwVfoViOs8VvBl+hWI6zxW8HX6FYjrPFbwhfoViOs8VvCV+hWI6zxW8KX6FYjrPFbxZfoVi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6Oc0R31HU1nIkWb0K65gNJWF5mja8Zks7XyXLKNfcgWjqSzkSdNE05GmspAnTWUhT5rKQp40lYUmaZbrk2Y939FUFnKkmeuW8XaaykKeNJWFPGkqC3nSNNF0pKks9D83bSad+dL0FB/llXs+SiD3fJQpbvkwX5qe4iPff88nlZOfuD3ec914nlJsdIpTudYpxal86JTiVM5ySnEqrzilOJX7m1Gc69rulOJUDm1KMZ3nynVfdkqx0Smm81y5LqpOKabzXLmuk04ppvNcuS59Timm81y5rmZOKabzXLkuUE4ppvNcua45Timm81y5LiNOKabzXLmuDE4ppvNcuS72TSmm81y5rt9NKabzXLkuyU0ppvNcjc5zNTrP1ek8V65bg1OK6TxXp/Nc3egU03muXBcUpxTTea5c1winFNN5rlyX/aYU03muXFfyphTTea5cF+emFNN5rlzX26YU03muXJfQphSzea6R66rYlGI2zzVyXeiaUszmucbD6BSzea6R62rUlGI2zzVyXV+aUkznuXJdMZpSTOe5cl0DmlJM57lyXdWZUkznuXJdp5lSTOe5cl15mVJM57lyXUuZUkznuXJdHZlSTOe5cl3vmFJM57lyXcGYUkznuXJdk5hSTOe5cl1lmFJM57lyXTeYUkznuXJdCZhSTOe5cnXzTymm81y5+vOnFNN5rlwd91OK6TwXXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQj1wd5c/P/fXl5/jmu7c+Pj/J+c3XFjt/fW2x6w3LXO3nm1mm8hCbWaZyJ5tZpvI9m1maWLqxTOXVNrNM5QI3s0y109vMMtW2cDNL5R4nlv2R6wLBQpb94xuXUd6xVO7xY6nc48dSucePpYnlFMv2xbK+Y6nc48dSucePpXKPH0vlHj+Wyj1uLHNdAVnIsnz8HLLU9o6lco8fS+UeP5bKPX4sTSzdWCr3+LFU7vFjqdzjx1K5x4+lco8by1yXeDazVO7xY6nc48dSucePpYmlG0vl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8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vA77H64Dv8Trge7wO+B6vE77H64Tv8Trhe7xO+B6v84H+Tj7he7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Tv8Trhe7xO+B6vE77H64Lv8brge7wu+B6vC77H63qgv5Mv+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8brge7wu+B6vC77H64Lv8TL4Hi+D7/Ey+B4vg+/xsgf6O9nge7wMvsfL4Hu8DL7Hy+B7vAy+x8vge7wMvsfL4Hu8DL7Hy+B7vAy+x8vge7wM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fpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keugnuR76Sa6HfpLroZ/keuinSh3l5z4/vnj//Tv/6K3UUG7SW+g5fR7PLz73d3oLPaVNegs9o016Cz2hTXoLZWKT3kKJ2KS30vvXoLdSW7VJb6EsbNJbKAmb9Ir5q0ot1Sa9w/qrFw3DeqYXDbl90NoeWfvczuNTMl8fH+O+VHr37y63D/LXm9sHuetN3iDtrze3D/LXm9sH+evN7YP89TYxvbl9kL/e3J7JX6+Yv0reGO2vV8xfJW+L9tcr5q+SN0X76xXzV8lbov31ivmr5A3R/nrF/FXydmh/vVr+ak7eDO2vV8tfzclbof31avmr+dbE9Gr5qzl5G7S/Xi1/NSdvgvbXK+avkrdA++sV81fJG6D99Yr5q+Ttz/56xfxV8uZnf71i/ip567O/XjF/lbzx2V+vmL9K3vbsr1fMXyVvevbXK+avkrc8++sV81fJG5799Yr5q+Ttzv56xfxV8mZnf71i/ip5q7O/XjF/lbzR2V+vmL9K3ubsr1fMXyVvcvbXK+avkrc4++sV81fJG5z99Yr5q+Ttzf56xfxV8uZmf71i/ip5a7O/XjF/lbyx2V+vmL9K3tbsr1fMXyVvavbXK+avVjF/lbyH211v8h5uf71i/moT81fJe9b99TYxvWL+KnnPur9eMX+VvGfdX6+Yv0res+6vV8xfJe9Z99cr5q+S96z76xXzV8k72f31ivkrsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRbrb5/F+ttnsf72Way/fRHrb1/E+tsXsf72Ray/fbk1Mb1a/moR629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629fxPrbF7H+9kWsv30R629f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4dr6nv168FAseffYWBqaB7JfaR2KJe8eP5bs3PxYsnNzY5n9SutQLPGXJpbbtP362m2Z37HEX/qxZOfmx7LB0o0lucePJbnHjyW5x48lucePJbnHi+WR/UrrUCzJPX4syT1+LMk9fiybMMsvPklb2mNR1Jb1ZVN0215pKicff5rK2cefpnL68aepnH/8aSonIHea2S+2DkZTOQV9RfO4PWke5zuayjnIn6ZyEvKn2aDpSJMs5EmTLORJkyzkSZMs9D3Nc3tHkyzkSDP7FdfBaJKFbDTb9EyWbX6XLLNfch2MJlnIk2aDpiNNspAnTbKQJ02ykCdNspCR5ro8aW7zO5pkIUeatW4Zh9MkC3nSJAt50iQLedJs0HSkSRb6zxdtJofypWkTH/LKNR8SyDUfMsUlH+VL0yY++P5rPqWcvOH2+FHrxrNJcZNTXMq1mhSX8qEmxaWcpUlxKa9oUlzK/VkU17q2a1JcyqGZFMt5rlr3ZU2Km5xiOc9V66KqSbGc56p1ndSkWM5z1br0aVIs57lqXc00KZbzXLUuUJoUy3muWtccTYrlPFety4gmxXKeq9aVQZNiOc9V62KfSbGc56p1/c6kWM5z1bokZ1Is57l2Oc+1y3muQ85z1bo1aFIs57kOOc91NDnFcp6r1gVFk2I5z1XrGqFJsZznqnXZz6RYznPVupJnUiznuWpdnDMplvNcta63mRTLea5al9BMitU811nrqphJsZrnOmtd6DIpVvNc563JKVbzXGetq1EmxWqe66x1fcmkWM5z1bpiZFIs57lqXQMyKZbzXLWu6pgUy3muWtdpTIrlPFetKy8mxXKeq9a1FJNiOc9V6+qISbGc56p1vcOkWM5z1bqCYVIs57lqXZMwKZbzXLWuMpgUy3muWtcNTIrlPFetKwEmxXKeq1Y3v0mxnOeq1Z9vUiznuWp13JsUy3kuuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76U66H/pTroT/leuhPuR76s1ZH+f1z/3z5fH747vtxPj/J/OFr1zb/+tq1LW9Y1mo/D2ZZykMEsyzlToJZlvI9wSwbLN1YlvJqwSxLucBglqV2esEsS20Lg1mSe5xYHrdaFwg6sjwe33g913csyT1+LMk9fizJPX4sGyxNLPcflts7luQeP5bkHj+W5B4/luQeP5bkHjeWta6AdGS5Pn4OuW77O5bkHj+W5B4/luQeP5YNlm4syT1+LMk9fizJPX4syT1+LMk9bixrXeIJZknu8WNJ7vFjSe7xY9lg6caS3OPHktzjx5Lc48eS3OPHktzjxrLWNaxgluQeP5bkHj+W5B4/lg2WbizJPX4syT1+LMk9fizJPX4syT1uLGtdpAtmSe7xY0nu8WNJ7vFj2WDpxpLc48eS3OPHktzjx5Lc48Yy+12/9VifH2Q7P7E890f7wLkv7xQnd4EdFCf3ah0UNznFyX1PB8XJ3cl3ir97C3xu6rzzSe44wvkkdxHhfJJvRKP5ZL9HGM6nlLPswKeUD+3Ap5Rr7Zfy3n/qF5YNlm4sSzntYJbCHt6dpbDfd2cpnA3cWQrnCG+W2e9xDsVSOJ+4sxTOMu4syT1+LBss3ViSe/xYknv8WJJ7/FiSe/xYknvcWGa/iTsUS3KPH0tyjx9Lco8fywZLN5bkHj+W5B4/luQeP5bkHj+W5B43ltkvhA/Fktzjx5Lc48eS3OPHssHSjSW5x48lucePJbnHjyW5x48luceL5ZT9enAWloZr63dSsHRjybvHxvJz88CU/UrrUCx597ixzH6ldSiW7Nz8WLJz82OJvzSx3Kbt19duy/yOZYOlG0t2bn4s2bn5sST3+LEk9/ixJPe4scx+pXUoluQeP5bkHj+W5B4/lg2WbizJPX4slXPPF5/kaPNjUXS05WVTdNteaSonH3+aytnHn6Zy+nGnmf1a62A0lROQP03lDORPUzkFfUVzuz1pbuc7mg2ajjSVk5A/TbKQJ02ykCdNspAnTbKQI83sF1xT0ty3dzTJQp40yUKeNMlCRprnM1mut3fJMvsl18FokoU8aZKFPGmShTxpkoU8aZKFHGmuZCEbzbU9/eba3iXLWveGw2mShTxpkoU8aTZoOtIkC3nSJAt50iQLfU9zfbeRU75L3YEmWciRpvLNa0tvkfLNaxMf8so1HxLINZ8Gn0s+pIRrPvj+az6lnPx5PNa75/muCabWpWeT4lKO2KK41tVkk+JSPtSkuJSzNCku5RVNipuc4lJ+zqS4lEMzKZbzXLWuzJoUy3muWhdbTYrlPFet66cmxXKeq9YlUZNiOc9V6yqnSbGc56p14dKkWM5z1boWaVIs57lqXV40KZbzXLWuGJoUy3muWhcBTYrlPFet63omxWqea76pea75pua55pua55pr3V80KW5yitU813xT81xzrXuVJsVqnmuudfvRorjWhUaTYjnPVevaoUmxnOeqdTnQpFjOc9W6wmdSLOe5al20MymW81y1rsOZFMt5rlqX1kyK5TxXratlJsVynqvWBTCTYjnPVeuSlkmxnOeqdZHKpFjOc9W67GRSLOe5al1IMimW81y1Lg2ZFMt5rloXe0yK5TxXrcs3JsVynqvWBRmTYjnPVesSi0mxnOeqddHEpFjOc9W6DGJSLOe5al3YMCmW81y1LlWYFMt5rloXH0yK5TxXrcsJJsVynqvWBQKTYjnPVavJ36RYznPVats3KZbzXLUa8U2K5TxXrdZ6k2I5zyXXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SzXQz/L9dDPcj30s1wP/SLXQ7/I9dAvcj30i1wP/XJrcorVPNci10O/yPXQL3I99ItcD/0i10O/yPXQL7U6yu+f+/b88vn88N3343x+kvnD165t/vW1a1vesSz1pg9mWcpDBLMs5U6CWZbyPcEsSzmqWJa1+uuDWZZygcEsS+30glmW2hYGs2ywdGNJ7rGxPB7feD3XdyzJPX4syT1+LMk9fizJPTaW+w/L7Q3LWjckglmSe/xYknv8WJJ7/Fg2WLqxJPfYWK6Pn0Ou27ufQ9a6LxLMktzjx5Lc48eS3OPGstYdl2CW5B4/luQeP5bkHj+WDZZuLMk9fizJPX4syT1+LMk9fizJPW4sa91SCmZJ7vFjSe7xY0nu8WPZYOnGktzjx5Lc48eS3OPHktzjx5Lc48ay1j2zYJbkHj+W5B4/luQeP5YNlm4syT1+LMk9fizJPX4syT1+LMk9bixr3RQMZknu8WNJ7vFjSe7xY5ncXy7T8vJBPrE890f7wLkv7xQnd4EdFCf3ah0UJ3dU/oqz3/XroDi5O/lO8XdvAUtTZ/YrgOF8kruIcD4NPpd8km85w/mUcpYd+JTyoR34lHKt/VLe+0/9wrKUH45lmf2a41AshT28O0thv+/OUjgbuLNssHRjKZw53FkK5xN3lsJZxp0lucePJbnHi2XLflF1KJbkHj+W5B4/luQeP5YNlm4syT1+LMk9fizJPX4syT1+LMk9biyzXzUeiiW5x48lucePJbnHj2WDpRtLco8fS3KPH0tyjx9Lco8fS3KPG8vsF8KHYtlgafqLxc/Xg1v268FDseTdY2P5+S9pW/YrrSOxzH6ldSiW7Nz8WLJz82PJzs2PZYOlheU2bb++dlvmdyzxl34s2bn5sWTn5seS3OPHktzjxjL7ldahWJJ7/FiSe/xYknv8WDZYurEk9/ixJPf4sVTOPd98knl/EpmP289Xz/MrTeXk409TOfu408x+q3Uwmsr5x5+mcgLyp6mcgfxpNmjaaLbjh+b0G83/+NXn8vCx5/byKY4/fornz+j2s71839chKcerYYaknNuGGRKBcIAhkTMHGBLxNf+Qsl/yZUj/DImwPcCQyPADDInVwABDagwp/5DYONg+yXJrj++8vH717zRZDXjSJMN70iRse9IkFTvSzH6QeTCa5ExPmgRCI81le9Js6zuaJDdPmg2ajjTJQp40yUKeNMlCnjTJQp40yULf03zV+BvNWkfaw2mShTxpkoX+81WFm/K5eBOfBp9LPiSQaz5kims+pIRrPvj+az6lnPx5PH78fZ7vSrFqHWo3KS7liE2KS7lWk+JSPtSkuMkpLuUVTYpLuT+T4lJ+zqS4lEMzKVbzXGutI9EmxWqea611cNmkWM1zrbcmp1jNc621DgGbFKt5rrXWUV2TYjnPVetArUmxnOeqdezVpFjOc9U6nGpSLOe5ah0hNSmW81y1DnqaFMt5rlrHMU2K5TzXLOe5ZjnPVeswq0mxnOea5TzXLOe5ah2yNSmW81y1jsKaFMt5rloHVk2K5TxXrWOlJsVynqvW4U+TYjnPVeuIpkmxnOeqdZDSpFjOc9U67mhSLOe5ah1KNCmW81y1jg6aFMt5rlrn+0yK5TxXrTN4JsVynqvWOTmTYjnPVessm0mxnOeqdTDMpFjOc9U6ZWVSLOe5ah1ZMimW81y1zv+YFMt5rlqHaUyK5TxXrUssJsVynqvWRROTYjnPVesyiEmxnOeqdWHDpFjOc9W6VGFSLOe5al18MCmW81y1LieYFMt5rloXCEyK5TxXrSZ/k2I5z1Wrbd+kWM5z1WrENymW81y1WutNiuU8l1wP/SrXQ7/K9dCvcj30q1wP/SrXQ7/K9dCvcj30q1wP/SrXQ7/J9dBvtTrKv7x/dZzPTzJ/+Nq1zb++dm3LO5al3vTBLJXvHnqzVL6R6M1S+Z6iN0vl24veLJUvrjuzrNWMH8xS+dq6N0vlW+veLMk9fiwbLE0sj8c3vq9I37Ek9/ixJPf4sST3+LEk99hY7j8st3csyT1uLGtdpwhmSe7xY0nu8WNJ7vFj2WBpYrk+fg65bu9+DlnrvkgwS3KPH0tyjx9Lco8fS3KPG8taF2KCWZJ7/FiSe/xYknv8WDZYurEk9/ixJPf4sST3+LEk9/ixJPe4sax1pSmYJbnHjyW5x48lucePZYOlG0tyjx9Lco8fS3KPH0tyjx9Lco8by1qX0oJZknv8WJJ7/FiSe/xYNli6sST3+LEk9/ixJPf4sST3+LEk97ixrHWtMJglucePJbnHj2VyfzltPx9knucPLC3tA9nv+nVQnNyrdVCc3FF1UJzc9/grzn7Xr4Pi5B6ig+Lkb/oOipPvITsobnKK5TxX9rt+Xyo2dLZkv+vXQXEtz2VRXMtzGRRnv+v3pWJDZ0P2u34dFNfyXBbFtTyXRXGTU1zLc1kU1/Jchl1m9rt+HRTX8lwWxbU8l0Fx9rt+HRTX8lwWxbU8l0VxLc9lUdzkFNfyXBbFcp4r+12/DorlPFf2u37uivfsd/06KFbzXPtNzXPt2W83dlDc5BSrea49+7XCDorVPNee/fJfB8Vyniv7Fb0OiuU8V/aLdB0Uy3mu7NfdOiiW81zZL6V1UCznubJfHeugWM5zZb/g1UGxnOfKfg2rg2I5z5X9slQHxanfx+d5/vwJ6DRPHwSf++NX6M99eSc49eu4h+DUb+MOgnOflekhOPW7uIfg1K/iLwV/93fr5/F4pp/nu2d67psr8XhSv+Tj8aTewsTjSb2yicdTyU92wFPJfXbAU8mr9iukef+hf1DmPjIyFspK/joYpa5zd0ep6/LdUTZQeqHUTQ/uKHWThjtK3VTijlI3wbijJO14ocx9WmQslKQdN5SkHTeUpB03lA2UXihJO24oSTtuKEk7bihJO24oSTteKHMfFBkLJWnHDSVpxw0laccNZQOlF0rSjhtK0o4bStKOG0rSjhtK0o4XytwHisZCSdpxQ0nacUNJ2nFD2UDphZK044aStOOGkrTjhpK044aStOOFMvdpsLFQknbcUJJ23FCSdtxQYoYsKA2XZffcF7CGQpn77FIelIZ2qtz3nMZCyWvHDWUDpRdKlmxuKFmyuaHEV1pQbtP262u3ZX6HEl/phpIlmxPKI/ddsrFQknbcUJJ23FCSdtxQNlB6oSTtuKEk7bihJO24oSTtuKEk7XihzH0RcCyUpB03lKQdN5SkHTeUDZReKIXTzhcfZJ6eLOdpWX8+x3H+6avX9fHF+/QOvHA2igUvnKRiwQvnrljwwinNCfwPzNxXREeDKZzU/GEKZzV/mMJpzR9mA6YfTBKbI0xSmCNMkpUN5vn07PPt+A3mv7bEKXUueSjwJCt/8PP85NHWN+BLnY8eCjyJLQg86S4IPEkwCHwDfAx4EmYQeNJoB/CGn5AIH0QPBk9yDQJPco0Br3zy/Rvw83I8JR7tA/hpfX7qtb0DT3INAk9y9Qfv3NJ0KB+qH2dIjSHlHxLpeYAhkbQHGBKpfIAhkeAHGBJpP/+QVjYDAwyJLcIAQ2LjMMCQ2DgMMKTGkPIPiY3DAENi4zDAkNg4DDAkNg4DDImNQ/4hbWwcBhgSG4cBhsTGYYAhsXEYYEiNIeUfEhuHAYbExmGAIbFxGGBIbBwGGBIbh/xD2tk4DDAkNg4DDImNwwBDYuMwwJAaQ8o/JHJS7JAMR9WPnZyUf0gH7i54SJ+PGx8H7m6AIeHuBhhSY0j5h8TPkwYYEj9PGmBI5KTYIVlqgw9y0gBD4udJ+Yd08vOkAYbExmGAIbFxGGBIbBwGGFJjSPmHxMZhgCGxcRhgSGwcBhgSG4cBhsTGIf2QzhsbhwGGxMZhgCGxcRhgSGwcBhhSY0j5h8TGocOQvvjO0/nzmc/p5TPf2r86UvYT5UbKNqPcSNl9lBspm5K8I/0Z08SuZIgxsS0ZYkzsS4YYExuTIcbUGNMIY2JrMsSY2IQMMSa2G0OMiY3FEGNiCxE9pv2Ber5N229j+sPn+Hyd/ZzZWJQbKduNkUbqXBx0zmxNpMfPNkZ6/I3xK4+f7ZH0+NlKSY+fbZf0+NmiSY+f7Zzy+Bc2edLjZ+snPX62ftLjZ+snPf7G+JXHz9ZPevxs/aTHz9ZPevxs/aTHz9ZPefyNrZ/0+Nn6SY+frZ/0+Nn6SY+/MX7l8bP1kx4/ub/q+A1Xbc9G7lce/4rzLzv+z1cPzxXnLz3+xviVx4/zlx4/P++XHj8/75ceP7m/6vgtTcAruV95/Bs/75cePz/vlx4/Wz/p8bP1kx5/Y/zK42frJz1+tn7S42frJz1+tn7S42frpzz+na2f9PjZ+g01/m++83Q+PvM0315+5ndMr/8A2PuJ/wNg8yf+D6DxD0D7HwDbP/F/AOz/xP8BsAEU/wfADrDGP4CXkbLXqzbSg11d7Ejn23p7jvRcP4zUclHvYP9WbqRs1EYaqXd5wsE+TXr8jfErj59dmvT42aRJj589mvT42aJJj5+Nm/L4T7Zz0uNnkyc9frZ+0uNn6yc9/sb4lcfP1k96/Gz9pMfP1k96/Gz9pMfP1k93/OedF+NXHj9bP+nxs/WTHj9bP+nxN8avPH62ftLjZ+snPX5yf9Xxf76Sd94mcr/0+HH+Zcf/8VLOffyN8SuPH+cvPX6cv/T4+Xm/9Pj5eb/0+Mn9Vcf/uTD5vM3kfunx8/N+6fHz837p8bP1kx5/Y/zK42frJz1+tn7S42frJz1+tn7S42frpzz+ha2f9PjZ+g01/i++s+U+xv0fAHs/8X8AbP7E/wE0/gFo/wNg+yf+D4D9n/g/ADaA4v8A2AHW+AfwMlL2etVG2tjVBY/0/jR9fOdp2T+MdLqP46FwWtq7obKBKzhUtmojDbU9v7gttw/f+fVrj3fjZ6cmPf7G+IuO//6ZH9+4re/Gzz5Nevxs06THzy5Nevxs0qTHz9ZNefwrG7qy41/Xxzfep3fjZ5cnPX62ftLjZ+snPf7G+JXHz9ZPevxs/aTHz9Zv1PG/+yneyiav3EjZzlUb6cbGrdxI2aKVGymbsXIjZdtVbqSNkVYbKVupciNl01RupGyPokf687da0/bpb7VsfwOysT8qOFQ2SPWGurNDKjhUtkgFh8oeqeBQ2SQVHGpjqPWGyjap4FDZJxUcKhulgkNlo1RwqGyU6g31YKNUcKhslAoOlY1SwaGyUSo41MZQ6w2VjVLBobJRKjhUNkoFh8pGqeBQ2SjVG+rJRqngUNkoFRwqG6WCQ2WjVHCojaHWGyobpYJDZaNUcKhslAoOlY1SwaGyUSo31DsGhlpvqGyUCg6VjVLBobJRKjjUxlDrDZWNUsGhslEqOFQ2SgWHykap4FDZKNUb6sRGqeBQ2SgVHCobpYJDZaNUcKiNodYbKhulgkNlo1RwqGyUCg6VjVLBobJRqjfUmY1SwaGyUSo4VDZKBYfKRqngUBtDrTdUNkoFh8pGqeBQ2SgVHCobpYJDZaNUb6gLG6WCQ2WjVHCobJQKDpWNUsGhNoZab6hslAoOlY1SwaGyUSo4VDZKBYfKRqneUBsbpYJDZaNUcKhslAoOlY1SwaE2hlpvqGyUCg6VjVLBobJRKjhUNkoFh8pGqd5QVzZKBYfKRqngUNkoFRwqG6WCQ20Mtd5Q2SgVHCobpYJDZaNUcKhslAoOlY1SvaFubJQKDpWNUsGhslEqOFQ2SgWH2hhqvaGyUSo4VDZKBYfKRqngUNkoFRwqG6V6Q93ZKBUcKhulgkNlo1RwqGyUCg61MdR6Q2WjVHCobJQKDpWNUsGhslEqOFQ2SvWGerBRKjhUNkoFh8pGqeBQ2SgVHGpjqPWGykap4FDZKBUcKhulgkNlo1RwqGyU6g31ZKNUcKhslAoOlY1SwaGyUSo41MZQ6w2VjVLBobJRKjhUNkoFh8pGqeBQ2SiVG+p8Y6NUcKhslAoOlY1SwaGyUSo41MZQ6w2VjVLBobJRKjhUNkoFh8pGqeBQ2SjVG+rERqngUNkoFRwqG6WCQ2WjVHCojaHWGyobpYJDZaNUcKhslAoOlY1SwaGyUao31JmNUsGhslEqOFQ2Sn9zqC/g2foEgW+AjwHP9iQIPBuOIPBsIYLAsykIAk+aN4Ff5vUhcXkF8kfwNie/kLnD0JOM/dEv7fGpl7V9+M7btP362m2Z3w2JpDvAkEjFAwypMaTQId192+Mbt/XdkEjbAwyJZD7AkEjxAwyJxD/AkNgO5B9SY48wwJDYOAQPaX1+4316NyQ2DgMMiY3DAENqDCn/kNg4DDAkNg4DDImNQ9chbW/Bs0UIAs9mIAb8StoPAk+CDwJPKreBP6Yn+PP4AN72ezIrWTsMfQO9O3rvX6xYSdADDIkEHTsky89HVhL0AEMibQ8wJJJ5/iFtpPgBhkTiH2BIbAeCh2T4+cjGHmGAITWGlH9IbBwGGBIbhwGGxMZhgCGxcRhgSGwcug7p7U9Gd7YIQeDZDASBJ+0HgSfBB4FvgI8BT9IOAk96DgJPIg4CT8oNAk9yNYFv0/mQ2JZPtYO23288yK5h6EmvYejJr2HoSbBh6Bvoo9CTYsPQk2PD0JNkw9CTZcPQk2aj0J+k2TD0pNkw9KTZMPSk2TD0DfRR6EmzYehJs2HoSbNh6EmzYehJs0HolxtpNgw9aTYMPWk2DD1pNgx9A30UetJsGHrSbBh60mwYetJsGHrSbBT6iTQbhp40G4aeNBuGnjQbhr6BPgo9aTYMPWk2DD1pNgw9aTYMPWk2Cv1Mmg1DT5oNQ0+aDUNPmg1D30AfhZ40G4aeNBuGnjQbhp40G4aeNBuFfiHNhqEnzYahJ82GoSfNhqFvoI9CT5oNQ0+aDUNPmg1DT5oNQ0+ajULfSLNh6EmzYehJs2HoSbNh6Bvoo9CTZsPQk2bD0JNmw9CTZsPQk2aj0K+k2TD0pNkw9KTZMPSk2TD0DfRR6EmzYehJs2HoSbNh6EmzYehJs1HoN9JsGHrSbBh60mwYetJsGPoG+ij0pNkw9KTZMPSk2TD0pNkw9KTZKPQ7aTYMPWk2DD1pNgw9aTYMfQN9FHrSbBh60mwYetJsGHrSbBh60mwU+oM0G4aeNBuGnjQbhp40G4a+gT4KPWk2DD1pNgw9aTYMPWk2DD1pNgr9SZoNQ0+aDUNPmg1DT5oNQ99AH4WeNBuGnjQbhp40G4aeNBuGnjQbhL7dSLNh6EmzYehJs2HoSbNh6Bvoo9CTZsPQk2bD0JNmw9CTZsPQk2aj0E+k2TD0pNkw9KTZMPSk2TD0DfRR6EmzYehJs2HoSbNh6EmzYehJs1HoZ9JsGHrSbBh60mwYetLsf/wgL3gaeK7wkAov8ZDcLvGQri7xkIAu8ZBSrvAsJIlLPLj9Szw48ks8uOZLPA08V3gquebzOH599Xnu7wRX8sEmwZWcrUlwJa9qElzJfVoEt0p+0iS4kkM0Ca7k+UyCK7k4k+CmJljNaTU1p9XUnFZTc1pNzWmtak5rVXNaq5rTWtWc1trUBKs5rVXNaa1qTmtVc1qrmtPa1JzWpua0NjWntak5ra2pCVZzWpua0yp1e94kWM1plbqzbhFc6rq5SbCa0yp1ydskWM1plbpabRKs5rRKXWg2CVZzWqWuEZsEqzmtUpd3TYLVnFapK7MmwWpOq9RFVZNgNadV6nqoSbCa0yp1KdMkWM1plboKaRKs5rRKXUA0CVZzWqWu/ZkEqzmtUpftTILVnFapK24mwWJOay11scwkWMxpraWuc5kEizmt9dbUBIs5rbXU1SWTYDGntZa6MGQSrOa0Sl3TMQlWc1qlLseYBKs5rVJXUkyC1ZxWqYsgJsFqTqvU9QuTYDWnVerSg0mwmtMqddXAJFjNaZW6DmASrOa0SjX4mwSrOa1SLfsmwWpOq1QTvkmwmtMq1VZvEqzmtEo1ypsEqzkttY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuJXtY74Va0jflXriF/VOuI3tY74Ta0jflPriN/UOuK3W1MTLOa0NrWO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1DriN7WO+E2tI35T64jf1Drit1IN4vePfXt++Xx++ObffJB5Xo6nxKP9fI7j/He/8219fOb5dq4v8NqfvvNxPr/z/OE7r23+9bVrW96Nv5IrYfzfjr9Uuzzj/3r8lRwr4/96/JX8O+P/evyV0gzj/3r8jfErj79S0mX8X4+/0k9YGP/X46/08ybG//X42fpJj5+tX9nxH49vvL5+39/GX+rSEeP/evxs/aTHz9ZPevxs/cqOf/8Z//Zu/I3xK4+frZ/0+Nn6SY+frZ/0+Nn6SY+frV/Z8a+Pj7xu737Tt9TVTcb/9fjZ+kmPn62f9PjZ+kmPvzF+5fGz9ZMeP1s/6fGz9ZMeP1s/6fGz9VMef6kL8Iz/6/Gz9ZMeP1s/6fGz9ZMef2P8yuNn6yc9frZ+0uNn6yc9frZ+0uNn66c8/pOtn/T42fpJj5+tn/T42fpJj78xfuXxs/WTHj9bP+nxs/WTHj9bP+nxs/UTHv9+Y+snPX62ftLjZ+snPX62ftLjb4xfefxs/aTHz9ZPevxs/ZTHP5H7Y8c/3WfwHP+0eY7/8zWPfSL3S4+f3C89fnK/9Pgb41ceP7lfevzkfunxk/ulx89v+0iPn9/2UR7/zNZPevxs/cqO//MZx31m6yc9frZ+0uNvjF95/Gz9yo7/8yG3fWbrJz1+tn7S42frJz1+tn7K41/Y+kmPn61f2fEbftN3YesnPX62ftLjb4xfefxs/aTHz9ZPevxs/aTHz9ZPevxs/ZTH39j6SY+frZ/0+Nn6SY+frZ/0+BvjVx4/Wz/p8bP1kx4/Wz/p8bP1kx4/Wz/l8a9s/aTHz9ZPevxs/aTHz9ZPevyN8SuPn62f9PjZ+kmPn62f9PjZ+kmPn62f8vg3tn7S42frJz1+tn7S42frJz3+xviVx8/WT3r8bP2kx8/WT3r8bP2kx8/WT3n8O7m/w/idb27spPMBhtQYUv4hkXQHGBJ5dIAhkRoHGBLZboAhkcDyD+ngtyMGGBK/wzDAkNg4DDAkNg7BQzKcYzsaQ8o/JDYOAwyJjcMAQ2LjEDwkw6Ggg43DAENi45B/SCcbhwGGxMZhgCGxcRhgSGwcgodk+G2hszGk/ENi4zDAkNg4DDAkNg4DDImNwwBDYuOQfkjHjY3DAENi4zDAkNg4DDAkNg4DDKkxpPxDYuMwwJDYOAwwJDYOAwyJjcMAQ2LjkH9IExuHAYbExmGAIbFxGGBIbBwGGFJjSPmHxMZhgCGxcRhgSGwcBhgSG4cBhsTGIf+QZjYOAwyJjcMAQ2LjMMCQ2DgMMKTGkPIPiY3DAENi4zDAkNg4DDAkNg4DDImNQ/4hLWwcBhgSG4cBhtR0h+Tb73gswmnGG6Vw5vBGKZwMvFEK+3dvlMIu2xllE/bC3iiFHas3SuGfZHmjFP55kzfKBkovlKQdE8rPJcxHI+24oSTtuKEk7bihJO2YUH6uND1W0o4bStKOG0rSjhtK0o4bygZKL5SkHa+fOK6kHTeUpB03lKQdN5SkHS+UG2nHDSVpxw0laccNJWnHDWUDpRdK0o4bStKOG0rSjhtK0o4bStKOF8qdtOOGkrTjhpK044aStOOGsoHSCyVpxw0laccNJWnHDSVpxw0laccL5UHacUNJ2nFDSdpxQ0nacUPZQOmFkrTjhpK044aStOOGkrTjhpK044XyJO24oSTtuKEk7bihJO24ocztK4/18cXnuW4fSJ77o0rg3N9VCZy5zZ+/3twOzV9vbhvlrfe85fY6/npzG5Kv9H735L9HhOe33t/Rye0xounktg3RdBp0LujkXmVG0ynkIjvQKeQ5O9Ap5FD7Zbn3n/mFZCHvG0tyKuSqg0nK+nV3krLe3p2kbA5wJ9kg6URSNl+4k5TNIu4kZXOLO0kyjhdJMo4TyeSX1EciScbxIknG8SJJxvEi2SDpRJKM40WSjONFkozjRZKM40WSjONEMvnt5pFIknG8SJJxvEiScbxINkg6kSTjeJEk43iRJON4kSTjeJEk4ziRTH6TeySSDZIuB3vP5Ad7RyLJG8fnL13P5IdRByKZ/C7qSCTZqnmRZKvmRZKtmhfJBsnPJLdp+/W12zK/I4mf9CLJVs2LJFs1L5JkHC+SZBwnksmvoY5EkozjRZKM40WSjONFskHSiSQZx4skGceLpG7G+eJzTMv6LPxcthce+/nKUjfl+LPUzTnuLJNfQh2LpW7W8Wepm3b8WermHX+WDZYWlsf6ZHm2dyx1M48/S93U48+S3OPHktzjx5Lc48Yy+U3UsViSe75k2W7TO5bkHj+W5B4/lg2WBpZt3p4sl/UdS3KPH0tyjx9Lco8fS3KPH0tyjxvL5NdRx2JJ7rn4e9rkF0+j6ZBNrug06FzQIT9c0SERXNHB41/RqXQv13B9rdS93I96//n3UulgrklwIY9qE1zIdtoEF3KSNsFNTXAhv2cTXMjC2QQXcmU2wVJG6x/Bak6r0hFVm2A1p1XpJKlNsJrTqnTg0yZYzWlVOpdpE6zmtCodn7QJVnNalU452gSrOa1KhxFtgtWcVqUzgzbBak6r0tE+m2A1p1XpBJ5NsJrTqnRQziZYzWlVOs9mE6zmtCodO7MJVnNalU6H2QSrOa1Kh7hsgtWcVqWzVjbBak6rqTmtpua0Kh1UswlWc1pNzWk1NadV6QCdTbCa06p0zs0mWM1pVTqOZhOs5rQqnRqzCVZzWpUOd9kEqzmtSmewbILVnFalo1I2wWpOq9KJJptgNadV6eCRTbCa06p0PsgmWM1pVTrFYxOs5rQqHbWxCVZzWpXOw9gEqzmtSodWbILVnFalkyU2wWpOq9LxD5tgNadV6YyGTbCa06p0kMImWM1pVTrtYBOs5rQqHUmwCVZzWpXODdgEqzmtSsX9NsFqTqtSYb5NsJrTqlRrbxOs5rQqlc/bBKs5La2K+H8EizmtSa0jflLriJ/UOuIntY74uxw1wWJOa1LriJ/UOuIntY74Sa0jfqrUID59d4zqOJ+fY/7wtWubf33t2pa3KHXvCbqjbKD0Qql7qdAdpe5ZQ3eUujcQ3VHqnjl3R6l75dwbZaVG/GiUujfO3VGSdtxQknYsKI/HN17P9S3KBkovlKQdN5SkHTeUpB0Lyv0H5fYWJWnHDSVpxwtlpasU0ShJO24oSTtuKEk7FpTr4yeO6/b2J46Vrn9EoyTtuKEk7bihJO24oSTtuKEk7XihrHQZJholaccNJWnHDSVpxw1lA6UXStKOG0rSjhtK0o4bStKOG0rSjhfKSteZolGSdtxQknbcUJJ23FA2UHqhJO24oSTtuKEk7bihJO24oSTteKGsdCEtGiVpxw0laccNJWnHDWUDpRdK0o4bStKOG0rSjhtK0o4bStKOF8pKVwqjUZJ23FC21Cj3+aH3POb9A8r7Vz++eH/bJZD87l4Hwbk9WgfBuZ1UB8G5/U4HwbldyVeCv3v+m3o2k1/pC8eT2z2E48m9/wzHk3unGY6ngecKTyH32QNPIa/aL9i9/8yvKAu54GiUhfx1NEpZ5+6OMvmFyKFQyiYCf5Sy6cEfpWzS8EfZQOmFUjbB+KMk7bihJO24oSTtuKEk7TihnJNfaR0KJWnHDSVpxw0laccNZQOlF0rSjhtK0o4bStKOG0rSjhtK0o4Xyom044aStOOGkrTjhpK044aygdILJWbI8nc1hpOVc/LzviOhTH5INQtKw197zckPqQ6FkteOG0qWbG4oWbK5oWTJ5oYSX2lAuU3br6/dlvktSnylF8rkh1SHQsmSzQ0laccNJWnHDWUDpRdK0o4bStKOG0rSjhtK0o4bStKOF8rkh1SHQqmbdr74HNNta8/v/NLlNG3rbzB1804HmLqJpwPMBkw/mLqppwNM3dzTAaZu8ukAUzf7fAXzfNjMabqtb2Hqph9/mMlPqw4GkwTkCJME5AiTBOQIswHTDyYJ6FuYL+u6/x4mCcgRJgnIESYJ6OpPTJKfT43Gk/wkajgecsclHpLEJR6ywSWeBp4rPJUORxnK+Ofkxz07CK50OMokuNLhKJPgQu7TJDj50ckOggs5RJvgQp7PJriQi7MJbmqC1ZxWqROdJsFqTqvUiU6TYDWnVenopk2wmtOqdBjTJljNaVU6XmkTrOa0Kh2YtAlWc1qVjjXaBKs5rUqHD22C1ZxWpSOCNsFqTqvSQT6bYDWnVem4nU2wmtOqdCjOJljMaS2Vjq7ZBIs5raXSATObYDGntdyammAxp7VUOqxlEyzmtJZKR6psgtWcVqWDTzbBak6r0vEkm2A1p1XpEJFNsJrTmtSc1qTmtCpdwLIJVnNas5rTmtWcVqV7YTbBak6r0u0tm2A1p1XpjpVNsJrTqnQTyiZYzWlVuq9kE6zmtCrdKrIJVnNale7+2ASrOa1KN3RsgtWcVqV7NDbBak6r0m0Xm2A1p1XpSopNsJrTEr7p8M256Tb/+tq1LW9RcsvODSW37NxQcsvOC6XwLQd3lFzudkPJ5W43lFzudkPZQOmFksvdbihJO24oSTsWlMfjG6/n+hYlaccNJWnHC6XwTQh3lKQdC8r9B+X2FiVpxw0laccNZQOlF0rSjhtK0o4bStKOBeX6+Injur39iWOl6x/RKEk7XigrXSyJRknacUNJ2nFDSdpxQ9lA6YWStOOGkrTjhpK044aStOOGkrTjhbLS1aBolKQdN5SkHTeUpB03lA2UXihJO24oSTtuKEk7bihJO24oSTteKCtd7opGSdpxQ0nacUNJ2nFD2UDphZK044aStOOGkrTjhpK044aStOOEslW6nheNkrTjhpK044aStOOGsoHSCyVpxw1lbl+5tvZAuZ3HB5R38I8v3pe3gnO7P3/Bye/udRCc20l1EJzb73QQnNuVfCX4u+e/pWezJb/SF44nt3sIx5N7/xmOJ/dOMxxPIT/ZA08h99kBT/LLhR3xfBPs3n/mV5SFXHA0ykL+OhqlrHP3R9lA6YVSNhH4o5RND/4oZZOGP0rZVOKPUjbBuKNMfj10KJSkHTeUpB03lKQdN5QNlF4oSTtuKEk7bihJO24oSTtuKEk7XiiTX/AdCiVpxw0laccNJWnHDWUDpRdK0o4bStKOG0rSjhtK0o4bStKOF8rk97uHQknacUNJ2nFDSdpxQ9lA6YWStOOGkrTjhTL5ed8kKC2n0Fvy875DoeS1Y0FpaRFIfkh1KJS8dtxQsmRzQ8mSzQ0lSzYvlMkPqSZBuU3br6/dlvktSnylG0qWbG4oWbK5oWyg9EJJ2nFDSdpxQ0nacUNJ2nFDSdrxQpn8kOpQKEk7bihJO24oSTtuKBsovVCSdtxQknbcUJJ23FDqpp0vPsfUniyntqw/n2Nv/zJ43WwUCz75kdbC4HVzVzB43ZTmBP4Vpm5O6wCzAdMPpm5W6wBTN611gKmb1zrAJLE5wiSFucFckx+EHQwmackRJgnIBPN4KJzWZfsN5h++emqPXeQ0rS+fel9/Q09eCkPfQO+N3vvPI9fk52wZ0v83JNLgAEMiZQ4wJNLrAEMiFecfUqXT3nWHRIofYEhsBwYYEnuEAYbUGFL+IbFxGGBIbBwGGBIbhwGGxMZhgCGxccg/pJmNwwBDYuMwwJDYOAwwJDYOAwypMaT8Q2LjMMCQ2DgMMCQ2DgMMiY3DAENi45B/SAsbhwGGxMZhgCGxcRhgSGwcBhhSY0j5h8TGYYAhsXEYYEjkpNAhWa6ZrY2cNMCQcHexQzJcFbpDYEj5h4S7G2BIuLsBhsTPkwYYEj9PGmBI5KTQIVmaUNeVnDTAkPh50gBD4udJAwyJjcMAQ2oMKf+Q2DgMMCQ2DgMMiY3DAENi4zDAkNg45B/SxsZhgCGxcfAf0jffebo9W7yn6bXF+7c+442dwxBjYuswxJgaYxphTGwehhgTu4chxsT2YYgxsX8IHtO0P8c0b2/HxAZihDHt7CCGGBNbiCHGxBZiiDGxhRhiTI0xjTAmthDBYzJd/NvZQgwxJrYQQ4yJLcQQY2ILMcKYDrYQQ4yJLcQQY2IL8RfH9AqevUIQ+AZ4A/j7z86e4I/pA/j7j+Pa82GztLfoSf9h6En07ujn+YmjrW/Bk9GDwJO6g8CTo2PAnyTjIPBk3SDwpFd/8Ov6wLFPb8GTXoPAN8DHgCe7BoEnuQaBJ7kGgSe5BoEnuYaA324k1yDwJNcg8CTXIPAk1yDwDfAG8Pcnw+M7b9P+Abzth3/bjewahp70Goae/BqGngQbhp4MG4V+IsWGoSfHhqEnyYahJ8uGoW+gj0JPmg1DT5oNQ0+aDUNPmg1DT5qNQj+TZsPQk2bD0JNmw9CTZsPQN9BHoSfNhqEnzYahJ82GoSfNhqEnzUahX0izYehJs2HoSbNh6EmzYegb6KPQk2bD0JNmw9CTZsPQk2bD0JNmo9A30mwYetJsGHrSbBh60mwY+gb6KPSk2TD0pNkw9KTZMPSk2TD0pNko9CtpNgw9aTYMPWk2DD1pNgx9A30UetJsGHrSbBh60mwYetJsGHrSbBT6jTQbhp40G4aeNBuGnjQbhr6BPgo9aTYMPWk2DD1pNgw9aTYMPWk2Cv1Omg1DT5oNQ0+aDUNPmg1D30AfhZ40G4aeNBuGnjQbhp40G4aeNBuF/iDNhqEnzYahJ82GoSfNhqFvoI9CT5oNQ0+aDUNPmg1DT5oNQ0+ajUJ/kmbD0JNmw9CTZsPQk2bD0DfQR6EnzYahJ82GoSfNhqEnzYahJ80God9vpNkw9KTZMPSk2TD0pNkw9A30UehJs2HoSbNh6EmzYehJs2HoSbNR6CfSbBh60mwYetJsGHrSbBj6Bvoo9KTZMPSk2TD0pNkw9KTZMPSk2Sj0M2k2DD1pNgw9aTYMPWk2DH0DfRR60mwYetJsGHrSbBh60mwYetJsFPqFNBuGnjQbhp40G4aeNBuGvoE+Cj1pNgw9aTYMPWk2DD1pNgw9aTYKfSPNhqEnzYahJ82GoSfNhqFvoI9CT5oNQ0+aDUNPmg1DT5oNQ0+ajUK/kmbD0JNmw9CTZsPQk2bD0DfQR6EnzYahJ82GoSfNhqEnzYahJ83+h8/xgmcjcV7iIRVe4iG5XeIhXV3iaeC5wkNKucRDkrjEg9u/xIMjv8SDa77Cs+OaL/EUcs3ncTy++NzfCi7kg22CCzlbm+CmJriQ+7QJLuQnbYILOUSb4EKezya4kIszCT4K+TKbYDWndag5rUPNaR1NTbCa0zrUnNah5rQONad1qDmtU81pnWpO61RzWqea0zqbmmA1p3WqOa1TzWmdak7rFHNax03MaR03Mad13MSc1lHp9rxNcFMTLOa0jkrXzW2CxZzWUemSt02wmtOqdLXaJljNaVW60GwTrOa0Kl0jtglWc1qVLu/aBKs5rUpXZm2C1ZxWpYuqNsFqTqvS9VCbYDWnVelSpk2wmtOqdBXSJljNaVW6gGgTrOa0Kl37swlWc1qVLtvZBKs5rUpX3GyC1ZxWpYtlNsFqTqvSdS6bYDWnVekSlU2wmtOqdHXJJljNaVW6MGQTrOa0Kl3TsQlWc1qVLsfYBKs5rUpXUmyC1ZxWpYsgNsFqTqvS9QubYDWnVenSg02wmtOqdNXAJljNaVW6DmATrOa0KjX42wSrOa1KLfs2wWpOq1ITvk2wmtOq1FZvE6zmtCo1ytsEqzkttY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuIPtY74Q60j/lDriD/UOuJPtY74U60j/lTriD/VOuLPW1MTLOa0TrWO+FOtI/5U64g/1TriT7WO+FOtI/5U64g/1TriT7WO+FOtI/6s1CB+/9S356eezw/f+5vPMbXjoXBal+3nc+ztT9/5OJ/fef7wndc2//ratS1vh1TIO5QdUqWm9rpDKuTR6g6pkK+sO6RCXrjukBpDyj+kQpmj7pAKbaTrDqnQFr3ukNg4DDAkNg6xQzoeH3k913dDqnSxpO6Q2DgMMCQ2DgMMiY1D7JD2nyFtb4fUGFL+IbFxGGBIbBwGGBIbhwGGxMZhgCGxcYgd0vr4baF1e/vbQpUud9UdEhuHAYbExmGAIbFxGGBIjSHlHxIbhwGGxMZhgCGxcRhgSGwcBhgSG4f8Q6p0wbLukNg4DDAkNg4DDImNwwBDagwp/5DYOAwwJDYOAwyJjcMAQ2LjMMCQ2DjkH1KlS851h8TGYYAhsXEYYEhsHAYYUmNI+YfExmGAIbFxGGBIbBwGGBIbhwGGxMYh/5B2Ng4DDImNwwBDYuMwwJDYOAwwpMaQ8g+JjcMAQ2LjMMCQ2DjkH9Khm5O8+x0P3TTjjlI3c7ij1E0G7igbKL1Q6rpsd5S6Xtgdpa5jdUep+5Msd5S6P2/yRnmSdtxQknYsKC0lzCdpxw0laccNZQOlF0rSjgWlpdL0JO24oSTtuKEk7bihJO34oPznPw5KL5SkHZ+fON7/46QdN5SkHTeUDZReKEk7bihJO24oSTtuKEk7bihJO14oJ9KOG0rSjhtK0o4bStKOG8oGSi+UpB03lKQdN5SkHTeUpB03lKQdL5QzaccNJWnHDSVpxw0laccNZQOlF0rSjhtK0o4bStKOG0rSjhtK0o4XyoW044aStOOGkrTjhpK044aygdILJWnHDSVpxw0laccNJWnHDSVpxwtly+0rl/2h4Wzn7QPKc390CZz78lZwbvfXQXBTE5zbSXUQnNvvdBCc25V8Jfi75/95PL/1+f6ZnttphOPJ7R6i8ay595/heHLvNMPxFPKTPfAUcp898DRVPN8Eu/ef+RVlIRccjbKQv45GKevc/VHKunx/lLKJwB3lJpse/FHKJg1/lLKpxB+lbILxR9lA6YWStOOGkrTjhpK044aStOOGkrTjhTL55e+hUJJ23FCSdtxQknbcUDZQeqEk7bihJO24oSTtuKEk7bihJO14oUx+v3solKQdN5SkHTeUmCHL39V8Pll5R4kZ8kKZ/JBqFpSWv/ZKfkh1KJS8dtxQsmRzQ9lA6YWSJZsbSnylAeU2bb++dlvmtyjxlW4oWbK5oWTJ5oRySn5IdSiUpB03lKQdN5SkHTeUDZReKEk7bihJO24oSTtuKEk7bih1084Xn+OfLpDnd96mn8+xT68wk59SHQymbuLpAFM383SAqZt6OsBswPSDqZt8OsDUzT5fwTza8zufy1uYuumnA0zd/NMBJgnID2by86qDwSQBOcIkATnCJAF9CfP+X3kLswHTDyYJyBEmCejiT0ym5OdTw/GQUi7xkDuu8CQ/XRqOh2xwiQe3f4mn0uEoQxn/lPy4ZwfBlQ5HmQRXOhxlElzIfdoEF/KTNsGFHKJJcCvk+WyCC7k4m+BKJzpNgtWcVqkTnSbBak6r1IlOk2A1p1Xp6KZNsJrTqnQY0yZYzWlVOl5pE6zmtCodmLQJVnNalY412gSrOa1Khw9tgtWcVqUjgjbBak6r0kE+m2A1p1XpuJ1NsJrTqnQoziZYzWlVOrpmE6zmtCodMLMJVnNalY6B2QSrOa1Kh7VsgtWcVqUjVTbBak6r0sEnm2A1p1XpeJJNsJrTqnSIyCZYzWkdTU2wmtOqdAHLJljNaR1qTutQc1qV7oXZBKs5rUq3t2yC1ZxWpTtWNsFqTqvSTSibYDWnVem+kk2wmNOaK90qsgkWc1pzpbs/NsFiTmu+NTXBYk5rrnSPxiZYzGnNlW672ASrOa1KV1JsgtWclvBNh2/OTbfHFYK1LW9RcsvODSW37NxQcsvODSW37NxQcrnbC6XwHQd3lFzudkPJ5W43lFzudkPZQOmFkrRjQXk8vvF6rm9RknbcUJJ23FCSdtxQknYsKPcflNs7lMK3JtxRknbcUJJ23FCSdtxQNlB6oSTtWFCuj4+xbm9/4ljp+kc0StKOG0rSjhtK0o4XykpXVqJRknbcUJJ23FCSdtxQNlB6oSTtuKEk7bihJO24oSTtuKEk7XihrHTpKBolaccNJWnHDSVpxw1lA6UXStKOG0rSjhtK0o4bStKOG0rSjhfKStfGolGSdtxQknbcUJJ23FA2UHqhJO24oSTtuKEk7bihJO24oSTteKGsdPEvGiVpxw0laccNJWnHDWVuXznPjy8+l+X8gPLcH10C5/62SyD53b0OgnN7tA6Cczspf8HJ7+51EJzblXwl+Lvnv6lnM/mVvnA8ud1DOJ4Gnis8uXea4XgK+ckeeAq5zx54CnnVfsHu/Wd+RVnIBQejTH5tcSiUss7dH6Wsy/dHKZsI/FE2UHqhlE0a/ihlU4k/StkE44+StOOGkrTjhHJJfvF0KJSkHTeUpB03lKQdN5QNlF4oSTtuKEk7bihJO24oSTtuKEk7XiiTXx0eCiVpxw0laccNJWnHDWUDpRdK0o4bStKOF8rk532ToLScrFySn/cdCiWvHae/9lqSH1IdCiWvHTeULNncULJkc0PJks0LZfJDqklQbtP262u3ZX6LEl/phpIlmxtKlmxuKBsovVCSdtxQknbcUJJ23FCSdtxQkna8UCY/pDoUStKOG0rSjhtK3bTzxeeYbuv8/M7b9PM59uk3mA2YfjB1E08HmLqZpwNM3dTTAaZu7ukAUzf5+MNMflY1DcyjPb/zubyFqZt+OsDUzT8dYJKAHGE2YPrBJAE5wiQBOcIkAX0J8/5feQuTBOQIkwTkBzP5qdUQmK94yDSXeEgpl3jIHZd4Gniu8JANLvHg9i/xVDocZSjjX5If9+wguNLhKIvg5IcyOwgu5D5tggv5SZvgQg7RJripCS7k4myCK53oNAlWc1qlTnSaBKs5rVInOk2C1ZxWpaObNsFqTqvSYUybYDWnVel4pU2wmtOqdGDSJljNaVU61mgTrOa0Kh0+tAlWc1qVjgjaBKs5rUoH+WyC1ZxWpeN2NsFiTqtVOhRnEyzmtFqlo2s2wWJOq92ammAxp9UqHQOzCRZzWq3SYS2bYDWnVelIlU2wmtOqdPDJJljNaVU6nmQTrOa0Kh0isglWc1qTmtOa1JxWpQtYNsFqTmtWc1qzmtOqdC/MJljNaVW6vWUTrOa0Kt2xsglWc1qVbkLZBKs5rUr3lWyC1ZxWpVtFNsFqTqvS3R+bYDWnVemGjk2wmtOqdI/GJljNaVW67WITrOa0Kl1JsQlWc1rCNx2+OTfdHlcI1ra8RcktOy+Uwvcc3FFyy84NJbfs3FByudsNZQOlF0oud7uh5HK3G0oud7uhJO24oSTtWFAej2+8nus7lMK3G9xRknbcUJJ23FCSdiwo9x+U21uUDZReKEk7bihJO24oSTtuKEk7bihJOxaU6+Mnjuv29ieOla5/RKMk7bihJO24oSTtuKFsoPRCSdpxQ0nacUNJ2nFDSdpxQ0na8UJZ6QJPNErSjhtK0o4bStKOG8oGSi+UpB03lKQdN5SkHTeUpB03lKQdL5SVrmBFoyTtuKEk7bihJO24oWyg9EJJ2nFDSdpxQ0nacUNJ2nFDSdpxQrlWukQXjZK044aStOOGkrTjhrKB0gslaccNJWnHDSVpxwtl8rt7U3t8jnM6jg8ovXsH1uQ3+oLh5PZ+wXByu7lgOA047+HkdlzBcHJ7qGA4uV1RMJzcW91gOLn3tLFwkt9LDIaj6pANVTxr8juMwXBUHbIJTgPOeziqDtlQHrImvxsZDEfVIZvgqDpkExxVh2yBk/zOZTAcVYds+elD8vuZwXBUHbIJTgPOeziqDtkER9Uhm+CoOmQTHFWHbIKj6pAtcJLfJw2Gg0O+gINDvoCDQ76A04DzHg4O+QIODvkCDg75Ag4O+QIODvk9nORXeIPh4JAv4OCQL+DgkC/gNOC8h4NDvoCDQ76Ag0O+gINDvoCDQ34PJ/nl1mA4OOQLODjkCzg45As4DTjv4eCQL+DgkC/g4JAv4OCQL+DgkN/DyX1X8Tievy583EF5wrH8pV7uS4nRcBpw3sNJ7XOi4aT2OdFwUvucaDipfU40nNQ+JxhO7jt/0XBSbwKj4eCQL+CoOmTLH93nvpcXDUfVIZvgqDpkExxVh2z50+ncd+ei4ag6ZAuc3LfhouGoOmQTHFWHbIKj6pAtP33IfWMtGo6qQzbBUXXIJjiqDtkER9Uhm+CoOmQDnC33PbFoOKoO2QRH1SGb4OCQL+A04LyHg0O+gINDvoCDQ76Ag0O+gINDfg8n92W0aDg45As4OOQLODjkCzgNOO/h4JAv4OCQL+DgkC/g4JAv4OCQ38PJfRktGg4O+QIODvkCDg75Ak4Dzns4OOQLODjkCzg45As4OOQLODjk93ByX0aLhoNDvoDT/joc57+n2wKuULlL2MaXsI8v4Rhfwjm8hIAbRu4SpvElzONLWMaXMP7bueV+Oxv+eHZrud/OJgm5384mCbnfziYJud/Ohj/N29bcb2eThNxvZ5OE3G9nk4Tcb2eThNxvZ5OE3G9nywZjzf12NknI/XY2Scj9djZJyP12tkjYcr+dTRJyv51NEnK/nU0Scr+dTRJyv51NEsZ/O2/jv5238d/O2/hv5238t/M+/tt5H//tvI//dt7HfzsHNOG7Sxj/7byP/3bex3877+O/nffx387H+G/nY/y38zH+2/kY/+0c0MLtLmH8t/Mx/tv5GP/tfIz/dj7Gfzuf47+dz/Hfzuf4b+dz/LezT4/r9PhU87Q1TwmW3wrzaVuNlXCML+EcXcLu0y8aK2EaX8I8voRlfAltfAnr+BKGfzvvt9xvZ8Ov2u633G9nk4Tcb2eLhCn329kkIffb2fBLnvuU++1skpD77WySkPvtbJKQ++1skpD77WySkPvtbNhg7FPut7NJQu63s0XCnPvtbJKQ++1skpD77WySkPvtbJKQ++1skpD77WySkPvtbJIw/tt5Hv/tPI//dl7Gfzsv47+dl/Hfzsv4b2eflqpYCeO/nZfx387L+G/nZfy38zL+27mN/3Zu47+d2/hv5zb+29mnpSpWwvhv5zb+27mN/3Zu47+d2/hv53X8t/M6/tt5Hf/tvI7/dvZpqYqVMP7b2aUf6dbWh4TbefOUYPmtMJd+pFgJLv1IwRKm8SXM40tYxpfQxpewji9hG1/CPr6E8d/OW+63s+VXbffcb2eThNxvZ5OE3G9nk4Tcb2fLL3m69CMFS8j9djZJyP12NknI/XY2Scj9djZJyP12tmwwjtxvZ5OE3G9nk4Tcb2eThNxvZ5OE3G9nk4Tcb2eThNxvZ5OE3G9nk4Tcb2eThPHfzuf4b+dz/LfzOf7b+Rz/7XyO/3Y+x387n+O/nc/x387n+G/nc/i383Eb/u183IZ/Ox+34d/Ox234t/NxG/7tfNyGfzsft+Hfzsdt+LfzcRv+7Xzcxn87T+O/nafx387T+G/nafy3s0tLVbCE8d/O0/hv52nUt/P9//V//af//b/8p//xf/mf/4/7/49//of/53/9n/7bf/lf/+uv/+d/+7//t///f3L/2v8X"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"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","debug_symbols":"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1//eWvQ6S+3rLHWss9S5zFLzy0xLx0t9mWnp6LuaLb/MtHS81JeZlo6Xai+y1MNvybb8MtPS0VcwW36Zael4qa8yLR1+XaflV5mWPrHUV5mWjpdaXmVa+sRSX2Va+sRSX2Va+sRSX2VaOvxuVXPYIvZplvoq09Inlvoq09Lht9paeZlp6fC7PuVlpqXjpb7MtHS4VHuVaen4Q0d7lWnpE0t9lWnpE0t9lWnpE0u1dZb6KtPSJ5b6KtPSJ5b6KtPS8VIdNvtK6TZoWxrbQfm5bLf6c0m7udJhOyz3krJeSUWvJNMrqUaXZPdvtv3379spqemV1PVKGnolTbmSWnj3LuWjpN0TSkt6JWW9kopeSaZXUtUrqemV1PVKGnolTbmSenj3zu1eUtm9JN6TXklZr6SiV5LplVT1Smp6JXW9koZeSVOupKHXvYde9x563Xvode+h172HXvceet176HXvode9h173nnrde+p176nXvade95563Xvqde+p172nXveeet17ynXvvsl1777Jde++yXXvvsl1775F96X0UVLKY7ekrlfS0CtpypWUNr2SovtSqv1eUsu7JWW9kopeSaZXUtUrKbx7fzy6KLWyW1LXK2nolTTlSsqbXklJr6SsV1LRK8n0Sqp6JYV37/vXct/+2XdL6nolDb2SplxJZdMrKemVlPVKKnolmV5JVa8kve5d9Lp30eveRa97m173Nr3ubXrd2/S6t+l1b9Pr3qbXvU2ve5te9za97l31unfV695Vr3tXve5d9bp31eveVa97V73uXfW6d9Xr3h73x5WPko43dKi323brN883zzndCypqBZlaQVWtoKZWUA8u6P4Mrra13YKGWkFTrCCP++F8C0pqBWW1gqI79bg97bmOsVuQqRVU1QpqagV1tYKGWkFTrKCxqRWU1ArKagWpdeqh1qmHWqceap16qHXqodaph1qnnmqdeqp16qnWqadap55qnXqqdeqp1qmnWqeeap16inXqsYl16rGJdeqxiXXqsYl16rGJdeqxiXXqsYl16rGJdeqxiXXqsal16qTWqZNOp377T//xu3/7w+/+8Y+///PbT/z0P/77j//0lz/86cf3//iX//zX//lf3l77Xw=="},{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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mgKgaRqApqkAmqYDaJoSoGlagKapAZqmB2iaIqBpmoCmqQKapgtomjKgadqApqkDmqYPaJpCoGkagaapBJqmE2iaUqBpWoGmqQWaphdommKgaZqBpqkGmqYbaJpyoGnagaapB5qmH2iagqBpGoKmqQiapiNompKgaVqCpqkJmqYnaJqioGmagqapCpqmK2iasqBp2oKmqQuapi9omsKgaRqDpqkMmqYzaJrSoGlag6apDZqmN2ia4qBpmoOmqQ6apjvomu6ga7qDrukOuqY76GNqlknNMqVZpjXLLM0yGgpouoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOuqY76JruoGu6g67pDrqmO+ia7qBruoOu6Q66pjvomu6ga7qDrukOhqY7GJruYGi6g6HpDsaYmmVSs0xplmnNMpq/ZEzTHQxNdzA03cHQdAdD0x0MTXcwNN3B0HQHQ9MdDE13MDTdwdB0B0PTHQxNdzA03cHQdAdD0x0MTXcwNN3B0HQHQ9MdDE13MDTdwdB0B0PTHQxNdzA03cHQdAdD0x0M0V87rOkOhqY7GJruYGi6g6HpDoamOxia7mBouoOh6Q6GpjsYmu5gaLqDoekOhqY7GJruYGi6g6HpDoamOxia7mBouoOh6Q6GpjsYmu5gaLqDoekOhqY7GJruYGi6g6HpDoamOxiP6A6+fBezT0dHR70eHXnj6Fz+6eBc63qsu10iPaJn+OhIxovkvEjBizR5kZIXqXiRmhdp8SLx6L149F48ei8evReP3otH78Wj9+LRe/HovXj0Xjx6bx69N4/em0fvzaP35tF78+i9efTePHpvHr03jt5z4Og9B47ec+DoPQeO3nPg6D0Hjt5z4Og9B47ec+DoPQeP3sajt/HobTx6G4/e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"}],"outputs":{"globals":{"notes":[{"fields":[{"kind":"integer","sign":false,"value":"00000000000000000000000000000000000000000000000000000000906cb9c3"},{"kind":"string","value":"EcdsaPublicKeyNote"}],"kind":"tuple"}],"storage":[{"fields":[{"name":"public_key","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"EcdsaAccount::entrypoint_parameters"}}],"kind":"struct","path":"EcdsaAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"EcdsaAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"EcdsaAccount::verify_private_authwit_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"signing_pub_key_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"signing_pub_key_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}}],"kind":"struct","path":"EcdsaAccount::constructor_parameters"}}],"kind":"struct","path":"EcdsaAccount::constructor_abi"}]}},"file_map":{"100":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash\n};\n\nuse dep::std::aes128::aes128_encrypt;\nuse dep::std::println;\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogOutgoingBody {\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint,\n}\n\nimpl EncryptedLogOutgoingBody {\n pub fn new(\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint\n ) -> Self {\n Self { eph_sk, recipient, recipient_ivpk_app }\n }\n\n pub fn compute_ciphertext(self, ovsk_app: GrumpkinPrivateKey, eph_pk: GrumpkinPoint) -> [u8; 176] {\n // Again, we could compute `eph_pk` here, but we keep the interface more similar\n // and also make it easier to optimise it later as we just pass it along\n\n let mut buffer: [u8; 160] = [0; 160];\n\n let serialized_eph_sk: [Field; 2] = self.eph_sk.serialize();\n let serialized_eph_sk_high = serialized_eph_sk[0].to_be_bytes(32);\n let serialized_eph_sk_low = serialized_eph_sk[1].to_be_bytes(32);\n\n let address_bytes = self.recipient.to_field().to_be_bytes(32);\n let serialized_recipient_ivpk_app = self.recipient_ivpk_app.serialize();\n let serialized_recipient_ivpk_app_x = serialized_recipient_ivpk_app[0].to_be_bytes(32);\n let serialized_recipient_ivpk_app_y = serialized_recipient_ivpk_app[1].to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = serialized_eph_sk_high[i];\n buffer[i + 32] = serialized_eph_sk_low[i];\n buffer[i + 64] = address_bytes[i];\n buffer[i + 96] = serialized_recipient_ivpk_app_x[i];\n buffer[i + 128] = serialized_recipient_ivpk_app_y[i];\n }\n\n // We compute the symmetric key using poseidon.\n let full_key: [u8; 32] = poseidon2_hash(\n [\n ovsk_app.high, ovsk_app.low, eph_pk.x, eph_pk.y,\n GENERATOR_INDEX__SYMMETRIC_KEY as Field\n ]\n ).to_be_bytes(32).as_array();\n\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(buffer, iv, sym_key).as_array()\n }\n}\n\nmod test {\n use crate::encrypted_logs::outgoing_body::EncryptedLogOutgoingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash\n };\n\n use crate::context::PrivateContext;\n\n #[test]\n fn test_encrypted_log_outgoing_body() {\n let eph_sk = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb,\n 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe\n );\n let recipient_ivsk_app = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31,\n 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022\n );\n let sender_ovsk_app = GrumpkinPrivateKey::new(\n 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b,\n 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e\n );\n\n let eph_pk = eph_sk.derive_public_key();\n let recipient_ivpk_app = recipient_ivsk_app.derive_public_key();\n\n let recipient = AztecAddress::from_field(0xdeadbeef);\n\n let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app);\n\n let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk);\n\n let expected_outgoing_body_ciphertext = [\n 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 122, 191, 158, 69, 35, 255, 215, 171, 196, 45, 91, 184, 83, 80, 238, 201, 1, 233, 235, 159, 171, 130, 158, 64, 176, 165, 132, 30, 84, 81, 71, 195, 145, 47, 82, 247, 210, 192, 23, 4, 220, 90, 56, 109, 46, 105, 79, 251, 165, 141, 185, 233, 191, 118, 219, 153, 191, 162, 99, 238, 241, 249, 9, 74, 210, 241, 54, 28, 126, 226, 85, 235, 174, 75, 239, 207, 100, 184, 248, 194\n ];\n\n for i in 0..expected_outgoing_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_outgoing_body_ciphertext[i]);\n }\n assert_eq(expected_outgoing_body_ciphertext.len(), ciphertext.len());\n }\n}\n"},"101":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nuse dep::std::aes128::aes128_encrypt;\n\nstruct EncryptedLogHeader {\n address: AztecAddress,\n}\n\nimpl EncryptedLogHeader {\n fn new(address: AztecAddress) -> Self {\n EncryptedLogHeader { address }\n }\n\n fn compute_ciphertext(self, secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 48] {\n let full_key = point_to_symmetric_key(secret, point);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n\n let input: [u8; 32] = self.address.to_field().to_be_bytes(32).as_array();\n aes128_encrypt(input, iv, sym_key).as_array()\n }\n}\n\n#[test]\nfn test_encrypted_log_header() {\n let address = AztecAddress::from_field(0xdeadbeef);\n let header = EncryptedLogHeader::new(address);\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let ciphertext = header.compute_ciphertext(secret, point);\n\n let expected_header_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 23, 131, 32, 226, 26, 176, 43, 39, 239, 177, 177, 192, 85, 216, 17, 15, 18, 187, 35, 225, 135, 192, 63, 88, 29, 173, 232, 46, 72, 82, 187, 139\n ];\n\n assert_eq(ciphertext, expected_header_ciphertext);\n}\n"},"102":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr","source":"use crate::note::note_interface::NoteInterface;\nuse crate::event::event_interface::EventInterface;\nuse dep::protocol_types::{grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse dep::std::aes128::aes128_encrypt;\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogIncomingBody {\n plaintext: [u8; M]\n}\n\nimpl EncryptedLogIncomingBody {\n pub fn from_note(note: T, storage_slot: Field) -> Self where T: NoteInterface {\n let mut plaintext = note.to_be_bytes(storage_slot);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface {\n let mut plaintext = event.private_to_be_bytes(randomness);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn compute_ciphertext(self, eph_sk: GrumpkinPrivateKey, ivpk_app: GrumpkinPoint) -> [u8] {\n let full_key = point_to_symmetric_key(eph_sk, ivpk_app);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(self.plaintext, iv, sym_key)\n }\n}\n\nmod test {\n use crate::encrypted_logs::incoming_body::EncryptedLogIncomingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, traits::Serialize,\n abis::event_selector::EventSelector\n };\n\n use crate::{\n note::{note_header::NoteHeader, note_interface::NoteInterface},\n event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand,\n context::PrivateContext\n };\n\n struct AddressNote {\n address: AztecAddress,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n }\n\n global ADDRESS_NOTE_LEN: Field = 3;\n global ADDRESS_NOTE_BYTES_LEN = 32 * 3 + 64;\n\n impl NoteInterface for AddressNote {\n fn compute_note_content_hash(self) -> Field {1}\n\n fn get_note_type_id() -> Field {\n 1\n }\n\n fn get_header(self) -> NoteHeader { self.header}\n\n fn set_header(&mut self, header: NoteHeader) {self.header = header; }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n (1, 1)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {(1,1)}\n\n fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]}\n\n fn deserialize_content(fields: [Field; ADDRESS_NOTE_LEN]) -> Self {\n AddressNote { address: AztecAddress::from_field(fields[0]), owner: AztecAddress::from_field(fields[1]), randomness: fields[2], header: NoteHeader::empty() }\n }\n\n fn to_be_bytes(self, storage_slot: Field) -> [u8; ADDRESS_NOTE_BYTES_LEN] {\n let serialized_note = self.serialize_content();\n\n let mut buffer: [u8; ADDRESS_NOTE_BYTES_LEN] = [0; ADDRESS_NOTE_BYTES_LEN];\n\n let storage_slot_bytes = storage_slot.to_be_bytes(32);\n let note_type_id_bytes = AddressNote::get_note_type_id().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = storage_slot_bytes[i];\n buffer[32 + i] = note_type_id_bytes[i];\n }\n\n for i in 0..serialized_note.len() {\n let bytes = serialized_note[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n buffer\n }\n }\n\n impl AddressNote {\n pub fn new(address: AztecAddress, owner: AztecAddress, randomness: Field) -> Self {\n AddressNote { address, owner, randomness, header: NoteHeader::empty() }\n }\n }\n\n #[test]\n fn test_encrypted_note_log_incoming_body() {\n let note = AddressNote::new(\n AztecAddress::from_field(0x1),\n AztecAddress::from_field(0x2),\n 3\n );\n\n let storage_slot = 2;\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let body = EncryptedLogIncomingBody::from_note(note, storage_slot);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_note_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100\n ];\n\n assert_eq(expected_note_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_note_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_note_body_ciphertext[i]);\n }\n }\n\n struct TestEvent {\n value0: Field,\n value1: Field,\n value2: Field,\n }\n\n impl Serialize<3> for TestEvent {\n fn serialize(self) -> [Field; 3] {\n [self.value0, self.value1, self.value2]\n }\n }\n\n global TEST_EVENT_LEN: Field = 3;\n global TEST_EVENT_BYTES_LEN = 32 * 3 + 64;\n global TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS = 32 * 3 + 32;\n\n impl EventInterface for TestEvent {\n fn get_event_type_id() -> EventSelector {\n EventSelector::from_signature(\"TestEvent(Field,Field,Field)\")\n }\n\n fn private_to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN] = [0; TEST_EVENT_BYTES_LEN];\n\n let randomness_bytes = randomness.to_be_bytes(32);\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = randomness_bytes[i];\n buffer[32 + i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn to_be_bytes(self) -> [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] = [0; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS];\n\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[32 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n }\n\n #[test]\n fn test_encrypted_log_event_incoming_body() {\n let test_event = TestEvent { value0: 1, value1: 2, value2: 3 };\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let randomness = 2;\n\n let body = EncryptedLogIncomingBody::from_event(test_event, randomness);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_event_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160\n ];\n\n assert_eq(expected_event_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_event_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_event_body_ciphertext[i]);\n }\n }\n}\n"},"107":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/utils.nr","source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n constants::GENERATOR_INDEX__INNER_NOTE_HASH,\n hash::{\n pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash,\n compute_siloed_nullifier as compute_siloed_nullifier_from_preimage\n},\n utils::arr_copy_slice\n};\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n pedersen_hash(\n [header.storage_slot, note_hash],\n GENERATOR_INDEX__INNER_NOTE_HASH\n )\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let (_, inner_nullifier) = note_with_header.compute_note_hash_and_nullifier(context);\n\n compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier)\n}\n\nfn compute_note_hash_for_read_request_from_innter_and_nonce(\n inner_note_hash: Field,\n nonce: Field\n) -> Field {\n // TODO(#1386): This if-else can be nuked once we have nonces injected from public\n if (nonce == 0) {\n // If nonce is zero, that means we are reading a public note.\n inner_note_hash\n } else {\n compute_unique_note_hash(nonce, inner_note_hash)\n }\n}\n\npub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface {\n let inner_note_hash = compute_inner_note_hash(note);\n let nonce = note.get_header().nonce;\n\n compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n if (header.note_hash_counter != 0) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n inner_note_hash\n } else {\n // If a note is not transient, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the siloed_note_hash which has already been hashed with\n // nonce and then contract address. This hash will match the existing leaf in the note hash\n // tree, so the kernel can just perform a membership check directly on this hash/leaf.\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce);\n compute_siloed_note_hash(header.contract_address, unique_note_hash)\n // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is\n // \"siloed\" by contract address. When a note hash is computed solely for the purpose of\n // nullification, it is not strictly necessary to silo the note hash before computing\n // its nullifier. In other words, it is NOT NECESSARY for protocol security that a nullifier\n // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are\n // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be\n // used for nullifier computation, and this achieves the (arguably unnecessary) property that\n // nullifiers are computed from a note hash's fully-computed note hash tree leaf.\n }\n}\n\npub fn compute_note_hash_and_optionally_a_nullifier(\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n compute_nullifier: bool,\n serialized_note: [Field; S]\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n note.set_header(note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, note_header.nonce);\n let siloed_note_hash = compute_siloed_note_hash(note_header.contract_address, unique_note_hash);\n\n let inner_nullifier = if compute_nullifier {\n let (_, nullifier) = note.compute_note_hash_and_nullifier_without_context();\n nullifier\n } else {\n 0\n };\n // docs:start:compute_note_hash_and_optionally_a_nullifier_returns\n [inner_note_hash, unique_note_hash, siloed_note_hash, inner_nullifier]\n // docs:end:compute_note_hash_and_optionally_a_nullifier_returns\n}\n"},"108":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr","source":"use dep::protocol_types::grumpkin_point::GrumpkinPoint;\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note\n) -> NoteEmission where Note: NoteInterface {\n let contract_address = (*context).this_address();\n let note_hash_counter = context.side_effect_counter;\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n let serialized_note = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash,\n note_hash_counter\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n NoteEmission::new(*note)\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(\n context: &mut PrivateContext,\n note: Note\n) where Note: NoteInterface {\n let (note_hash, nullifier) = note.compute_note_hash_and_nullifier(context);\n\n let note_hash_counter = note.get_header().note_hash_counter;\n let note_hash_for_consumption = if (note_hash_counter == 0) {\n // Counter is zero, so we're nullifying a non-transient note and we don't populate the note_hash with real\n // value (if we did so the `notifyNullifiedNote` oracle would throw).\n 0\n } else {\n // A non-zero note hash counter implies that we're nullifying a transient note (i.e. one that has not yet been\n // persisted in the trees and is instead in the pending new note hashes array). In such a case we populate its\n // hash with real value to inform the kernel which note we're nullifyng so that it can find it and squash both\n // the note and the nullifier.\n note_hash\n };\n\n let nullifier_counter = context.side_effect_counter;\n assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0);\n\n context.push_new_nullifier(nullifier, note_hash_for_consumption)\n}\n"},"109":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_emission.nr","source":"/**\n * A note emission struct containing the information required for emitting a note.\n * The exact `emit` logic is passed in by the application code\n */\nstruct NoteEmission {\n note: Note\n}\n\nimpl NoteEmission {\n pub fn new(note: Note) -> Self {\n Self { note }\n }\n\n pub fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n\n pub fn discard(self) {}\n}\n\n/**\n * A struct wrapping note emission in `Option`.\n * This is the struct provided to application codes, which can be used to emit\n * only when a note was actually inserted.\n * It is fairly common to have cases where a function conditionally inserts,\n * and this allows us to keep the same API for emission in both cases (e.g. inserting \n * a change note in a token's transfer function only when there is \"change\" left).\n */\nstruct OuterNoteEmission {\n emission: Option>,\n}\n\nimpl OuterNoteEmission {\n pub fn new(emission: Option>) -> Self {\n Self { emission }\n }\n\n pub fn emit(self, _emit: fn[Env](NoteEmission) -> ()) {\n if self.emission.is_some() {\n _emit(self.emission.unwrap());\n }\n }\n\n pub fn discard(self) {}\n}\n"},"112":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_getter.nr","source":"use dep::protocol_types::{constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTES_ORACLE_RETURN_LENGTH}};\nuse crate::context::PrivateContext;\nuse crate::note::{\n constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH},\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_request\n};\nuse crate::oracle;\n\nmod test;\n\nfn extract_property_value_from_selector(\n serialized_note: [Field; N],\n selector: PropertySelector\n) -> Field {\n // Selectors use PropertySelectors in order to locate note properties inside the serialized note. \n // This allows easier packing and custom (de)serialization schemas. A note property is located\n // inside the serialized note using the index inside the array, a byte offset and a length.\n let value = serialized_note[selector.index].to_be_bytes(32);\n let offset = selector.offset;\n let length = selector.length;\n let mut value_field = 0 as Field;\n let mut acc: Field = 1;\n for i in 0..32 {\n if i < length {\n value_field += value[31 + offset - i] as Field * acc;\n acc = acc * 256;\n }\n }\n value_field\n}\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note: Note\n) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address), \"Mismatch note header contract address.\");\n assert(header.storage_slot == storage_slot, \"Mismatch note header storage slot.\");\n}\n\nfn check_note_fields(serialized_note: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n let value_field = extract_property_value_from_selector(serialized_note, select.property_selector);\n\n // Values are computed ahead of time because circuits evaluate all branches\n let is_equal = value_field == select.value.to_field();\n let is_lt = value_field.lt(select.value.to_field());\n\n if (select.comparator == Comparator.EQ) {\n assert(is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(is_lt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(is_lt | is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!is_lt & !is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!is_lt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let field_0 = extract_property_value_from_selector(fields_0, sort.property_selector);\n let field_1 = extract_property_value_from_selector(fields_1, sort.property_selector);\n let eq = field_0 == field_1;\n let lt = field_0.lt(field_1);\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n\n context.push_note_hash_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n\n constrain_get_notes_internal(context, storage_slot, opt_notes, options)\n}\n\nfn constrain_get_notes_internal(\n context: &mut PrivateContext,\n storage_slot: Field,\n opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let mut returned_notes = BoundedVec::new();\n\n // The filter is applied first to avoid pushing note read requests for notes we're not interested in. Note that\n // while the filter function can technically mutate the contents of the notes (as opposed to simply removing some),\n // the private kernel will later validate that these note actually exist, so transformations would cause for that\n // check to fail.\n let filter_fn = options.filter;\n let filter_args = options.filter_args;\n let filtered_notes = filter_fn(opt_notes, filter_args);\n\n let mut prev_fields = [0; N];\n for i in 0..filtered_notes.len() {\n let opt_note = filtered_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_note_hash_read_request(note_hash_for_read_request);\n\n // The below code is used to collapse a sparse array into one where the values are guaranteed to be at the \n // front of the array. This is highly useful because the caller knows that the returned array won't have\n // more than option.limits notes, and can therefore loop over this limit value instead of the entire array,\n // resulting in a smaller circuit and faster proving times.\n // We write at returned_notes[num_notes] because num_notes is only advanced when we have a value in \n // filtered_notes.\n returned_notes.push(note);\n };\n }\n\n assert(returned_notes.len() <= options.limit, \"Got more notes than limit.\");\n assert(returned_notes.len() != 0, \"Cannot return zero notes\");\n\n returned_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n // This function simply performs some transformations from NoteGetterOptions into the types required by the oracle.\n\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> BoundedVec where Note: NoteInterface {\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n let notes_array = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let mut notes = BoundedVec::new();\n for i in 0..notes_array.len() {\n if notes_array[i].is_some() {\n notes.push(notes_array[i].unwrap_unchecked());\n }\n }\n\n notes\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [u8; N], [u8; N], [Field; N], [u8; N], [u8; N], [u8; N], [u8; N], [u8; N]) {\n let mut num_selects = 0;\n let mut select_by_indexes = [0; N];\n let mut select_by_offsets = [0; N];\n let mut select_by_lengths = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by_indexes[num_selects] = select.unwrap_unchecked().property_selector.index;\n select_by_offsets[num_selects] = select.unwrap_unchecked().property_selector.offset;\n select_by_lengths[num_selects] = select.unwrap_unchecked().property_selector.length;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by_indexes = [0; N];\n let mut sort_by_offsets = [0; N];\n let mut sort_by_lengths = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by_indexes[i] = sort.unwrap_unchecked().property_selector.index;\n sort_by_offsets[i] = sort.unwrap_unchecked().property_selector.offset;\n sort_by_lengths[i] = sort.unwrap_unchecked().property_selector.length;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (\n num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order\n )\n}\n"},"113":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_header.nr","source":"use dep::protocol_types::address::AztecAddress;\nuse dep::protocol_types::traits::{Empty, Eq, Serialize};\n\nstruct NoteHeader {\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)\n // Check the nonce to see whether a note is transient or not.\n note_hash_counter: u32, // a note_hash_counter of 0 means non-transient\n}\n\nimpl Empty for NoteHeader {\n fn empty() -> Self {\n NoteHeader { contract_address: AztecAddress::zero(), nonce: 0, storage_slot: 0, note_hash_counter: 0 }\n }\n}\n\nimpl Eq for NoteHeader {\n fn eq(self, other: Self) -> bool {\n (self.contract_address == other.contract_address) & \n (self.nonce == other.nonce) & \n (self.storage_slot == other.storage_slot)& \n (self.note_hash_counter == other.note_hash_counter)\n }\n}\n\nimpl NoteHeader {\n pub fn new(contract_address: AztecAddress, nonce: Field, storage_slot: Field) -> Self {\n NoteHeader { contract_address, nonce, storage_slot, note_hash_counter: 0 }\n }\n}\n\nimpl Serialize<4> for NoteHeader {\n fn serialize(self) -> [Field; 4] {\n [self.contract_address.to_field(), self.nonce, self.storage_slot, self.note_hash_counter as Field]\n }\n}\n"},"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"118":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/initializer.nr","source":"use dep::protocol_types::{\n address::AztecAddress, hash::{compute_siloed_nullifier, pedersen_hash},\n constants::GENERATOR_INDEX__CONSTRUCTOR, abis::function_selector::FunctionSelector\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext}, oracle::get_contract_instance::get_contract_instance,\n oracle::get_contract_instance::get_contract_instance_avm\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn assert_is_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_contract_initialization_nullifier(context.this_address());\n let header = context.get_header();\n header.prove_nullifier_inclusion(init_nullifier);\n}\n\nfn compute_contract_initialization_nullifier(address: AztecAddress) -> Field {\n compute_siloed_nullifier(\n address,\n compute_unsiloed_contract_initialization_nullifier(address)\n )\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let instance = get_contract_instance_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn compute_initialization_hash(init_selector: FunctionSelector, init_args_hash: Field) -> Field {\n pedersen_hash(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n"},"120":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr","source":"use dep::protocol_types::{\n abis::nullifier_leaf_preimage::{NullifierLeafPreimage, NULLIFIER_LEAF_PREIMAGE_LENGTH},\n constants::NULLIFIER_TREE_HEIGHT, hash::pedersen_hash, utils::arr_copy_slice\n};\n\n// INDEX_LENGTH + NULLIFIER_LEAF_PREIMAGE_LENGTH + NULLIFIER_TREE_HEIGHT\nglobal NULLIFIER_MEMBERSHIP_WITNESS: Field = 24;\n\nstruct NullifierMembershipWitness {\n index: Field,\n leaf_preimage: NullifierLeafPreimage,\n path: [Field; NULLIFIER_TREE_HEIGHT],\n}\n\nimpl NullifierMembershipWitness {\n pub fn deserialize(fields: [Field; NULLIFIER_MEMBERSHIP_WITNESS]) -> Self {\n let leaf_preimage_fields = arr_copy_slice(fields, [0; NULLIFIER_LEAF_PREIMAGE_LENGTH], 1);\n Self {\n index: fields[0],\n leaf_preimage: NullifierLeafPreimage::deserialize(leaf_preimage_fields),\n path: arr_copy_slice(\n fields,\n [0; NULLIFIER_TREE_HEIGHT],\n 1 + NULLIFIER_LEAF_PREIMAGE_LENGTH\n )\n }\n }\n}\n\n#[oracle(getLowNullifierMembershipWitness)]\nunconstrained fn get_low_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_low_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n\n#[oracle(getNullifierMembershipWitness)]\nunconstrained fn get_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"126":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr","source":"use dep::protocol_types::{\n grumpkin_point::GrumpkinPoint,\n abis::validation_requests::{KeyValidationRequest, key_validation_request::KEY_VALIDATION_REQUEST_LENGTH}\n};\n\n#[oracle(getKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field\n) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {}\n\nunconstrained fn get_key_validation_request_internal(npk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n let result = get_key_validation_request_oracle(npk_m_hash, key_index);\n KeyValidationRequest::deserialize(result)\n}\n\npub fn get_key_validation_request(pk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n get_key_validation_request_internal(pk_m_hash, key_index)\n}\n\n"},"130":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/unsafe_rand.nr","source":"#[oracle(getRandomField)]\nunconstrained fn rand_oracle() -> Field {}\n\n// Called `unsafe_rand` because we do not constrain in circuit that we are dealing with an actual random value.\n// Instead we just trust our PXE.\nunconstrained pub fn unsafe_rand() -> Field {\n rand_oracle()\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"133":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/keys.nr","source":"use crate::keys::PublicKeys;\nuse dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {}\n\nunconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] {\n get_public_keys_and_partial_address_oracle(address)\n}\n\nfn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle_wrapper(address);\n\n let keys = PublicKeys {\n npk_m: GrumpkinPoint::new(result[0], result[1]),\n ivpk_m: GrumpkinPoint::new(result[2], result[3]),\n ovpk_m: GrumpkinPoint::new(result[4], result[5]),\n tpk_m: GrumpkinPoint::new(result[6], result[7])\n };\n\n let partial_address = PartialAddress::from_field(result[8]);\n\n (keys, partial_address)\n}\n"},"135":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/notes.nr","source":"use crate::note::{note_header::NoteHeader, note_interface::NoteInterface};\n\nuse dep::protocol_types::{address::AztecAddress, utils::arr_copy_slice};\n\n#[oracle(notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field,\n _counter: u32\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_created_note_oracle(\n storage_slot,\n note_type_id,\n serialized_note,\n inner_note_hash,\n counter\n )\n}\n\n#[oracle(notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field, _counter: u32) -> Field {}\n\nunconstrained pub fn notify_nullified_note(\n nullifier: Field,\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash, counter)\n}\n\n#[oracle(getNotes)]\nunconstrained fn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by_indexes: [u8; N],\n _select_by_offsets: [u8; N],\n _select_by_lengths: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u8; N],\n _sort_by_indexes: [u8; N],\n _sort_by_offsets: [u8; N],\n _sort_by_lengths: [u8; N],\n _sort_order: [u8; N],\n _limit: u32,\n _offset: u32,\n _status: u8,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; N],\n select_by_offsets: [u8; N],\n select_by_lengths: [u8; N],\n select_values: [Field; N],\n select_comparators: [u8; N],\n sort_by_indexes: [u8; N],\n sort_by_offsets: [u8; N],\n sort_by_lengths: [u8; N],\n sort_order: [u8; N],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; M],\n select_by_offsets: [u8; M],\n select_by_lengths: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by_indexes: [u8; M],\n sort_by_offsets: [u8; M],\n sort_by_lengths: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i < num_notes {\n // lengths named as per typescript.\n let return_header_length: u32 = 2; // num_notes & contract_address.\n let extra_preimage_length: u32 = 2; // nonce & note_hash_counter.\n let read_offset: u32 = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let note_hash_counter = fields[read_offset + 1] as u32;\n let header = NoteHeader { contract_address, nonce, storage_slot, note_hash_counter };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n note.set_header(header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n// Only ever use this in private!\n#[oracle(checkNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\n// Only ever use this in private!\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"154":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header};\n\nuse crate::context::PrivateContext;\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange}\n};\n\nstruct SharedMutablePrivateGetter {\n context: &mut PrivateContext,\n // The contract address of the contract we want to read from\n other_contract_address: AztecAddress,\n // The storage slot where the SharedMutable is stored on the other contract\n storage_slot: Field,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numberic value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\n// We have this as a view-only interface to reading Shared Mutables in other contracts.\n// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date\nimpl SharedMutablePrivateGetter {\n pub fn new(\n context: &mut PrivateContext,\n other_contract_address: AztecAddress,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n assert(other_contract_address.to_field() != 0, \"Other contract address cannot be 0\");\n Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] }\n }\n\n pub fn get_value_in_private(self, header: Header) -> T where T: FromField {\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header);\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // If our context has the same header as the one we pass in via the parameter, we are trying to read the \"current\" value\n // and thus need to set the tx max block number below. If the context header is not the same as the one we pass in, this means\n // we are trying to read a historical value and thus have no constraint on the max block number that this transaction can be included in.\n if (self.context.historical_header.global_variables.block_number.eq(header.global_variables.block_number)) {\n self.context.set_tx_max_block_number(block_horizon);\n }\n\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n header: Header\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n self.other_contract_address\n );\n }\n\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"159":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash\n};\n\nuse crate::context::{PrivateContext, UnconstrainedContext};\nuse crate::note::{\n lifecycle::create_note, note_getter::{get_note, view_notes}, note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions, note_emission::NoteEmission\n};\nuse crate::oracle::notes::check_nullifier_exists;\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct PrivateImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:struct\n\nimpl Storage for PrivateImmutable {}\n\nimpl PrivateImmutable {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. \n // e.g. the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n}\n\nimpl PrivateImmutable {\n // docs:start:initialize\n pub fn initialize(\n self,\n note: &mut Note\n ) -> NoteEmission where Note: NoteInterface {\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_new_nullifier(nullifier, 0);\n\n create_note(self.context, self.storage_slot, note)\n }\n // docs:end:initialize\n\n // docs:start:get_note\n pub fn get_note(self) -> Note where Note: NoteInterface {\n let storage_slot = self.storage_slot;\n get_note(self.context, storage_slot)\n }\n // docs:end:get_note\n}\n\nimpl PrivateImmutable {\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // view_note does not actually use the context, but it calls oracles that are only available in private\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let mut options = NoteViewerOptions::new();\n view_notes(self.storage_slot, options.set_limit(1)).get(0)\n }\n // docs:end:view_note\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"187":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr","source":"global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3;\n\nuse crate::{\n abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::compute_siloed_nullifier,\n merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash}\n};\n\nstruct NullifierLeafPreimage {\n nullifier : Field,\n next_nullifier :Field,\n next_index : u32,\n}\n\nimpl Empty for NullifierLeafPreimage {\n fn empty() -> Self {\n Self {\n nullifier : 0,\n next_nullifier : 0,\n next_index : 0,\n }\n }\n}\n\nimpl Hash for NullifierLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash(self.serialize())\n }\n }\n}\n\nimpl LeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl IndexedTreeLeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn get_next_key(self) -> Field {\n self.next_nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl Readable for NullifierLeafPreimage {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n let siloed_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.nullifier, siloed_value, \"Value of the nullifier leaf does not match read request\");\n }\n}\n\nimpl NullifierLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.nullifier == 0) & (self.next_nullifier == 0) & (self.next_index == 0)\n }\n\n pub fn serialize(self) -> [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH] {\n [self.nullifier, self.next_nullifier, self.next_index as Field]\n }\n\n pub fn deserialize(fields: [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH]) -> Self {\n Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u32 }\n }\n}\n\nimpl Eq for NullifierLeafPreimage {\n fn eq(self, other: Self) -> bool {\n (self.nullifier == other.nullifier) &\n (self.next_nullifier == other.next_nullifier) &\n (self.next_index == other.next_index)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NullifierLeafPreimage::empty();\n let serialized = item.serialize();\n let deserialized = NullifierLeafPreimage::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"20":{"path":"std/embedded_curve_ops.nr","source":"use crate::ops::arith::{Add, Sub, Neg};\nuse crate::cmp::Eq;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct EmbeddedCurvePoint {\n x: Field,\n y: Field,\n is_infinite: bool\n}\n\nimpl EmbeddedCurvePoint {\n fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n fn neg(self) -> EmbeddedCurvePoint { \n EmbeddedCurvePoint {\n x: self.x,\n y: -self.y,\n is_infinite: self.is_infinite\n }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\n// Scalar represented as low and high limbs\nstruct EmbeddedCurveScalar {\n lo: Field,\n hi: Field,\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the \n// underlying proof system.\n#[foreign(multi_scalar_mul)]\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N]\n) -> [Field; 3]\n// docs:end:multi_scalar_mul\n{}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(\n scalar_low: Field,\n scalar_high: Field\n) -> [Field; 3]\n// docs:end:fixed_base_scalar_mul\n{\n let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false };\n let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high };\n multi_scalar_mul([g1], [scalar])\n}\n\n// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray\n// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format.\n// docs:start:embedded_curve_add\nfn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint\n) -> EmbeddedCurvePoint\n// docs:end:embedded_curve_add\n{\n let point_array = embedded_curve_add_array_return(point1, point2);\n let x = point_array[0];\n let y = point_array[1];\n EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"220":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr","source":"use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash};\nuse dep::std::cmp::Eq;\n\nglobal GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct GrumpkinPoint {\n x: Field,\n y: Field,\n}\n\nimpl Serialize for GrumpkinPoint {\n fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] {\n [self.x, self.y]\n }\n}\n\nimpl Deserialize for GrumpkinPoint {\n fn deserialize(serialized: [Field; GRUMPKIN_POINT_SERIALIZED_LEN]) -> Self {\n Self {\n x: serialized[0],\n y: serialized[1],\n }\n }\n}\n\nimpl Eq for GrumpkinPoint {\n fn eq(self, point: GrumpkinPoint) -> bool {\n (point.x == self.x) & (point.y == self.y)\n }\n}\n\nimpl Hash for GrumpkinPoint {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl GrumpkinPoint {\n pub fn new(x: Field, y: Field) -> Self {\n Self { x, y }\n }\n\n pub fn zero() -> Self {\n Self { x: 0, y: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.x == 0) & (self.y == 0)\n }\n\n // TODO(David): Would be quite careful here as (0,0) is not a point\n // on the curve. A boolean flag may be the better approach here,\n // would also cost less constraints. It seems like we don't need to \n // group arithmetic either. \n fn assert_is_zero(self) {\n assert(self.x == 0);\n assert(self.y == 0);\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 64] {\n let mut result = [0 as u8; 64];\n let x_bytes = self.x.to_be_bytes(32);\n let y_bytes = self.y.to_be_bytes(32);\n for i in 0..32 {\n result[i] = x_bytes[i];\n result[i + 32] = y_bytes[i];\n }\n result\n }\n}\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"225":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr","source":"use dep::std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul};\nuse crate::{grumpkin_point::GrumpkinPoint, traits::Empty};\n\nglobal GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN: Field = 2;\n\nstruct GrumpkinPrivateKey {\n high: Field,\n low: Field,\n}\n\nimpl Eq for GrumpkinPrivateKey {\n fn eq(self, key: GrumpkinPrivateKey) -> bool {\n (key.high == self.high) & (key.low == self.low)\n }\n}\n\nimpl Empty for GrumpkinPrivateKey {\n fn empty() -> Self {\n Self { high: 0, low: 0 }\n }\n}\n\nimpl GrumpkinPrivateKey {\n pub fn new(high: Field, low: Field) -> Self {\n GrumpkinPrivateKey { high, low }\n }\n\n pub fn zero() -> Self {\n Self { high: 0, low: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.high == 0) & (self.low == 0)\n }\n\n pub fn serialize(self) -> [Field; GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN] {\n [self.high, self.low]\n }\n\n pub fn derive_public_key(self) -> GrumpkinPoint {\n let public_key = fixed_base_scalar_mul(self.low, self.high);\n GrumpkinPoint { x: public_key[0], y: public_key[1] }\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"345":{"path":"/usr/src/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/main.nr","source":"mod ecdsa_public_key_note;\n\n// Account contract that uses ECDSA signatures for authentication on the same curve as Ethereum.\n// The signing key is stored in an immutable private note and should be different from the signing key.\ncontract EcdsaAccount {\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteGetterOptions, PrivateContext, PrivateImmutable};\n use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;\n\n use dep::aztec::protocol_types::abis::call_context::CallContext;\n use dep::std;\n\n use dep::authwit::{\n entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions,\n auth_witness::get_auth_witness\n };\n\n use crate::ecdsa_public_key_note::EcdsaPublicKeyNote;\n\n #[aztec(storage)]\n struct Storage {\n public_key: PrivateImmutable,\n }\n\n // Creates a new account out of an ECDSA public key to use for signature verification\n #[aztec(private)]\n #[aztec(initializer)]\n fn constructor(signing_pub_key_x: [u8; 32], signing_pub_key_y: [u8; 32]) {\n let this = context.this_address();\n let header = context.get_header();\n let this_npk_m_hash = header.get_npk_m_hash(&mut context, this);\n // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we\n // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that\n // important.\n\n let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash);\n storage.public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this));\n }\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(noinitcheck)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n // Load public key from storage\n let storage = Storage::init(context);\n let public_key = storage.public_key.get_note();\n\n // Load auth witness\n let witness: [Field; 64] = get_auth_witness(outer_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n\n // Verify payload signature using Ethereum's signing scheme\n // Note that noir expects the hash of the message/challenge as input to the ECDSA verification.\n let outer_hash_bytes: [u8; 32] = outer_hash.to_be_bytes(32).as_array();\n let hashed_message: [u8; 32] = std::hash::sha256(outer_hash_bytes);\n let verification = std::ecdsa_secp256k1::verify_signature(public_key.x, public_key.y, signature, hashed_message);\n assert(verification == true);\n\n true\n }\n}\n"},"346":{"path":"/usr/src/noir-projects/noir-contracts/contracts/ecdsa_account_contract/src/ecdsa_public_key_note.nr","source":"use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, NoteInterface, NoteGetterOptions, PrivateContext};\n\nuse dep::aztec::{\n note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app,\n protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}\n};\n\nglobal ECDSA_PUBLIC_KEY_NOTE_LEN: Field = 5;\n// ECDSA_PUBLIC_KEY_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)\nglobal ECDSA_PUBLIC_KEY_NOTE_BYTES_LEN: Field = 5 * 32 + 64;\n\n// Stores an ECDSA public key composed of two 32-byte elements\n// TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value?\n#[aztec(note)]\nstruct EcdsaPublicKeyNote {\n x: [u8; 32],\n y: [u8; 32],\n // We store the npk_m_hash only to get the secret key to compute the nullifier\n npk_m_hash: Field,\n}\n\nimpl NoteInterface for EcdsaPublicKeyNote {\n // Cannot use the automatic serialization since x and y don't fit. Serialize the note as 5 fields where:\n // [0] = x[0..31] (upper bound excluded)\n // [1] = x[31]\n // [2] = y[0..31]\n // [3] = y[31]\n // [4] = npk_m_hash\n fn serialize_content(self) -> [Field; ECDSA_PUBLIC_KEY_NOTE_LEN] {\n let mut x: Field = 0;\n let mut y: Field = 0;\n let mut mul: Field = 1;\n\n for i in 1..32 {\n let byte_x: Field = self.x[31 - i] as Field;\n x = x + (byte_x * mul);\n let byte_y: Field = self.y[31 - i] as Field;\n y = y + (byte_y * mul);\n mul *= 256;\n }\n\n let last_x = self.x[31] as Field;\n let last_y = self.y[31] as Field;\n \n [x, last_x, y, last_y, self.npk_m_hash]\n }\n\n // Cannot use the automatic deserialization for the aforementioned reasons\n fn deserialize_content(serialized_note: [Field; ECDSA_PUBLIC_KEY_NOTE_LEN]) -> EcdsaPublicKeyNote {\n let mut x: [u8; 32] = [0; 32];\n let mut y: [u8; 32] = [0; 32];\n\n let part_x = serialized_note[0].to_be_bytes(32);\n for i in 0..31 {\n x[i] = part_x[i + 1];\n }\n x[31] = serialized_note[1].to_be_bytes(32)[31];\n\n let part_y = serialized_note[2].to_be_bytes(32);\n for i in 0..31 {\n y[i] = part_y[i + 1];\n }\n y[31] = serialized_note[3].to_be_bytes(32)[31];\n\n EcdsaPublicKeyNote { x, y, npk_m_hash: serialized_note[4], header: NoteHeader::empty() }\n }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n}\n\nimpl EcdsaPublicKeyNote {\n pub fn new(x: [u8; 32], y: [u8; 32], npk_m_hash: Field) -> Self {\n EcdsaPublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() }\n }\n}\n"},"35":{"path":"std/option.nr","source":"use crate::hash::{Hash, Hasher};\nuse crate::cmp::{Ordering, Ord, Eq};\nuse crate::default::Default;\n\nstruct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some { self._value } else { default }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some { self } else { other }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some { self } else { default() }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some { Option::none() } else { self }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option where T: Eq {\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option where T: Ord {\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else {\n if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"62":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_private_key::GrumpkinPrivateKey,\n grumpkin_point::GrumpkinPoint, utils::arr_copy_slice\n};\nuse dep::std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}};\n\n// TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since\n// point is not the only input of the function. Unify naming with TS once we have a better name.\npub fn point_to_symmetric_key(secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 32] {\n let shared_secret_fields = multi_scalar_mul(\n [EmbeddedCurvePoint { x: point.x, y: point.y, is_infinite: false }],\n [EmbeddedCurveScalar { lo: secret.low, hi: secret.high }]\n );\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly\n let shared_secret = GrumpkinPoint::new(shared_secret_fields[0], shared_secret_fields[1]);\n let mut shared_secret_bytes_with_separator = [0 as u8; 65];\n shared_secret_bytes_with_separator = arr_copy_slice(shared_secret.to_be_bytes(), shared_secret_bytes_with_separator, 0);\n shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY;\n sha256(shared_secret_bytes_with_separator)\n}\n\n#[test]\nfn check_point_to_symmetric_key() {\n // Value taken from \"derive shared secret\" test in encrypt_buffer.test.ts\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let key = point_to_symmetric_key(secret, point);\n // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1\n let expected_key = [\n 49, 167, 146, 222, 151, 129, 138, 184, 87, 210, 245, 249, 99, 100, 1, 59, 223, 180, 5, 99, 14, 7, 177, 236, 159, 203, 231, 72, 220, 180, 241, 23\n ];\n assert_eq(key, expected_key);\n}\n"},"63":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/getters.nr","source":"use dep::protocol_types::{\n header::Header, abis::validation_requests::KeyValidationRequest, address::AztecAddress,\n constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint,\n storage::map::derive_storage_slot_in_map\n};\nuse crate::{\n context::PrivateContext,\n oracle::{keys::get_public_keys_and_partial_address, key_validation_request::get_key_validation_request},\n keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}},\n state_vars::{shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter}\n};\n\nglobal DELAY = 5;\n\n// docs:start:key-getters\ntrait KeyGetters {\n fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;\n}\n\nimpl KeyGetters for Header {\n fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, NULLIFIER_INDEX, self)\n }\n\n fn get_ivpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, INCOMING_INDEX, self)\n }\n\n fn get_ovpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, OUTGOING_INDEX, self)\n }\n\n fn get_tpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, TAGGING_INDEX, self)\n }\n\n fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {\n get_master_key(context, address, NULLIFIER_INDEX, self).hash()\n }\n}\n// docs:end:key-getters\n\nfn get_master_key(\n context: &mut PrivateContext,\n address: AztecAddress,\n key_index: Field,\n header: Header\n) -> GrumpkinPoint {\n let key = fetch_key_from_registry(context, key_index, address, header);\n if key.is_zero() {\n // Keys were not registered in registry yet --> fetch key from PXE\n let keys = fetch_and_constrain_keys(address);\n // Return the corresponding to index\n keys.get_key_by_index(key_index)\n } else {\n // Keys were registered --> return the key\n key\n }\n}\n\nfn fetch_key_from_registry(\n context: &mut PrivateContext,\n key_index: Field,\n address: AztecAddress,\n header: Header\n) -> GrumpkinPoint {\n let x_coordinate_map_slot = key_index * 2 + 1;\n let y_coordinate_map_slot = x_coordinate_map_slot + 1;\n let x_coordinate_derived_slot = derive_storage_slot_in_map(x_coordinate_map_slot, address);\n let y_coordinate_derived_slot = derive_storage_slot_in_map(y_coordinate_map_slot, address);\n\n let x_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n x_coordinate_derived_slot\n );\n let y_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n y_coordinate_derived_slot\n );\n let x_coordinate = x_coordinate_registry.get_value_in_private(header);\n let y_coordinate = y_coordinate_registry.get_value_in_private(header);\n\n GrumpkinPoint::new(x_coordinate, y_coordinate)\n}\n\n// Passes only when keys were not rotated - is expected to be called only when keys were not registered yet\nfn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys {\n let (public_keys, partial_address) = get_public_keys_and_partial_address(address);\n\n let computed_address = AztecAddress::compute(public_keys.hash(), partial_address);\n\n assert(computed_address.eq(address));\n\n public_keys\n}\n\n// A helper function since requesting nsk_app is very common\n// TODO(#6543)\npub fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"80":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/nullifier_inclusion.nr","source":"use dep::std::merkle::compute_merkle_root;\nuse dep::protocol_types::header::Header;\n\nuse crate::{\n context::PrivateContext, oracle::get_nullifier_membership_witness::get_nullifier_membership_witness,\n note::{utils::compute_siloed_nullifier, note_interface::NoteInterface}\n};\n\ntrait ProveNullifierInclusion {\n fn prove_nullifier_inclusion(header: Header, nullifier: Field);\n}\n\nimpl ProveNullifierInclusion for Header {\n fn prove_nullifier_inclusion(self, nullifier: Field) {\n // 1) Get the membership witness of the nullifier\n let witness = get_nullifier_membership_witness(self.global_variables.block_number as u32, nullifier);\n\n // 2) Check that the witness we obtained matches the nullifier\n assert(witness.leaf_preimage.nullifier == nullifier, \"Nullifier does not match value in witness\");\n\n // 3) Compute the nullifier tree leaf\n let nullifier_leaf = witness.leaf_preimage.hash();\n\n // 4) Prove that the nullifier is in the nullifier tree\n assert(\n self.state.partial.nullifier_tree.root\n == compute_merkle_root(nullifier_leaf, witness.index, witness.path), \"Proving nullifier inclusion failed\"\n );\n // --> Now we have traversed the trees all the way up to archive root and verified that the nullifier\n // was included in the nullifier tree.\n }\n}\n\ntrait ProveNoteIsNullified {\n fn prove_note_is_nullified(header: Header, note: Note, context: &mut PrivateContext) where Note: NoteInterface;\n}\n\nimpl ProveNoteIsNullified for Header {\n fn prove_note_is_nullified(self, note: Note, context: &mut PrivateContext) where Note: NoteInterface {\n let nullifier = compute_siloed_nullifier(note, context);\n\n self.prove_nullifier_inclusion(nullifier);\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"98":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash\n};\n\nuse dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field};\n\nuse crate::oracle::unsafe_rand::unsafe_rand;\n\nuse crate::event::event_interface::EventInterface;\nuse crate::note::note_interface::NoteInterface;\n\nuse crate::encrypted_logs::{\n header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody,\n outgoing_body::EncryptedLogOutgoingBody\n};\n\npub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n event: Event\n) -> [u8; OB] where Event: EventInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; OB] = [0; OB];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = OB - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\npub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n note: Note\n) -> [u8; M] where Note: NoteInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; M] = [0; M];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = M - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\nfn fr_to_private_key(r: Field) -> GrumpkinPrivateKey {\n let r_bytes = r.to_be_bytes(32);\n\n let mut high_bytes = [0; 32];\n let mut low_bytes = [0; 32];\n\n for i in 0..16 {\n high_bytes[16 + i] = r_bytes[i];\n low_bytes[16 + i] = r_bytes[i + 16];\n }\n\n let low = bytes32_to_field(low_bytes);\n let high = bytes32_to_field(high_bytes);\n\n GrumpkinPrivateKey::new(high, low)\n}\n\nfn compute_ivpk_app(ivpk: GrumpkinPoint, contract_address: AztecAddress) -> GrumpkinPoint {\n // It is useless to compute this, it brings no value to derive fully.\n // Issue(#6955)\n ivpk\n /*\n // @todo Just setting infinite to false, but it should be checked.\n // for example user could define ivpk = infinity using the registry\n assert((ivpk.x != 0) & (ivpk.y != 0), \"ivpk is infinite\");\n\n let i = fr_to_private_key(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M]));\n let I = i.derive_public_key();\n\n let embed_I = EmbeddedCurvePoint { x: I.x, y: I.y, is_infinite: false };\n let embed_ivpk = EmbeddedCurvePoint { x: ivpk.x, y: ivpk.y, is_infinite: false };\n\n let embed_result = embedded_curve_add(embed_I, embed_ivpk);\n\n GrumpkinPoint::new(embed_result.x, embed_result.y)*/\n}\n"},"99":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr","source":"use crate::{\n context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},\n encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog\n};\nuse dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash,\n constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index\n};\n\nfn emit_with_keys(\n context: &mut PrivateContext,\n note: Note,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n let note_header = note.get_header();\n let note_hash_counter = note_header.note_hash_counter;\n let storage_slot = note_header.storage_slot;\n\n let note_exists_index = find_index(\n context.new_note_hashes.storage,\n |n: NoteHash| n.counter == note_hash_counter\n );\n assert(\n note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, \"Can only emit a note log for an existing note.\"\n );\n\n let contract_address: AztecAddress = context.this_address();\n let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());\n\n let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);\n\n context.emit_raw_note_log(note_hash_counter, encrypted_log);\n}\n\npub fn encode_and_encrypt_note(\n context: &mut PrivateContext,\n ov: AztecAddress,\n iv: AztecAddress\n) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n let header = context.get_header();\n let ovpk = header.get_ovpk_m(context, ov);\n let ivpk = header.get_ivpk_m(context, iv);\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n\npub fn encode_and_encrypt_note_with_keys(\n context: &mut PrivateContext,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/accounts/src/artifacts/SchnorrAccount.json b/yarn-project/accounts/src/artifacts/SchnorrAccount.json deleted file mode 100644 index 954e40db2de0..000000000000 --- a/yarn-project/accounts/src/artifacts/SchnorrAccount.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"SchnorrAccount","functions":[{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"},{"name":"constructor","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(initializer)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"signing_pub_key_x","type":{"kind":"field"},"visibility":"private"},{"name":"signing_pub_key_y","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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KuvXCP56A7gaz67Ishc6ZwYDY9vd9vOm7vMt3d7W7R3d3tXtPd3e1+0D3T7U7SPdPtbtE90+1e0z3T7X7QvdvtTtK92+1u0b3b7V7TvdvtftB91+1O0n3X7W7RfdZun2q26/6fa7brN1+0O3Obr9afJIt78K5yddi6L5q9zsc4g3bfyz928592879+849+869+859+879x849x869x859x879584958695859587918491869185918799849986998599879z849z869z859z87978497Oc+1+d+9+c+9+d+9nO/R/O/Rzn/k/nfq5z/5dzPy/nAvctiv7/gmdJDwotiabDsuxNQF/pzPzrLeC4TvH87IO1OfU2zn/17+D6Uu8CY3GqiFik1Xsw/zWp92F9JdUHwFicJiIWUfUhyn/pqPoI1VdTVH0MjMXpEmKRjKpPUP7Tc8+noL7Suq/PgLE4Q0AsmrTNn4P8l9R9fQHqS5usvgTG4kz/Y5E2Nn+F8V+T6etrTF9J09c3wFic5X8sTNfqW4j/0vP6+g7SV9O8vr4HxmKq97FIzrP5B4j/5g1T/YjoKz2/r5+AsTjb91g0zbf5Z4T/kvP7+gXR13yT1SxgLM7xPBYpa/OvAJsbbV+/AfpK2L5+B8biXL9jEct+E3N2eJtVtq8/QveVzGT7mgOMxXlexyLZmLX5z/D+W/AN27mh+0os6OsvYCzO9zoWtblvKBeF7Ust6KtFEW7P8hTgd3Eu8OTLtou5FHDfTAH3fdTpwFhcKCQWwP0BBaxv1VnAWEwTEgtgHaSA63h1DjAWFwmJBXC9p4DrFXU+MBYXC4kFcF5TQC6racBYXCLkzTlA/Spg/imW/yKO/3x4rpztKwJch5o+0GdszPmlNwrx54wKi7CxRtu9ZWHufA3S7ts9P/Vv8rGwCG/3HULeMVAE1CMw1uoOz/PG6CVCyJu7PbfbMIKhl3uE6KUYqBdgrBXSf9lzv9l1hGGEOd9bXJQ751tiF8zo/BpemDvXiYzbDM/f6mlsLiHo6n4h9VJJEc7mUqBGgXmjpMRiOHC9X1bE0bBPunB5WWo5WRbgZTmJlyMKc+feg/2Gfhu057w0NpcTePmwEI2WA3VVAeQlMG+UlFiMAPKysoijYZ904fKywnKyMsDLKhIvRxbmvhcU7Desfx7znJfG5ioCLx8XotEq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","debug_symbols":"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vG5M3l/86PfPi8f+3b+tAi5fa/J17ndfXxrb24uXfZexvH7Hw1NtOZvajaptE0DtJtWeOksUatek9n7UQxmWv1PbJofajaptnUTtitQu66729PoT9k9fLar4eidfC1/5eiNfLdf4eidfre34WpGv8/D8o45hnvvji/t1GneXlvJGbjs+cjcrty0fue8q97btX7nr178rcFaC5sAcTL39oTkwB1Nv2WgObjoHQzfsbyPRTcPfzYHNpDkwB1Nv42kOvnkOtudXHrbu5NXL2R8mTH3hK18r8vW6R1x7y1FqN6q2PSq1a1L7ukdce1tUajeqth0qtStS++xprd6uk6838nWwk+TrnXy1O+TrnXy14+NrRb5e+oDrYHFH7mblLuQm903lvvBpvcFK0ByYg8ere3NgDszBYNloDm46B1c+tTrYTJoDczANNp7m4HvnYFv2TzbouuUvu85o48nXO/lq48nXiny98FZytByldqNqW41Su1G1C7Wp3abadp3UrkftKzPdaH1J7UbVtpGk9tfV3p/cfph9cvGlH2w6jTaHfK3J1+veZGG0DKR2m2oXe0NqN6q2FSO1a1L7uvcPKVaM1G5UbStGalek9tmfwpfCV77eyFfLQL7eyVcbPr7eyVdrO75W5Oul7x5S7PjI3azctnzkvqvcFz4uOlkJmgNzME32h+bAHEyTZaM5uOkcXPlA9mQzaQ7MwTQVc2AOvncOrvxg08nGk681+XrdI66T5Si1G1XbHpXaNal93SOuky0qtRtV2w6V2hWpffa01mzXydc7+Wonydc7+Wp3yNc7+WrHx9eKfL30Ade5kJvcrcpty0fuu8p94dN6s5WgOTAH02x/aA7MwTRbNpqDm87BlU+tzjaT5sAcTIuNpzn43jm49IMiFxtPvt7JVxtPvlbk64W3kovlKLUbVbtQm9ptqm0xSu1G1bbrpHY9al+a6awvqd2o2jaSv6v23O0/4jxPN1G7357f9ON/vnmXj8V+j1WXW7XalrHqeqvstFh1vVU2T6z6slXDtt8FjH33xipLH1Zdb1VhFau+nDf2ox4ffeOkWHztA0xP3kNytUTha02+XvdGe6slCrUbVdsShdqNqm2JQu2a1L7uPSRXmxxqt6n2Zp1E7YrUPns7tM2iiq938tUKjK938tVyja938rXwla/1+HrpO0hudnzkblZuWz5y31XuC/9kcLMSNAfmYNrsD82BOXg4YA7MwT3n4MI/yp07m0lzYA4eFMyBOfjeOfjSZ/Me/2HC3Nl48rUmXy97xHXuLEep3ajahdrUrkjtyx5xnTtbVGo3qrYdKrUrUvvkaa25s+vk6518tZPk6518tTvk64187e34+FqRr1c+4Dr3FnfkblZuWz5y31Xu657Wm3srQXNgDua+mANzYA56y0ZzcNM5uPKp1d5m0hyYg7m38TQH3zsHX/qs09OuY+PJ1zv5auPJ14p8vfBWcrAcpXajaluNUrtRtS1Gqd2o2nad1K5H7Ssz3VCoTe021baRpPbX1d6f3H6YfXLxpR9sOg82h3ytydfr3mRhsAykdqNq2xtSu1G1rRipXZPa171/yGjFSO1G1bZipHZFap/9Kfxob8jXO/lqGcjXO/la+MrXG/lqbcfXiny99N1DRjs+cjcrty0fue8q94WPi45WgubAHMyj/aE5MAdzsWw0BzedgysfyC42k+bAHMzFxtMcfPMcXPnBpsXGk681+XrdI66lUJvabaptj0rtmtS+7hHXYotK7UbVtkOldkVqnz2tVew6+XonX+0k+XojXye7Q77eyVc7Pr5W5OulD7hOFnfkblZuWz5y31XuC5/Wm4o5MAfmYLI/NAfmYJ4sG83BTefgyqdWJ5tJc2AO5snG0xx87xxc+kGRk40nX2/k62zjydeKfL3wVnK2HKV2o2pbjVK7UbUtRqndqNqF2tSuRu0rM91sfUntRtW2kfxltfd/gfulL69qfwCyKqsckB1O5YAsLX4X0NK/fO3hT0CLSl85IK25ckCK6S8D2j4XkcM7QLpf5YAKQL8LaBk+AY1vAGkwlQNSEn4X0NY949Qj689vACkJlQNSEioHpCTUDWhVEn4V0DCOn2//XE4WNWV7HsfUvaxpxvnNtdv+NH/f9d2/Lv4gL1Gkktc+UsmLKm2Sf/DeD7ob36Iv0KeiF4Ji0UtMrf5T/0l+mt6R167aJ7++nXlR7D7kp+m5I5in7uzX/dDt3/Tw8k0Pe8xR20LJbzLeL5PvP8kvZ+SH51eeXv7pHt/+ucn+iUQPgJ/Yn88ibxpeJHYBLxK7eheJvcCeiF21i8Su2EVil+sisWt1kdiFukDsS6fSRWJX6SKxq3SR2FW6SOwF9kTsKl0kdpUuErtKF4ldpYvErtIlYu9VukjsKl0kdpUuErtKF4m9wJ6IXaWLxK7SRWJX6SKxq3SR2FW6ROyDSheJXaWLxK7SRWJX6SKxF9gTsat0kdhVukjsKl0kdpUuErtKl4h9VOkisat0kdhVukjsKl0k9gJ7InaVLhK7SheJXaWLxK7SRWJX6RKxF5UuErtKF4ldpYvErtJFYi+wJ2JX6SKxq3SR2FW6SOwqXSR2lS4R+6TSRWJX6e6Dfennj2uXYX3F/sFSemuHpZ52H5br8DyOdRlOfh2ffNb6MhXgM8FraqHgVbVQ8LpaKHhlLRS8tpYJflbXQsHra6HgxbhQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywS/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhVuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywS/KXeh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5Hg1065CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBN8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAH5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qNyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCL8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+Em5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBD8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAX5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qtyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWC35S7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtI8Fun3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYLvlbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwg3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflTuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywRflLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yk3IWCV+5CwSt3oeCVu1DwBfhM8Mrd74IfpvIf4D8AKWxXAxr3n3AsZTy5el3KsE/b8nr1/O5nLPPzQB7j9nn1Y76fPIWztnjqYW3xlLma4jmrV23xFKXa4qk1tcVTQmqLZ8GzKZ6CT1s89aGreZZl2L/02J1cvX1+19swvfIc3lxdhvV51GXsPr/t8u5LL9P6ce2yfWIZhid5JSmVvOZ0J/LjsO7kx/mV/AdOyaklnIvi1BROwakpnHpTUzjlpqZwFjhbwik2NYVTa2oKp4DUFE5V6Hdxjuvza2+lm/6F84OQ0FM5oVW7qZ2QHFM7IYWldkKiSe2ECkKVE5I2aiekVtROSIConZCm8NuE1p1Qv74jpClUTmjTFGonpCnUTkhT+G1Cy05oWN4R0hRqJ1QQqpyQplA7IU3hdwmV/e1ytrKWd4Q0hdoJaQq1E9IUqiY0dJ2m8LuEpmEnNE1vCWkKtRPSFGonpCnUTqgg9MuExp3QPL8jpCnUTkhTqJ2QplA7IU3hdwnN3U5oHsd3hDSFygn1mkLthDSF2glpCr9MaNn/pHJ580Tjg5CmUDuhglDlhDSF2glpCr+9wdtfKZRteEdIU6idkKbw26+2h/3VdunfEdIUKic0aArnhJb9qcN+naaTM58f/7Z/XD1387t70EEl+Pkzd9//82fuTv7nz7w488r/xXVvXjsh9+a1E3JvXjsh9+a1E3JvXjmh0b157YTcyddOyH3/xfeg6+NUP65e++Vdlx/d9//8mRdn/uNn7k6+8g3h6E6+dkLu5Gsn5E6+dkLu5CsnVNzJ107InXzthNzJ107IfX/lNawUhConpCnUTkhTqJ2QplA7IU2hdkKaQuWEJk2hdkKawtU7uWF6ful17Kd3Z64S/PyZu+//+TMvzvzHz9y9+c+fubvtnz9z98+XP0u0X72Ow/avM39z9Vye3/U6Ty8n/fY1a/f8ZKaxDN3LtR8s3Wm3w9I9eTMsZ3fv7bB0n98OS/3gRix3KmN5pfJkqUu0w7Jg2QxLHaUdlu5JKmX5D5/FfUbdfNw71M3H/UDdfLzG//H9wFKc+Y+fudfMP3/mdo8/f+Z2jz9/5naEP3/m7pt//MxX98I/f+bub3/+zN2z/vyZuw/9+TMvzvzHz9x96M+fufvQyv/SZ3XXWjsh97i1E3JHXDmhzf1z7YTcbddOyL35OaH183ve5rPXz6UfnsdR+uWV0Pw8c/fmP3/mxZn/+Jm7N//5M3dvfvGZT/3yPI5p6Id3Z+5u++fP3P3zz5+5O+KfPvO+c4978Zkvc/+8epnH7d2Zu2v9+TN3H3r1mU9beZ750v/7teKbrc91f7Pad+5v22FZsGyGpfvxdli6z2+HpX5wI5aHf3/cd7pEOyz1jmZY9jpKOywLlnWy/ODjPqNuPu4d6ubjfqBuPl7jX74fmJ5/obDM2/wvPh9n7rX4j5/54DXzz5+53ePPn7nd48+fuR3hz595ceY/fubuhX/+zN3f/vyZu2f9+TN3H/rzZ+4+9MfPfHQf+vNn7j7058/cfejPn7n70B//m4axOPMfP3P3oT9/5u5Df/7M3Yf+/Jm7D/35M3cfenrmw9Q9X/0N07SenPk2js/vYyvd53ls/Vuc47ofxzTuFz8W1R+AipvWygG5w60ckNvhygG9v3ceh+ezVv348i/de0D9tv9LN3TD2so/z6U4mv86msnR/NfRzI7mv45mcTT/dTSro/mvo3GXdPX7T3bdfhz96dUPhs8v3a2f38eyffCZ3CTVzSf0Hmnef3eO88s3fQGfx3/7eXbDus5nNJey/+X4sp6+vH/8Fny+vJ9efsZh3HmG3lJ9H8+vzdvy+dEK6/I6bv9PMENXl7XAPP3lWfCpmk/oSrQWPo9Xf/t5THM5/nX4f7yeFw/D57+bw7y8zWL7v5vDtHy+7/nw7iOdx7LOz++6bOUldL27uN/6/UfclteLP6wKXfqy6lutCl1rs+pbrQpd3LPqW60KjW6s+hurhv0dGsbx5R0adqvm0FTIqm+1SuBk1ZetGvejHsfSHV88rPNn8F2Gk4sfp/e8eOzf/Ns6C7h8rcnXud99fWlsby9epufPt7x+x8NTbTmb2o2qXahN7TbVtkShdk1q70c9lGH5O7VtcqjdqNrWSdSuSO2y7mpPrz/hnj0sqvh6J1+twPh6I18XyzW+3slXazu+VuTrPAzPi+e5P774//6YendpKW/ktuMjd7Ny2/KR+65yb9v+lbt+/asCtxRzYA7MwWJ/aA7MQb9YNpqDm87B0O0Qh24a/m4ObCbNgTl4aGkOzMH3zsH2/MrD1p28ejn9w4TFxpOvNfl63SOuq+UotRtV2x6V2jWpfd0jrqstKrUbVdsOldoVqX32tNZa+MrXG/lqJ8nXO/lqd8jXO/lqx8fXiny99AHX1eKO3M3KbctH7rvKfeHTepuVoDkwB/1mf2gOzEG/WTaag5vOwZVPrW42k+bAHPRbMQfm4FvnYFv2o+665S+7zmbjydc7+WrjydeKfL3yVtJylNqNqm01Su1G1bYYpXaTag+dXSe161H7wkz3GA1qU7tNtW0kqf11tfcntx9mn1x86QebDp3NIV9r8vWyN1kYukJtareptr0htRtV24qR2jWpfdn7hwydFSO1G1XbipHaFal98qfwQ2dvyNcb+dpbBvL1Tr7a8PH1Tr5a2/G1Il+vfPeQobfjI3ezchdyk/umcl/4uGhvJWgOzMHQ2x+aA3Mw9JaN5uCmc3DlA9m9zaQ5MAdDb+NpDr55Di78YNPHip6vfK3I1+secR0sR6ndqNr2qNSuSe3rHnEdbFGp3ajahdrUrkfts6e1BrtOvt7JVztJvt7JV7tDvt7JVzs+vlbk66UPuA4Wd+RuVe7Rlo/cd5X7wqf1RitBc2AOhtH+0ByYg2G0bDQHN52DK59aHYs5MAfmYLTxNAffOwdXflDkMNp48vVOvtp48rUiX6+8lbQcpXajaluNUrtNtYvFKLUbVduuk9r1qH1lpivWl9RuVG0byd9Ve+72H3Gep5uo3W/9/iNub97loxRWsepyq2zLWHW9VXZarLreKpsnVn3ZqmHbT2/suzdWWfqw6nqr7FtY9fW8sR/1+OgbJ8Xiax9gevIekpMlCl9r8vW6N9qbLFGo3ajalijUblRtSxRq16T2de8hORVqU7tNta2TqF2R2mdvhzZZVPH1Tr5agfH1Tr5arvH1Tr5a2/G1Il8vfQfJ2Y6P3M3KbctH7rvKfeGfDM5WgubAHAyz/aE5MAfDXMyBObjnHFz5R7mzzaQ5MAeP/5g5MAffOwdf+mzekz9MmG08+VqTr9c94jpbjlK7UbXtUaldk9rXPeK62KJSu1G17VCpXZHaZ09rLXadfL2Tr3aSfL2Tr4WvfL2Rr3Z8fK3I10sfcF0s7sjdrNy2fOS+q9wXPq23WAmaA3MwLPaH5sAcDKtlozm46Rxc+dTqajNpDszBsNp4moPvnYMvfdbpWddZbTz5eidfC1/5Wo+vV95KWo5Su1G1rUap3ajaFqPUblRtu05q16P2pZnO+pLabaq92UhS++tq709uP8w+ufjaDzbdbA75WpOv173JwmYZSO1G1bY3pHajahdqU7sita97/5DNipHajaptxUjtitQ++1P4zd6Qr3fy1TKQr3fy1YaPr/fx9XG4fOVrPb5e+e4hY2fHR+5m5bblI/dd5b7ucdGxsxI0B+Zg7Io5MAfmoLNsNAc3nYMLH8geO5tJc2AOxs7G0xx88xxc+MGmY2fjydeafL3sEdexsxyldptq9/ao1K5J7csecR17W1RqN6q2HSq1K1L77Gmt3q6Tr3fytfCVrzfy1e6Qr3fy1Y6PrxX5eukDrr3FHbmblduWj9x3lfvCp/V6K0FzYA7Gwf7QHJiDcbBsNAc3nYMrn1odbCbNgTkYBxtPc/C9c3DlB0WOQ+ErX2/kq40nXyvy9cpbSctRajeqttUotRtV22KU2o2qbddJ7XrUvjLTjdaX1G5UbRvJX1Z7/xe4X/ryqvYHIKuyygHZ4VQOqAD0q4CW/uVrD28AqfSVA9KaKwekmP4yoO1zETm8A6T7VQ5IvfplQMvwCWj8E1DRYCoHpCT8LqCte8apR9af3wBSEioHpCRUDqgAVDcgJeFXAf3fquz5XT9gvAL68+KyPY9j6l7WNOP85tptf5q/7/ruXxd/kJcoUslrH6nkRZU2yT947wfdjW/RyzWp6CchKBa9xNTqP/Wf5KfpHXntqn3y69uZF8XuQ36anjuCeerOft0P3f5NDy/fxvCMOVNBPpS8jPfL5PtP8ssZ+eH5fUwv/3SPb//cZP9EogfAT+zPZ5EnDS8Su4AXiV29i8Su3CVin1W7SOyKXSR2uS4Su1YXib3AnohdpYvErtJFYlfpIrGrdJHYVbpE7ItKF4ldpYvErtJFYlfpIrEX2BOxq3SR2FW6SOwqXSR2lS4Su0qXiH1V6SKxq3SR2FW6SOwqXST2AnsidpUuErtKF4ldpYvErtJFYlfpErFvKl0kdpUuErtKF4ldpYvEXmBPxK7SRWJX6SKxq3SR2FW6SOwqXSD20ql0kdhVukjsKl0kdpUuEnuBPRG7SheJXaWLxK7SRWJX6SKxq3SJ2HuVLhK7SheJXaWLxK7SRWIvsCdiV+kisat098G+9PPHtcuwvmL/YCm9tcNST7sPy3V4Hse6DCe/jk8+a730ilom+EFTCwWvqoWC19VCwStroeAL8Jng1bVQ8PpaKHgxLhS8chcKXrnLBD8qd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meCLchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+Uu5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBz8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+EW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBL8qd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meA35S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhL81Cl3oeCVu1Dwyl0oeOUuFHwBPhO8chcKXrkLBa/chYJX7kLBK3eZ4HvlLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yg3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYIflbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwRbkLBa/chYJX7kLBK3eh4AvwmeCVu1Dwyl0oeOUuFLxyFwpeucsEPyl3oeCVu1Dwyl0oeOUuFHwBPhO8chcKXrkLBa/chYJX7kLBK3eZ4GflLhS8chcKXrkLBa/chYIvwGeCV+5CwSt3oeCVu1Dwyl0oeOUuE/yi3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYJflbtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwm3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8chcJfu6Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7TPC9chcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+UO5+F/wwlf8A/wFIYftVQMv0/NLruhzP5Tbtg7lNLz/gMO4wVbOGYCphvwpzm/fj6NbtzW/Ogk/VfHSlX+XTT91+HtNcjn8d9kO/XzwM8+evw3l5dyBTWZ8HMi3959XDu++6rPPzuy7b5/cxvHtBO/Zbv/+I2/J68YdVohWrrrdKEWPV9VbJbay63iotj1VftmrY9tN7tMg/rRqFQlZdb5W6yaovWzXuRz2OpTu+eFjnfbPyui55f/Hj9J4Xj/2bf1tHAZevNfk697uvL43t7cXL9Pz5ltfveHiqLWdTu1G1C7Wp3abalijUrknt/aiHMix/p7ZNDrUbVds6idoVqV3WXe3p9Sfcs4dFFV/v5KsVGF9v5GuxXOPrnXy1tuNrRb7Ow/C8eJ7744v7dRp3l5byRm47PnI3K7ctH7nvKve27V+569e/KnClmANzYA6K/aE5MAdzsWw0Bzedg6HbIQ7dNPzdHNhMmgNzMBcbT3PwzXOwPb/ysHUnr15O/zCh2HjytSZfr3vEdbIcpXajatujUrsmta97xHWyRaV2o2rboVK7IrXPntaaCl/5eiNf7ST5eidf7Q75eidf7fj4WpGvlz7gOlnckbtZuW35yH1XuS98Wm+2EjQH5uDx3zIH5sAczJaN5uCmc3DlU6uzzaQ5MAfzXMyBOfjWOdiW/ai7bvnLrjPbePL1Tr7aePK1Il+vvJW0HKV2o2pbjVK7UbUtRqndptqLXSe161H7yky3WF9Su1G1bSSp/XW19ye3H2afXHztB5suNod8rcnX695kYSnUpnabatsbUrtRta0YqV2T2te9f8hixUjtRtW2YqR2RWqf/Sn8Ym/I1xv5uloG8vVOvtrw8fVOvlrb8bUiXy9995DVjo/czcpdyE3um8p94eOiq5WgOTAH82p/aA7MwbxaNpqDm87BlQ9krzaT5sAczKuNpzn45jm48oNNNxtPvtbk63WPuG6Wo9RuVG17VGrXpPZ1j7hutqjUblTtQm1q16P22dNam10nX+/kq50kX+/kq90hX+/kqx0fXyvy9dIHXDeLO3I3KvfS2fKR+65yX/e03tJZCZoDc7B09ofmwBwsnWWjObjpHFz41OrSFXNgDsxBZ+NpDr53Dq78oMils/Hk6518tfHka0W+XnkraTlK7UbVthqldptq9xaj1G5UbbtOatej9pWZrre+pHajattI/q7ac7f/iPM83UTtfuv3H3H7810+lr6wilWXW2VbxqrrrbLTYtX1Vtk8serLVg3bfnpj372xytKHVddbZd/Cqq/njf2ox0ffOCkWX/sA0+P3kFwGSxS+1uTrZW+0twyWKNRuVG1LFGo3qrYlCrVrUvuy95BchkJtareptnUStStS++Tt0JbBooqvd/LVCoyvd/LVco2vd/LV2o6vFfl66TtIjnZ85G5Wbls+ct9V7gv/ZHC0EjQH5mAZ7Q/NgTlYxmIOzME95+DKP8odbSbNgTlYRhtPc/DNc/Clz+Y9+cOE0caTrzX5et0jrqPlKLUbVdseldo1qX3dI67FFpXajapth0rtitQ+e1qr2HXy9U6+2kny9U6+Fr7y9Ua+2vHxtSJfL33AtVjckbtZuW35yH1XuS98Wq9YCZoDc7AU+0NzYA6WybLRHNx0Dq58anWymTQH5mCZbDzNwffOwZc+6/Ss60w2nny9k6+Fr3ytx9crbyUtR6ndqNpWo9RuVG2LUWo3qrZdJ7XrUfvSTGd9Se021Z5tJKn9dbX3J7cfZp9cfO0Hm842h3ytydfr3mRhtgykdqNq2xtSu1G1C7WpXZHa171/yGzFSO1G1bZipHZFap/9Kfxsb8jXO/lqGcjXO/lqw8fXG/m6WNvxtSJfL333kMWOj9zNym3LR+67yn3h46KLlaA5MAfLUsyBOTAHi2WjObjpHFz5QPZiM2kOzMGy2Hiag2+egys/2HSx8eRrTb5e94jrYjlK7TbVXu1RqV2T2tc94rraolK7UbXtUKldkdpnT2utdp18vZOvha98vZGvdod8vZOvdnx8rcjXSx9wXS3uyN2s3LZ85L6r3Bc+rbdaCZoDc7Bs9ofmwBwsm2WjObjpHFz51OpmM2kOzMGy2Xiag++dg0s/KHIrfOXrjXy18eRrRb5eeStpOUrtRtW2GqV2o2pbjFK7UbXtOqldj9oXZrq1s76kdqNq20j+str7v8D90pdXtT8AWZVVDsgOp3JABaBfBbT0L197eANIpa8ckNZcOSDF9JcBbZ+LyOEdIN2vckDq1S8DWoZPQOOfgHoNpnJASsLvAtq6Z5x6ZP35DSAloXJASkLlgApAdQNSEn4V0DCOn2//XE4WNWV7HsfUvaxpxvnNtdv+NH/f9d2/Lv4gL1Gkktc+UsmLKm2Sf/DeD7ob36KXa1LRD0JQLHqJqdV/6j/JT9M78tpV++TXtzMvit2H/DQ9dwTz1J39uh+6/ZseXr6N4RlzhoJ8KHkZ75fJ95/klzPyw/P7mF7+6R7f/rnJ/olED4Cf2J/PIg8aXiR2AS8Su3oXiV25S8Q+qnaR2BW7SOxyXSR2rS4Se4E9EbtKF4ldpYvErtJFYlfpIrGrdInYi0oXiV2li8Su0kViV+kisRfYE7GrdJHYVbpI7CpdJHaVLhK7SpeIfVLpIrGrdJHYVbpI7CpdJPYCeyJ2lS4Su0oXiV2li8Su0kViV+kSsc8qXSR2lS4Su0oXiV2li8ReYE/ErtJFYlfpIrGrdJHYVbpI7CpdIvZFpYvErtJFYlfpIrGrdJHYC+yJ2FW6SOwqXSR2lS4Su0oXiV2lS8S+qnSR2FW6SOwqXSR2lS4Se4E9EbtKF4ldpbsP9qWfP65dhvUV+wdL6a0dlnrafViuw/M41mU4+XV89lnrq6KWCX7T1ELBq2qh4HW1UPDKWij4AnwmeHUtFLy+FgpejAsFr9yFglfuIsFvnXIXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJvlfuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywQ/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhRuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywRflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwk3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflbuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywS/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhVuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywS/KXeh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd4ngH9+kchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwm+V+5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBD8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+FG5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBF+Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7TPCTchcKXrkLBa/chYJX7kLBF+AzwSt3oeCVu1Dwyl0oeOUuFLxylwl+Vu5CwSt3oeCVu1Dwyl0o+AJ8JnjlLhS8chcKXrkLBa/chYJX7jLBL8pdKHjlLhS8chcKXrkLBV+AzwSv3IWCV+5CwSt3oeCVu1Dwyl0m+FW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBL8pd78LfpjKf4D/AKSw/SqgZXp+6XVdjudym/bB3KaXH3AYd5iqWUMwlbBfhbnN+3E8Xr+8+c1Z8Kmaj670q3z6qdvPY5rL8a/Dfuj3i4dh/vx1OC/vDmQq6/NApqX/vHp4912XdX5+12X7/D6Gdy9ox37r9x9xW14v/rBKtGLV9VYpYqy63iq5jVXXW6XlserLVg3bfnqPFvmHVX0nFLLqeqvUTVZ92apxP+pxLN3xxcM675uV13XJ+4sfp/e8eOyXN74KuHytyde53319aWxvL16m58+3vH7Hw1NtOZvajapdqE3tNtW2RKF2TWrvRz2UYfk7tW1yqN2o2tZJ1K5I7bLuak+vP+GePSyq+HonX63A+HojX3vLNb7eyVdrO75W5Os8DM+L57k/vrhfp3F3aSlv5LbjI3ezctvykfuucm/b/pW7fv2rAtcXc2AOzEFvf2gOzEHfWzaag5vOwdDtEIduGv5uDmwmzYE56HsbT3PwzXOwPb/ysHUnr15O/zCht/Hka02+XveI62A5Su1G1bZHpXZNal/3iOtgi0rtRtW2Q6V2RWqfPa01FL7y9Ua+2kny9U6+2h3y9U6+2vHxtSJfL33AdbC4I3ezctvykfuucl/4tN5oJWgOzMHj/5kDc2AORstGc3DTObjyqdXRZtIcmIN+LObAHHzrHGzLftRdt/xl1xltPPl6J19tPPlaka9X3kpajlK7UbWtRqndqNoWo9RuU+1i10ntetS+MtMV60tqN6q2jSS1v672/uT2w+yTi6/9YNNic8jXmny97k0WSqE2tdtU296Q2o2qbcVI7ZrUvu79Q4oVI7UbVduKkdoVqX32p/DF3pCvN/J1sgzk6518teHj6518tbbja0W+XvruIZMdH7mblbuQm9w3lfvCx0UnK0FzYA4eZ28OzIE5mCwbzcFN5+DKB7Inm0lzYA76ycbTHHzzHFz5waazjSdfa/L1ukdcZ8tRajeqtj0qtWtS+7pHXGdbVGo3qnahNrXrUfvsaa3ZrpOvd/LVTpKvd/LV7pCvd/LVjo+vFfl66QOus8UduVuVe7HlI/dd5b7wab3FStAcmIN+sT80B+agXywbzcFN5+DKp1aXYg7MgTlYbDzNwffOwaUfFLnYePL1Tr7aePK1Il+vvJW0HKV2o2pbjVK7TbVXi1FqN6q2XSe161H7yky3Wl9Su1G1bSR/V+2523/EeZ5uona/9fuPuL15l4+1sIpVl1tlW8aq662y02LV9VbZPLHqy1YN2356Y9+9scrSh1XXW2Xfwqqv5439qMdH3zgpFl/7ANOT95DcLFH4WpOv173R3maJQu1G1bZEoXajaluiULsmta97D8mtUJvabaptnUTtitQ+ezu0zaKKr3fy1QqMr3fy1XKNr3fy1dqOrxX5euU7SA6dHR+5m5Xblo/cd5X7uj8ZHDorQXNgDobO/tAcmIOhK+bAHNxzDi78o9zH/705MAfmoLPxNAffPAdf+mze4z9MGDobT77W5Otlj7gOneUotRtV2x6V2jWpfdkjrkNvi0rtRtW2Q6V2RWqfPK019HadfL2Tr3aSfL2Tr4WvfL2Rr3Z8fK3I10sfcO0t7sjdrNy2fOS+q9wXPq3XWwmaA3Mw9PaH5sAcDINlozm46Rxc+dTqYDNpDszBQx5zYA6+dQ6+9FmnZ11nsPHk6518LXzlaz2+XnkraTlK7UbVthqldqNqW4xSu1G17TqpXY/al2Y660tqt6n2aCNJ7a+rvT+5/TD75OJLP9j08f/JV75W5Ot1b7IwWgZSu1G17Q2p3ajahdrUrkjt694/ZLRipHajalsxUrsitc/+FH60N+TrnXy1DOTrnXy14ePrjXwt1nZ8rcjXS989pNjxkbtZuW35yH1XuS98XLRYCZoDczCUYg7MgTkolo3m4KZzcOUD2cVm0hyYg6HYeJqDb56DKz/YtNh48rUmX697xLVYjlK7TbUne1Rq16T2dY+4Trao1G5UbTtUalek9tnTWpNdJ1/v5GvhK19v5KvdIV/v5KsdH18r8vXSB1wniztyNyu3LR+57yr3hU/rTVaC5sAcDLP9oTkwB8Ns2WgObjoHVz61OttMmgNzMMw2nubge+fg0g+KnAtf+XojX208+VqRr1feSlqOUrtRta1Gqd2o2haj1G5UbbtOatej9pWZbrG+pHajattI/rLa+7/A/dKXV7U/AFmVVQ7IDqdyQAWgXwW09C9fe3gDSKWvHJDWXDkgxfSXAW2fi8jhHSDdr3JA6tUvA1qGT0Djn4BWDaZyQErC7wLaumecemT9+Q0gJaFyQEpC5YAKQHUDUhJ+FdAwjp9v/1xOFjVlex7H1L2sacb5zbXb/jR/3/Xdvy7+IC9RpJLXPlLJiyptkn/w3g+6G9+il2tS0W9CUCx6ianVf+o/yU/TO/LaVfvk17czL4rdh/w0PXcE89Sd/bofuv2bHl6+jeEZc7aCfCh5Ge+Xyfef5Jcz8sPz+5he/uke3/65yf6JRA+An9ifzyJvGl4kdgEvErt6F4lduQvE/vgeYU/ErthFYpfrIrFrdZHYC+yJ2FW6SOwqXSR2lS4Su0oXiV2lS8Teq3SR2FW6SOwqXSR2lS4Se4E9EbtKF4ldpYvErtJFYlfpIrGrdInYB5UuErtKF4ldpYvErtJFYi+wJ2JX6SKxq3SR2FW6SOwqXSR2lS4R+6jSRWJX6SKxq3SR2FW6SOwF9kTsKl0kdpUuErtKF4ldpYvErtIlYi8qXSR2lS4Su0oXiV2li8ReYE/ErtJFYlfpIrGrdJHYVbpI7CpdIvZJpYvErtJFYlfpIrGrdJHYC+yJ2FW6SOwq3X2wL/38ce0yrK/YP1hKb+2w1NPuw3IdnsexLsPJr+OTz1ofJ0UtE/ysqYWCV9VCwetqoeCVtVDwBfhM8OpaKHh9LRS8GBcKXrkLBa/cZYJflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwq3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflPuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4iwZdOuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywTfK3eh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5ngB+UuFLxyFwpeuQsFr9yFgi/AZ4JX7kLBK3eh4JW7UPDKXSh45S4T/KjchYJX7kLBK3eh4JW7UPAF+Ezwyl0oeOUuFLxyFwpeuQsFr9xlgi/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhJuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65ywQ/K3eh4JW7UPDKXSh45S4UfAE+E7xyFwpeuQsFr9yFglfuQsErd5ngF+UuFLxyFwpeuQsFr9yFgi/AZ4JX7kLBK3eh4JW7UPDKXSh45S4T/KrchYJX7kLBK3eh4JW7UPAF+Ezwyl0oeOUuFLxyFwpeuQsFr9xlgt+Uu1Dwyl0oeOUuFLxyFwq+AJ8JXrkLBa/chYJX7kLBK3eh4JW7SPBTp9yFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWC75W7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtM8INyFwpeuQsFr9yFglfuQsEX4DPBK3eh4JW7UPDKXSh45S4UvHKXCX5U7kLBK3eh4JW7UPDKXSj4AnwmeOUuFLxyFwpeuQsFr9yFglfuMsEX5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8pNyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCn5W73wU/TOU/wH8AUtiuBtRvw/NLP76Rs6vXaX1evW5nV2/TPpvb9PIzDuPOUzi7mucwP68ex6mcXL1Mz4vXdTn+Pfs/wBTDfhXmNu/H0a3bm1+eBZ+q+UhLv8qnn7r9PB7DcvzrsB/6/eJhmD9/Hc7LuwOZyvPfzWFa+s+rh3ffdVnn53ddts/vY+jf//vd7y+wtuX14g+rdCtWXW+VKMaq661S3Fh1vVVyHqu+bNWw7af3yJF/WrVohay63iqBk1Vftmrcj3ocS3d88bDO+3LldWPy/uJHv39ePPZv/m1dBFy+1uTr3O++vjS2txcv+y5jef2Oh6facja1G1W7UJvabaptiULtmtTej3oow/J3atvkULtRta2TqF2R2mXd1Z5ef8I9e1hU8fVOvlqB8fVGvq6Wa3y9k6/WdnytyNd5eP5RxzDP/fHF/TqNu0tLeSO3HR+5m5Xblo/cd5V72/av3PXrXxW4tZgDc2AOVvtDc2AOptWy0RzcdA6Gboc4dNPwd3NgM2kOzMG02niag2+eg+35lYetO3n1cvqHCauNJ19r8vW6R1w3y1FqN6q2PSq1a1L7ukdcN1tUajeqth0qtStS++xpra3wla838tVOkq938tXukK938tWOj68V+XrpA66bxR25m5Xblo/cd5X7uqf15s5K0ByYg7mzPzQH5mDuLBvNwU3n4MKnVufOZtIcmIO5K+bAHHzrHGzLftRdt/xd15k7G0++3slXG0++VuTrlbeSlqPUblRtq1FqN6q2xSi121S7t+ukdj1qX5npeutLajeqto0ktb+u9v7k9sPsk4sv/WDTubc55GtNvl72JgtzX6hN7TbVtjekdqNqWzFSuya1L3v/kLm3YqR2o2pbMVK7IrVP/hR+7u0N+XojXwfLQL7eyVcbPr7eyVdrO75W5OuV7x4yD3Z85G5W7kJuct9U7gsfFx2sBM2BOZgH+0NzYA7mwbLRHNx0Dq58IHuwmTQH5mAebDzNwTfPwYUfbDqPNp58rcnX6x5xHS1Hqd2o2vao1K5J7esecR1tUandqNqF2tSuR+2zp7VGu06+3slXO0m+3slXu0O+3slXOz6+VuTrpQ+4jhZ35G5V7mLLR+67yn3h03rFStAcmIO52B+aA3MwF8tGc3DTObjyqdVSzIE5MAfFxtMcfO8cXPpBkcXGk6938tXGk68V+XrlraTlKLUbVdtqlNptqj1ZjFK7UbXtOqldj9pXZrrJ+pLajaptI/m7as/d/iPO83QTtfvt+U0//uebd/mYCqtYdblVtmWsut4qOy1WXW+VzROrvmzVsO2nN/bdG6ssfVh1vVX2Laz6et7Yj3p89I2TYvG1DzA9eQ/J2RKFrzX5et0b7c2WKNRuVG1LFGo3qrYlCrVrUvu695CcC7Wp3aba1knUrkjts7dDmy2q+HonX63A+HonXy3X+HonX63t+FqRr5e+g+Rix0fuZuW25SP3XeW+8E8GFytBc2AO5sX+0ByYg4cD5sAc3HMOrvyj3MVm0hyYg3mx8TQH3zwHX/ps3pM/TFhsPPlak6/XPeK6WI5Su1G17VGpXZPa1z3iutqiUrtRte1QqV2R2mdPa612nXy9k692kny9k6+Fr3y9ka92fHytyNdLH3BdLe7I3azctnzkvqvcFz6tt1oJmgNzMK/2h+bAHMybZaM5uOkcXPnU6mYzaQ7MwbzZeJqD752DL33W6VnX2Ww8+XonXwtf+VqPr1feSlqOUrtRta1Gqd2o2haj1G5UbbtOatej9qWZzvqS2k2qvXQ2ktT+utr7k9sPs08uvvSDTZfO5pCvNfl62ZssLJ1lILUbVdvekNqNql2oTe2K1L7s/UOWzoqR2o2qbcVI7YrUPvlT+KWzN+TrnXy1DOTrnXy14ePrjXztre34WpGvV757yNLb8ZG7Wblt+ch9V7mve1x06a0EzYE5WPpiDsyBOegtG83BTefgygeye5tJc2AOlt7G0xx88xxc+MGmS2/jydeafL3uEdfecpTabao92KNSuya1r3vEdbBFpXajatuhUrsitc+e1hrsOvl6J18LX/l6I1/tDvl6J1/t+Phaka+XPuA6WNyRu1m5bfnIfVe5L3xab7ASNAfmYBntD82BOVhGy0ZzcNM5uPKp1dFm0hyYg2W08TQH3zsHV35Q5DIWvvL1Rr7aePK1Il+vvJW0HKV2o2pbjVK7UbUtRqndqNp2ndSuR+0rM12xvqR2o2rbSP6y2vu/wP3Sl1e1PwBZlVUOyA6nckAFoF8FtPQvX3t4A0ilrxyQ1lw5IMX0lwFtn4vI4R0g3a9yQOrVLwNahk9A45+AJg2mckBKwu8C2rpnnHpk/fkNICWhckBKQuWACkB1A1ISfhXQMI6fb/9cThY1ZXsex9S9rGnG+c212/40f9/13b8u/iAvUaSS1z5SyYsqbZJ/8N4PuhvfopdrUtHPQlAseomp1X/qP8lP0zvy2lX75Ne3My+K3Yf8ND13BPPUnf26H7r9mx5evunhGXPmgnwoeRnvl8n3n+SXM/LD8ytPL/90j2//3GT/RKIHwE/sz2eRZw0vEruAF4ldvYvErtwlYl9Uu0jsil0kdrkuErtWF4m9wJ6IXaWLxK7SRWJX6SKxq3SR2FW6ROyrSheJXaWLxK7SRWJX6SKxF9gTsat0kdhVukjsKl0kdpUuErtKl4h9U+kisat0kdhVukjsKl0k9gJ7InaVLhK7SheJXaWLxK7SRWJX6QKxr51KF4ldpYvErtJFYlfpIrEX2BOxq3SR2FW6SOwqXSR2lS4Su0qXiL1X6SKxq3SR2FW6SOwqXST2AnsidpUuErtKF4ldpYvErtJFYlfpErEPKl0kdpUuErtKF4ldpYvEXmBPxK7SRWJX6e6Dfennj2uXYX3F/sFSemuHpZ52H5aPG+OPa9dlOPl1fPJZ6+ugqGWCHzW1UPCqWih4XS0UvLIWCr4AnwleXQsFr6+FghfjQsErd6HglbtM8EW5CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBD8pd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meBn5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8otyFglfuQsErd6HglbtQ8AX4TPDKXSh45S4UvHIXCl65CwWv3GWCX5W7UPDKXSh45S4UvHIXCr4AnwleuQsFr9yFglfuQsErd6HglbtM8JtyFwpeuQsFr9yFglfuQsEX4DPBK3eh4JW7UPDKXSh45S4UvHIXCX7rlLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zwvXIXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflDuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywY/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvii3IWCV+5CwSt3oeCVu1DwBfhM8MpdKHjlLhS8chcKXrkLBa/cZYKflLtQ8MpdKHjlLhS8chcKvgCfCV65CwWv3IWCV+5CwSt3oeCVu0zws3IXCl65CwWv3IWCV+5CwRfgM8Erd6HglbtQ8MpdKHjlLhS8cpcJflHuQsErd6HglbtQ8MpdKPgCfCZ45S4UvHIXCl65CwWv3IWCV+4ywa/KXSh45S4UvHIXCl65CwVfgM8Er9yFglfuQsErd6HglbtQ8MpdJvhNuQsFr9yFglfuQsErd6HgC/CZ4JW7UPDKXSh45S4UvHIXCl65SwRfuk65CwWv3IWCV+5CwSt3oeAL8JnglbtQ8MpdKHjlLhS8chcKXrnLBN8rd6HglbtQ8MpdKHjlLhR8AT4TvHIXCl65CwWv3IWCV+5CwSt3meAH5S4UvHIXCl65CwWv3IWCL8BnglfuQsErd6HglbtQ8MpdKHjlLhP8qNz9LvhhKv8B/gOQwnY1oHH/CcdSxpOr16UM+7Qtr1fP737GMj8P5DFun1c/5vvJUzhri6ce1hbPgmdTPNWrtniKUm3x1Jra4ikhtcVTGWqKZxF82uKpD13NsyxPQuM0didXb5/f9TZMrzyHN1eXYX0edRn/73w/ri7vvvQyrR/XLtvnTzgMT/JKUip5zelO5Mdh3cmP8yv5D5wFzpZwKk5N4RScmsKpNzWFU25qCqfa1BLOSWxqCqfW1BROAakpnKrQ7+Ic1+fX3h40/oXzg1BBqHJC2k3thOSY2gkpLLUTEk1qJ6SDVE5oljZqJ6RW1E5IgKidkKbw24TWnVC/viNUEKqckKZQOyFNoXZCmsJvE1p2QsPyjpCmUDshTaFyQoumUDshTeF3CZX97XK2spZ3hDSF2glpCrUTKghVTkhT+F1C0/6NbNP0lpCmUDshTaF2QppC7YQ0hd8mNO6E5vkNoVVTqJ2QplA7IU2hdkKawu8Smrud0DyO7wgVhConpCnUTkhTqJ2QpvDLhJb9TyqXt080rppC7YQ0hcoJbZpC7YQ0hd/e4O2vFMo2vCOkKdROSFP47Vfbw/5qu/TvCBWEKiekKZwTWvanDvt1mk7OfO76+ePquZvf3YNuKsHPn7n7/p8/c3fyP3/m7s3r/he379yb107IvXnthNyb107IvXnthApClRNyb147IXfytRNy33/xPejaD8+zW/tleHfm7vt//szd9//4mffu5OveEPa9O/naCbmTr52QO/naCRWEKifkTr52Qu7kayfkTr52Qu77K69hvUpQOaFBU6idkKZQOyFNoXZCmkLthApClRPSFGonpClcvZMbpifPdeynd2euEvz8mbvv//kzdyf/42c+ujf/+TN3t/3zZ+7++fJnifar13HY/nXmb66ey/O7Xufp5aTfvmbtnp/MNJahe7n2g6U77XZYFiybYenuvR2W7vPbYakf3IjlTmUsr1SeLHWJdljqHc2wLDpKOywLlnWy/ODjPqNuPu4d6ubjfqBuPl7j//h+oHgt/uNnPnnN/PNnbvf482du9/jzZ25H+PNnXpz5j5+5e+GfP3P3tz9/5u5Zf/7M3Yf+/Jm7D/3xM5/dh/78mbsPrfwvfWZ3rbUTco9bO6GCUOWE3D/XTsjddu2E3JufE1o/v+dtPnv9/H/vJvFxdemXV0Lz88zdm//8mbs3//EzX9yb//yZuze/+MynfnkexzT0w7szd7f982fu/vnnz7w48x8/c/e4F5/5MvfPq5d53N6dubvWnz9z96FXn/m0Pb/0svT/fq34Zutz4d+sLu5v22HpvrkZlqv78XZYus9vh6V+cCOWx39/vOoS7bAsWDbDUkdph6V7kkpZ/sNnc59RNx/3DnXzcT9QNx+v8S/fD0zPv1BY5m3+F5+PMy/O/MfP3Gvmnz9zu8efP3O7x58/czvCnz9z980/feZD517458/c/e3Pn7l71p8/c/ehP3/mxZn/+Jm7D/35M3cf+vNn7j7058/cfehP/03D0LkP/fEz792H/vyZuw/9+TN3H/rzZ+4+9OfPvDjzszMfpu756m+YpvXkzLdxfH4fW+k+v/TWv8U5rvtxTON+8eN3/hOQm9bKAbnDrRyQ2+HKAb2/dx73778fX/6lew/osXx/EnrsENYrz3Eqz/fVGqdt++F/njdH8x9HM3SO5r+Opnc0/3U0g6P5r6MZHc1/HU3xEuLi95/suv04+tOrHwyfX7pbP9kv25OPm6S6+TR0j7T/BcAwdsvJkff9/ruzHz6/8uO1y/NgGro3ufZgGtqnXXswDS29Lj2YsaHN1LUH09D66NqDaWjH86WDGfcfsH95M++Xg2loEXPtwRQH8/5gGnoBfu3BpL7yPT2Y1Fe+pwfTzivfx27geTBlPDmYcSvPDcS4bf3xxdP0/DiKuX/5NIpxfJ5hOy+Sv+0Ml3H/U/YyvjnD0s7r6a+c4ePa/a3xu/nUw/0j7l7zy/tEsvfLbek+D24Y3/184yfI9bOi/l9Q/fPSZR+GcVmm44sfy7iXj/BbXi/+oN7OzQLq/zv1du6EUP/fqbdzm4f6fm7jvGf+cRveUC+oB1Jv5wYd9f+dejv1AfX/nXo7aQX1/dym/cGAxw5+Pr543d8ofB3WN4JkJiaC/M+CZPYzgvyvgkziIEEOBcksSl8q8PMyf1w7vzzp91ngJ33GkB0OWSEIQY4EUX0IciiIQESQQ0G0JIIcCqIlEeRQEC2JIEeCzFoSQQ4F8UwaQQ4F8fgaQQ4FUVIJcihIIQhBjgRRUglyKIiSSpBDQZRUghwKIpQR5EiQRSgjyKEgQhlBDgURyghyKIhQRpBDQQpBCHIkiFBGkENBhDKCHAoilBHkUBCPHBLkUBAllSBHgqxKKkEOBVFSCXIoiJJKkENBlFSCHApSCEKQI0F0kHBB+m58+Vyt8kYRJYQiJ4poIRQ5VmRTQyhyooi7mQYVWdb13SF/Ui+oB1L3BEcidY9lJFLXGBKpywaJ1JWAPOpj5+Y+kbrnFxKpeyghkbo2l0i9oB5IXZtLpK7NBVIfvIbP+1DmcfAaPpG61/CJ1AvqgdS9hk+k7jV8InX79UTq9uuJ1O3XA6mP9uuJ1L2GT6TuNXwida/hE6l7DZ9I3Wv4QOrFa/hE6vbridTt1xukPs7P76Ift+ENdfv1ROoF9UDq2lwidW3O2+k9f7o3b6f3+BYJQpAjQRQ/ghwKIg4S5EiQyStPghwK4kUqQQ4F8SKVIIeCeJFKkENBvEglyJEgs2U3QQ4FsRcnyKEgVugEORTEtp0gh4IUghDkSBAllSCHgiipBDkUREklyKEgSipBDgVRUglyJMiipBLkUBB3MQQ5FMRdDEEOBXEXQ5BDQdzFEORQEHcxBDkSZHUXQ5BDQTwPQpBDQTwPQpBDQTwPQpBDQQpBCHIkiJJKkENBlFSCHAqipBLkUBAllSCHgiipBDkSZFNSCXIoiLuYcEH6btwv7tbyRhH3MRQ5UcSdDEVOFHEvQ5ETRdzNUORQkdK5n6HIiSKeDaHIiSKeDqHIiSKeD6HIiSKFIhQ5VkRdpciJIrpIg4os6/r/sXdGSY7kOJC9y36PtQUQJIM8zB5l7r4CqxSVvROSsiQB6R7CX5t1Kv0VQRJJiKAfDfKfqGep4wOjLlm9+MSoZ0HiE6OeNYZPjHqWDT4x6iWj/oFRz8P9J0Y9b0N9YtTzgtMnRj1rc58Y9azNfWDUNWtznxj1rM19YNTX/Bv+hFHv67YPct0Oop5/w39i1PNv+E+Mev4N/4FRL/k3/CdGPf+G/8So5/frnxj1/H79E6NeMuofGPX8fv0Do14z6p8Y9azIfmLUsyL7iVHPiuwnRj0rsh8Y9ZYV2U+MelZkPzHqWZE9YdTXdqWQdehB1LMi+4lRLxn1D4x61uY+MepZm8s35K//Ou0HEyTLeDlB7k6QrPjlBLk7QbI4mBPk3gTZ8i/PnCB3J0j+kZoT5O4EyT9Sc4LcnSD5R2pOkLsTJP9IzQlyb4L0/LI7J8jdCZLfi+cEuTtB8iv0nCB3J0h+254T5O4EKTlBcoLcmyBZSc0JcneCZCU1J8jdCZKV1JwgdydIVlJzgtydIFlJzQlyb4KMrKTmBLk7QfIUkxPk7gTJU0xOkLsTJE8xOUHuTpA8xeQEuTtB8hSTE+TOBKlLnmJygtydIHkfJCfI3QmS90FygtydIHkfJCfI3QlScoLkBLk3QbKSmhPk7gTJSmpOkLsTJCupOUHuTpCspOYEuTtBspKaE+TeBJGspOYEuTtB8hTz4RNElnX/4aWXgymS55icIg+mSJ5kcoo8mCJ5lskp8mCK5Gkmp8j9KaJ5nskp8mCK5N2QnCIPpkjeDskp8mCK5P2QnCIPpkjJKZJT5P4UyepqTpEHUySrqzlFHkyRrK7mFHkwRbK6mlPkwRTJ6mpOkftTZM3qak6RB1Mk6yInnCJb70eD/CfqJaP+gVHP6sUnRj0LEp8Y9awxfGLUs2zwiVHPSsAHRr3k4f4To563oT4x6nnB6ROjnrW5T4x6yah/YNSzNveJUc/a3AdGveXf8CeMel+3fZDrdhD1/Bv+E6Oef8N/YtRLRv0Do55/w39i1PNv+E+Men6//olRz+/XPzHq+f36B0Z9y+/XPzDqPaP+iVHPiuwnRj0rsp8Y9azIfmLUS0b9A6OeFdlPjHpWZD8x6lmRPWHU13alkHXoQdSzIvuJUc+K7AdGfWRt7hOjnrW5tDy6/uu0H0yQLOPlBLk7QbLilxPk7gQpOUFygtyeIG3JvzxzgtydIPlHak6QuxMk/0jNCXJ3guQfqTlB7k6QkhMkJ8i9CZJfducEuTtB8nvxnCB3J0h+hZ4T5O4EyW/bc4LcnSD5xXxOkHsTRLKSmhPk7gTJSmpOkLsTJCupOUHuTpCspOYEuTtBSk6QnCD3JkhWUnOC3JsgmqeYnCB3J0ieYnKC3J0geYrJCXJ3guQpJifI3QlScoLkBLk3QfIUkxPk7gTJ+yA5Qe5OkLwPkhPk7gTJ+yA5Qe5OkLwPkhPk3gRZs5KaE+TuBMlKak6QuxMkK6k5Qe5OkKyk5gS5O0FKTpCcIPcmSFZSc4LcmyAlTzEfPkFkWfcfXno5mCJ5jskp8mCK5Ekmp8iDKZJnmZwiD6ZIySmSU+T+FMnzTE6RB1Mk74bkFHkwRfJ2SE6RB1Mk74fkFHkwRfKGSE6R+1OkZnU1p8iDKZLV1ZwiD6ZIVldzijyYIlldzSnyYIqUnCI5Re5Pkayu5hR5MEWyLnLCKbL1fjTIf6KepY4PjHrL6sUnRj0LEp8Y9awxfGLUs2zwiVEvGfUPjHoe7j8x6nkb6hOjnhecPjHqWZv7xKhnbe4Do75lbe4To561uQ+Mes+/4U8Y9b5u+yDX7SDq+Tf8J0Y9/4b/xKjn3/AfGPWRf8N/YtTzb/hPjHp+v/6JUc/v1z8x6iWj/oFRz+/XPy/q25JR/8SoZ0X2E6OeFdlPjHpWZD8x6lmR/cCoS1ZkPzHqWZH9xKhnRfaEUV/blULWoQdRz4rsJ0a9ZNQ/MOpZm/vEqGdtLi2Prv867QcTJMt4OUHuTpCs+OUEuTtBsjiYE+TeBNH8yzMnyN0Jkn+k5gS5O0Hyj9ScIHcnSP6RmhPk7gTJP1JzgtybIGt+2Z0T5O4Eye/Fc4LcnSD5FXpOkLsTJL9tzwlyd4KUnCA5Qe5NkKyk5gS5O0GykpoT5O4EyUpqTpC7EyQrqTlB7k6QrKTmBLk3QUpWUnOC3J0geYrJCXJ3guQpJifI3QmSp5icIHcnSJ5icoLcnSB5iskJcm+C1DzF5AS5O0HyPkhOkLsTJO+D5AS5O0HyPkhOkLsTpOQEyQlyb4JkJTUnyN0JkpXUnCB3J0hWUnOC3J0gWUnNCXJ3gmQlNSfIvQnSspKaE+TuBMlTzIdPEFnW/YeXXg6mSJ5jcoo8mCJ5kskp8mCK5Fkmp8iDKZKnmZwi96fIlueZnCIPpkjeDckp8mCK5O2QnCIPpkjeD8kp8mCKlJwiOUXuT5GsruYUeTBFsrqaU+TBFMnqak6RB1Mkq6s5RR5Mkayu5hS5P0V6VldzijyYIlkXOeEU2Xo/GuQ/US8Z9Q+MelYvPjHqWZD4xKhnjeETo55lg0+MelYCPjDqIw/3nxj1vA31iVHPC06fGPWszX1i1EtG/QOjnrW5T4x61uY+L+pd8m/4E0a9r9s+yHU7iHr+Df+JUc+/4T8x6iWj/oFRz7/hPzHq+Tf8J0Y9v1//xKjn9+ufGPX8fv0Do675/foHRn3NqH9i1LMi+4lRz4rsJ0Y9K7KfGPWSUf/AqGdF9hOjnhXZT4x6VmRPGPW1XSlkHXoQ9azIfmLUsyL7gVEvWZv7xKhnbS4tj67/Ou0HEyTLeDlB7k6QrPjlBLk7QUpOkJwgdyZIzb88c4LcnSD5R2pOkLsTJP9IzQlyd4LkH6k5Qe5OkJITJCfIvQmSX3bnBLk7QfJ78ZwgdydIfoWeE+TuBMlv23OC3J0g+cV8TpB7E6RlJTUnyN0JkpXUnCB3J0hWUnOC3J0gWUnNCXJ3gpScIDlB7k2QrKTmBLk3QbY8xeQEuTtB8hSTE+TuBMlTTE6QuxMkTzE5Qe5OkJITJCfIvQmSp5icIHcnSN4HyQlyd4LkfZCcIHcnSN4HyQlyd4LkfZCcIPcmSM9Kak6QuxMkK6k5Qe5OkKyk5gS5O0GykpoT5O4EKTlBcoLcmyBZSc0Jcm+CjDzFfPgEkWXdf3jp5WCK5Dkmp8iDKZInmZwiD6ZInmVyijyYIiWnSE6R+1MkzzM5RR5MkbwbklPkwRTJ2yE5RR5MkbwfklPkwRTJGyI5Re5OkbFkdTWnyIMpktXVnCIPpkhWV3OKPJgiWV3NKfJgipScIjlF7k+RrK7mFHkwRbIucsIpsvV+NMh/op6ljg+MumT14hOjngWJT4x61hg+MepZNvjEqJeM+gdGPQ/3nxj1vA31iVHPC06fGPWszX1i1LM294FRX0tG/XxR7+u2D3LdDqKef8N/YtTzb/hPjHr+Df+JUc+/4T8x6vk3/AdGveT3658Y9fx+/ROjnt+vf2LU8/v1D4x6zah/YtRLRv0Do54V2U+MelZkPzHqWZH9xKhnRfYTo54V2Q+MesuKLEXUi2zXX1xkPIi69v1fp72V+z98/7n00bJ4mxPk7gTJOm9OkLsTJIuDOUHuTpCsLeQEuTtBsgyRE+TuBMmKRU6QuxMkixs5Qe5NkC3rIDlB7k6QrIPkBLk7QbIOkhPk7gTJOkhOkLsTpOQEyQlyb4Lk1aucIHcnSFZSc4LcnSBZSc0JcneCZCU1J8jdCZKV1Jwg9yZIz0pqTpC7EyQrqTlB7k6QPMXkBLk7QfIUkxPk7gTJU0xOkLsTJE8xOUHuTZCRp5icIHcnSJ5icoLcnSB5HyQnyN0JkvdBcoLcnSAlJ0hOkHsTJO+D5AS5O0GykpoT5O4EyUpqTpC7EyQrqTlB7k6QrKTmBLk9QeqyZCU1J8jdCZKV1JwgdydInmI+fILIsu4RWXo5mCJ5jskp8mCK5Ekmp8iDKZJnmZwi96eI5Gkmp8iDKZLnmZwiD6ZI3g3JKfJgiuTtkJwiD6ZIySmSU+T+FMkbIjlFHkyRrK7mFHkwRbK6mlPkwRTJ6mpOkQdTJKurOUXuTxHN6mpOkQdTJKurOUUeTJGsrp5viqyyD/Iq4+CWkH5qwVRlj/o27v+wlNJ2jPp16cg59oYHN8m05BzJOfJgjnxqyTTnyPfnyKfWTHOOfH+OfGrRNOfI9+fIp1ZNc458f458atk058i358j6qXXTnCPfnyOfWjjNOfL9OfKpldOcI9+fI1lnzTnyaI6UnCM5Rx7Mkayz5hx5NEeyzppz5NEcyTprzpFHcyRraDlHHsyRkjW0nCOP5kjW0HKOPJojWUPLOfJojmQNLefIozlSco7kHHkwR7KGlnPk0RzJGlrOkUdzJGtoOUcezZG8q5hz5NEcyTprzpEHc6RmnTXnyKM5knXWnCOP5kjWWXOOPJojWWfNOfJojpScIzlHHsyRrI/kHHn47kzNCknOksezJGskOUsezpKWVZKcJY9nyafWScb+0pnov146+z0un1obeDQun3oefjQu5SPHZR1/drkxHrwYuK3XX7yV9c+/b93H8DPvorx3DD/zrsbfjWG5Im9fcv6XMYw+q3f9M4atPxhDqfsYStP7P9x35PH17xVdPuWvm56RPEkkR0byHJHclozkSSIpGcmTRFIzkieJ5JqRPEkkC3Qktf2J5Prgh5dLmXH/t07164/L8cj8IbmMktz/8Y+fJzXnif33l4G8/PjvsWk5NjfHBrvK8bNjg103+NmxwT6Je47NpmP/8W3b7v94G3+qjH/G48L3exw79jnYcRwvv/zPn4FSlo/O7w/ujXXsM3bOEoxZgn1+z1mCMUuwawM5SzBmScm/797y993Hnstztf3FavvYCkXOkr+YJR9bq8lZ8hez5GOrVjlL/mKWfGz9LmfJ92fJyOpkzpLHsySrkzlLHs+SrE7mLHk8S7I6mbPk8SwpOUtyljycJVl7zVnyeJZk7TVnyeNZkrXXnCWPZ0nWXnOWPJ4lWXvNWfJollyGNmdJzpKHsyRrrzlLHs+SrL3mLPk/D7vILv8/50nOk2/Mk5LzxP67rl9//PfYZNXx9thkre3m2Hzjmy9tD8ZGa99XeVu/vAxWj/8Nfb/pLOuX28vL0abQln0s21LK/X+vXga+7/uN9u3g31s+7N9bP+zf2z7s37t92L+3f9S/V2+ctFe9vk8o89949997mST7v3f5clA7fvpQ93+Aan/wTuJa978y1zrG/R++ZNk9LY4v0GIPIf7PT1fZoavKl2Gv7To0mkNza2jWHJpbQ1NyaG4NTc2huTU0LYfm1tBgf0c99uT9dRgPf3jV9XoUuwT2y9mqX/+p2F+0/tU/Vfr+T63L13/q0RzYD52X6dDv//DoXw6o65cq1RHyOvazb1n/9cO/Bxz7O8vzDbhgf/13wgHH/ibthAOO/aXUCQcc+9udEw54yQGPHXDs715OOODYX+iccMBPdMbjGPA8aQYPeJ40Ywdc86QZPOB50gwe8DxpBg94njSDB7zkgMcOeJ40gwc8T5rBA54nzeABz5Nm8IDnSTN2wNc8aQYPeJ40gwc8T5rBA54nzeABLzngsQOeJ83gAc+TZvCA50kzeMDzpBk84HnSjB3wkifN4AHPk2bwgOdJM3jA86QZPOAlBzx2wPOkGTzgedIMHvA8aQYPeJ40gwc8T5qxA17zpBk84HnSDB7wPGkGD3ieNIMHvOSAxw54njSDBzxPmsEDfqKTZtufNNIvzwwfj+Gff98iX19GPvr36Z/3/FRU/vz0ch3EE50ef24QT3Qi/LFBbCc65f3cIJ7o5PZzg3ii09jPDeKJTlg/N4glB/H1QTzRSejnBvFEp5ufG8Q8sbxhEPPE8oZBzBPL64O45YnlDYOYJ5Y3DGKeWN4wiHliecMglhzE1wfxPCeWur+ov7YvA3P8VYLq75+tZk6zIx+5ybSdeBt/RrBdvxvYznNc+akRPM9Z5adG8DwHlZ8awfOcUn5oBPt5jiheIyjyx9dG6r/G8OCH23KlkKb1S6I/9KV959fd/TwHpY8P5XmOax8fyvMcGj8+lCVDeZZQ5gH6NKHMk/xpQpklhdOEMmsbpwllFlnOEsqR1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7ThLKdclqz2lCmdWe04Qyqz2nCWVWe04TypKhPEsos9pzmlBmtec0ocxqz2lCmdWe04Qyqz1nCaVktec0ocxqz2lCmdWe04Qyqz2nCWXJUJ4llFntOU0os9pzmlBmtec0ocxqz2lCmdWes4RSs9pzmlBmtec0ocxqz2lCmdWe04SyZCjPEsqs9pwmlFntOU0os9pzmlBmtec0ocxqz5tDWXbktklkKNes9pwmlFntOU0os9pzmlBmtec0oSwZyrOEMqs9pwllVntOE8qs9pwmlFntOU0os9pzllCWrPacJpRZ7TlNKLPac5pQZrXnNKEsGcqzhDKrPacJZVZ7ThPKrPacJpRZ7TlNKLPac5ZQ1qz2nCaUWe05TSiz2nOaUGa15zShLBnKs4Qyqz2nCWVWe04Tyqz2nCaUWe05TSiz2nOWULas9pwmlFntOU0os9pzmlBmtec0oSwZyrOEMqs9pwllVntOE8qs9pwmlFntOU0os9pzllBuWe05TSiz2nOaUGa15zShzGrPaUJZMpRnCWVWe04Tyqz2nCaUWe05TSiz2vMwlLrtoVylfQ3l7zHMMsvLY9g/s76xtesv7kt/MIZvXff9M4sQPzfen1kp+Lnx/szj/M+Nd8nxDh3vzzwY/9x4f+bp9efG+zOPmD833p95Dvy58f7MM+OPjffI82XseOf5Mna883wZO955vowd75LjHTreeb6MHe88X8aOd54vY8c7z5ex453ny8jxLkueL2PHO8+XseOd58vY8c7zZex4lxzv0PHO82XseOf5Mna883wZO955vowd7zxfho635PkydrzzfBk73nm+jB3vPF/GjnfJ8Q4d7zxfxo53ni9jxzvPl7HjnefL2PHO82XoeGueL2PHO8+XseOd58vY8c7zZex4lxzv0PHO82XseOf5Mna883wZO955vowd7888X3bdx7ut/xrvX8OynucY2JrsGMtyf1j+5imjthNv41/vev0ewfMc7LxG8C/fRluugyGXof+ykr3fRivrec6MHx/K8xxHPz6UJUN5llCe5xD98aE8z/n840N5nqP/x4fyPFWFjw/leQoWnx7KkkWW04Qyqz2nCWVWe04Tyqz2nCaUJUN5llBmtec0ocxqz2lCmdWe04Qyqz2nCWVWe84SyprVntOEMqs9pwllVntOE8qs9pwmlCVDeZZQZrXnNKHMas9pQpnVntOEMqs9pwllVnvOEsqW1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7zhLKLas9pwllVntOE8qs9pwmlFntOU0oS4byLKHMas9pQpnVntOEMqs9pwllVntOE8qs9pwllD2rPW8OZdmR2yahocxqz2lCmdWe04Qyqz2nCWXJUJ4llFntOU0os9pzmlBmtec0ocxqz2lCmdWes4RyZLXnNKHMas9pQpnVntOEMqs9pwllyVCeJZRZ7TlNKLPac5pQZrXnNKHMas9pQpnVnpOEsi5Z7TlNKLPac5pQZrXnNKHMas9pQlkylGcJZVZ7ThPKrPacJpRZ7TlNKLPac5pQZrXnLKGUrPacJpRZ7TlNKLPac5pQZrXnNKEsGcqzhDKrPacJZVZ7ThPKrPacJpRZ7TlNKLPac5ZQalZ7ThPKrPacJpRZ7TlNKLPac5pQlgzlWUKZ1Z7ThDKrPacJZVZ7ThPKrPacJpRZ7XkYSt32UK7Svoby1xiun1lm2dr1F/elPxjDt87Z9TNrIT833p9ZsPi58f7MqsLPjXfJ8Q4d7888n//ceH/mIfrnxvszT7o/N96feRz9ufH+zDPjj413yfNl7Hjn+TJ2vPN8GTveeb6MHe+S4x063nm+jB3vPF/GjneeL2PHO8+XseOd58vQ8a55vowd7zxfxo53ni9jxzvPl7HjXXK8Q8c7z5ex453ny9jxzvNl7Hjn+TJ2vPN8GTreLc+XseOd58vY8c7zZex45/kydrxLjnfoeOf5Mna883wZO955vowd7zxfxo53ni9Dx3vL82XseOf5Mna883wZO955vowd75LjHTreeb6MHe88X8aOd54vY8c7z5ex4/2Z58uu+3i39V/j/WtY+nmOgdu67RhD7w9L3Yfl308ZHU2tbVyJL4P5ZSia95Tt5zkyni825zleni825zmKni82JWMDG5vzHHHPF5vzHIfPF5vzHJ3PF5vzHLPPF5vzHMlPF5uRdQHc2GRdADc2WRfAjU3WBXBjUzI2sLHJugBubLIugBubrAvgxibrArixyboAamzaknUB3NhkXQA3NlkXwI1N1gVwY1MyNrCxyboAbmyyLoAbm6wL4MYm6wK4scm6AGxsJOsCuLHJugBubLIugBubrAvgxqZkbGBjk3UB3NhkXQA3NlkXwI1N1gVwY5N1AdjYaNYFcGOTdQHc2GRdADc2WRfAjU3J2MDGJusCuLHJugBubLIugBubrAvgxibrArCxWbMugBubrAvgxibrArixyboAbmxKxgY2NlkXwI1N1gVwY5N1AdzYZF0ANzZZF4CNTcm6AG5ssi6AG5usC+DGJusCuLEpGRvY2GRdADc2WRfAjU3WBXBjk3UB3NhkXQA2NjXrArixyboAbmyyLoAbm6wL4MamZGxgY5N1AdzYZF0ANzZZF8CNTdYFcGOTdQHY2LSsC+DGJusCuLHJugBubLIugBubkrGBjU3WBXBjk3UB3NhkXQA3NlkXwI1N1gVgY7NlXQA3NlkXwI1N1gVwY5N1AdzYlIwNbGyyLoAbm6wL4MYm6wK4scm6AG5ssi4AG5uedQHc2GRdADc2WRfAjU3WBXBjUzI2sLHJugBubLIugBubrAvgxibrArixyboAbGxG1gVwY5N1AdzYZF0ANzZZF8CNTcnYwMYm6wK4scm6AG5ssi6AG5usC+DGJusCqLHZlqwL4MYm6wK4scm6AG5ssi6AG5uSsYGNTdYFcGOTdQHc2GRdADc2WRfAjU3WBWBjI1kXwI1N1gVwY5N1AdzYZF0ANzYlYwMbm6wL4MYm6wK4scm6AG5ssi6AG5usC8DGRrMugBubrAvgxibrArixyboAbmxKxgY2NlkXwI1N1gVwY3PKusDXQTyMzajXnx1jexCbthNvQ/afbfsInvL0/tYRFNFypZD6rzE8+OG2XAdDLkP/Zcou7ovhlIf9jwzlesrawGeG8pSlhM8M5SkrD58ZylMWKj4zlCVDeZZQnrIM8pmhPGXV5DNDmUWW04Qyqz2nCWVWe84SypLVntOEMqs9pwllVntOE8qs9pwmlCVDeZZQZrXnNKHMas9pQpnVntOEMqs9pwllVnvOEsqa1Z7ThDKrPacJZVZ7ThPKrPacJpQlQ3mWUGa15zShzGrPaUKZ1Z7ThDKrPacJZVZ7zhLKltWe04Qyqz2nCWVWe04Tyqz2nCaUJUN5llBmtec0ocxqz2lCmdWe04Qyqz2nCWVWe84Syi2rPacJZVZ7ThPKrPacJpRZ7TlNKEuG8iyhzGrPaUKZ1Z7ThDKrPW8OZdmR2yahocxqz2lCmdWes4SyZ7XnNKHMas9pQpnVntOEMqs9pwllyVCeJZRZ7TlNKLPac5pQZrXnNKHMas9pQpnVnrOEcmS15zShzGrPaUKZ1Z7ThDKrPacJZclQniWUWe05TSiz2nOaUGa15zShzGrPaUKZ1Z6ThLIvWe05TSiz2nOaUGa15zShzGrPaUJZMpRnCWVWe04Tyqz2nCaUWe05TSiz2nOaUGa15yyhlKz2nCaUWe05TSiz2nOaUGa15zShLBnKs4Qyqz2nCWVWe04Tyqz2nCaUWe05TSiz2nOWUGpWe04Tyqz2nCaUWe05TSiz2nOaUJYM5VlCmdWe04Qyqz0PQ6nbHspV2tdQ/h7DzyyziPR9XFT/PYq/B+YzixbfGJjPLAE8Hpj1Mw/U3xiYzzyefmNgznPYG/X6m9fxhflwYKq0618BVbb+INu98y+G9TxHMpIBLzngsQN+nuMNyYCf5xBCMuDnObGQDPh5TkIkA36eExbHgJfznNxIBvw8J0KSAc+TZvCA50kzeMBLDnjsgOdJM3jA86QZPOB50gwe8DxpBg94njRjB7zmSTN4wPOkGTzgedIMHvA8aQYPeMkBjx3wPGkGD3ieNIMHPE+awQOeJ83gAc+TZuyAtzxpBg94njSDBzxPmsEDnifN4AEvOeCxA54nzeABz5Nm8IDnSTN4wPOkGTzgedKMHfAtT5rBA54nzeABz5Nm8IDnSTN4wEsOeOyA50kzeMDzpBk84HnSDB7wPGkGD3ieNGMHvOdJM3jA86QZPODnOWle/gDYB3zI/TEU0f03S6tfoN0fEeznOWqyjHjJEQ8e8fMcNllG/DynTZYRP89xk2XEz3PeZBnx8xw4SUZ8nOfEyTLi5zlysox4njmjRzzPnNEjXnLEg0c8z5zRI55nzugRzzNn9IjnmTN6xPPMGTviY8kzZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BGXPHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwecc0zZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BFf88wZPeIfeubUZd1/8zpCR/xDz5w/OOIfeub8wREvOeLBI/6hZ84fHPEPPXP+4Ih/6JnzB0f8Q8+cPzjiH3rm/LkRLx965vzBEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnMEjXvPMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMRbnjmjRzzPnNEjnmfO6BHPM2f0iJcc8eARzzNn9IjnmTN6xPPMGT3ieeaMHvE8cwaP+JZnzugRzzNn9IjnmTN6xPPMGT3iJUc8eMTzzBk94nnmjB7xPHNGj3ieOaNHPM+cwSPeP/TMWcr+Dyy9h474h545f3DEP/TM+YMj/qFnzh8c8ZIjHjziH3rm/MER/9Az5w+O+IeeOX9wxD/0zPmDI/6hZ86fG/GRZ87oEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnKEj3pYlz5zRI55nzugRzzNn9IjnmTN6xEuOePCI55kzesTzzBk94nnmjB7xPHNGj3ieOYNHXPLMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMQ1z5zRI55nzugRzzNn9IjnmTN6xEuOePCI55kzesTzzBk94nnmjB7xPHNGj/iHnjnruo9L7SVyxNcPPXP+4Ih/6JnzB0f8Q8+cPzjiH3rm/MERLzniwSP+oWfOHxzxDz1z/uCIf+iZ8wdH/EPPnD844nnmDB7xkmfO6BHPM2f0iOeZM3rE88wZPeIlRzx4xPPMGT3ieeaMHvE8c0aPeJ45o0c8z5zBI17zzBk94nnmjB7xPHNGj3ieOaNHvOSIB494njmjRzzPnNEjnmfO6BHPM2f0iOeZM3jEW545o0c8z5zRI55nzugRzzNn9IiXHPHgEc8zZ/SI55kzesTzzBk94nnmjB7xPHMGj/iWZ87oEc8zZ/SI55kzesTzzBk94iVHPHjE88wZPeJ55owe8TxzRo/4h545xz4uehnyRyPeypVjbMuf4dD1EKTsHF9eJ9IjjHWrug/dVu//sNQ/Q1dLe/DDy7r/8PJlSl1++HfgP/To+/GB7x96As/Af2ghIAP/ofWIDPyHlkUy8CUD/5mB/9AiUQb+Q2tVGfgPLZll4LNy96GBz8rdZwZ+ZOXuQwOflbsfDHyR7fqLi4wHgdderuOsvZVXA5+Vuw8NfFbuPjTwJQO/hd6AGFkyix7xrFVFj3gWiaJHPKsz0SOeZZHYEb8o5IgHj3gWAqJHPE/g0SOeR9/oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwecckzZ/SI55kzesTzzBk94nnmjB7xkiMePOJ55owe8TxzRo94njmjRzzPnNEjnmfO4BHXPHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwe8TXPnNEjnmfO6BHPM2f0iOeZM3rES4548IjnmTN6xPPMGT3ieeaMHvE8c0aPeJ45g0e85JkzesTzzBk94nnmjB7xzzxz6rrtzwKV5d9PGf0emHKWgSmyXOdAuXwD9WAqtuXKLE2/PK6k/lPxNEdDmhE/zdGQZsRPczSkGfHTHA1pRvw0R0OWEa+nORrSjPhpjoY0I36aoyHNiJ/maEgz4iVHPHjE88wZPeJ55owe8TxzRo94njmjRzzPnMEj3vLMGT3ieeaMHvE8c0aPeJ45o0e85IgHj3ieOaNHPM+c0SOeZ87oEc8zZ/SI55kzeMS3PHNGj3ieOaNHPM+c0SOeZ87oES854sEjnmfO6BHPM2f0iOeZM3rE88wZPeJ55gwe8Z5nzugRzzNn9IjnmTN6xPPMGT3iJUc8eMTzzBk94nnmjB7xPHNGj3ieOaNHPM+cwSM+8swZPeJ55owe8TxzRo/4p545y/6b2yahI15yxINH/FPPnD834p965vy5Ef/UM+fPjfinnjl/bsQ/9cz5UyOuy6eeOX9uxD/1zPlzI/6pZ86fG/E8c0aPeMkRDx7xPHNGj3ieOaNHPM+c0SOeZ87oEc8zZ/CIS545o0c8z5zRI55nzugRzzNn9IiXHPHgEc8zZ/SI55kzesTzzBk94nnmjB7xPHMGj7jmmTN6xPPMGT3ieeaMHvE8c0aPeMkRDx7xPHNGj3ieOaNHPM+c0SOeZ87oEc8zZ/CIr3nmjB7xPHNGj3ieOaNHPM+c0SNecsSDRzzPnNEjnmfO6BHPM2f0iOeZM3rE88wZPOIlz5zRI55nzugRhz5z6tDrD69VHvxwbX3/6botX35cDn5cLyD9949f/rtvX3/899hAnw5/eGzKecZm2/o+Nn3p98fmsua2ffmtf374kp+vQwN94Pq7oRl/hqYtpRzMg8OzzvVfujz4Z/4Zky5/NlSRo02ylXL9Z7bSyuszeKMl72Hk656YLuTbffJar6mmbn8yTblCD0LoujBCCyO0QkK35brZNx3/C70yQhdG6MoI3RihN0ZozIz4ABozI96HbpgZ8QE0ZkZ8AM2YERtjRmx0GVGXf47bXlovvz+z6Z/Dnazt96eOWzcefkqe+pQ+9an1rz/V9J/ja56bXE9S25c/OUXr9VPbU5/qT31qPPOp42tPDz8lT31Kn/rUYby6XOPV9fBT5alP1ac+1Z761PbUp/pTnxrPfOr464ner5WjPvToU/LUp/SpT61Pfao89an61KfaU586nBtjudblhyxHn+pPfWo886njwsXDT8lTn9KnPrU+9anDuTH0ulLGerRSjk+PDz/VnvrU9tSn+lOfGs986vhP+IefkgefKkfxOv4j9uGn1qc+dTw36nUtj3a0llt96lPtqU9tT32qP/Wp8cyntuWpTx3Pjb5/4bHU/q+P/edvfvi3hgZorAEaJUCjBmi0AI0tQKMHaAx/jWOT5TdrBKzzHrDOe8A67wHrvAes8x6wznvAOu8B67wHrPMRsM5HwDofAet8BKzzEbDOR8A6HwHrfASs8xGwzkfAOpdliRCRCBGNEFkjREqESI0QaREiW4RIjxCJWPESseIlYsVLxIqXiBUvESteIla8RKx4iVjxErHiJWLFa8SK14gVrxErXiNWvEaseI1Y8Rqx4jVixWvEiteIFb9GrPg1YsWvESt+jVjxa8SKXyNW/Bqx4teIFb9GrPg1YsWXiBVfIlZ8iVjxJWLFl4gVXyJWfIlY8SVixZeIFV8iVnyNWPE1YsXXiBVfI1Z8jVjxNWLF14gVXyNWfI1Y8TVixbeIFd8iVnyLWPEtYsW3iBXfIlZ8i1jxLWLFt4gV3yJW/Bax4iPu1UnExTqJuFknEVfrJOJunURcrpOI23UScb1OIu7XScQFO4m4YScRV+wk4o6dRFyyk4hbdhJxzU4i7tlJxEU7ibhpJxFX7STirp1EXLaTiNt2EnHdTiLu20nEhTuJuHEnEVfuJOLOnUbcudOIO3cacedOI+7c6VIiRGqESIsQ2SJEeoRIxIqPuHOnEXfuNOLOnUbcudOIO3cacedOI+7cacSdO424c6cRd+404s6dRty504g7dxpx504j7txpxJ07jbhzpxF37jTizp1G3LnTiDt3GnHnTiPu3GnEnTuNuHOnEXfuNOLOnUbcudOIO3cacedOI+7cacSdO424c6cRd+404s6dvuGmWq3XJ/rqv6wYZNfo/hpvuN1V9xf/a++HGhqgsQZolACNGqDxt4nk+rntuc+94Tv5h/P4DV/JP9aoARotQCNg73rD1/F17GYGSz3UGP4ab/gy/rGGBGhogMYb1vmQXaMdapQAjRqg0QI0tgCNHqAx/HPiG76Cf6wR8LfWCPhbawT8rfWGr98fawT8rfWGL98fa2wBGj1Aw3+dr8sSoCEBGhqgsQZolACNGqDRAjS2AI0eoBGwziVgnUvAOpeAdS4B61wC1rkErHMJWOcSsM4lYJ1LwDrXgHWuAetcA9a5BqxzDVjnGrDONWCdq/c67/8cKkgtu7Ns/WIOpEfmQL1eFXqX+z8q0ncPaNX/3wP6QtOhaAYUzfEfLD+HI1g4ioWzYuEULJyKhdOwcLD2ZMHalAVrV1asXVmxdmXF2pUVa1dWrF1ZsXZlddyVfyts7gqv751ffMjW5dUhHVA464KFI1g4ioWzYuEULJyKhdOwcDYsHKxdecXalQvWrlywduWCtSsXrF25YO3KBWtXLli7cnHclX8rdHeF4a1QF3cFcVdQd4XVXaG4K1R3heau4L6m2+uzVZbl6uIri+iBhgZovB5t0fJnh20Hx/82/P8d2xKgERDzrbxBo41do7cDjRqg0QI0tgCNHqDxjvXR5I/G9r8afQnQkAANDdBYAzRKgEYN0GgBGluARg/QeMM6FynXH5Zy8HfJWAI0JEBDAzTWAI0SoFEDNFqAxhag8YZ1LpvuGl9vk+0aw1/jhhvxu0VW/9PBDQ/fd4vUCJEWITICRN5wy+4bIhIhohEi3utkW46vqG77h7btQSG0LP33jxat93+07/vCWMp/v1RM/7a8esHunNiDE/t43RJwCym3knKvpNyFlLuScjdSbtJsKaTpUkjzpZLmSyXNl0qaL5U0XyppvlTSfKlu+fL379+cf//L+adev98stRz8/uH7+9fF+feL8+9X59//8j62N9KWvh78/uL8+6vz72/Ov//V9VuXa0mpLv3g93fn3z98f39ZnH+/OP/+V+dn1euPVj36/c35978a37Ze7zq0qv/7++vi/Pudx6e+vH73knCt28Hv786/f/j+/rY4/35x/v3q/PtX599fnH9/df79zfn3v3H9tnbw+7vz7399/e7723bw+7eX1+867v5+cf796vz7X12/bb//2ZZx8PuL8++vzr+/Of/+zfn3v7x+/zz+LMvB7x++v78vzr9fnH+/Ov/+1fn3F+ffX51/f3P+/dsbf//B+u3d+fe/vn6v99OaHvz+8fL63QuUx79fnH+/Ov/+l/Pv/fPjKM6/vzr//ub8+zfn39+df79zfePGtcw3CfQbt8Ckrfut11YffN0hZblucVJE/lfixt2/v9MofdfYHn3/8q7Xcvqte0Qk7ErMvhKzF2L2SszeiNk3YvZOzD542ZU4rypxXlXivKrEeVWJ86oS51UlzqtKnFeVOK8qSl79hbOipMrfOMHZ723PW/VbN8pI2Fdi9kLMXonZGzH7RszeidkHL3tZiNmJ82ohzquFOK8W4rxaiPNqIc6rhTivFuK8WojzakXJq79xUFLlbxyU7PcbByWh/cZByVG/cVDSzm8clEzyGwclOfzGQdnvf+OgbOG/cBrWrtyCF/r954P7rf6MnwQKns73n9HqtzoQfnCENkUDWtGAWjTQvQeb+60uhJ8E6mhAAwyoL2hA4fvQvdeJ+63Wi58EWtGAChpQRQNqaEAbGlBHAxpgQGNBA4reqe++Yd1vNdn8JNCKBlTQgCoaUEMD2tCAOhrQAAO69Qa9I9G9B+snkcARKRxRBSvJ3Ho3/yeJNjgitEKaRPfafYNI4YhWOKICR4S1H22UTgsXbManoy/YjC9HX7ApnRaMm/HlaONmfDnauBlfjjbuQsrN+HK0cTM6LRg3abakdFowbtJ8Sem0YNyk+ZLSacG4SfMlpdOCcZPmS1enBfv9m/Pv93RasN8/fH+/q9OC/X5x/v3q/Ps9nRbs9xfn31+df39z/v2eTgv2+7vz7x++v9/VacF+vzj/fk+nBfv9zfn3e75EePn9rk4L9vudx8fVacF+f3f+/cP397s6LdjvF+ffr86/f3X+/cX591fn39+cf7+n04L9/u78+z2dFuxLJk+nBfv94vz71fn3ezot2O8vzr+/Ov/+5vz7N+ff7+m0YL9/+P5+V6cF+/3i/PvV+fevzr+/OP/+6vz7m/Pv93RasN/fnX+/p9OCXTvwdFqw3y/Ov1+df7+n04L9/uL8+6vz72/Ov39z/v3d+fc71zd8nRZGc3dauEjQOi0YO+uL0MbO+iK0sbO+CG3shZid9UVoY2d9EdrYWV+ENnbWF6GNndVp4cJO67Rg7MR5ldZpwdiJ8yqt04KxE+dVWqcFYyfOq7ROC8YO5LRwwUFyWjAc1hehjZ31RWhjZ30R2tgLMTvri9DGzvoitLGzvght7KwvQhs764vQF3ZapwVjJ86rtE4Lxk6cV2mdFoydOK/SOi0YO3FepXVaMHbivIrktGA4QE4LhgPktGA4QE4LhoOSo37jADktGA6Q04LhADktGA6Q04LhADktXHCQnBYMJ3ih33+U3oCgnBYMCOqBOLtABeW0YEBQTgsGBOW0YEBQTgsGBOW0YEBQTgsGBOW0cAHCclowICinBQOCclowICinBQMqaEBQTgsGBOW0YEBQTgsGBOW0YEBQTgsXICynBQOCclowICinBQOCclowoIIGBOW0YEBQTgsGBOW0YEBQTgsGBOW0MBuFoJwWJhGU08IkgnJamERQL5tPIiinhUkE5bQwidAKaWBOC5MIymlhEkE5LUyiAkcEtR/Jsro32ZoGbZfthGdtB5rwrP1AE561IWjCF2Z41pagCc/aEzThWZuCJjxrV9CEZ223NXjaftsJz5xhaTtuJzxzhqXtuZ3wzBmWtut2wjNnWNq+2wkP1HhrPEidt5OHtUVowrP2CE141iahCV+Y4VnbhCY8a5/QhGdtFJrwrJ1CE561VcjgaXtwJzxzhqXtwp3wzBmWtg93wjNnWNpO3AnPnGFpe3EnPHOGRerGnTxA7biTB6gfd/IANeROHpRsdeUBasmdPEA9uZMHqCl38gB15U4eoLZc40Hqy508wev9fg/jJILqzJ1EUDcK570rqN7cSQTVnDuJoLpzJxFUe+4kgurPnURQDbqTCKpD14iwWnQnEVSP7iSCatKdRFBdupOowBFB9elOIqhG3UkE1ak7iaBadScRVK+uEWE1604iqG7dSQTVrjuJoPp1J1GBI4Lq2J1EUC27kwiqZ3cSQTXtTiKort1fnUdQbbu/kKD6dn8hQTXu/kKC65QDa939hQTVu/sLCa7UBta9+wsJqn33FxJU/+4vpIKHhLUvifzzqk1xWa40RR/A9H3bHkv586P6999zX7g7Kfcg5ZaFFVxYwZUVfGUFL6zglRW8sYKz5k1hTZzCmjmVNXMqa+ZU1syprJlTWTOnsmZOdcucV4HNW+DlTFSv921KLUcCw1lgXbwFxFtAvQVe3tH6ddGUvh4JFG+B6i3QvAVeXcl12X7/aF36kUD3FhjOAmXxFhBvgVenadXrj1Y9FGjeAq8Gua3XW2qt6oFAXbwFvIeovrySyz6L6nYk0L0FhrNAW7wFxFtAvQVWb4HiLVC9BZq3wBtXcmtHAt1b4PWVvG9225HA9vJK3rfrGwLiLaDeAq+u5La3LLRlHAkUb4HqLdC8BTZvgZdX8ri+sNxkORIYzgJ98RYQbwH1Fli9BYq3QPUWaN4C2xsFjlZy794Cr6/k60WUpkcC4+WVvNc1bwiIt4B6C7yckx+cMkfxFqjeAs1bYPMW6N4C3sWQG3eb36Wg4u8NoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaGC5Q2hguUNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A2hQuwNoULsDaFC7A1h8MwZltcbwuCZMyyvN4QKsTeEwTNnWF5vCBVibwgVLG8I40HyhjAeJG8I40HyhjAelGx15UHyhlDB8oZQwfKGUMHyhlDB8oZQwfKGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUEHzhlBB84ZQQfOGUIHzhphIWN4QEwnLG2IiYb3BPpGwvCEmEpY3xESCK7WheUNMJCxviImE5Q0xkQoeEti+1Dm9IS7clE9cX7gpX7i+cHN6Qxg45QvXBk75wrWBU75wbeCFFZzyhWsDp/SGMHDWvMnpDWHgrJmT0xvCwFkzJ6c3hIGzZk5ObwgDZ82cvt4QJrB5C7h6Q5jAcBbw9YYwAfEWUG8BV28IEyjeAtVboHkLuHpDmED3FhjOAr7eECYg3gKu3hAm0LwFXJ9DvAj4ekOYgPcQ+XpDmED3FhjOAr7eECYg3gLqLbB6CxRvgeot0LwFXL0hTKB7C7h6Q9g3U67eECYg3gLqLeDqDWECxVugegs0b4HNW8DVG8IEhrOArzeECYi3gHoLrN4CxVugegs0bwFXbwgT6N4Crt4QdnvB1RvCBMRbQL0FXL0hTKB4C1RvgeYtsHkLdG8B72KIszfEuvl7Q1w0eL0hDJ725WqDp3252uBpX642+MIMT/tytcHTvlxt8LQvVxs87cvVBk/rDXGB5/WGMHjmDMvrDWHwzBmW1xvC4JkzLK83hMEzZ1hebwiDR/KGuPBAeUMYD+3L1QZP+3K1wdO+XG3whRme9uVqg6d9udrgaV+uNnjal6sNnvbl6gs8rzeEwTNnWF5vCINnzrC83hAGz5xheb0hDJ45w/J6Qxg8c4aF8oYwHiRvCONB8oYwHiRvCONByVZXHiRvCONB8oYwHiRvCONB8oYwHiRviAsPlDeE8QSv9wcv6BsRljeEEWE9WGf3rrC8IYwIyxvCiLC8IYwIyxvCiLC8IYwIyxvCiLC8IS5EYN4QRoTlDWFEWN4QRoTlDWFEBY4IyxvCiLC8IYwIyxvCiLC8IYwIyxviQgTmDWFEWN4QRoTlDWFEWN4QRlTgiLC8IYwIyxvCiLC8IYwIyxvCiLC8IWbnEZY3xETC8oaYSFjeEBMJ6w32iYTlDTGRsLwhJhJcqQ3NG2IiYXlDTCQsb4iJVPCQsPalUvw7eC8avB28Bk/bX2TwtP1FBk/bX2TwhRmetr/I4Gn7iwyetr/I4Gn7iwyetoP3As/bwWvwzBmWt4PX4JkzLG8Hr8EzZ1jeDl6DZ86wvB28Bo/UwXvhgergNR7a/iKDp+0vMnja/iKDL8zwtP1FBk/bX2TwtP1FBk/bX2TwtP1FF3jeDl6DZ86wvB28Bs+cYXk7eA2eOcPydvAaPHOG5e3gNXjmDAvVwWs8SB28xoPUwWs8SB28xoOSra48SB28xoPUwWs8SB28xoPUwWs8SB28Fx6oDl7jCV7vD/ocjQirg9eIsK4V2r0rrA5eI8Lq4DUirA5eI8Lq4DUirA5eI8Lq4DUirA7eCxFYB68RYXXwGhFWB68RYXXwGlGBI8Lq4DUirA5eI8Lq4DUirA5eI8Lq4L0QgXXwGhFWB68RYXXwGhFWB68RFTgirA5eI8Lq4DUirA5eI8Lq4DUirA7e2XmE1cE7kbA6eCcSVgfvRILrlEPr4J1IWB28Ewmu1IbWwTuRsDp4JxJWB+9EKnhIWPtSbTc6eGvZrh+rbbuv8b5b3hecjoUzsHButEL/HI+A8SgYzwrGU8B4KhhPA+MB250FbHsWsP1ZwfZnBdufFWx/VrD9WcH2ZwXbn9Vxf75KbP4Sr++i77syajwDi2ddwHgEjEfBeFYwngLGU8F4GhjPBsYDtj+vYPtzAdufC9j+XMD25wK2Pxew/bmA7c8FbH8ujvvzVaL7Swx3ibr4S4i/hPpLrP4SxV+i+ks0fwn/1d1en7QPLtebiEaIvB7yx1/JtRHwL9mWCJGIwG/lDSJ3L7ibSI0QaREiW4RIjxB5xzq5e0v2ItKXCBGJENEIkTVCpESI1AiRFiGyRYj0CJE3rPj7tz4vImOJEJEIEY0QWSNESoRIjRBpESJbhMgbVvz9m7wmMgJEbt3zfrfKGnB4kKWEqNQQlRaiMiJU3nB37zsqEqKiISr+66Uf33/d9k9t24PyaVmut3GLPriM2/cdYizlv1/qrH9flO3HF2UJuAcp9/HyZQAXVnBlBV9ZwQsreGUFb6zgrHlTWBOnsGZOZc2cypo5lTVzKmvmVNbMqayZU90y51Vg8xZ4ORPV6zejpZYjgeEssC7eAuItoN4CL+9o/bpoSl+PBIq3QPUWaN4Cr67kulwrTnXpRwLdW2A4C5TFW0C8BV6dplWvP1r1UKB5C7wa5LZeL0y0qgcCdfEW8B6i+vJK3mvHtW5HAt1bYDgLtMVbQLwF1Ftg9RYo3gLVW6B5C7xxJbd2JNC9BV5fyftmtx0JbC+v5H27viEg3gLqLfDqSm775dK2jCOB4i1QvQWat8DmLfDySh71KiDLkcBwFuiLt4B4C6i3wOotULwFqrdA8xbY3ihwtJJ79xZ4fSVfL701PRIYL6/kva55Q0C8BdRb4OWc/OCUOYq3QPUWaN4Cm7dA9xbwLobcuPP5LoV242bZXz71uFz3OykiBxqCYkL/11/htFs3k1jglRl+ZYYvzPCVGb4xw2/M8J0ZfhDDK3OGVeYMq8wZVpkzrDJnWGXOsMqcYZU5wypzhlWUDPubZ0VJmlceFBP6Z4K7ojjWPwWPYm//FHxhhq/M8I0ZfmOG78zwgxi+LMzwzBm2MGfYwpxhC3OGLcwZtjBn2MKcYQtzhi3MGbaiZNgrD0rSvPKg5MErD0pqu/KgZKsrD0oCuvKg5JQrD0qauPKg7PxXHpTN/DdPA9ufW/B6f/DWcbvV+PGjRFiGze1WW8NPjtGmcEQrHFG0Pfr956XbrcaGHyXqcEQDjagvcETh+9HdZ5TbrW6OHyVa4YgKHFGFI2pwRBscUYcjGmhEY4Ejit6z77+23W717fwo0QpHVOCIKhxRgyPa4Ig6HNFAI7r1Zr4j0t0H9ieS4CEpHlJFq9jceuf/R5E2PCS4UptEt/B9B0nxkFY8pIKHhLUvbZXTG+LCTfnE9YWb8oXrCzenN4SBU75wbeCUL1wbOOUL1wZeWMEpX7g2cEpvCANnzZuc3hAGzpo5Ob0hDJw1c3J6Qxg4a+bk9IYwcNbM6esNYQKbt4CrN4QJDGcBX28IExBvAfUWcPWGMIHiLVC9BZq3gKs3hAl0b4HhLODrDWEC4i3g6g1hAs1bwPU5xIuArzeECXgPka83hAl0b4HhLODrDWEC4i2g3gKrt0DxFqjeAs1bwNUbwgS6t4CrN4R9M+XqDWEC4i2g3gKu3hAmULwFqrdA8xbYvAVcvSFMYDgL+HpDmIB4C6i3wOotULwFqrdA8xZw9YYwge4t4OoNYbcXXL0hTEC8BdRbwNUbwgSKt0D1FmjeApu3QPcW8C6GOHtD9OLvDXHR4PWGMHjal6sNnvblaoOnfbna4AszPO3L1QZP+3K1wdO+XG3wtC9XGzytN8QFntcbwuCZMyyvN4TBM2dYXm8Ig2fOsLzeEAbPnGF5vSEMHskb4sID5Q1hPLQvVxs87cvVBk/7crXBF2Z42perDZ725WqDp3252uBpX642eNqXqy/wvN4QBs+cYXm9IQyeOcPyekMYPHOG5fWGMHjmDMvrDWHwzBkWyhvCeJC8IYwHyRvCeJC8IYwHJVtdeZC8IYwHyRvCeJC8IYwHyRvCeJC8IS48UN4QxhO83h+8oG9EWN4QRoT1YJ3du8LyhjAiLG8II8LyhjAiLG8II8LyhjAiLG8II8LyhrgQgXlDGBGWN4QRYXlDGBGWN4QRFTgiLG8II8LyhjAiLG8II8LyhjAiLG+ICxGYN4QRYXlDGBGWN4QRYXlDGFGBI8LyhjAiLG8II8LyhjAiLG8II8LyhpidR1jeEBMJyxtiImF5Q0wkrDfYJxKWN8REwvKGmEhwpTY0b4iJhOUNMZGwvCEmUsFDwtqXhvh38F40eDt4DZ62v8jgafuLDJ62v8jgCzM8bX+RwdP2Fxk8bX+RwdP2Fxk8bQfvBZ63g9fgmTMsbwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DR6pg/fCA9XBazy0/UUGT9tfZPC0/UUGX5jhafuLDJ62v8jgafuLDJ62v8jgafuLLvC8HbwGz5xheTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGRaqg9d4kDp4jQepg9d4kDp4jQclW115kDp4jQepg9d4kDp4jQepg9d4kDp4LzxQHbzGE7zeH/Q5GhFWB68RYV0rtHtXWB28RoTVwWtEWB28RoTVwWtEWB28RoTVwWtEWB28FyKwDl4jwurgNSKsDl4jwurgNaICR4TVwWtEWB28RoTVwWtEWB28RoTVwXshAuvgNSKsDl4jwurgNSKsDl4jKnBEWB28RoTVwWtEWB28RoTVwWtEWB28s/MIq4N3ImF18E4krA7eiQTXKYfWwTuRsDp4JxJcqQ2tg3ciYXXwTiSsDt6JVPCQwPal8c+rPshludIUfQDT9217LOXPj+oT33OPfzop9yDlloUVXFjBlRV8ZQUvrOCVFbyxgrPmTWFNnMKaOZU1cypr5lTWzKmsmVNZM6eyZk51y5xXgc1b4OVMVK/3bUotRwLDWWBdvAXEW0C9BV7e0fp10ZS+HgkUb4HqLdC8BV5dyXXZfv9oXfqRQPcWGM4CZfEWEG+BV6dp1euPVj0UaN4Crwa5rddbaq3qgUBdvAW8h6i+vJLLPovqdiTQvQWGs0BbvAXEW0C9BVZvgeItUL0FmrfAG1dya0cC3Vvg9ZW8b3bbkcD28kret+sbAuItoN4Cr67ktrcstGUcCRRvgeot0LwFNm+Bl1fyuL6w3GQ5EhjOAn3xFhBvAfUWWL0FirdA9RZo3gLbGwWOVnLv3gKvr+TrRZSmRwLj5ZW81zVvCIi3gHoLvJyTH5wyR/EWqN4CzVtg8xbo3gLexZAbd5vfpKDLcPeGMA1ab4gJz/py9YRnfbl6wrO+XD3hCzM868vVE5715eoJz/py9YRnfbl6wrN6Qxg8rTfEhGfOsLTeEBOeOcPSekNMeOYMS+sNMeGZMyytN8SEB/KGMB4kb4jJw/py9YRnfbl6wrO+XD3hCzM868vVE5715eoJz/py9YRnfbl6wrO+XG3wtN4QE545w9J6Q0x45gxL6w0x4ZkzLK03xIRnzrC03hATnjnDInlDTB4gb4jJA+QNMXmAvCEmD0q2uvIAeUNMHiBviMkD5A0xeYC8ISYPkDeE8SB5Q0ye4PV+/wX9SQTlDTGJoB6sm/euoLwhJhGUN8QkgvKGmERQ3hCTCMobYhJBeUNMIihvCCPC8oaYRFDeEJMIyhtiEkF5Q0yiAkcE5Q0xiaC8ISYRlDfEJILyhphEUN4QRoTlDTGJoLwhJhGUN8QkgvKGmEQFjgjKG2ISQXlDTCIob4hJBOUNMYmgvCF+dR5BeUP8QoLyhviFBOUN8QsJ6g32X0hQ3hC/kKC8IX4hwZXawLwhfiFBeUP8QoLyhviFVPCQsPYlaZTeEMbN+MS1cTO+cG3clN4QE5zxhesJzvjC9QRnfOF6ghdWcMYXric4ozfEBGfNm5TeEBOcNXNSekNMcNbMSekNMcFZMyelN8QEZ82crt4QU2DzFvD0hpgCw1nA1RtiCoi3gHoLeHpDTIHiLVC9BZq3gKc3xBTo3gLDWcDVG2IKiLeApzfEFGjeAp7PIZqAqzfEFPAeIldviCnQvQWGs4CrN8QUEG8B9RZYvQWKt0D1FmjeAp7eEFOgewt4ekPMb6Y8vSGmgHgLqLeApzfEFCjeAtVboHkLbN4Cnt4QU2A4C7h6Q0wB8RZQb4HVW6B4C1RvgeYt4OkNMQW6t4CnN8S8veDpDTEFxFtAvQU8vSGmQPEWqN4CzVtg8xbo3gLexRBnbwit/t4QFw1ebwiDp3252uBpX642eNqXqw2+MMPTvlxt8LQvVxs87cvVBk/7crXB03pDXOB5vSEMnjnD8npDGDxzhuX1hjB45gzL6w1h8MwZltcbwuCRvCEuPFDeEMZD+3K1wdO+XG3wtC9XG3xhhqd9udrgaV+uNnjal6sNnvblaoOnfbn6As/rDWHwzBmW1xvC4JkzLK83hMEzZ1hebwiDZ86wvN4QBs+cYaG8IYwHyRvCeJC8IYwHyRvCeFCy1ZUHyRvCeJC8IYwHyRvCeJC8IYwHyRviwgPlDWE8wev9wQv6RoTlDWFEWA/W2b0rLG8II8LyhjAiLG8II8LyhjAiLG8II8LyhjAiLG+ICxGYN4QRYXlDGBGWN4QRYXlDGFGBI8LyhjAiLG8II8LyhjAiLG8II8LyhrgQgXlDGBGWN4QRYXlDGBGWN4QRFTgiLG8II8LyhjAiLG8II8LyhjAiLG+I2XmE5Q0xkbC8ISYSljfERMJ6g30iYXlDTCQsb4iJBFdqQ/OGmEhY3hATCcsbYiIVPCSsfWlV/w7eiwZvB6/B0/YXGTxtf5HB0/YXGXxhhqftLzJ42v4ig6ftLzJ42v4ig6ft4L3A83bwGjxzhuXt4DV45gzL28Fr8MwZlreD1+CZMyxvB6/BI3XwXnigOniNh7a/yOBp+4sMnra/yOALMzxtf5HB0/YXGTxtf5HB0/YXGTxtf9EFnreD1+CZMyxvB6/BM2dY3g5eg2fOsLwdvAbPnGF5O3gNnjnDQnXwGg9SB6/xIHXwGg9SB6/xoGSrKw9SB6/xIHXwGg9SB6/xIHXwGg9SB++FB6qD13iC1/uDPkcjwurgNSKsa4V27wqrg9eIsDp4jQirg9eIsDp4jQirg9eIsDp4jQirg/dCBNbBa0RYHbxGhNXBa0RYHbxGVOCIsDp4jQirg9eIsDp4jQirg9eIsDp4L0RgHbxGhNXBa0RYHbxGhNXBa0QFjgirg9eIsDp4jQirg9eIsDp4jQirg3d2HmF18E4krA7eiYTVwTuR4Drl0Dp4JxJWB+9Egiu1oXXwTiSsDt6JhNXBO5EKHhLUvlRv3sbf5KqxbX++ZRat+8e25z7Wn/vYeOpjx1e0H39MnvuYPvexw4XT979Nuh5/rDz3sfrcx9pzH9ue+1h/7mPjqY8d30ns/VrM70MPPybPfUyf+9j63MfKcx+rz32sPfexw1ny5YtLWQ4/1p/72HjqY8f3ah5/TJ77mD73sfW5jx3OkqHXhTPWw4VzfDXj8cfacx/bnvtYf+5j46mPHX+7//hj8uBj5TBuTZ/72Prcx45nSb2u7tEOV/fx1/mPP9ae+9j23Mf6cx8bT31sW5772PEs6cte5639X5/7z9/88FVEI0TWCJESIVIjRFqEyBYh0iNERoDI8Xfw7xaJWPE9YsX3iBXfI1Z8j1jxPWLF94gV3yNWfI9Y8SNixY+IFT8iVvyIWPEjYsWPiBU/Ilb8iFjxI2LFj4gVf+P7v7erSIiKhqisISolRKWGqLQQlS1EpYeohKx9CVn7ErL2JWTtS8jal5C1LyFrX0LWvoSsfQlZ+xKy9jVk7WvI2teQta8ha19D1r6GrH0NWfsasvY1ZO1ryNpfQ9b+GrL215C1v4as/TVk7a8ha38NWftryNpfQ9b+GrL2S8jaLyFrv4Ss/RKy9kvI2i8ha7+ErP0SsvZLyNovIWu/hqz9GrL2a8jaryFrv4as/Rqy9mvI2q8ha7+GrP0asvZbyNpvIWu/haz9FrL2W8jabyFrv4Ws/Ray9lvI2m8ha38LWfshd/ck5PKehNzek5DrexJyf09CLvBJyA0+CbnCJyF3+CTkEp+E3OKTkGt8EnKPT0Iu8knITT4JuconIXf5JOQyn4Tc5pOQ63wScp9PQi70SciNPgm50ichd/ok5FKfhNzqk5BrfRJyr09D7vVpyL0+DbnXpyH3+nQpISo1RKWFqGwhKj1EJWTth9zr05B7fRpyr09D7vVpyL0+DbnXpyH3+jTkXp+G3OvTkHt9GnKvT0Pu9WnIvT4NudenIff6NORen4bc69OQe30acq9PQ+71aci9Pg2516ch9/o05F6fhtzr05B7fRpyr09D7vVpyL0+DbnXpyH3+jTkXp+G3OvTkHt9GnKvT99wF67WqwFC3b68ovflGb03XIV7LPKG22O1X99OrV+fTv0qohEia4RIiRCpESJ/m1j2D25PfvANX/I/ns9v+I7/GyI1QqRFiERsZG/4fr+O+vuH21KPRUaAyBu+3f+GiESIaITIG1b8kF2kHYuUCJEaIdIiRLYIkR4hMgLS5Bu+0/+GSMQfYSPij7AR8UfYG77P/4ZIxB9hb/g2/xsiW4RIjxAJWPHrskSISISIRoisESIlQqRGiLQIkS1CpEeIRKx4iVjxErHiJWLFS8SKl4gVLxErXiJWvESseIlY8RKx4jVixWvEiteIFa8RK14jVrxGrHiNWPHqvuL7P8dmXrVsV43a/mUD+r8SvV4lepf7PyrS/xgLffFVUb3idCycgYVz/FfMD/IIGI+C8axgPAWMp4LxNDAesN1ZwLZnAdufFWx/VrD9WcH2ZwXbnxVsf1aw/Vkd9+erxOYv8fou+sWcbV1eHtWBxbMuYDwCxqNgPCsYTwHjqWA8DYxnA+MB259XsP25gO3PBWx/LmD7cwHbnwvY/lzA9ucCtj8Xx/35KtH9JYa7RF38JcRfQv0lVn+J4i9R/SWav4T/6m6vT1pZlqvPsSyiRyIaIfJ6yEXLn/22HdUH2gj4l2xLhEhE4LfyBpE2dpHejkRqhEiLENkiRHqEyDvWSZM/ItuBSF8iRCRCRCNE1giREiFSI0RahMgWIdIjRN6w4kXK9YelHP21MpYIEYkQ0QiRNUKkRIjUCJEWIbJFiLxhxcumu8jX+2l/REaAyA3H5rerrAGHhxsux29XqSEqLURlRKi84e7ed1QkREVDVNzXS1mO779u+6e27UH5tCz9948Wrfd/tO87xFjKf7/UWf+6KHvh7qTcg5T7ePkygAsruLKCr6zghRW8soI3VnDWvCmsiVNYM6eyZk5lzZzKmjmVNXMqa+ZU1sypbpnzKrB5C7ycier1m9FSy5HAcBZYF28B8RZQb4GXd7S9gbf09UigeAtUb4HmLfDqSq7LteJUl34k0L0FhrNAWbwFxFvg1Wla9fqjVQ8FmrfAq0Fu6/XCRKt6IFAXbwHvIaovr+S9dlzrdiTQvQWGs0BbvAXEW0C9BVZvgeItUL0FmrfAG1dya0cC3Vvg9ZW8b3bbkcD28kpex30B8RZQb4FXV3LbL5e2ZRwJFG+B6i3QvAU2b4GXV/KfR6xlORIYzgJ98RYQbwH1Fli9BYq3QPUWaN4C2xsFjlZy794Cr6/k66W3pkcC4+WVvNc1bwiIt4B6C7yckx+cMkfxFqjeAs1bYPMW6N4C3sWQG3c+36VQb9wsk7bu12pbffCFiZTlut9JETnQuHGp8O9ESt9Ftkdf4bztNZ9662YSC7wyw6/M8IUZvjLDN2b4jRm+M8MPYnhlzrDKnGGVOcMqc4ZV5gyrzBlWmTOsMmdYZc6wipJhf/OsKEnzyhOcB9/3/Fa9dUeNBX5lhi/M8JUZvjHDb8zwnRl+EMOXhRmeOcMW5gxbmDNsYc6whTnDFuYMW5gzbGHOsIU5w1aUDHvlQUmaVx6UPHjlQUltVx6UbHXlQUlAVx6UnHLlQUkTVx6Unf/Kg7KZ/+ZpYPtzC17vD946rrcaP36UKHhOP3jRq95qa/jJMdoUjmiFI2rRRHefl663Ght+lKjDEQ00or7AEYXvR3efUa63ujl+lGiFIypwRBWOqMERbXBEHY5ooBGNBY4oes++/9p2vdW386NEKxxRgSOqcEQNjmiDI+pwRAON6Nab+Y5Idx/Yn0iCh6R4SBWtYnPrnf8fRdrwkOBKbRLdwvcdJMVDWvGQCh4S2L60cXpDXLgpn7i+cFO+cH3h5vSGMHDKF64NnPKFawOnfOHawAsrOOUL1wZO6Q1h4Kx5k9MbwsBZMyenN4SBs2ZOTm8IA2fNnJzeEAbOmjl9vSFMYPMWcPWGMIHhLODrDWEC4i2g3gKu3hAmULwFqrdA8xZw9YYwge4tMJwFfL0hTEC8BVy9IUygeQu4Pod4EfD1hjAB7yHy9YYwge4tMJwFfL0hTEC8BdRbYPUWKN4C1VugeQu4ekOYQPcWcPWGsG+mXL0hTEC8BdRbwNUbwgSKt0D1FmjeApu3gKs3hAkMZwFfbwgTEG8B9RZYvQWKt0D1FmjeAq7eECbQvQVcvSHs9oKrN4QJiLeAegu4ekOYQPEWqN4CzVtg8xbo3gLexRBnb4jW/L0hLhq83hAGT/tytcHTvlxt8LQvVxt8YYanfbna4GlfrjZ42perDZ725WqDp/WGuMDzekMYPHOG5fWGMHjmDMvrDWHwzBmW1xvC4JkzLK83hMEjeUNceKC8IYyH9uVqg6d9udrgaV+uNvjCDE/7crXB075cbfC0L1cbPO3L1QZP+3L1BZ7XG8LgmTMsrzeEwTNnWF5vCINnzrC83hAGz5xheb0hDJ45w0J5QxgPkjeE8SB5QxgPkjeE8aBkqysPkjeE8SB5QxgPkjeE8SB5QxgPkjfEhQfKG8J4gtf7gxf0jQjLG8KIsB6ss3tXWN4QRoTlDWFEWN4QRoTlDWFEWN4QRoTlDWFEWN4QFyIwbwgjwvKGMCIsbwgjwvKGMKICR4TlDWFEWN4QRoTlDWFEWN4QRoTlDXEhAvOGMCIsbwgjwvKGMCIsbwgjKnBEWN4QRoTlDWFEWN4QRoTlDWFEWN4Qs/MIyxtiImF5Q0wkLG+IiYT1BvtEwvKGmEhY3hATCa7UhuYNMZGwvCEmEpY3xEQqeEhY+9K2+nfwXjR4O3gNnra/yOBp+4sMnra/yOALMzxtf5HB0/YXGTxtf5HB0/YXGTxtB+8FnreD1+CZMyxvB6/BM2dY3g5eg2fOsLwdvAbPnGF5O3gNHqmD98ID1cFrPLT9RQZP219k8LT9RQZfmOFp+4sMnra/yOBp+4sMnra/yOBp+4su8LwdvAbPnGF5O3gNnjnD8nbwGjxzhuXt4DV45gzL28Fr8MwZFqqD13iQOniNB6mD13iQOniNByVbXXmQOniNB6mD13iQOniNB6mD13iQOngvPFAdvMYTvN4f9DkaEVYHrxFhXSu0e1dYHbxGhNXBa0RYHbxGhNXBa0RYHbxGhNXBa0RYHbwXIrAOXiPC6uA1IqwOXiPC6uA1ogJHhNXBa0RYHbxGhNXBa0RYHbxGhNXBeyEC6+A1IqwOXiPC6uA1IqwOXiMqcERYHbxGhNXBa0RYHbxGhNXBa0RYHbyz8wirg3ciYXXwTiSsDt6JBNcph9bBO5GwOngnElypDa2DdyJhdfBOJKwO3olU8JCw9qUu/7zqg1yWK03RBzB937bHUv78qP7999wX7k7KPUi5ZWEFF1ZwZQVfWcELK3hlBW+s4Kx5U1gTp7BmTmXNnMqaOZU1cypr5lTWzKmsmVPdMudVYPMWeDkT1et9m1LLkcBwFlgXbwHxFlBvgZd3tH5dNKWvRwLFW6B6CzRvgVdXcl223z9al34k0L0FhrNAWbwFxFvg1Wla9fqjVQ8FmrfAq0Fu6/WWWqt6IFAXbwHvIaovr+Syz6K6HQl0b4HhLNAWbwHxFlBvgdVboHgLVG+B5i3wxpXc2pFA9xZ4fSXvm912JLC9vJL37fqGgHgLqLfAqyu57S0LbRlHAsVboHoLNG+BzVvg5ZU8ri8sN1mOBIazQF+8BcRbQL0FVm+B4i1QvQWat8D2RoGjldy7t8DrK/l6EaXpkcB4eSXvdc0bAuItoN4CL+fkB6fMUbwFqrdA8xbYvAW6t4B3MeTG3eZ3KQzx94YYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEECxviCFY3hBDiL0hhhB7Qwwh9oYYQuwNMYTYG2IIsTfEEGJviCHE3hBDiL0hhhB7Qwwh9oYweOYMy+sNYfDMGZbXG2IIsTeEwTNnWF5viCHE3hBDsLwhjAfJG8J4kLwhjAfJG8J4ULLVlQfJG2IIljfEECxviCFY3hBDsLwhhmB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD0LwhhqB5QwxB84YYguYNMQTNG2IImjfEEDRviCFo3hBD4LwhJhKWN8REwvKGmEhYb7BPJCxviImE5Q0xkeBKbWjeEBMJyxtiImF5Q0ykgocEti91Tm+ICzflE9cXbsoXri/cnN4QBk75wrWBU75wbeCUL1wbeGEFp3zh2sApvSEMnDVvcnpDGDhr5uT0hjBw1szJ6Q1h4KyZk9MbwsBZM6evN4QJbN4Crt4QJjCcBXy9IUxAvAXUW8DVG8IEirdA9RZo3gKu3hAm0L0FhrOArzeECYi3gKs3hAk0bwHX5xAvAr7eECbgPUS+3hAm0L0FhrOArzeECYi3gHoLrN4CxVugegs0bwFXbwgT6N4Crt4Q9s2UqzeECYi3gHoLuHpDmEDxFqjeAs1bYPMWcPWGMIHhLODrDWEC4i2g3gKrt0DxFqjeAs1bwNUbwgS6t4CrN4TdXnD1hjAB8RZQbwFXbwgTKN4C1VugeQts3gLdW8C7GOLrDdGWzd0bwjRovSEmPOvL1ROe9eXqCc/6cvWEL8zwrC9XT3jWl6snPOvL1ROe9eXqCc/qDWHwtN4QE545w9J6Q0x45gxL6w0x4ZkzLK03xIRnzrC03hATHsgbwniQvCEmD+vL1ROe9eXqCc/6cvWEL8zwrC9XT3jWl6snPOvL1ROe9eXqCc/6crXB03pDTHjmDEvrDTHhmTMsrTfEhGfOsLTeEBOeOcPSekNMeOYMi+QNMXmAvCEmD5A3xOQB8oaYPCjZ6soD5A0xeYC8ISYPkDfE5AHyhpg8QN4QxoPkDTF5gtf7/Rf0JxGUN8Qkgnqwbt67gvKGmERQ3hCTCMobYhJBeUNMIihviEkE5Q0xiaC8IYwIyxtiEkF5Q0wiKG+ISQTlDTGJChwRlDfEJILyhphEUN4QkwjKG2ISQXlDGBGWN8QkgvKGmERQ3hCTCMobYhIVOCIob4hJBOUNMYmgvCEmEZQ3xCSC8ob41XkE5Q3xCwnKG+IXEpQ3xC8kqDfYfyFBeUP8QoLyhviFBFdqA/OG+IUE5Q3xCwnKG+IXUsFDwtqXpPh38F40eDt4DZ62v8jgafuLDJ62v8jgCzM8bX+RwdP2Fxk8bX+RwdP2Fxk8bQfvBZ63g9fgmTMsbwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DR6pg/fCA9XBazy0/UUGT9tfZPC0/UUGX5jhafuLDJ62v8jgafuLDJ62v8jgafuLLvC8HbwGz5xheTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGRaqg9d4kDp4jQepg9d4kDp4jQclW115kDp4jQepg9d4kDp4jQepg9d4kDp4LzxQHbzGE7zeH/Q5GhFWB68RYV0rtHtXWB28RoTVwWtEWB28RoTVwWtEWB28RoTVwWtEWB28FyKwDl4jwurgNSKsDl4jwurgNaICR4TVwWtEWB28RoTVwWtEWB28RoTVwXshAuvgNSKsDl4jwurgNSKsDl4jKnBEWB28RoTVwWtEWB28RoTVwWtEWB28s/MIq4N3ImF18E4krA7eiQTXKYfWwTuRsDp4JxJcqQ2tg3ciYXXwTiSsDt6JVPCQsPYlbTc6eGvZrh+rbbuv8b5b3hecjoUzsHButEL/HI+A8SgYzwrGU8B4KhhPA+MB250FbHsWsP1ZwfZnBdufFWx/VrD9WcH2ZwXbn9Vxf75KbP4Sr++i77syajwDi2ddwHgEjEfBeFYwngLGU8F4GhjPBsYDtj+vYPtzAdufC9j+XMD25wK2Pxew/bmA7c8FbH8ujvvzVaL7Swx3ibr4S4i/hPpLrP4SxV+i+ks0fwn/1d1en7QPLtebiEaIvB7yx1/JtRHwL9mWCJGIwG/lDSJ3L7ibSI0QaREiW4RIjxB5xzq5e0vWvpBeIkQkQkQjRNYIkRIhUiNEWoTIFiHSI0TesOLv3/q0Ox9LhIhEiGiEyBohUiJEaoRIixDZIkTesOLv3+Q1kREgcuue97tV1oDDgywlRKWGqLQQlRGh8oa7e99RkRAVDVHxXy/9+P7rtn9q2x6UT8tyvY1b9MFl3L7vEGMp//1SZ/37omw/vihLwD1IuY+XLwO4sIIrK/jKCl5YwSsreGMFZ82bwpo4hTVzKmvmVNbMqayZU1kzp7JmTmXNnOqWOa8Cm7fAy5moXr8ZLbUcCQxngXXxFhBvAfUWeHlH69dFU/p6JFC8Baq3QPMWeHUl1+VacapLPxLo3gLDWaAs3gLiLfDqNK16/dGqhwLNW+DVILf1emGiVT0QqIu3gPcQ1ZdX8l47rnU7EujeAsNZoC3eAuItoN4Cq7dA8Rao3gLNW+CNK7m1I4HuLfD6St43u+1IYHt5Je/b9Q0B8RZQb4FXV3LbL5e2ZRwJFG+B6i3QvAU2b4GXV/KoVwFZjgSGs0BfvAXEW0C9BVZvgeItUL0FmrfA9kaBo5Xcu7fA6yv5eumt6ZHAeHkl73XNGwLiLaDeAi/n5AenzFG8Baq3QPMW2LwFureAdzHkxp3PdymsN26W/eVTj8t1v5MicqAhKCb0f/0VznrrZhILvDLDr8zwhRm+MsM3ZviNGb4zww9ieGXOsMqcYZU5wypzhlXmDKvMGVaZM6wyZ1hlzrCKkmF/86woSfPKg2JC/0xwVxTH+qfgUeztn4IvzPCVGb4xw2/M8J0ZfhDDl4UZnjnDFuYMW5gzbGHOsIU5wxbmDFuYM2xhzrCFOcNWlAx75UFJmlcelDx45UFJbVcelGx15UFJQFcelJxy5UFJE1celJ3/yoOymf/maWD7cwte7w/eOl5vNX78KBGWYfN6q63hJ8doUziiFY4o2h79/vPS663Ghh8l6nBEA42oL3BE4fvR3WeU11vdHD9KtMIRFTiiCkfU4Ig2OKIORzTQiMYCRxS9Z99/bXu91bfzo0QrHFGBI6pwRA2OaIMj6nBEA43o1pv5jkh3H9ifSIKHpHhIFa1ic+ud/x9F2vCQ4EptEt3C9x0kxUNa8ZAKHhLWvlQqpzfEhZvyiesLN+UL1xduTm8IA6d84drAKV+4NnDKF64NvLCCU75wbeCU3hAGzpo3Ob0hDJw1c3J6Qxg4a+bk9IYwcNbMyekNYeCsmdPXG8IENm8BV28IExjOAr7eECYg3gLqLeDqDWECxVugegs0bwFXbwgT6N4Cw1nA1xvCBMRbwNUbwgSat4Drc4gXAV9vCBPwHiJfbwgT6N4Cw1nA1xvCBMRbQL0FVm+B4i1QvQWat4CrN4QJdG8BV28I+2bK1RvCBMRbQL0FXL0hTKB4C1RvgeYtsHkLuHpDmMBwFvD1hjAB8RZQb4HVW6B4C1RvgeYt4OoNYQLdW8DVG8JuL7h6Q5iAeAuot4CrN4QJFG+B6i3QvAU2b4HuLeBdDHH2hqjF3xviosHrDWHwtC9XGzzty9UGT/tytcEXZnjal6sNnvblaoOnfbna4GlfrjZ4Wm+ICzyvN4TBM2dYXm8Ig2fOsLzeEAbPnGF5vSEMnjnD8npDGDySN8SFB8obwnhoX642eNqXqw2e9uVqgy/M8LQvVxs87cvVBk/7crXB075cbfC0L1df4Hm9IQyeOcPyekMYPHOG5fWGMHjmDMvrDWHwzBmW1xvC4JkzLJQ3hPEgeUMYD5I3hPEgeUMYD0q2uvIgeUMYD5I3hPEgeUMYD5I3hPEgeUNceKC8IYwneL0/eEHfiLC8IYwI68E6u3eF5Q1hRFjeEEaE5Q1hRFjeEEaE5Q1hRFjeEEaE5Q1xIQLzhjAiLG8II8LyhjAiLG8IIypwRFjeEEaE5Q1hRFjeEEaE5Q1hRFjeEBciMG8II8LyhjAiLG8II8LyhjCiAkeE5Q1hRFjeEEaE5Q1hRFjeEEaE5Q0xO4+wvCEmEpY3xETC8oaYSFhvsE8kLG+IiYTlDTGR4EptaN4QEwnLG2IiYXlDTKSCh4S1LzXx7+C9aPB28Bo8bX+RwdP2Fxk8bX+RwRdmeNr+IoOn7S8yeNr+IoOn7S8yeNoO3gs8bwevwTNnWN4OXoNnzrC8HbwGz5xheTt4DZ45w/J28Bo8UgfvhQeqg9d4aPuLDJ62v8jgafuLDL4ww9P2Fxk8bX+RwdP2Fxk8bX+RwdP2F13geTt4DZ45w/J28Bo8c4bl7eA1eOYMy9vBa/DMGZa3g9fgmTMsVAev8SB18BoPUgev8SB18BoPSra68iB18BoPUgev8SB18BoPUgev8SB18F54oDp4jSd4vT/oczQirA5eI8K6Vmj3rrA6eI0Iq4PXiLA6eI0Iq4PXiLA6eI0Iq4PXiLA6eC9EYB28RoTVwWtEWB28RoTVwWtEBY4Iq4PXiLA6eI0Iq4PXiLA6eI0Iq4P3QgTWwWtEWB28RoTVwWtEWB28RlTgiLA6eI0Iq4PXiLA6eI0Iq4PXiLA6eGfnEVYH70TC6uCdSFgdvBMJrlMOrYN3ImF18E4kuFIbWgfvRMLq4J1IWB28E6ngIYHtS+OfV32Qy3KlKfoApu/b9ljKnx/VJ77nHv90Uu5Byi0LK7iwgisr+MoKXljBKyt4YwVnzZvCmjiFNXMqa+ZU1syprJlTWTOnsmZOZc2c6pY5rwKbt8DLmahe79uUWo4EhrPAungLiLeAegu8vKP166IpfT0SKN4C1VugeQu8upLrsv3+0br0I4HuLTCcBcriLSDeAq9O06rXH616KNC8BV4Ncluvt9Ra1QOBungLeA9RfXkll30W1e1IoHsLDGeBtngLiLeAegus3gLFW6B6CzRvgTeu5NaOBLq3wOsred/stiOB7eWVvG/XNwTEW0C9BV5dyW1vWWjLOBIo3gLVW6B5C2zeAi+v5HF9YbnJciQwnAX64i0g3gLqLbB6CxRvgeot0LwFtjcKHK3k3r0FXl/J14soTY8Exssrea9r3hAQbwH1Fng5Jz84ZY7iLVC9BZq3wOYt0L0FvIshN+42v0thG/7eENsg9obYBrE3xDaIvSG2QewNsQ1ib4htEHtDbIPYG2IbxN4Q2yD2htgGsTfENoi9IbZB7A2xDWJviG0Qe0Nsg9gbYhvE3hDbIPaG2AaxN8Q2iL0htoHlDbENLG+IbRB7Q2yD2BtiG8TeENsg9obYBrE3xDaIvSG2QewNsQ1ib4htEHtDbIPYG2IbxN4QBs+cYXm9IQyeOcPyekNsg9gbwuCZMyyvN8Q2iL0htoHlDWE8SN4QxoPkDWE8SN4QxoOSra48SN4Q28DyhtgGljfENrC8IbaB5Q2xDSxviG2geUNsA80bYhto3hDbQPOG2AaaN8Q20LwhtoHmDbENNG+IbaB5Q2wDzRtiG2jeENtA84bYBpo3xDbQvCG2geYNsQ00b4htoHlDbAPNG2IbaN4Q20DzhtgGmjfENtC8IbaB5g2xDTRviG2geUNsA80bYhto3hDbQPOG2AaaN8Q20LwhtgHnDTGRsLwhJhKWN8REwnqDfSJheUNMJCxviIkEV2pD84aYSFjeEBMJyxtiIhU8JKx9qTdOb4gLN+UT1xduyheuL9yc3hAGTvnCtYFTvnBt4JQvXBt4YQWnfOHawCm9IQycNW9yekMYOGvm5PSGMHDWzMnpDWHgrJmT0xvCwFkzp683hAls3gKu3hAmMJwFfL0hTEC8BdRbwNUbwgSKt0D1FmjeAq7eECbQvQWGs4CvN4QJiLeAqzeECTRvAdfnEC8Cvt4QJuA9RL7eECbQvQWGs4CvN4QJiLeAegus3gLFW6B6CzRvAVdvCBPo3gKu3hD2zZSrN4QJiLeAegu4ekOYQPEWqN4CzVtg8xZw9YYwgeEs4OsNYQLiLaDeAqu3QPEWqN4CzVvA1RvCBLq3gKs3hN1ecPWGMAHxFlBvAVdvCBMo3gLVW6B5C2zeAt1bwLsY4uwNMaq/N8RFg9cbwuBpX642eNqXqw2e9uVqgy/M8LQvVxs87cvVBk/7crXB075cbfC03hAXeF5vCINnzrC83hAGz5xheb0hDJ45w/J6Qxg8c4bl9YYweCRviAsPlDeE8dC+XG3wtC9XGzzty9UGX5jhaV+uNnjal6sNnvblaoOnfbna4Glfrr7A83pDGDxzhuX1hjB45gzL6w1h8MwZltcbwuCZMyyvN4TBM2dYKG8I40HyhjAeJG8I40HyhjAelGx15UHyhjAeJG8I40HyhjAeJG8I40HyhrjwQHlDGE/wen/wgr4RYXlDGBHWg3V27wrLG8KIsLwhjAjLG8KIsLwhjAjLG8KIsLwhjAjLG+JCBOYNYURY3hBGhOUNYURY3hBGVOCIsLwhjAjLG8KIsLwhjAjLG8KIsLwhLkRg3hBGhOUNYURY3hBGhOUNYUQFjgjLG8KIsLwhjAjLG8KIsLwhjAjLG2J2HmF5Q0wkLG+IiYTlDTGRsN5gn0hY3hATCcsbYiLBldrQvCEmEpY3xETC8oaYSAUPCWpf2hZ17+A1DdoO3gnP2l804Vn7iyY8a3/RhC/M8Kz9RROetb9owrP2F0141v6iCc/awWvwtB28E545w9J28E545gxL28E74ZkzLG0H74RnzrC0HbwTHqiD13iQOngnD2t/0YRn7S+a8Kz9RRO+MMOz9hdNeNb+ognP2l804Vn7iyY8a3+RwdN28E545gxL28E74ZkzLG0H74RnzrC0HbwTnjnD0nbwTnjmDIvUwTt5gDp4Jw9QB+/kAergnTwo2erKA9TBO3mAOngnD1AH7+QB6uCdPEAdvMaD1ME7eYLX+/0+x0kE1cE7iaCuFc57V1AdvJMIqoN3EkF18E4iqA7eSQTVwTuJoDp4JxFUB68RYXXwTiKoDt5JBNXBO4mgOngnUYEjgurgnURQHbyTCKqDdxJBdfBOIqgOXiPC6uCdRFAdvJMIqoN3EkF18E6iAkcE1cE7iaA6eCcRVAfvJILq4J1EUB28vzqPoDp4fyFBdfD+QoLq4P2FBNcpB9bB+wsJqoP3FxJcqQ2sg/cXElQH7y8kqA7eX0gFDwlqX7rkt1vX8Te5imzbn6+ZReufz21Pfq4/+bnx3OeO72l/43Py5Of0yc8dLqC+/43S9cbnypOfq09+rj35ue3Jz/UnPzee+9zxFcXer7X9PvT4c/Lk5/TJz61Pfq48+bn65Ofak587nC9fvs6U5fhz/cnPjec+d3zh5hufkyc/p09+bn3yc4fzZeh1HY31eB0dX9z4xufak5/bnvxcf/Jz47nPHV8A+Mbn5MHnynH8mj75ufXJzx3Pl3pd76Mdr/fjr/2/8bn25Oe2Jz/Xn/zceO5z2/Lk547nS1/2qnDt//rgf/7mh3cVDVFZQ1RKiEoNUWkhKluISg9RGREqx1/dv10lZO33kLXfQ9Z+D1n7PWTt95C130PWfg9Z+z1k7Y+QtT9C1v4IWfsjZO2PkLU/Qtb+CFn7I2Ttj5C1P0LW/o2vEt8vIzEyGiOzxsiUGJkaI9NiZLYYmR4jE7MLSMwuIDG7gMTsAhKzC0jMLiAxu4DE7AISswtIzC4gMbuAxuwCGrMLaMwuoDG7gMbsAhqzC2jMLqAxu4DG7AIaswusMbvAGrMLrDG7wBqzC6wxu8AaswusMbvAGrMLrDG7wBqzC5SYXaDE7AIlZhcoMbtAidkFSswuUGJ2gRKzC5SYXaDE7AI1ZheoMbtAjdkFaswuUGN2gRqzC9SYXaDG7AI1ZheoMbtAi9kFWswu0GJ2gRazC7SYXaDF7AItZhdoMbtAi9kFWswusMXsAjH3AyXmgqDE3BCUmCuCEnNHUGIuCUrMLUGJuSYoMfcEJeaioMTcFJSYq4ISc1dQYi4LSsxtQYm5Ligx9wUl5sKgxNwYlJgrgxJzZ1BiLg1KzK1Bibk2KDH3BiXm4qDE3ByUmKuDEnN3UGPuDmrM3UGNuTuoMXcHdSkxMjVGpsXIbDEyPUYmZheIuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gvuG2Xa1Xc4e6fXkh8OsTgW+4bPcNlTfcTqv9+jJs/fow7L9UNERlDVEpISo1ROVvE82fT27PfvINtwa+Ma/fcGngOyo1RKWFqITsam+4MFBH/f3Dbak3VEaEyhuuC3xHRUJUNETlDWt/yK7SbqiUEJUaotJCVLYQlR6iMiIy5xsuCXxHJeSvsxHy19kI+evsDRcEvqMS8tfZG64HfEdlC1HpISoRa39dlhAVCVHREJU1RKWEqNQQlRaisoWo9BCVkLUvIWtfQta+hKx9CVn7ErL2JWTtS8jal5C1LyFrX0LWvoasfQ1Z+xqy9jVk7WvI2teQta8ha1/9137/59jorJbtKlLbvyxS/1ej16tG73L/R0X6H9OlLy4zqjtPB+MZYDzHf9r8JJCgASka0IoGVNCAKhpQQwNC26cFbaMWtJ1a0XZqRdupFW2nVrSdWtF2akXbqdVxp941tgCN1/fTL4516/L6wA4woHVBAxI0IEUDWtGAChpQRQNqaEAbGhDaTr2i7dQFbacuaDt1QdupC9pOXdB26oK2Uxe0nbo47tS7Rg/QGP4adQnQkAANDdBYAzRKgEYN0GgBGgHrvL0+dy+/5+oELYvooYqGqLwed9HyZ/dthwWENiL+LdsSohIS/a28QaWNXaW3Q5UaotJCVLYQlR6i8o710uSPynak0pcQFQlR0RCVNUSlhKjUEJUWorKFqPQQlTesfZFy/WEph3/DjCVERUJUNERlDVEpISo1RKWFqGwhKm9Y+7LprvL1xtsXlRGhIssSI7NGnC1u+EC/X6bGyLQYmREi84Ybgd+SkRgZjZHxXzeyHF+u3faPbduDomtZ+u8fLVrv/2jf94qxlP9+qc7+fSn3At5ZwQcr+PEqpiAXWnKlJV9pyQsteaUlb7TktBlUaFOo0OZQpc2hSptDlTaHKm0OVdocqrQ5VN1y6K6wuSu8nJPq9TvVUsuhwvBWWBd3BXFXUHeFl/e2vXG49PVQobgrVHeF5q7w6pquy7UgVZd+qNDdFYa3QlncFcRd4dXZWvX6o1WPFZq7wquRbuv11kWreqRQF3cF91GqL6/pvchc63ao0N0VhrdCW9wVxF1B3RVWd4XirlDdFZq7whvXdGuHCt1d4fU1ve9826HC9vKaXscDBXFXUHeFV9d022+utmUcKhR3hequ0NwVNneFl9f0n8e4ZTlUGN4KfXFXEHcFdVdY3RWKu0J1V2juCtsbFQ7XdO/uCq+v6etNuqaHCuPlNb2XQ28piLuCuiu8nKcfnUVHcVeo7grNXWFzV+juCu6VkxsXSt8moTduq0lb93u7rT74ykXKct38pIgcidy4rfh3KqXvKtujb4He99qQ3rrrREOv1PQrNX2hpq/U9I2afqOm79T0g5leqXOtUudapc61Sp1rlTrXKnWuVepcq9S5VqlzraLk2ivQipI+d6DgjPjG58H01q03GvqVmr5Q01dq+kZNv1HTd2r6wUxfFmp66lxbqHNtoc61hTrXFupcW6hzbaHOtYU61xbqXFtRcu0OhJI+dyCUjLgDoSS5HQglb+1AKKloB0LJLjsQSsLYgVBywA6Esq1fgRraTt2Cl/2jh5n1VkfJzyIFT+xHj4vprV6JHx2lTfGQVjykFo10/zFsvdUr8bNIHQ9pwCH1BQ8pfF+6/96z3moQ+VmkFQ+p4CFVPKSGh7ThIXU8pAGHNBY8pOjd+8G74HqrFehnkVY8pIKHVPGQGh7ShofU8ZAGHNKtN/4dme4bAkwmAWRSQKYKV9C55Uvws0wbIBNeMU6iOwO/xaSATCsgUwFkQtufNlI3iws451PcF3DOl7gv4KRuFkbO+RK3kXO+xG3knC9xG3mhJed8idvIOd0sjJw2g5K6WRg5bQ4ldbMwctocSupmYeS0OZTUzcLIaXOos5uFKWzuCr5uFqYwvBWc3SxMQdwV1F3B183CFIq7QnVXaO4Kvm4WptDdFYa3grObhSmIu4Kvm4UpNHcF3zcZLwrObham4D5Kzm4WptDdFYa3grObhSmIu4K6K6zuCsVdoborNHcFXzcLU+juCr5uFvZ1lq+bhSmIu4K6K/i6WZhCcVeo7grNXWFzV/B1szCF4a3g7GZhCuKuoO4Kq7tCcVeo7grNXcHXzcIUuruCr5uFXYLwdbMwBXFXUHcFXzcLUyjuCtVdobkrbO4K3V3BvXLi7WaxtgA3i4sIsZuF0fO+sG30vC9sGz3vC9tGX6jpeV/YNnreF7aNnveFbaPnfWHb6HndLC70xG4WRk+da4ndLIyeOtcSu1kYPXWuJXazMHrqXEvsZmH0UG4WFyAsNwsD4n1h2+h5X9g2et4Xto2+UNPzvrBt9LwvbBs97wvbRs/7wrbR876wfaEndrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0VPnWmI3C6OnzrVYbhYGBOVmYUBQbhYGBOVmYUAoeWsHgnKzMCAoNwsDgnKzMCAoNwsDgnKzuABhuVkYUPCyf/TcvyGBuVkYEtgDenZdC8zNwpDA3CwMCczNwpDA3CwMCczNwpDA3CwMCczN4oKE5mZhSGBuFoYE5mZhSGBuFoZU8JDA3CwMCczNwpDA3CwMCczNwpDA3CwuSGhuFoYE5mZhSGBuFoYE5mZhSAUPCczNwpDA3CwMCczNwpDA3CwMCczNYrYygblZTCYwN4vJBOZmMZnAXoufTGBuFpMJzM1iMuEV4+DcLCYTmJvFZAJzs5hMBZAJbH8qa0B/8EWEuD/Y6Hl7loyet2fJ6Hl7loy+UNPz9iwZPW/PktHz9iwZPW/PktHz9gdf6In7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LmWuD/Y6KH6gy9AWP3BBsTbs2T0vD1LRs/bs2T0hZqet2fJ6Hl7loyet2fJ6Hl7loyet2fpQk/cH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da7H6gw0Iqj/YgKD6gw0Iqj/YgFDy1g4E1R9sQFD9wQYE1R9sQFD9wQYE1R98AcLqDzag4GX/qIHSkMD6gw0J7EqiXdcC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w+erUxg/cGTCaw/eDKB9QdPJrz+O7j+4MkE1h88mfCKcXD9wZMJrD94MoH1B0+mAsgEtj9V+edVH+eyXHGKPqDp+wY+lvLnR/WJb8cv4J0VfLCCy0JLLrTkSku+0pIXWvJKS95oyWkzqNCmUKHNoUqbQ5U2hyptDlXaHKq0OVRpc6i65dBdYXNXeDkn1etNnVLLocLwVlgXdwVxV1B3hZf3tn5dPKWvhwrFXaG6KzR3hVfXdF223z9al36o0N0VhrdCWdwVxF3h1dla9fqjVY8VmrvCq5Fu6/WqW6t6pFAXdwX3Uaovr+myz6W6HSp0d4XhrdAWdwVxV1B3hdVdobgrVHeF5q7wxjXd2qFCd1d4fU3vO992qLC9vKb33fuWgrgrqLvCq2u67f0QbRmHCsVdoborNHeFzV3h5TU9ro8/N1kOFYa3Ql/cFcRdQd0VVneF4q5Q3RWau8L2RoXDNd27u8Lra/p6o6XpocJ4eU3v5dBbCuKuoO4KL+fpR2fRUdwVqrtCc1fY3BW6u4J75eTG1em3STQJcLNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFEzA3iyZgbhZNmN0smjC7WTRhdrNowuxm0YTZzaIJs5tFE2Y3iybMbhZNmN0smjC7WTRhdrMweupcS+xmYfTUuZbYzaIJs5uF0VPnWmI3iybMbhZNwNwsDAjKzcKAoNwsDAjKzcKAUPLWDgTlZtEEzM2iCZibRRMwN4smYG4WTcDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smcG4WTeDcLJrAuVk0gXOzaALnZtEEzs2iCZybRRM4N4smeG4WkwnMzWIygblZTCaw1+InE5ibxWQCc7OYTHjFODg3i8kE5mYxmcDcLCZTAWRC2586qZvFBZzzKe4LOOdL3BdwUjcLI+d8idvIOV/iNnLOl7iNvNCSc77EbeScbhZGTptBSd0sjJw2h5K6WRg5bQ4ldbMwctocSupmYeS0OdTZzcIUNncFXzcLUxjeCs5uFqYg7grqruDrZmEKxV2huis0dwVfNwtT6O4Kw1vB2c3CFMRdwdfNwhSau4Lvm4wXBWc3C1NwHyVnNwtT6O4Kw1vB2c3CFMRdQd0VVneF4q5Q3RWau4Kvm4UpdHcFXzcL+zrL183CFMRdQd0VfN0sTKG4K1R3heausLkr+LpZmMLwVnB2szAFcVdQd4XVXaG4K1R3heau4OtmYQrdXcHXzcIuQfi6WZiCuCuou4Kvm4UpFHeF6q7Q3BU2d4XuruBeOfF2s9i2ADeLiwixm4XR876wbfS8L2wbPe8L20ZfqOl5X9g2et4Xto2e94Vto+d9Ydvoed0sLvTEbhZGT51rid0sjJ461xK7WRg9da4ldrMweupcS+xmYfRQbhYXICw3CwPifWHb6Hlf2DZ63he2jb5Q0/O+sG30vC9sGz3vC9tGz/vCttHzvrB9oSd2szB66lxL7GZh9NS5ltjNwuipcy2xm4XRU+daYjcLo6fOtVhuFgYE5WZhQFBuFgYE5WZhQCh5aweCcrMwICg3CwOCcrMwICg3CwOCcrO4AGG5WRhQ8LJ/9Ny/IYG5WRgS2AN6dl0LzM3CkMDcLAwJzM3CkMDcLAwJzM3CkMDcLAwJzM3igoTmZmFIYG4WhgTmZmFIYG4WhlTwkMDcLAwJzM3CkMDcLAwJzM3CkMDcLC5IaG4WhgTmZmFIYG4WhgTmZmFIBQ8JzM3CkMDcLAwJzM3CkMDcLAwJzM1itjKBuVlMJjA3i8kE5mYxmcBei59MYG4WkwnMzWIy4RXj4NwsJhOYm8VkAnOzmEwFkAlsf+oloD/4IkLcH2z0vD1LRs/bs2T0vD1LRl+o6Xl7loyet2fJ6Hl7loyet2fJ6Hn7gy/0xP3BRk+da4n7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z0UP3BFyCs/mAD4u1ZMnreniWj5+1ZMvpCTc/bs2T0vD1LRs/bs2T0vD1LRs/bs3ShJ+4PNnrqXEvcH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861WP3BBgTVH2xAUP3BBgTVH2xAKHlrB4LqDzYgqP5gA4LqDzYgqP5gA4LqD74AYfUHG1Dwsn/UQGlIYP3BhgR2JdGua4H1BxsSWH+wIYH1BxsSWH+wIYH1BxsSWH+wIYH1B1+Q0PqDDQmsP9iQwPqDDQmsP9iQCh4SWH+wIYH1BxsSWH+wIYH1BxsSWH/wBQmtP9iQwPqDDQmsP9iQwPqDDangIYH1BxsSWH+wIYH1BxsSWH+wIYH1B89WJrD+4MkE1h88mcD6gycTXv8dXH/wZALrD55MeMU4uP7gyQTWHzyZwPqDJ1MBZALbn0a70R9cy3b9XG3bfZE3Xhi/8HQwngHGc6PV+geBBA1I0YBWNKCCBlTRgBoaENo+LWgbtaDt1Iq2UyvaTq1oO7Wi7dSKtlMr2k6tjjv1rrEFaLy+n77x9qkBDTCgdUEDEjQgRQNa0YAKGlBFA2poQBsaENpOvaLt1AVtpy5oO3VB26kL2k5d0HbqgrZTF7Sdujju1LtGD9AY/hp1CdCQAA0N0FgDNEqARg3QaAEaAeu8vT53H13aNxUNUXk97t/4Iq+NiH/LtoSohER/K29QuX9z3lRqiEoLUdlCVHqIyjvWy/2bt/Z19hKiIiEqGqKyhqiUEJUaotJCVLYQlR6i8oa1/+AqqV0dWUJUJERFQ1TWEJUSolJDVFqIyhai8oa1/+CSsKmMCJVb18jfLrNGnC1kKTEyNUamxciMEJk33Aj8lozEyGiMTMC66ceXa7f9Y9v2oOhalutd36IPrvr2fa8YS/nvl+rsE6XcfnwLlwF8sIIfr2IKcqElV1rylZa80JJXWvJGS06bQYU2hQptDlXaHKq0OVRpc6jS5lClzaFKm0PVLYfuCpu7wss5qV6/Uy21HCoMb4V1cVcQdwV1V3h5b+vXxVP6eqhQ3BWqu0JzV3h1TdflWpCqSz9U6O4Kw1uhLO4K4q7w6mytev3RqscKzV3h1Ui39XrrolU9UqiLu4L7KNWX1/ReZK51O1To7grDW6Et7grirqDuCqu7QnFXqO4KzV3hjWu6tUOF7q7w+pred77tUGF7eU3vu/ctBXFXUHeFV9d022+utmUcKhR3hequ0NwVNneFl9f0qFcFWQ4VhrdCX9wVxF1B3RVWd4XirlDdFZq7wvZGhcM13bu7wutr+nqTrumhwnh5Te/l0FsK4q6g7gov5+lHZ9FR3BWqu0JzV9jcFbq7gnvl5MaF0ndJyHLjttpfPk65XDc/KSJHIhL8vPL7Xhua9EJNr9T0KzV9oaav1PSNmn6jpu/U9IOZXqlzrVLnWqXOtUqda5U61yp1rlXqXKvUuVapc62i5Nor0IqSPneg4Iz4vufBJr1S06/U9IWavlLTN2r6jZq+U9MPZvqyUNNT59pCnWsLda4t1Lm2UOfaQp1rC3WuLdS5tlDn2oqSa3cglPS5A6FkxB0IJcntQCh5awdCSUU7EEp22YFQEsYOhJIDdiCUbf0K1NB26ha87B88zDyRKh4Sljv1vK4lcKO0KR7SiocU7Qh//zHsibThIXU8pAGH1Bc8pPB96e57zxNJ8ZBWPKSCh1TxkBoe0oaH1PGQBhzSWPCQonfv+++CTyTFQ1rxkAoeUsVDanhIGx5Sx0MacEi33vh3ZLprCPCLSQCZFJCpwhV0bvkS/CzTBsiEV4yT6M7AbzEpINMKyFQAmcD2J6mcbhYGTvkUt4FTvsRt4JxuFpOc8iXuSU75Evckp3yJe5IXWnLKl7gnOaWbxSSnzaCcbhaTnDaHcrpZTHLaHMrpZjHJaXMop5vFJKfNob5uFlNhc1dwdbOYCsNbwdfNYiqIu4K6K7i6WUyF4q5Q3RWau4Krm8VU6O4Kw1vB181iKoi7gqubxVRo7gqubzKagq+bxVRwHyVfN4up0N0VhreCr5vFVBB3BXVXWN0VirtCdVdo7gqubhZTobsruLpZzK+zXN0spoK4K6i7gqubxVQo7grVXaG5K2zuCq5uFlNheCv4ullMBXFXUHeF1V2huCtUd4XmruDqZjEVuruCq5vFvATh6mYxFcRdQd0VXN0spkJxV6juCs1dYXNX6O4K7pUTbzcLLQFuFhcRYjcLo+d9YdvoeV/YNnreF7aNvlDT876wbfS8L2wbPe8L20bP+8K20fO6WVzoid0sjJ461xK7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoodwsLkBYbhYGxPvCttHzvrBt9LwvbBt9oabnfWHb6Hlf2DZ63he2jZ73hW2j531h+0JP7GZh9NS5ltjNwuipcy2xm4XRU+daYjcLo6fOtcRuFkZPnWux3CwMCMrNwoCg3CwMCMrNwoBQ8tYOBOVmYUBQbhYGBOVmYUBQbhYGBOVmcQHCcrMwoOBl/+i5f0MCc7MwJLAH9Oy6FpibhSGBuVkYEpibhSGBuVkYEpibhSGBuVkYEpibxQUJzc3CkMDcLAwJzM3CkMDcLAyp4CGBuVkYEpibhSGBuVkYEpibhSGBuVlckNDcLAwJzM3CkMDcLAwJzM3CkAoeEpibhSGBuVkYEpibhSGBuVkYEpibxWxlAnOzmExgbhaTCczNYjKBvRY/mcDcLCYTmJvFZMIrxsG5WUwmMDeLyQTmZjGZCiAT2P60SkB/8EWEuD/Y6Hl7loyet2fJ6Hl7loy+UNPz9iwZPW/PktHz9iwZPW/PktHz9gdf6In7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LmWuD/Y6KH6gy9AWP3BBsTbs2T0vD1LRs/bs2T0hZqet2fJ6Hl7loyet2fJ6Hl7loyet2fpQk/cH2z01LmWuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da7H6gw0Iqj/YgKD6gw0Iqj/YgFDy1g4E1R9sQFD9wQYE1R9sQFD9wQYE1R98AcLqDzag4GX/qIHSkMD6gw0J7EqiXdcC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w+erUxg/cGTCaw/eDKB9QdPJrz+O7j+4MkE1h88mfCKcXD9wZMJrD94MoH1B0+mAsiEtj+Nf171cS7LFafoA5q+b+BjKX9+VJ/5dnz801nBByu4LLTkQkuutOQrLXmhJa+05I2WnDaDCm0KFdocqrQ5VGlzqNLmUKXNoUqbQ5U2h6pbDt0VNneFl3NSvd7UKbUcKgxvhXVxVxB3BXVXeHlv69fFU/p6qFDcFaq7QnNXeHVN12X7/aN16YcK3V1heCuUxV1B3BVena1Vrz9a9VihuSu8Gum2Xq+6tapHCnVxV3Afpfrymi77XKrboUJ3VxjeCm1xVxB3BXVXWN0VirtCdVdo7gpvXNOtHSp0d4XX1/S+822HCtvLa3rfvW8piLuCuiu8uqbb3g/RlnGoUNwVqrtCc1fY3BVeXtPj+vhzk+VQYXgr9MVdQdwV1F1hdVco7grVXaG5K2xvVDhc0727K7y+pq83WpoeKoyX1/ReDr2lIO4K6q7wcp5+dBYdxV2huis0d4XNXaG7K7hXTm5cnX6bRBkBbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZzG4WZTC7WZTB7GZRBrObRRnMbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZYG4WZYC5WZTB7GZRBrObRRnMbhZlMLtZlMHsZlEGs5tFGcxuFmUwu1mUwexmUQazm0UZzG4WRk+da4ndLIyeOtcSu1mUwexmYfTUuZbYzaIMZjeLMsDcLAwIys3CgKDcLAwIys3CgFDy1g4E5WZRBpibRRlgbhZlgLlZlAHmZlEGmJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZQB52ZRBpybRRlwbhZlwLlZlAHnZlEGnJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZQB52ZRBpybRRlwbhZlwLlZlAHnZlEGnJtFGXBuFmXAuVmUAedmUQacm0UZcG4WZcC5WZSB52YxmcDcLCYTmJvFZAJ7LX4ygblZTCYwN4vJhFeMg3OzmExgbhaTCczNYjIVQCaw/ak2UjeLCzjnU9wXcM6XuC/gpG4WRs75EreRc77EbeScL3EbeaEl53yJ28g53SyMnDaDkrpZGDltDiV1szBy2hxK6mZh5LQ5lNTNwshpc6izm4UpbO4Kvm4WpjC8FZzdLExB3BXUXcHXzcIUirtCdVdo7gq+bham0N0VhreCs5uFKYi7gq+bhSk0dwXfNxkvCs5uFqbgPkrObham0N0VhreCs5uFKYi7grorrO4KxV2huis0dwVfNwtT6O4Kvm4W9nWWr5uFKYi7gror+LpZmEJxV6juCs1dYXNX8HWzMIXhreDsZmEK4q6g7gqru0JxV6juCs1dwdfNwhS6u4Kvm4VdgvB1szAFcVdQdwVfNwtTKO4K1V2huSts7grdXcG9cuLtZtFqgJvFRYTYzcLoeV/YNnreF7aNnveFbaMv1PS8L2wbPe8L20bP+8K20fO+sG30vG4WF3piNwujp861xG4WRk+da4ndLIyeOtcSu1kYPXWuJXazMHooN4sLEJabhQHxvrBt9LwvbBs97wvbRl+o6Xlf2DZ63he2jZ73hW2j531h2+h5X9i+0BO7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0VPnWiw3CwOCcrMwICg3CwOCcrMwIJS8tQNBuVkYEJSbhQFBuVkYEJSbhQFBuVlcgLDcLAwoeNk/eu7fkMDcLAwJ7AE9u64F5mZhSGBuFoYE5mZhSGBuFoYE5mZhSGBuFoYE5mZxQUJzszAkMDcLQwJzszAkMDcLQyp4SGBuFoYE5mZhSGBuFoYE5mZhSGBuFhckNDcLQwJzszAkMDcLQwJzszCkgocE5mZhSGBuFoYE5mZhSGBuFoYE5mYxW5nA3CwmE5ibxWQCc7OYTGCvxU8mMDeLyQTmZjGZ8IpxcG4WkwnMzWIygblZTKYCyAS2P20a0B98ESHuDzZ63p4lo+ftWTJ63p4loy/U9Lw9S0bP27Nk9Lw9S0bP27Nk9Lz9wRd64v5go6fOtcT9wUZPnWuJ+4ONnjrXEvcHGz11riXuDzZ6qP7gCxBWf7AB8fYsGT1vz5LR8/YsGX2hpuftWTJ63p4lo+ftWTJ63p4lo+ftWbrQE/cHGz11riXuDzZ66lxL3B9s9NS5lrg/2Oipcy1xf7DRU+darP5gA4LqDzYgqP5gA4LqDzYglLy1A0H1BxsQVH+wAUH1BxsQVH+wAUH1B1+AsPqDDSh42T9qoDQksP5gQwK7kmjXtcD6gw0JrD/YkMD6gw0JrD/YkMD6gw0JrD/YkMD6gy9IaP3BhgTWH2xIYP3BhgTWH2xIBQ8JrD/YkMD6gw0JrD/YkMD6gw0JrD/4goTWH2xIYP3BhgTWH2xIYP3BhlTwkMD6gw0JrD/YkMD6gw0JrD/YkMD6g2crE1h/8GQC6w+eTGD9wZMJr/8Orj94MoH1B08mvGIcXH/wZALrD55MYP3Bk6kAMmHtT+Xm1f5NriLb9ue7adH653Pbk5/rT35uPPe54/ve3/icPPk5ffJzh0uo73+vdL3xufLk5+qTn2tPfm578nP9yc+N5z53fMGx92v9vw89/pw8+Tl98nPrk58rT36uPvm59uTnDufLly8+ZTn+XH/yc+O5zx1f0vnG5+TJz+mTn1uf/NzhfBl6XUdjPV5Hx/c8vvG59uTntic/15/83Hjuc8dXBb7xOXnwuXIcv6ZPfm598nPH86Ve1/tox+v9+HrANz7Xnvzc9uTn+pOfG899blue/NzxfOnLXiqu/V8f/M/f/PCuoiEqa4hKCVGpISotRGULUekhKiNC5fib/berhKz9HrL2e8ja7yFrv4es/R6y9nvI2u8ha7+HrP0RsvZHyNofIWt/hKz9EbL2R8jaHyFrf4Ss/RGy9kfI2r/xreL7ZSRGRmNk1hiZEiNTY2RajMwWI9NjZGJ2AYnZBSRmF5CYXUBidgGJ2QUkZheQmF1AYnYBidkFJGYX0JhdQGN2AY3ZBTRmF9CYXUBjdgGN2QU0ZhfQmF1AY3aBNWYXWGN2gTVmF1hjdoE1ZhdYY3aBNWYXWGN2gTVmF1hjdoESswuUmF2gxOwCJWYXKDG7QInZBUrMLlBidoESswuUmF2gxuwCNWYXqDG7QI3ZBWrMLlBjdoEaswvUmF2gxuwCNWYXaDG7QIvZBVrMLtBidoEWswu0mF2gxewCLWYXaDG7QIvZBbaYXSDmfqDEXBCUmBuCEnNFUGLuCErMJUGJuSUoMdcEJeaeoMRcFJSYm4ISc1VQYu4KSsxlQYm5LSgx1wUl5r6gxFwYlJgbgxJzZVBi7gxKzKVBibk1KDHXBiXm3qDEXByUmJuDEnN1UGLuDmrM3UGNuTuoMXcHNebuoC4lRqbGyLQYmS1GpsfIxOwCMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Dfctqv16v1Qty8vBH59IvANl+2+ofKG22m1X5+IrV9fiP2XioaorCEqJUSlhqj8baL588nt2U++4dbAN+b1Gy4NfEelhqi0EJWQXe0NFwbqqL9/uC31hsqIUHnDdYHvqEiIioaovGHtD9lV2g2VEqJSQ1RaiMoWotJDVEZE5nzDJYHvqIT8dTZC/jobIX+dveGCwHdUQv46e8P1gO+obCEqPUQlYu2vyxKiIiEqGqKyhqiUEJUaotJCVLYQlR6iErL2JWTtS8jal5C1LyFrX0LWvoSsfQlZ+xKy9iVk7UvI2teQta8ha19D1r6GrH0NWfsasvY1ZO2r/9rv/xzbndWyXUVq+5dv6v9q9HrV6F3u/6hI/2O69MVlRnXn6WA8A4zn+E+bnwQSNCBFA1rRgAoaUEUDamhAaPu0oG3UgrZTK9pOrWg7taLt1Iq2UyvaTq1oO7U67tS7xhag8fp++sWxbl1eH9gBBrQuaECCBqRoQCsaUEEDqmhADQ1oQwNC26lXtJ26oO3UBW2nLmg7dUHbqQvaTl3QduqCtlMXx5161+gBGsNfoy4BGhKgoQEaa4BGCdCoARotQCNgnbfX564sy9UJWhbRQxUNUXk97qLlz+7bDgsIbUT8W7YlRCUk+lt5g0obu0pvhyo1RKWFqGwhKj1E5R3rpckfle1IpS8hKhKioiEqa4hKCVGpISotRGULUekhKm9Y+yLl+sNSDv+GGUuIioSoaIjKGqJSQlRqiEoLUdlCVN6w9mXTXeXrjbcvKiNC5Yar9ftl1oizxQ0f6PfL1BiZFiMzQmTecCPwWzISI6MxMv7rpi/Hl2u3/WPb9qDoWpb++0eL1vs/2ve9Yizlv1+qs39fyr2Ad1bwwQp+vIopyIWWXGnJV1ryQkteackbLTltBhXaFCq0OVRpc6jS5lClzaFKm0OVNocqbQ5Vtxy6K2zuCi/npHr9TrXUcqgwvBXWxV1B3BXUXeHlvW1vHC59PVQo7grVXaG5K7y6putyLUjVpR8qdHeF4a1QFncFcVd4dbZWvf5o1WOF5q7waqTber110aoeKdTFXcF9lOrLa3ovMte6HSp0d4XhrdAWdwVxV1B3hdVdobgrVHeF5q7wxjXd2qFCd1d4fU3vO992qLC9vKbX8UBB3BXUXeHVNd32m6ttGYcKxV2huis0d4XNXeHlNf3nMW5ZDhWGt0Jf3BXEXUHdFVZ3heKuUN0VmrvC9kaFwzXdu7vC62v6epOu6aHCeHlN7+XQWwrirqDuCi/n6Udn0VHcFaq7QnNX2NwVuruCe+XkxoXSt0mMG7fVpK37vd1WH3zlImW5bn5SRI5EbtxW/DuV0neV7dG3QO97bWjcuutEQ6/U9Cs1faGmr9T0jZp+o6bv1PSDmV6pc61S51qlzrVKnWuVOtcqda5V6lyr1LlWqXOtouTaK9CKkj53oOCM+MbnwcatW2809Cs1faGmr9T0jZp+o6bv1PSDmb4s1PTUubZQ59pCnWsLda4t1Lm2UOfaQp1rC3WuLdS5tqLk2h0IJX3+3ysQSkbcgVCS3A6Ekrd2IJRUtAOhZJcdCCVh7EAoOWAHQtnWr0ANbaduwcv+0cPM41ZHyc8iBU/sR4+LjVu9Ej86SpviIa14SC0a6f5j2ONWr8TPInU8pAGH1Bc8pPB96f57z+NWg8jPIq14SAUPqeIhNTykDQ+p4yENOKSx4CFF794P3gUft1qBfhZpxUMqeEgVD6nhIW14SB0PacAh3Xrj35HpviHAZBJAJgVkqnAFnVu+BD/LtAEy4RXjJLoz8FtMCsi0AjIVQCa0/WkjdbO4gHM+xX0B53yJ+wJO6mZh5JwvcRs550vcRs75EreRF1pyzpe4jZzTzcLIaTMoqZuFkdPmUFI3CyOnzaGkbhZGTptDSd0sjJw2hzq7WZjC5q7g62ZhCsNbwdnNwhTEXUHdFXzdLEyhuCtUd4XmruDrZmEK3V1heCs4u1mYgrgr+LpZmEJzV/B9k/Gi4OxmYQruo+TsZmEK3V1heCs4u1mYgrgrqLvC6q5Q3BWqu0JzV/B1szCF7q7g62ZhX2f5ulmYgrgrqLuCr5uFKRR3hequ0NwVNncFXzcLUxjeCs5uFqYg7grqrrC6KxR3hequ0NwVfN0sTKG7K/i6WdglCF83C1MQdwV1V/B1szCF4q5Q3RWau8LmrtDdFdwrJ85uFnVp/m4WJsLrZjHpaV/YnvS0L2xPetoXtid9oaanfWF70tO+sD3paV/YnvS0L2xPelo3C6PndbOY9NS5ltfNYtJT51peN4tJT51red0sJj11ruV1s5j0SG4WBgTlZjGBaF/YnvS0L2xPetoXtid9oaanfWF70tO+sD3paV/YnvS0L2xPetoXto2e181i0lPnWl43i0lPnWt53SwmPXWu5XWzmPTUuZbXzWLSU+daKDeLCYTkZjGBkNwsJhCSm8UEQslbOxCSm8UEQnKzmEBIbhYTCMnNYgIhuVkYEJSbxQQKXvYPnvufSFhuFhMJ6wG9eV0Ly81iImG5WUwkLDeLiYTlZjGRsNwsJhKWm8VEwnKzMCQwN4uJhOVmMZGw3CwmEpabxUQqeEhYbhYTCcvNYiJhuVlMJCw3i4mE5WZhSGBuFhMJy81iImG5WUwkLDeLiVTwkLDcLCYSlpvFRMJys5hIWG4WEwnLzeJXKxOWm8UvJiw3i19MWG4Wv5iwXov/xYTlZvGLCcvN4hcTXjEOzc3iFxOWm8UvJiw3i19MBZAJbH+SNaA/+CJC3B9s9Lw9S0bP27Nk9Lw9S0ZfqOl5e5aMnrdnyeh5e5aMnrdnyeh5+4Mv9MT9wUZPnWuJ+4ONnjrXEvcHGz11riXuDzZ66lxL3B9s9FD9wRcgrP5gA+LtWTJ63p4lo+ftWTL6Qk3P27Nk9Lw9S0bP27Nk9Lw9S0bP27N0oSfuDzZ66lxL3B9s9NS5lrg/2Oipcy1xf7DRU+da4v5go6fOtVj9wQYE1R9sQFD9wQYE1R9sQCh5aweC6g82IKj+YAOC6g82IKj+YAOC6g++AGH1BxtQ8LJ/1EBpSGD9wYYEdiXRrmuB9QcbElh/sCGB9QcbElh/sCGB9QcbElh/sCGB9QdfkND6gw0JrD/YkMD6gw0JrD/YkAoeElh/sCGB9QcbElh/sCGB9QcbElh/8AUJrT/YkMD6gw0JrD/YkMD6gw2p4CGB9QcbElh/sCGB9QcbElh/sCGB9QfPViaw/uDJBNYfPJnA+oMnE17/HVx/8GQC6w+eTHjFOLj+4MkE1h88mcD6gydTAWQC259U/nnVx7ksV5yiD2j6voGPpfz5UX3i2/ELeGcFH6zgstCSCy250pKvtOSFlrzSkjdactoMKrQpVGhzqNLmUKXNoUqbQ5U2hyptDlXaHKpuOXRX2NwVXs5J9XpTp9RyqDC8FdbFXUHcFdRd4eW9rV8XT+nroUJxV6juCs1d4dU1XZft94/WpR8qdHeF4a1QFncFcVd4dbZWvf5o1WOF5q7waqTber3q1qoeKdTFXcF9lOrLa7rsc6luhwrdXWF4K7TFXUHcFdRdYXVXKO4K1V2huSu8cU23dqjQ3RVeX9P7zrcdKmwvr+l9976lIO4K6q7w6ppuez9EW8ahQnFXqO4KzV1hc1d4eU2P6+PPTZZDheGt0Bd3BXFXUHeF1V2huCtUd4XmrrC9UeFwTffurvD6mr7eaGl6qDBeXtN7OfSWgrgrqLvCy3n60Vl0FHeF6q7Q3BU2d4XuruBeOblxdfptEqsEuFmswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbharMLtZrMLsZrEKs5vFKsxuFqswu1mswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbhargLlZrALmZrEKs5vFKsxuFqswu1mswuxmsQqzm8UqzG4WqzC7WazC7GaxCrObxSrMbharMLtZGD11riV2szB66lxL7GaxCrObhdFT51piN4tVmN0sVgFzszAgKDcLA4JyszAgKDcLA0LJWzsQlJvFKmBuFquAuVmsAuZmsQqYm8UqYG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnJvFKnBuFqvAuVmsAudmsQqcm8UqcG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnJvFKnBuFqvAuVmsAudmsQqcm8UqcG4Wq8C5WawC52axCpybxSpwbharwLlZrALnZrEKnpvFZAJzs5hMYG4WkwnstfjJBOZmMZnA3CwmE14xDs7NYjKBuVlMJjA3i8lUAJnQ9qdO6mZxAed8ivsCzvkS9wWc1M3CyDlf4jZyzpe4jZzzJW4jL7TknC9xGzmnm4WR02ZQUjcLI6fNoaRuFkZOm0NJ3SyMnDaHkrpZGDltDnV2szCFzV3B183CFIa3grObhSmIu4K6K/i6WZhCcVeo7grNXcHXzcIUurvC8FZwdrMwBXFX8HWzMIXmruD7JuNFwdnNwhTcR8nZzcIUurvC8FZwdrMwBXFXUHeF1V2huCtUd4XmruDrZmEK3V3B183Cvs7ydbMwBXFXUHcFXzcLUyjuCtVdobkrbO4Kvm4WpjC8FZzdLExB3BXUXWF1VyjuCtVdobkr+LpZmEJ3V/B1s7BLEL5uFqYg7grqruDrZmEKxV2huis0d4XNXaG7K7hXTrzdLMoW4GZxESF2szB63he2jZ73hW2j531h2+gLNT3vC9tGz/vCttHzvrBt9LwvbBs9r5vFhZ7YzcLoqXMtsZuF0VPnWmI3C6OnzrXEbhZGT51rid0sjB7KzeIChOVmYUC8L2wbPe8L20bP+8K20Rdqet4Xto2e94Vto+d9YdvoeV/YNnreF7Yv9MRuFkZPnWuJ3SyMnjrXErtZGD11riV2szB66lxL7GZh9NS5FsvNwoCg3CwMCMrNwoCg3CwMCCVv7UBQbhYGBOVmYUBQbhYGBOVmYUBQbhYXICw3CwMKXvaPnvs3JDA3C0MCe0DPrmuBuVkYEpibhSGBuVkYEpibhSGBuVkYEpibhSGBuVlckNDcLAwJzM3CkMDcLAwJzM3CkAoeEpibhSGBuVkYEpibhSGBuVkYEpibxQUJzc3CkMDcLAwJzM3CkMDcLAyp4CGBuVkYEpibhSGBuVkYEpibhSGBuVnMViYwN4vJBOZmMZnA3CwmE9hr8ZMJzM1iMoG5WUwmvGIcnJvFZAJzs5hMYG4Wk6kAMoHtT7UE9AdfRIj7g42et2fJ6Hl7loyet2fJ6As1PW/PktHz9iwZPW/PktHz9iwZPW9/8IWeuD/Y6KlzLXF/sNFT51ri/mCjp861xP3BRk+da4n7g40eqj/4AoTVH2xAvD1LRs/bs2T0vD1LRl+o6Xl7loyet2fJ6Hl7loyet2fJ6Hl7li70xP3BRk+da4n7g42eOtcS9wcbPXWuJe4PNnrqXEvcH2z01LkWqz/YgKD6gw0Iqj/YgKD6gw0IJW/tQFD9wQYE1R9sQFD9wQYE1R9sQFD9wRcgrP5gAwpe9o8aKA0JrD/YkMCuJNp1LbD+YEMC6w82JLD+YEMC6w82JLD+YEMC6w82JLD+4AsSWn+wIYH1BxsSWH+wIYH1BxtSwUMC6w82JLD+YEMC6w82JLD+YEMC6w++IKH1BxsSWH+wIYH1BxsSWH+wIRU8JLD+YEMC6w82JLD+YEMC6w82JLD+4NnKBNYfPJnA+oMnE1h/8GTC67+D6w+eTGD9wZMJrxgH1x88mcD6gycTWH/wZCqATGD7U2s3+oNr2a6fq227L/LGC+MXng7GM8B4brRa/yCQoAEpGtCKBlTQgCoaUEMDQtunBW2jFrSdWtF2akXbqRVtp1a0nVrRdmpF26nVcafeNbYAjdf30zfePjWgAQa0LmhAggakaEArGlBBA6poQA0NaEMDQtupV7SduqDt1AVtpy5oO3VB26kL2k5d0HbqgrZTF8edetfoARrDX6MuARoSoKEBGmuARgnQqAEaLUAjYJ231+fuo0v7pqIhKq/H/Rtf5LUR8W/ZlhCVkOhv5Q0q92/Om0oNUWkhKluISg9Recd6uX/z1r7OXkJUJERFQ1TWEJUSolJDVFqIyhai0kNU3rD2H1wltasjS4iKhKhoiMoaolJCVGqISgtR2UJU3rD2H1wSNpURoXLrGvnbZdaIs4UsJUamxsi0GJkRIvOGG4HfkpEYGY2RCVg3/fhy7bZ/bNseFF3Lcr3rW/TBVd++7xVjKf/9Up19opTbj2/hMoAPVvDjVUxBLrTkSku+0pIXWvJKS95oyWkzqNCmUKHNoUqbQ5U2hyptDlXaHKq0OVRpc6i65dBdYXNXeDkn1et3qqWWQ4XhrbAu7grirqDuCi/vbf26eEpfDxWKu0J1V2juCq+u6bpcC1J16YcK3V1heCuUxV1B3BVena1Vrz9a9VihuSu8Gum2Xm9dtKpHCnVxV3Afpfrymt6LzLVuhwrdXWF4K7TFXUHcFdRdYXVXKO4K1V2huSu8cU23dqjQ3RVeX9P7zrcdKmwvr+l9976lIO4K6q7w6ppu+83VtoxDheKuUN0VmrvC5q7w8poe9aogy6HC8Fboi7uCuCuou8LqrlDcFaq7QnNX2N6ocLime3dXeH1NX2/SNT1UGC+v6b0cektB3BXUXeHlPP3oLDqKu0J1V2juCpu7QndXcK+c3LhQ+jaJ7cZttb98nHK5bn5SRI5EJPh55Te+NrTduutEQ6/U9Cs1faGmr9T0jZp+o6bv1PSDmV6pc61S51qlzrVKnWuVOtcqda5V6lyr1LlWqXOtouTaK9CKkj53oOCM+MbnwbZbt95o6Fdq+kJNX6npGzX9Rk3fqekHM31ZqOmpc22hzrWFOtcW6lxbqHNtoc61hTrXFupcW6hzbUXJtTsQSvrcgVAy4g6EkuR2IJS8tQOhpKIdCCW77EAoCWMHQskBOxDKtn4Famg7dQte9o8eZt5udZT8LBKYO/V2q1fiR0dpUzykFQ8p2hH+wWPY261eiZ9F6nhIAw6pL3hI4fvS/feet1sNIj+LtOIhFTykiofU8JA2PKSOhzTgkMaChxS9ez94F3y71Qr0s0grHlLBQ6p4SA0PacND6nhIAw7p1hv/jkz3DQEmkwAyKSBThSvo3PIl+FmmDZAJrxgn0Z2B32JSQKYVkKkAMoHtT72SullcwDmf4r6Ac77EfQEndbMwcs6XuI2c8yVuI+d8idvICy0550vcRs7pZmHktBmU1M3CyGlzKKmbhZHT5lBSNwsjp82hpG4WRk6bQ53dLExhc1fwdbMwheGt4OxmYQrirqDuCr5uFqZQ3BWqu0JzV/B1szCF7q4wvBWc3SxMQdwVfN0sTKG5K/i+yXhRcHazMAX3UXJ2szCF7q4wvBWc3SxMQdwV1F1hdVco7grVXaG5K/i6WZhCd1fwdbOwr7N83SxMQdwV1F3B183CFIq7QnVXaO4Km7uCr5uFKQxvBWc3C1MQdwV1V1jdFYq7QnVXaO4Kvm4WptDdFXzdLOwShK+bhSmIu4K6K/i6WZhCcVeo7grNXWFzV+juCu6VE283i1EC3CwuIsRuFkbP+8K20fO+sG30vC9sG32hpud9YdvoeV/YNnreF7aNnveFbaPndbO40BO7WRg9da4ldrMweupcS+xmYfTUuZbYzcLoqXMtsZuF0UO5WVyAsNwsDIj3hW2j531h2+h5X9g2+kJNz/vCttHzvrBt9LwvbBs97wvbRs/7wvaFntjNwuipcy2xm4XRU+daYjcLo6fOtcRuFkZPnWuJ3SyMnjrXYrlZGBCUm4UBQblZGBCUm4UBoeStHQjKzcKAoNwsDAjKzcKAoNwsDAjKzeIChOVmYUDBy/7Rc/+GBOZmYUhgD+jZdS0wNwtDAnOzMCQwNwtDAnOzMCQwNwtDAnOzMCQwN4sLEpqbhSGBuVkYEpibhSGBuVkYUsFDAnOzMCQwNwtDAnOzMCQwNwtDAnOzuCChuVkYEpibhSGBuVkYEpibhSEVPCQwNwtDAnOzMCQwNwtDAnOzMCQwN4vZygTmZjGZwNwsJhOYm8VkAnstfjKBuVlMJjA3i8mEV4yDc7OYTGBuFpMJzM1iMhVAJqz9qS3i3x9sIrz9wZOetmdp0tP2LE162p6lSV+o6Wl7liY9bc/SpKftWZr0tD1Lk562P9joefuDJz11ruXtD5701LmWtz940lPnWt7+4ElPnWt5+4MnPVJ/sAFB9QdPINqepUlP27M06Wl7liZ9oaan7Vma9LQ9S5Oetmdp0tP2LE162p4lo+ftD5701LmWtz940lPnWt7+4ElPnWt5+4MnPXWu5e0PnvTUuRaqP3gCIfUHTyCk/uAJhNQfPIFQ8tYOhNQfPIGQ+oMnEFJ/8ARC6g+eQEj9wQYE1R88gYKX/YMGyomE1R88kbCuJM7rWlj9wRMJqz94ImH1B08krP7giYTVHzyRsPqDJxJWf7AhgfUHTySs/uCJhNUfPJGw+oMnUsFDwuoPnkhY/cETCas/eCJh9QdPJKz+YEMC6w+eSFj9wRMJqz94ImH1B0+kgoeE1R88kbD6gycSVn/wRMLqD55IWP3Bv1qZsPqDfzFh9Qf/YsLqD/7FhNd/h9Yf/IsJqz/4FxNeMQ6tP/gXE1Z/8C8mrP7gX0wFkAltfxr/vOrjXJYrTtEHNH3fwMdS/vyoPvPt+Pins4IPVnBZaMmFllxpyVda8kJLXmnJGy05bQYV2hQqtDlUaXOo0uZQpc2hSptDlTaHKm0OVbccuits7gov56R6valTajlUGN4K6+KuIO4K6q7w8t7Wr4un9PVQobgrVHeF5q7w6pquy/b7R+vSDxW6u8LwViiLu4K4K7w6W6tef7TqsUJzV3g10m29XnVrVY8U6uKu4D5K9eU1Xfa5VLdDhe6uMLwV2uKuIO4K6q6wuisUd4XqrtDcFd64pls7VOjuCq+v6X3n2w4VtpfX9L5731IQdwV1V3h1Tbe9H+Ly6w4VirtCdVdo7gqbu8LLa3pcH39ushwqDG+FvrgriLuCuius7grFXaG6KzR3he2NCodrund3hdfX9PVGS9NDhfHymt7LobcUxF1B3RVeztOPzqKjuCtUd4XmrrC5K3R3BffKyY2r02+TkBHgZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZYG4WMsDcLGQwu1nIYHazkMHsZiGD2c1CBrObhQxmNwsZzG4WMpjdLGQwu1nIYHazkMHsZmH01LmW2M3C6KlzLbGbhQxmNwujp861xG4WMpjdLGSAuVkYEJSbhQFBuVkYEJSbhQGh5K0dCMrNQgaYm4UMMDcLGWBuFjLA3CxkgLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLg3CxkwLlZyIBzs5AB52YhA87NQgacm4UMODcLGXBuFjLw3CwmE5ibxWQCc7OYTGCvxU8mMDeLyQTmZjGZ8IpxcG4WkwnMzWIygblZTKYCyAS2P2kjdbO4gHM+xX0B53yJ+wJO6mZh5JwvcRs550vcRs75EreRF1pyzpe4jZzTzcLIaTMoqZuFkdPmUFI3CyOnzaGkbhZGTptDSd0sjJw2hzq7WZjC5q7g62ZhCsNbwdnNwhTEXUHdFXzdLEyhuCtUd4XmruDrZmEK3V1heCs4u1mYgrgr+LpZmEJzV/B9k/Gi4OxmYQruo+TsZmEK3V1heCs4u1mYgrgrqLvC6q5Q3BWqu0JzV/B1szCF7q7g62ZhX2f5ulmYgrgrqLuCr5uFKRR3hequ0NwVNncFXzcLUxjeCs5uFqYg7grqrrC6KxR3hequ0NwVfN0sTKG7K/i6WdglCF83C1MQdwV1V/B1szCF4q5Q3RWau8LmrtDdFdwrJ95uFmsNcLO4iBC7WRg97wvbRs/7wrbR876wbfSFmp73hW2j531h2+h5X9g2et4Xto2e183iQk/sZmH01LmW2M3C6KlzLbGbhdFT51piNwujp861xG4WRg/lZnEBwnKzMCDeF7aNnveFbaPnfWHb6As1Pe8L20bP+8K20fO+sG30vC9sGz3vC9sXemI3C6OnzrXEbhZGT51rid0sjJ461xK7WRg9da4ldrMweupci+VmYUBQbhYGBOVmYUBQbhYGhJK3diAoNwsDgnKzMCAoNwsDgnKzMCAoN4sLEJabhQEFL/tHz/0bEpibhSGBPaBn17XA3CwMCczNwpDA3CwMCczNwpDA3CwMCczNwpDA3CwuSGhuFoYE5mZhSGBuFoYE5mZhSAUPCczNwpDA3CwMCczNwpDA3CwMCczN4oKE5mZhSGBuFoYE5mZhSGBuFoZU8JDA3CwMCczNwpDA3CwMCczNwpDA3CxmKxOYm8VkAnOzmExgbhaTCey1+MkE5mYxmcDcLCYTXjEOzs1iMoG5WUwmMDeLyVQAmcD2p6IB/cEXEeL+YKPn7Vkyet6eJaPn7Vky+kJNz9uzZPS8PUtGz9uzZPS8PUtGz9sffKEn7g82eupcS9wfbPTUuZa4P9joqXMtcX+w0VPnWuL+YKOH6g++AGH1BxsQb8+S0fP2LBk9b8+S0Rdqet6eJaPn7Vkyet6eJaPn7Vkyet6epQs9cX+w0VPnWuL+YKOnzrXE/cFGT51rifuDjZ461xL3Bxs9da7F6g82IKj+YAOC6g82IKj+YANCyVs7EFR/sAFB9QcbEFR/sAFB9QcbEFR/8AUIqz/YgIKX/aMGSkMC6w82JLAriXZdC6w/2JDA+oMNCaw/2JDA+oMNCaw/2JDA+oMNCaw/+IKE1h9sSGD9wYYE1h9sSGD9wYZU8JDA+oMNCaw/2JDA+oMNCaw/2JDA+oMvSGj9wYYE1h9sSGD9wYYE1h9sSAUPCaw/2JDA+oMNCaw/2JDA+oMNCaw/eLYygfUHTyaw/uDJBNYfPJnw+u/g+oMnE1h/8GTCK8bB9QdPJrD+4MkE1h88mQogE9T+pKLjxtX+Ta4i2/bnu2nR+udz25Of609+bjz3ueP73t/4nDz5OX3yc4dLqO9/r3S98bny5Ofqk59rT35ue/Jz/cnPjec+d3zBsfdr/b8PPf6cPPk5ffJz65OfK09+rj75ufbk5w7ny5cvPmU5/lx/8nPjuc8dX9L5xufkyc/pk59bn/zc4XwZel1HYz1eR8f3PL7xufbk57YnP9ef/Nx47nPHVwW+8Tl58LlyHL+mT35uffJzx/OlXtf7aMfr/fh6wDc+15783Pbk5/qTnxvPfW5bnvzc8Xzpy14qrv1fH/zP3/zwrqIhKmuISglRqSEqLURlC1HpISojQuX4m/23q4Ss/R6y9nvI2u8ha7+HrP0esvZ7yNrvIWu/h6z9EbL2R8jaHyFrf4Ss/RGy9kfI2h8ha3+ErP0RsvZHyNq/8a3i+2UkRkZjZNYYmRIjU2NkWozMFiPTY2RidgGJ2QUkZheQmF1AYnYBidkFJGYXkJhdQGJ2AYnZBSRmF9CYXUBjdgGN2QU0ZhfQmF1AY3YBjdkFNGYX0JhdQGN2gTVmF1hjdoE1ZhdYY3aBNWYXWGN2gTVmF1hjdoE1ZhdYY3aBErMLlJhdoMTsAiVmFygxu0CJ2QVKzC5QYnaBErMLlJhdoMbsAjVmF6gxu0CN2QVqzC5QY3aBGrML1JhdoMbsAjVmF2gxu0CL2QVazC7QYnaBFrMLtJhdoMXsAi1mF2gxu0CL2QW2mF0g5n6gxFwQlJgbghJzRVBi7ghKzCVBibklKDHXBCXmnqDEXBSUmJuCEnNVUGLuCkrMZUGJuS0oMdcFJea+oMRcGJSYG4MSc2VQYu4MSsylQYm5NSgx1wYl5t6gxFwclJibgxJzdVBi7g5qzN1Bjbk7qDF3BzXm7qAuJUamxsi0GJktRqbHyMTsAjF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdSYu4Mac3dQY+4OaszdQY25O6gxdwc15u6gxtwd1Ji7gxpzd1Bj7g5qzN1Bjbk7qDF3BzXm7qDG3B3UmLuDGnN3UGPuDmrM3UGNuTuoMXcHNebuoMbcHdQ33Lar9er9ULcvLwR+fSLwDZftvqHyhttptV+fiK1fX4j9l4qGqKwhKiVEpYao/G2i+fPJ7dlPvuHWwDfm9RsuDXxHpYaotBCVkF3tDRcG6qi/f7gt9YbKiFB5w3WB76hIiIqGqLxh7Q/ZVdoNlRKiUkNUWojKFqLSQ1RGROZ8wyWB76iE/HU2Qv46GyF/nb3hgsB3VEL+OnvD9YDvqGwhKj1EJWLtr8sSoiIhKhqisoaolBCVGqLSQlS2EJUeohKy9iVk7UvI2peQtS8ha19C1r6ErH0JWfsSsvYlZO1LyNrXkLWvIWtfQ9a+hqx9DVn7GrL2NWTtq/vaX+s/x3ZntWxXkdr+5Zv6vxq9XjV6l/s/KtL/mC59cZlR3Xk6GM8A4zn+0+YngQQNSNGAVjSgggZU0YAaGhDaPi1oG7Wg7dSKtlMr2k6taDu1ou3UirZTK9pOrY479a6xBWi8vp9+caxbl9cHdoABrQsakKABKRrQigZU0IAqGlBDA9rQgNB26hVtpy5oO3VB26kL2k5d0HbqgrZTF7SduqDt1MVxp941eoDG8NeoS4CGBGhogMYaoFECNGqARgvQCFjn7fW5K8tydYKWRfRQRUNUXo+7aPmz+7bDAkIbEf+WbQlRCYn+Vt6g0sau0tuhSg1RaSEqW4hKD1F5x3pp8kdlO1LpS4iKhKhoiMoaolJCVGqISgtR2UJUeojKG9a+SLn+sJTDv2HGEqIiISoaorKGqJQQlRqi0kJUthCVN6x92XRX+Xrj7YvKiFC54Wr9fpk14mxxwwf6/TI1RqbFyIwQmTfcCPyWjMTIaIxMwLrZji/XbvvHtu1B0bUs/fePFq33f7Tve8VYyn+/VGefKOVux7dwGcAHK/jxKqYgF1pypSVfackLLXmlJW+05LQZVGhTqNDmUKXNoUqbQ5U2hyptDlXaHKq0OVTdcuiusLkrvJyT6vU71VLLocLwVlgXdwVxV1B3hZf3tr1xuPT1UKG4K1R3heau8Oqarsu1IFWXfqjQ3RWGt0JZ3BXEXeHV2Vr1+qNVjxWau8KrkW7r9dZFq3qkUBd3BfdRqi+v6b3IXOt2qNDdFYa3QlvcFcRdQd0VVneF4q5Q3RWau8Ib13RrhwrdXeH1Nb3vfNuhwvbyml7HAwVxV1B3hVfXdNtvrrZlHCoUd4XqrtDcFTZ3hZfX9J/HuGU5VBjeCn1xVxB3BXVXWN0VirtCdVdo7grbGxUO13Tv7gqvr+nrTbqmhwrj5TW9l0NvKYi7grorvJynH51FR3FXqO4KzV1hc1fo7grulZMbF0rfJlFu3FaTtu73dlt98JWLlOW6+UkRORK5cVvx71RK31W2R98Cve+1oXLrrhMNvVLTr9T0hZq+UtM3avqNmr5T0w9meqXOtUqda5U61yp1rlXqXKvUuVapc61S51qlzrWKkmuvQCtK+tyBgjPiG58HK7duvdHQr9T0hZq+UtM3avqNmr5T0w9m+rJQ01Pn2kKdawt1ri3UubZQ59pCnWsLda4t1Lm2UOfaipJrdyCU9LkDoWTEHQglye1AKHlrB0JJRTsQSnbZgVASxg6EkgN2IJRt/QrU0HbqFrzsHz3MXG51lPwsUvDEfvS4WLnVK/Gjo/T/qDvb5MZxptlu6MYEUcRHYXHP3i8LHrF74qVablFZzvxvzjljGyg3hUQO41Pa+ZR6ttKfL8Ouz7ISP6vkfEqTTsk3PqX0fenP9z3XZwGRn1Xa+ZQqn1LjU+p8SoNPyfmUJp3S3PiUsnfvF/eC12dRoJ9V2vmUKp9S41PqfEqDT8n5lCad0rM7/oFOfy4EWE6F0MkInRrdC51nvQQ/6zQInfhexpXsZOC3nIzQaSd0qoROZPtTq6JtFoe45lXch7jmTdyHuGibRZhr3sQd5po3cYe55k3cYV5lzTVv4g5zzTaLMJedoKJtFmEuO0NF2yzCXHaGirZZhLnsDBVtswhz2RkKbrMIwoATsG0WQZhoArjNIggFTjA4AdtmEYQKJzQ4ocMJ2DaLIDicMNEEcJtFEAqcgG2zCEKHE7B3Mh4EcJtFEODfJXCbRRAcTphoArjNIggFTjA4YYcTKpzQ4IQOJ2DbLILgcAK2zSI+zsK2WQShwAkGJ2DbLIJQ4YQGJ3Q4YcAJ2DaLIEw0AdxmEYQCJxicsMMJFU5ocEKHE7BtFkFwOAHbZhGHILBtFkEocILBCdg2iyBUOKHBCR1OGHCCwwnwNyfoNou+J7RZHBDhNouw171hO+x1b9gOe90btsO+Stvr3rAd9ro3bIe97g3bYa97w3bY67ZZHPbCbRZhLz1rhdsswl561gq3WYS99KwVbrMIe+lZK9xmEfZUbRaHEFebRQjp3rAd9ro3bIe97g3bYV+l7XVv2A573Ru2w173hu2w171hO+x1b9g+7IXbLMJeetYKt1mEvfSsFW6zCHvpWSvcZhH20rNWuM0i7KVnLVebRQhRtVmEEFWbRQhRtVmEEMvcOoWo2ixCiKrNIoSo2ixCiKrNIoSo2iwOIa42ixBKXvavrvsPJbI2i1Aiu0AvjmuRtVmEElmbRSiRtVmEElmbRSiRtVmEElmbRSiRtVkcSmxtFqFE1mYRSmRtFqFE1mYRSpVPiazNIpTI2ixCiazNIpTI2ixCiazN4lBia7MIJbI2i1Aia7MIJbI2i1CqfEpkbRahRNZmEUpkbRahRNZmEUpkbRYrykTWZrGcyNoslhNZm8VyIrstfjmRtVksJ7I2i+XE9zKOrs1iOZG1WSwnsjaL5VQJncj2p7El5IMPiHA+OOx1M0thr5tZCnvdzFLYV2l73cxS2OtmlsJeN7MU9rqZpbDXzQcf9sL54LCXnrXC+eCwl561wvngsJeetcL54LCXnrXC+eCwp8oHH0Jc+eAQ0s0shb1uZinsdTNLYV+l7XUzS2Gvm1kKe93MUtjrZpbCXjezdNgL54PDXnrWCueDw1561grng8NeetYK54PDXnrWCueDw1561nLlg0OIKh8cQlT54BCiygeHEMvcOoWo8sEhRJUPDiGqfHAIUeWDQ4gqH3wIceWDQyh52b8KUIYSWT44lMiOJMZxLbJ8cCiR5YNDiSwfHEpk+eBQIssHhxJZPjiUyPLBhxJbPjiUyPLBoUSWDw4lsnxwKFU+JbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwfvKJMZPng5USWD15OZPng5cSXv6PLBy8nsnzwcuJ7GUeXD15OZPng5USWD15OldCJbX/yf+72ONftoVPthY2fG/jc6q8vtXc+Hfd/XFV8qoqXTda8yJqbrPkua15lzZuseZc1l52gRXaEFtkZarIz1GRnqMnOUJOdoSY7Q012hhpshp6EASfcnkntcVKntnpJmGjCvsEJBU4wOOH23uaPxVN9vyRUOKHBCR1OuLum2zb+/dK2+SXB4YSJJtQNTihwwt3f1maPL212Tehwwt2fdN8fR916sytC2+AE+Hep3V7T9fxdauOS4HDCRBP6BicUOMHghB1OqHBCgxM6nPDBNd37JcHhhPtr+tz5xiVh3F7T5+79jFDgBIMT7q7pfuYh+jYvCRVOaHBChxMGnHB7Tc/H5c+9bJeEiSb4BicUOMHghB1OqHBCgxM6nDA+SLhc0+5wwv01/TjR0u2SMG+v6fN16DNCgRMMTrg9p1/9W3RWOKHBCR1OGHCCwwnwNydPjk5/DOGe0Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4U7WZuFO1mbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZuGu3Gbhrtxm4a7cZhH20rNWuM0i7KVnrXCbhbtym0XYS89a4TYLd+U2C3eyNosQomqzCCGqNosQomqzCCGWuXUKUbVZuJO1WbiTtVm4k7VZuJO1WbiTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm407VZuNO1WbjTtVm487VZLCeyNovlRNZmsZzIbotfTmRtFsuJrM1iOfG9jKNrs1hOZG0Wy4mszWI5VUInsv1pNtE2i0Nc8yruQ1zzJu5DXLTNIsw1b+IOc82buMNc8ybuMK+y5po3cYe5ZptFmMtOUNE2izCXnaGibRZhLjtDRdsswlx2hoq2WYS57AwFt1kEYcAJ2DaLIEw0AdxmEYQCJxicgG2zCEKFExqc0OEEbJtFEBxOmGgCuM0iCAVOwLZZBKHDCdg7GQ8CuM0iCPDvErjNIggOJ0w0AdxmEYQCJxicsMMJFU5ocEKHE7BtFkFwOAHbZhEfZ2HbLIJQ4ASDE7BtFkGocEKDEzqcMOAEbJtFECaaAG6zCEKBEwxO2OGECic0OKHDCdg2iyA4nIBts4hDENg2iyAUOMHgBGybRRAqnNDghA4nDDjB4QT4mxNwm4VtFd9mERDdNotlL3vD9rKXvWF72cvesL3sq7S97A3by172hu1lL3vD9rKXvWF72cu2WYS9bpvFspeetbptFsteetbqtlkse+lZq9tmseylZ61um8WyZ2qzCCGqNoslJHvD9rKXvWF72cvesL3sq7S97A3by172hu1lL3vD9rKXvWF72cvesB32um0Wy1561uq2WSx76Vmr22ax7KVnrW6bxbKXnrW6bRbLXnrWUrVZLCGmNoslxNRmsYSY2iyWEMvcOoWY2iyWEFObxRJiarNYQkxtFkuIqc0ihKjaLJZQ8rJ/cd3/UuJqs1hKXBforeNaXG0WS4mrzWIpcbVZLCWuNoulxNVmsZS42iyWElebRSiRtVksJa42i6XE1WaxlLjaLJZS5VPiarNYSlxtFkuJq81iKXG1WSwlrjaLUCJrs1hKXG0WS4mrzWIpcbVZLKXKp8TVZrGUuNoslhJXm8VS4mqzWEpcbRZfUSauNosvJ642iy8nrjaLLyeu2+K/nLjaLL6cuNosvpz4XsaxtVl8OXG1WXw5cbVZfDlVQiey/amUhHzwARHOB4e9bmYp7HUzS2Gvm1kK+yptr5tZCnvdzFLY62aWwl43sxT2uvngw144Hxz20rNWOB8c9tKzVjgfHPbSs1Y4Hxz20rNWOB8c9lT54EOIKx8cQrqZpbDXzSyFvW5mKeyrtL1uZinsdTNLYa+bWQp73cxS2Otmlg574Xxw2EvPWuF8cNhLz1rhfHDYS89a4Xxw2EvPWuF8cNhLz1qufHAIUeWDQ4gqHxxCVPngEGKZW6cQVT44hKjywSFElQ8OIap8cAhR5YMPIa58cAglL/tXAcpQIssHhxLZkcQ4rkWWDw4lsnxwKJHlg0OJLB8cSmT54FAiyweHElk++FBiyweHElk+OJTI8sGhRJYPDqXKp0SWDw4lsnxwKJHlg0OJLB8cSmT54EOJLR8cSmT54FAiyweHElk+OJQqnxJZPjiUyPLBoUSWDw4lsnxwKJHlg1eUiSwfvJzI8sHLiSwfvJz48nd0+eDlRJYPXk58L+Po8sHLiSwfvJzI8sHLqRI6ke1Ptj/JB7c6Hs+1Pv4M+eCB8cPHyXwmmc+TqPUPChU2IWMT2tmEKptQYxPqbEJs+3Rh26gL205tbDu1se3UxrZTG9tObWw7tbHt1AbcqU/GSGDc308/ePo0hCaZ0L6xCRU2IWMT2tmEKptQYxPqbEKDTYhtp97ZdurKtlNXtp26su3UlW2nrmw7dWXbqSvbTl2BO/XJ8ATGxDPalsAoCQxLYOwJjJrAaAmMnsBIWOf9/u/uq0P7QbEUyv2f+zc+yOsz4/9lbCmUlJ/+qB+g/PnkfFBaCqWnUEYKxVMon1gvfz55Gx9nbymUkkKxFMqeQqkplJZC6SmUkULxFMoH1v6Lo6RxdGRLoZQUiqVQ9hRKTaG0FEpPoYwUygfW/otDwkGZGZRnx8g/jtkz/m1RtpqDaTmYnoOZKZgPnAj8FqbkYCwHk7Bu2vXh2nE+NsaLl651e5z1rfbiqK+fe8Xc6v9+ezv7xqvcdn0KV0F8qopfr2IJ8yJrbrLmu6x5lTVvsuZd1lx2ghbZEVpkZ6jJzlCTnaEmO0NNdoaa7Aw12RlqsBl6EgaccHsmtcdnqrXVS8JEE/YNTihwgsEJt/c2fyye6vslocIJDU7ocMLdNd22xwuptvklweGEiSbUDU4ocMLd39Zmjy9tdk3ocMLdn3TfH6cuerMrQtvgBPh3qd1e0+dL5tbGJcHhhIkm9A1OKHCCwQk7nFDhhAYndDjhg2u690uCwwn31/S5841Lwri9ps/d+xmhwAkGJ9xd0/08udq3eUmocEKDEzqcMOCE22t6tgehbJeEiSb4BicUOMHghB1OqHBCgxM6nDA+SLhc0+5wwv01/ThJ1+2SMG+v6fN16DNCgRMMTrg9p1/9W3RWOKHBCR1OGHCCwwnwNydPDpR+DLE/Oa32l5dTbo/Nr9RSriAl+XrlD942tD876yRjb9L2u7R9lbZv0vZd2n5I27u0/VS2N+lZa9Kz1qRnrUnPWpOetSY9a0161pr0rDXpWWsss/YhtLOMz1MoeSJ+8Hqw/dmpNxn7Xdq+Sts3afsubT+k7V3afirb103aXnrWVulZW6VnbZWetVV61lbpWVulZ22VnrVVetY2lll7CrGMz1OIZSKeQixD7hRimVunEMsoOoVYpsspxDIwTiGWGXAKsWzrD6HOtlP35GX/6mLm/Vmi5GeVyNqp92dZiR/9Lg3jU9r5lLIb4V9chr0/y0r8rJLzKU06Jd/4lNL3pT/f97w/C4j8rNLOp1T5lBqfUudTGnxKzqc06ZTmxqeUvXu/uBd8fxYF+lmlnU+p8ik1PqXOpzT4lJxPadIpPbvjH+j050KA5VQInYzQqdG90HnWS/CzToPQie9lXMlOBn7LyQiddkKnSuhEtj9VE22zOMQ1r+I+xDVv4j7ERdsswlzzJu4w17yJO8w1b+IO8yprrnkTd5hrtlmEuewEFW2zCHPZGSraZhHmsjNUtM0izGVnqGibRZjLzlBwm0UQBpyAbbMIwkQTwG0WQShwgsEJ2DaLIFQ4ocEJHU7AtlkEweGEiSaA2yyCUOAEbJtFEDqcgL2T8SCA2yyCAP8ugdssguBwwkQTwG0WQShwgsEJO5xQ4YQGJ3Q4AdtmEQSHE7BtFvFxFrbNIggFTjA4AdtmEYQKJzQ4ocMJA07AtlkEYaIJ4DaLIBQ4weCEHU6ocEKDEzqcgG2zCILDCdg2izgEgW2zCEKBEwxOwLZZBKHCCQ1O6HDCgBMcToC/OUG3WbSS0GZxQITbLMJe94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gv22Zx2Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2FO1WRxCXG0WIaR7w3bY696wHfa6N2yHfZW2171hO+x1b9gOe90btsNe94btsNe9YfuwF26zCHvpWSvcZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561XG0WIUTVZhFCVG0WIUTVZhFCLHPrFKJqswghqjaLEKJqswghqjaLEKJqsziEuNosQih52b+67j+UyNosQonsAr04rkXWZhFKZG0WoUTWZhFKZG0WoUTWZhFKZG0WoUTWZnEosbVZhBJZm0UokbVZhBJZm0UoVT4lsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WawoE1mbxXIia7NYTmRtFsuJ7Lb45UTWZrGcyNoslhPfyzi6NovlRNZmsZzI2iyWUyV0YtufPCMf7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0PtjZ8sHOlg926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7Gz5YGfLBztbPtjZ8sHOlg92tnyws+WDnS0f7Gz5YGfLBztbPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YCfMBzthPtgJ88FOmA92wnywE+aDnTAf7IT5YCfMBzthPtgJ88HOlw/u/Z+7Pc51e+hUe2Hj5wY+t/rrS+2NT8cPcVcVn6riZZM1L7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe5zUqa1eEiaasG9wQoETDE64vbf5Y/FU3y8JFU5ocEKHE+6u6baNf7+0bX5JcDhhogl1gxMKnHD3t7XZ40ubXRM6nHD3J933x1G33uyK0DY4Af5darfXdD1/l9q4JDicMNGEvsEJBU4wOGGHEyqc0OCEDid8cE33fklwOOH+mj53vnFJGLfX9Ll7PyMUOMHghLtrup95iL7NS0KFExqc0OGEASfcXtPzcflzL9slYaIJvsEJBU4wOGGHEyqc0OCEDieMDxIu17Q7nHB/TT9OtHS7JMzba/p8HfqMUOAEgxNuz+lX/xadFU5ocEKHEwac4HAC/M3Jk6PTH0OMntBmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjK7cZjG6cpvF6MptFqMrt1mMrtxmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjE7WZjE6WZvF6MptFqMrt1mMrtxmMbpym8Xoym0Woyu3WYyu3GYxunKbxejKbRajK7dZjK7cZhH20rNWuM0i7KVnrXCbxejKbRZhLz1rhdssRldusxidrM0ihKjaLEKIqs0ihKjaLEKIZW6dQlRtFqOTtVmMTtZmMTpZm8XoZG0Wo5O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HRtFqPTtVmMTtdmMTpdm8XodG0Wo9O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HRtFqPTtVmMTtdmMTpdm8XodG0Wo9O1WYxO12YxOl2bxeh0bRaj07VZjE7XZjE6XZvF6HxtFsuJrM1iOZG1WSwnstvilxNZm8VyImuzWE58L+Po2iyWE1mbxXIia7NYTpXQiWx/8l20zeIQ17yK+xDXvIn7EBdtswhzzZu4w1zzJu4w17yJO8yrrLnmTdxhrtlmEeayE1S0zSLMZWeoaJtFmMvOUNE2izCXnaGibRZhLjtDwW0WQRhwArbNIggTTQC3WQShwAkGJ2DbLIJQ4YQGJ3Q4AdtmEQSHEyaaAG6zCEKBE7BtFkHocAL2TsaDAG6zCAL8uwRuswiCwwkTTQC3WQShwAkGJ+xwQoUTGpzQ4QRsm0UQHE7AtlnEx1nYNosgFDjB4ARsm0UQKpzQ4IQOJww4AdtmEYSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yziEAS2zSIIBU4wOAHbZhGECic0OKHDCQNOcDgB/uYE3WYxLaHN4oAIt1mEve4N22Gve8N22OvesB32Vdpe94btsNe9YTvsdW/YDnvdG7bDXrfN4rAXbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWuE2i7CnarM4hLjaLEJI94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gve8P2YS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a7naLEKIqs0ihKjaLEKIqs0ihFjm1ilE1WYRQlRtFiFE1WYRQlRtFiFE1WZxCHG1WYRQ8rJ/dd1/KJG1WYQS2QV6cVyLrM0ilMjaLEKJrM0ilMjaLEKJrM0ilMjaLEKJrM3iUGJrswglsjaLUCJrswglsjaLUKp8SmRtFqFE1mYRSmRtFqFE1mYRSmRtFocSW5tFKJG1WYQSWZtFKJG1WYRS5VMia7MIJbI2i1Aia7MIJbI2i1Aia7NYUSayNovlRNZmsZzI2iyWE9lt8cuJrM1iOZG1WSwnvpdxdG0Wy4mszWI5kbVZLKdK6MS2P82MfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdPtnzwZMsHT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88JTOB0/pfPCUzgdP6XzwlM4HT+l88GTLB0+2fPBkywdPtnzwZMsHT7Z88GTLB0+2fPBkywdPtnzwZMsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT7588OTLB0++fPDkywdPvnzw5MsHT8J88CTMB0/CfPAkzAdPwnzwJMwHT8J88CTMB0/CfPAkzAdPwnzwpMsHt6dH+0d5QMb49dl0sfbrufHmc/7mc/O9567Pe3/jufLmc/bmc5dLyM+/V9yePFfffK69+Vx/87nx5nP+5nPzveeuDzi6P97/+7Tr58qbz9mbz+1vPlfffK69+Vx/87nL35ffPvgs2/Vz/uZz873nrg/pfOO58uZz9uZz+5vPXf6+THuso7lfr6Prcx7feK6/+dx48zl/87n53nPXRwW+8Vx58Vy9/vl1e/O5/c3nrn9f2mO9z3693q+PB3zjuf7mc+PN5/zN5+Z7z43tzeeuf198O18VN//Pg//vb774pFgKZU+h1BRKS6H0FMpIoXgKZWZQrj/Z/zglZe17ytr3lLXvKWvfU9a+p6x9T1n7nrL2PWXtz5S1P1PW/kxZ+zNl7c+UtT9T1v5MWfszZe3PlLU/U9b+k08VP48pORjLwew5mJqDaTmYnoMZORjPweTsAiVnFyg5u0DJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u4Dl7AKWswtYzi5gObuA5ewClrMLWM4uYDm7gOXsApazC+w5u8CeswvsObvAnrML7Dm7wJ6zC+w5u8CeswvsObvAnrML1JxdoObsAjVnF6g5u0DN2QVqzi5Qc3aBmrML1JxdoObsAi1nF2g5u0DL2QVazi7QcnaBlrMLtJxdoOXsAi1nF2g5u0DP2QV6zi7Qc3aBnrML9JxdoOfsAj1nF+g5u0DP2QV6zi4wcnaBnPOBJeeAYMk5IVhyjgiWnDOCJeeQYMk5JVhyjgmWnHOCJeegYMk5KVhyjgqWnLOCJeewYMk5LVhyjguWnPOCJefAYMk5MVhyjgyWnDODJefQYMk5NVhyjg2WnHODJefgYMk5OVhyjg6WnLODlnN20HLODlrO2UHLOTtoW83BtBxMz8GMHIznYHJ2gZyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODlrO2UHLOTtoOWcHLefsoOWcHbScs4OWc3bQcs4OWs7ZQcs5O2g5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODtoHTtu19uh+aOO3GwJ/vyLwA4ftvkH5wOm05o8rYtvvN8T+h2IplD2FUlMoLYXyt4Pm15Pj3Sc/cGrgG7/XHzg08B1KS6H0FErKrvaBAwNttn+/uG/tCWVmUD5wXOA7lJJCsRTKB9b+LCelP6HUFEpLofQUykiheAplZkzODxwS+A4l5a+zmfLX2Uz56+wDBwS+Q0n56+wDxwO+QxkpFE+hZKz9fdtSKCWFYimUPYVSUygthdJTKCOF4imUlLVfUtZ+SVn7JWXtl5S1X1LWfklZ+yVl7ZeUtV9S1n5JWfuWsvYtZe1bytq3lLVvKWvfUta+pax9Q6/94w3QP9d1Z62OB6T1//Sm/l+GtwfDvfz5S0vxX6VLv7XMmJ0+TuYzyXyu/7T5SaHCJmRsQjubUGUTamxCnU2IbZ8ubBt1YdupjW2nNrad2th2amPbqY1tpza2ndqAO/XJGAmM+/vpb411+3b/GzvJhPaNTaiwCRmb0M4mVNmEGptQZxMabEJsO/XOtlNXtp26su3UlW2nrmw7dWXbqSvbTl3ZduoK3KlPhicwJp7RtgRGSWBYAmNPYNQERktg9ARGwjrv9393y7Y9mqDLVuySYimU+z/3YvXX7tsvXyD0mfH/MrYUSspPf9QPUPo8Kd4vKS2F0lMoI4XiKZRPrJdeflHGFcW3FEpJoVgKZU+h1BRKS6H0FMpIoXgK5QNrv5T6+OJSL/+GmVsKpaRQLIWyp1BqCqWlUHoKZaRQPrD2y7CT8vuJt98oM4PypNX685g9498WT3qgP49pOZieg5kpmA+cCPwWpuRgLAeTsG7G9eHacT42xouXrnXzf7+0Wvvzl/q5V8yt/u+3t7NvvMod16dwFcSnqvj1KpYwL7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe3ymWlu9JEw0Yd/ghAInGJxwe287g8PV90tChRManNDhhLtrum2PF1Jt80uCwwkTTagbnFDghLu/rc0eX9rsmtDhhLs/6b4/Tl30ZleEtsEJ8O9Su72mz5fMrY1LgsMJE03oG5xQ4ASDE3Y4ocIJDU7ocMIH13TvlwSHE+6v6XPnG5eEcXtN7/MFocAJBifcXdP9PLnat3lJqHBCgxM6nDDghNtr+tdl3GW7JEw0wTc4ocAJBifscEKFExqc0OGE8UHC5Zp2hxPur+nHSbpul4R5e02fr0OfEQqcYHDC7Tn96t+is8IJDU7ocMKAExxOgL85eXKg9GOI8uS0Wun7eW63txcfuZS6PTa/Uku5gjw5rfh3lOonZbz6FOhztw2VZ2edZOxN2n6Xtq/S9k3avkvbD2l7l7afyvYmPWtNetaa9Kw16Vlr0rPWpGetSc9ak561Jj1rjWXWPoR2lvF5CiVPxA9eD1aenXqTsd+l7au0fZO279L2Q9repe2nsn3dpO2lZ22VnrVVetZW6VlbpWdtlZ61VXrWVulZW6VnbWOZtacQy/g8hVgm4inEMuROIZa5dQqxjKJTiGW6nEIsA+MUYpkBpxDLtv4Q6mw7dU9e9q8uZi7PEiU/q5T8i/3qcrHyLCvxo9+lYXxKO59Sz1b682XY5VlW4meVnE9p0in5xqeUvi/9+b7n8iwg8rNKO59S5VNqfEqdT2nwKTmf0qRTmhufUvbu/eJe8PIsCvSzSjufUuVTanxKnU9p8Ck5n9KkU3p2xz/Q6c+FAMupEDoZoVOje6HzrJfgZ50GoRPfy7iSnQz8lpMROu2ETpXQiWx/siraZnGIa17FfYhr3sR9iIu2WYS55k3cYa55E3eYa97EHeZV1lzzJu4w12yzCHPZCSraZhHmsjNUtM0izGVnqGibRZjLzlDRNoswl52h4DaLIAw4AdtmEYSJJoDbLIJQ4ASDE7BtFkGocEKDEzqcgG2zCILDCRNNALdZBKHACdg2iyB0OAF7J+NBALdZBAH+XQK3WQTB4YSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yzi4yxsm0UQCpxgcAK2zSIIFU5ocEKHEwacgG2zCMJEE8BtFkEocILBCTucUOGEBid0OAHbZhEEhxOwbRZxCALbZhGEAicYnIBtswhChRManNDhhAEnOJwAf3OCbrPY94Q2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPZ/lS3hHzwARHOB4e9bmYp7HUzS2Gvm1kK+yptr5tZCnvdzFLY62aWwl43sxT2uvngw144Hxz20rNWOB8c9tKzVjgfHPbSs1Y4Hxz20rNWOB8c9lT54EOIKx8cQrqZpbDXzSyFvW5mKeyrtL1uZinsdTNLYa+bWQp73cxS2Otmlg574Xxw2EvPWuF8cNhLz1rhfHDYS89a4Xxw2EvPWuF8cNhLz1qufHAIUeWDQ4gqHxxCVPngEGKZW6cQVT44hKjywSFElQ8OIap8cAhR5YMPIa58cAglL/tXAcpQIssHhxLZkcQ4rkWWDw4lsnxwKJHlg0OJLB8cSmT54FAiyweHElk++FBiyweHElk+OJTI8sGhRJYPDqXKp0SWDw4lsnxwKJHlg0OJLB8cSmT54EOJLR8cSmT54FAiyweHElk+OJQqnxJZPjiUyPLBoUSWDw4lsnxwKJHlg1eUiSwfvJzI8sHLiSwfvJz48nd0+eDlRJYPXk58L+Po8sHLiSwfvJzI8sHLqRI6se1P/s/dHue6PXSqvbDxcwOfW/31pfbOp+P+j6uKT1XxssmaF1lzkzXfZc2rrHmTNe+y5rITtMiO0CI7Q012hprsDDXZGWqyM9RkZ6jJzlCDzdCTMOCE2zOpPU7q1FYvCRNN2Dc4ocAJBifc3tv8sXiq75eECic0OKHDCXfXdNvGv1/aNr8kOJww0YS6wQkFTrj729rs8aXNrgkdTrj7k+7746hbb3ZFaBucAP8utdtrup6/S21cEhxOmGhC3+CEAicYnLDDCRVOaHBChxM+uKZ7vyQ4nHB/TZ8737gkjNtr+ty9nxEKnGBwwt013c88RN/mJaHCCQ1O6HDCgBNur+n5uPy5l+2SMNEE3+CEAicYnLDDCRVOaHBChxPGBwmXa9odTri/ph8nWrpdEubtNX2+Dn1GKHCCwQm35/Srf4vOCic0OKHDCQNOcDgB/ubkydHpjyGaJ7RZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNojlZm0VzsjaL5sptFs2V2yyaK7dZNFdus2iu3GbRXLnNorlym0Vz5TaL5sptFs2V2yyaK7dZhL30rBVuswh76Vkr3GbRXLnNIuylZ61wm0Vz5TaL5mRtFiFE1WYRQlRtFiFE1WYRQixz6xSiarNoTtZm0ZyszaI5WZtFc7I2i+ZkbRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc7o2i+Z0bRbN6dosmtO1WTSna7NoTtdm0ZyuzaI5XZtFc742i+VE1maxnMjaLJYT2W3xy4mszWI5kbVZLCe+l3F0bRbLiazNYjmRtVksp0roRLY/9SbaZnGIa17FfYhr3sR9iIu2WYS55k3cYa55E3eYa97EHeZV1lzzJu4w12yzCHPZCSraZhHmsjNUtM0izGVnqGibRZjLzlDRNoswl52h4DaLIAw4AdtmEYSJJoDbLIJQ4ASDE7BtFkGocEKDEzqcgG2zCILDCRNNALdZBKHACdg2iyB0OAF7J+NBALdZBAH+XQK3WQTB4YSJJoDbLIJQ4ASDE3Y4ocIJDU7ocAK2zSIIDidg2yzi4yxsm0UQCpxgcAK2zSIIFU5ocEKHEwacgG2zCMJEE8BtFkEocILBCTucUOGEBid0OAHbZhEEhxOwbRZxCALbZhGEAicYnIBtswhChRManNDhhAEnOJwAf3OCbrMYNaHN4oAIt1mEve4N22Gve8N22OvesB32Vdpe94btsNe9YTvsdW/YDnvdG7bDXrfN4rAXbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWuE2i7CnarM4hLjaLEJI94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gve8P2YS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a7naLEKIqs0ihKjaLEKIqs0ihFjm1ilE1WYRQlRtFiFE1WYRQlRtFiFE1WZxCHG1WYRQ8rJ/dd1/KJG1WYQS2QV6cVyLrM0ilMjaLEKJrM0ilMjaLEKJrM0ilMjaLEKJrM3iUGJrswglsjaLUCJrswglsjaLUKp8SmRtFqFE1mYRSmRtFqFE1mYRSmRtFocSW5tFKJG1WYQSWZtFKJG1WYRS5VMia7MIJbI2i1Aia7MIJbI2i1Aia7NYUSayNovlRNZmsZzI2iyWE9lt8cuJrM1iOZG1WSwnvpdxdG0Wy4mszWI5kbVZLKdK6ES2P3lJyAcfEOF8cNjrZpbCXjezFPa6maWwr9L2upmlsNfNLIW9bmYp7HUzS2Gvmw8+7IXzwWEvPWuF88FhLz1rhfPBYS89a4XzwWEvPWuF88FhT5UPPoS48sEhpJtZCnvdzFLY62aWwr5K2+tmlsJeN7MU9rqZpbDXzSyFvW5m6bAXzgeHvfSsFc4Hh730rBXOB4e99KwVzgeHvfSsFc4Hh730rOXKB4cQVT44hKjywSFElQ8OIZa5dQpR5YNDiCofHEJU+eAQosoHhxBVPvgQ4soHh1Dysn8VoAwlsnxwKJEdSYzjWmT54FAiyweHElk+OJTI8sGhRJYPDiWyfHAokeWDDyW2fHAokeWDQ4ksHxxKZPngUKp8SmT54FAiyweHElk+OJTI8sGhRJYPPpTY8sGhRJYPDiWyfHAokeWDQ6nyKZHlg0OJLB8cSmT54FAiyweHElk+eEWZyPLBy4ksH7ycyPLBy4kvf0eXD15OZPng5cT3Mo4uH7ycyPLBy4ksH7ycKqET2f409yf54FbH47nWx58hHzwwfvg4mc8k83kStf5BocImZGxCO5tQZRNqbEKdTYhtny5sG3Vh26mNbac2tp3a2HZqY9upjW2nNrad2oA79ckYCYz7++kHT5+G0CQT2jc2ocImZGxCO5tQZRNqbEKdTWiwCbHt1DvbTl3ZdurKtlNXtp26su3UlW2nrmw7dWXbqStwpz4ZnsCYeEbbEhglgWEJjD2BURMYLYHRExgJ67zf/919dWg/KJZCuf9z/8YHeX1m/L+MLYWS8tMf9QOUP5+cD0pLofQUykiheArlE+vlzydv4+PsLYVSUiiWQtlTKDWF0lIoPYUyUiieQvnA2n9xlDSOjmwplJJCsRTKnkKpKZSWQukplJFC+cDaf3FIOCgzg/LsGPnHMXvGvy3KVnMwLQfTczAzBfOBE4HfwpQcjOVgEtZNuz5cO87Hxnjx0rVuj7O+1V4c9fVzr5hb/d9vb2ffeJXbrk/hKohPVfHrVSxhXmTNTdZ8lzWvsuZN1rzLmstO0CI7QovsDDXZGWqyM9RkZ6jJzlCTnaEmO0MNNkNPwoATbs+k9vhMtbZ6SZhowr7BCQVOMDjh9t7mj8VTfb8kVDihwQkdTri7ptv2eCHVNr8kOJww0YS6wQkFTrj729rs8aXNrgkdTrj7k+7749RFb3ZFaBucAP8utdtr+nzJ3Nq4JDicMNGEvsEJBU4wOGGHEyqc0OCEDid8cE33fklwOOH+mj53vnFJGLfX9Ll7PyMUOMHghLtrup8nV/s2LwkVTmhwQocTBpxwe03P9iCU7ZIw0QTf4IQCJxicsMMJFU5ocEKHE8YHCZdr2h1OuL+mHyfpul0S5u01fb4OfUYocILBCbfn9Kt/i84KJzQ4ocMJA05wOAH+5uTJgdJPIcb25LTaX15OuT02v1JLuYKU5OuVP3fb0LIv0vYmbb9L21dp+yZt36Xth7S9S9tPZXuTnrUmPWtNetaa9Kw16Vlr0rPWpGetSc9ak561xjJrH0I7y/g8hZIn4ueuB1v2Jm2/S9tXafsmbd+l7Ye0vUvbT2X7uknbS8/aKj1rq/SsrdKztkrP2io9a6v0rK3Ss7ZKz9rGMmtPIZbxeQqxTMRTiGXInUIsc+sUYhlFpxDLdDmFWAbGKcQyA04hlm39IdTZduqevOxfXMy8lBqfElc79TquVei+S8P4lHY+pexG+D9fhr2UBp+S8ylNOiXf+JTS96U/3ve8lIxPaedTqnxKjU+p8ykNPiXnU5p0SnPjU8revf98L/hSMj6lnU+p8ik1PqXOpzT4lJxPadIpPbvjH+j0x0KAL6dC6GSETo3uhc6zXoKfdRqETnwv40p2MvBbTkbotBM6VUInsv2pmGabRYhLXsUd4pI3cYe4ZpvFMpe8iXuZS97Evcwlb+Je5lXWXPIm7mUu2WaxzGUnqGabxTKXnaGabRbLXHaGarZZLHPZGarZZrHMZWcots1iEQacAG2zWISJJmDbLBahwAkGJ0DbLBahwgkNTuhwArTNYhEcTphoArbNYhEKnABts1iEDidA72QMArbNYhHg3yVsm8UiOJww0QRsm8UiFDjB4IQdTqhwQoMTOpwAbbNYBIcToG0W6+MsaJvFIhQ4weAEaJvFIlQ4ocEJHU4YcAK0zWIRJpqAbbNYhAInGJywwwkVTmhwQocToG0Wi+BwArTNYh2CgLZZLEKBEwxOgLZZLEKFExqc0OGEASc4nAB/c4Jus7CS0GZxQITbLMJe94btsNe9YTvsdW/YDvsqba97w3bY696wHfa6N2yHve4N22Gv22Zx2Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2FO1WRxCXG0WIaR7w3bY696wHfa6N2yHfZW2171hO+x1b9gOe90btsNe94btsNe9YfuwF26zCHvpWSvcZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561XG0WIUTVZhFCVG0WIUTVZhFCLHPrFKJqswghqjaLEKJqswghqjaLEKJqsziEuNosQih52b+67j+UyNosQonsAr04rkXWZhFKZG0WoUTWZhFKZG0WoUTWZhFKZG0WoUTWZnEosbVZhBJZm0UokbVZhBJZm0UoVT4lsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WawoE1mbxXIia7NYTmRtFsuJ7Lb45UTWZrGcyNoslhPfyzi6NovlRNZmsZzI2iyWUyV0YtufPCMf7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0PtjZ8sHOlg926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7NL5YJfOB7t0Ptil88EunQ926XywS+eDXTof7Gz5YGfLBztbPtjZ8sHOlg92tnyws+WDnS0f7Gz5YGfLBztbPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YOfLBztfPtj58sHOlw92vnyw8+WDnS8f7Hz5YCfMBzthPtgJ88FOmA92wnywE+aDnTAf7IT5YCfMBzthPtgJ88HOlw/e+z93e5zr9tCp9sLGzw18bvXXl9obn44f4q4qPlXFyyZrXmTNTdZ8lzWvsuZN1rzLmstO0CI7QovsDDXZGWqyM9RkZ6jJzlCTnaEmO0MNNkNPwoATbs+k9jipU1u9JEw0Yd/ghAInGJxwe2/zx+Kpvl8SKpzQ4IQOJ9xd020b/35p2/yS4HDCRBPqBicUOOHub2uzx5c2uyZ0OOHuT7rvj6NuvdkVoW1wAvy71G6v6Xr+LrVxSXA4YaIJfYMTCpxgcMIOJ1Q4ocEJHU744Jru/ZLgcML9NX3ufOOSMG6v6XP3fkYocILBCXfXdD/zEH2bl4QKJzQ4ocMJA064vabn4/LnXrZLwkQTfIMTCpxgcMIOJ1Q4ocEJHU4YHyRcrml3OOH+mn6caOl2SZi31/T5OvQZocAJBifcntOv/i06K5zQ4IQOJww4weEE+JuTJ0enP4aoPaHNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqF25zaJ25TaL2pXbLGpXbrOoXbnNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqJ2szaJ2sjaL2pXbLGpXbrOoXbnNonblNovaldssaldus6hduc2iduU2i9qV2yxqV26zqF25zSLspWetcJtF2EvPWuE2i9qV2yzCXnrWCrdZ1K7cZlE7WZtFCFG1WYQQVZtFCFG1WYQQy9w6hajaLGona7OonazNonayNovaydosaidrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2unaLGqna7Oona7Nona6Nova6dosaqdrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2unaLGqna7Oona7Nona6Nova6dosaqdrs6idrs2idro2i9rp2ixqp2uzqJ2uzaJ2ujaL2vnaLJYTWZvFciJrs1hOZLfFLyeyNovlRNZmsZz4XsbRtVksJ7I2i+VE1maxnCqhE9n+1HbRNotDXPMq7kNc8ybuQ1y0zSLMNW/iDnPNm7jDXPMm7jCvsuaaN3GHuWabRZjLTlDRNoswl52hom0WYS47Q0XbLMJcdoaKtlmEuewMBbdZBGHACdg2iyBMNAHcZhGEAicYnIBtswhChRManNDhBGybRRAcTphoArjNIggFTsC2WQShwwnYOxkPArjNIgjw7xK4zSIIDidMNAHcZhGEAicYnLDDCRVOaHBChxOwbRZBcDgB22YRH2dh2yyCUOAEgxOwbRZBqHBCgxM6nDDgBGybRRAmmgBuswhCgRMMTtjhhAonNDihwwnYNosgOJyAbbOIQxDYNosgFDjB4ARsm0UQKpzQ4IQOJww4weEE+JsTdJtFt4Q2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPb/jQz8sFTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh882fLBky0fPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwVM6Hzyl88FTOh88pfPBUzofPKXzwZMtHzzZ8sGTLR882fLBky0fPNnywZMtHzzZ8sGTLR882fLBky0fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPPnywZMvHzz58sGTLx88+fLBky8fPAnzwZMwHzwJ88GTMB88CfPBkzAfPAnzwZMwHzwJ88GTMB88CfPBky0fvG9Pj/aP8oCM8euz6WLt13Pjzef8zefme89dn/f+xnPlzefszecul5Cff6+4PXmuvvlce/O5/uZz483n/M3n5nvPXR9wdH+8//dp18+VN5+zN5/b33yuvvlce/O5/uZzl78vv33wWbbr5/zN5+Z7z10f0vnGc+XN5+zN5/Y3n7v8fZn2WEdzv15H1+c8vvFcf/O58eZz/uZz873nro8KfOO58uK5ev3z6/bmc/ubz13/vrTHep/9er1fHw/4xnP9zefGm8/5m8/N954b25vPXf+++Ha+Km7+nwf/39988UmxFMqeQqkplJZC6SmUkULxFMrMoFx/sv9xSsra95S17ylr31PWvqesfU9Z+56y9j1l7XvK2p8pa3+mrP2ZsvZnytqfKWt/pqz9mbL2Z8ranylrf6as/SefKn4eU3IwloPZczA1B9NyMD0HM3IwnoPJ2QVKzi5QcnaBkrMLlJxdoOTsAiVnFyg5u0DJ2QVKzi5QcnYBy9kFLGcXsJxdwHJ2AcvZBSxnF7CcXcBydgHL2QUsZxfYc3aBPWcX2HN2gT1nF9hzdoE9ZxfYc3aBPWcX2HN2gT1nF6g5u0DN2QVqzi5Qc3aBmrML1JxdoObsAjVnF6g5u0DN2QVazi7QcnaBlrMLtJxdoOXsAi1nF2g5u0DL2QVazi7QcnaBnrML9JxdoOfsAj1nF+g5u0DP2QV6zi7Qc3aBnrML9JxdYOTsAjnnA0vOAcGSc0Kw5BwRLDlnBEvOIcGSc0qw5BwTLDnnBEvOQcGSc1Kw5BwVLDlnBUvOYcGSc1qw5BwXLDnnBUvOgcGSc2Kw5BwZLDlnBkvOocGSc2qw5BwbLDnnBkvOwcGSc3Kw5BwdLDlnBy3n7KDlnB20nLODlnN20Laag2k5mJ6DGTkYz8Hk7AI5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20nLODlnN20HLODlrO2UHLOTtoOWcHLefsoOWcHbScs4OWc3bQcs4OWs7ZQcs5O2g5Zwct5+yg5ZwdtJyzg5ZzdtByzg5aztlByzk7aDlnBy3n7KDlnB20D5y2a+3R/dDGbzcE/n5F4AcO232D8oHTac0fV8S232+I/Q/FUih7CqWmUFoK5W8Hza8nx7tPfuDUwDd+rz9waOA7lJZC6SmUlF3tAwcG2mz/fnHf2hPKzKB84LjAdyglhWIplA+s/VlOSn9CqSmUlkLpKZSRQvEUysyYnB84JPAdSspfZzPlr7OZ8tfZBw4IfIeS8tfZB44HfIcyUiieQslY+/u2pVBKCsVSKHsKpaZQWgqlp1BGCsVTKClrv6Ss/ZKy9kvK2i8pa7+krP2SsvZLytovKWu/pKz9krL2LWXtW8rat5S1bylr31LWvqWsfUtZ+wZf+6P9c1131up4QFr/T2/q/2V4ezDcy5+/tBT/Vbr0W8uM2enjZD6TzOf6T5ufFCpsQsYmtLMJVTahxibU2YTY9unCtlEXtp3a2HZqY9upjW2nNrad2th2amPbqQ24U5+MkcC4v5/+1li3b/e/sZNMaN/YhAqbkLEJ7WxClU2osQl1NqHBJsS2U+9sO3Vl26kr205d2XbqyrZTV7adurLt1JVtp67AnfpkeAJj4hltS2CUBIYlMPYERk1gtARGT2AkrPN+/3e3bNujCbpsxS4plkK5/3MvVn/tvv3yBUKfGf8vY0uhpPz0R/0Apc+T4v2S0lIoPYUyUiieQvnEeunlF2VcUXxLoZQUiqVQ9hRKTaG0FEpPoYwUiqdQPrD2S6mPLy718m+YuaVQSgrFUih7CqWmUFoKpadQRgrlA2u/DDspv594+40yMyhPWq0/j9kz/m3xpAf685iWg+k5mJmC+cCJwG9hSg7GcjAJ62ZcH64d52NjvHjpWjf/90urtT9/qZ97xdzq/357O/vGq9xxfQpXQXyqil+vYgnzImtusua7rHmVNW+y5l3WXHaCFtkRWmRnqMnOUJOdoSY7Q012hprsDDXZGWqwGXoSBpxweya1x2eqtdVLwkQT9g1OKHCCwQm397YzOFx9vyRUOKHBCR1OuLum2/Z4IdU2vyQ4nDDRhLrBCQVOuPvb2uzxpc2uCR1OuPuT7vvj1EVvdkVoG5wA/y6122v6fMnc2rgkOJww0YS+wQkFTjA4YYcTKpzQ4IQOJ3xwTfd+SXA44f6aPne+cUkYt9f0Pl8QCpxgcMLdNd3Pk6t9m5eECic0OKHDCQNOuL2mf13GXbZLwkQTfIMTCpxgcMIOJ1Q4ocEJHU4YHyRcrml3OOH+mn6cpOt2SZi31/T5OvQZocAJBifcntOv/i06K5zQ4IQOJww4weEE+JuTJwdKP4bwJ6fVSt/Pc7u9vfjIpdTtsfmVWsoV5Mlpxb+jVD8p49WnQJ+7bcifnXWSsTdp+13avkrbN2n7Lm0/pO1d2n4q25v0rDXpWWvSs9akZ61Jz1qTnrUmPWtNetaa9Kw1lln7ENpZxucplDwRP3g9mD879SZjv0vbV2n7Jm3fpe2HtL1L209l+7pJ20vP2io9a6v0rK3Ss7ZKz9oqPWur9Kyt0rO2Ss/axjJrTyGW8XkKsUzEU4hlyJ1CLHPrFGIZRacQy3Q5hVgGxinEMgNOIZZt/SHU2XbqnrzsX13M7M8SJT+rlPyL/epyMX+WlfjR79IwPqWdT6lnK/35Mmx/lpX4WSXnU5p0Sr7xKaXvS3++79mfBUR+VmnnU6p8So1PqfMpDT4l51OadEpz41PK3r1f3Avuz6JAP6u08ylVPqXGp9T5lAafkvMpTTqlZ3f8A53+XAiwnAqhkxE6NboXOs96CX7WaRA68b2MK9nJwG85GaHTTuhUCZ3I9qdZRdssDnHNq7gPcc2buA9x0TaLMNe8iTvMNW/iDnPNm7jDvMqaa97EHeaabRZhLjtBRdsswlx2hoq2WYS57AwVbbMIc9kZKtpmEeayMxTcZhGEASdg2yyCMNEEcJtFEAqcYHACts0iCBVOaHBChxOwbRZBcDhhogngNosgFDgB22YRhA4nYO9kPAjgNosgwL9L4DaLIDicMNEEcJtFEAqcYHDCDidUOKHBCR1OwLZZBMHhBGybRXychW2zCEKBEwxOwLZZBKHCCQ1O6HDCgBOwbRZBmGgCuM0iCAVOMDhhhxMqnNDghA4nYNssguBwArbNIg5BYNssglDgBIMTsG0WQahwQoMTOpww4ASHE+BvTsBtFmXb8W0WAdFts1j2sjdsL3vZG7aXvewN28u+StvL3rC97GVv2F72sjdsL3vZG7aXvWybRdjrtlkse+lZq9tmseylZ61um8Wyl561um0Wy1561uq2WSx7pjaLEKJqs1hCsjdsL3vZG7aXvewN28u+StvL3rC97GVv2F72sjdsL3vZG7aXvewN22Gv22ax7KVnrW6bxbKXnrW6bRbLXnrW6rZZLHvpWavbZrHspWctVZvFEmJqs1hCTG0WS4ipzWIJscytU4ipzWIJMbVZLCGmNoslxNRmsYSY2ixCiKrNYgklL/sX1/0vJa42i6XEdYHeOq7F1WaxlLjaLJYSV5vFUuJqs1hKXG0WS4mrzWIpcbVZhBJZm8VS4mqzWEpcbRZLiavNYilVPiWuNoulxNVmsZS42iyWElebxVLiarMIJbI2i6XE1WaxlLjaLJYSV5vFUqp8SlxtFkuJq81iKXG1WSwlrjaLpcTVZvEVZeJqs/hy4mqz+HLiarP4cuK6Lf7LiavN4suJq83iy4nvZRxbm8WXE1ebxZcTV5vFl1MldCLbn8qWkA8+IML54LDXzSyFvW5mKex1M0thX6XtdTNLYa+bWQp73cxS2OtmlsJeNx982Avng8NeetYK54PDXnrWCueDw1561grng8NeetYK54PDnioffAhx5YNDSDezFPa6maWw180shX2VttfNLIW9bmYp7HUzS2Gvm1kKe93M0mEvnA8Oe+lZK5wPDnvpWSucDw576VkrnA8Oe+lZK5wPDnvpWcuVDw4hqnxwCFHlg0OIKh8cQixz6xSiygeHEFU+OISo8sEhRJUPDiGqfPAhxJUPDqHkZf8qQBlKZPngUCI7khjHtcjywaFElg8OJbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwffCix5YNDiSwfHEpk+eBQIssHh1LlUyLLB4cSWT44lMjywaFElg8OJbJ88IoykeWDlxNZPng5keWDlxNf/o4uH7ycyPLBy4nvZRxdPng5keWDlxNZPng5VUIntv3J/7nb41y3h061FzZ+buBzq7++1N75dNz/cVXxqSpeNlnzImtusua7rHmVNW+y5l3WXHaCFtkRWmRnqMnOUJOdoSY7Q012hprsDDXZGWqwGXoSBpxweya1x0md2uolYaIJ+wYnFDjB4ITbe5s/Fk/1/ZJQ4YQGJ3Q44e6abtv490vb5pcEhxMmmlA3OKHACXd/W5s9vrTZNaHDCXd/0n1/HHXrza4IbYMT4N+ldntN1/N3qY1LgsMJE03oG5xQ4ASDE3Y4ocIJDU7ocMIH13TvlwSHE+6v6XPnG5eEcXtNn7v3M0KBEwxOuLum+5mH6Nu8JFQ4ocEJHU4YcMLtNT0flz/3sl0SJprgG5xQ4ASDE3Y4ocIJDU7ocML4IOFyTbvDCffX9ONES7dLwry9ps/Xoc8IBU4wOOH2nH71b9FZ4YQGJ3Q4YcAJDifA35w8OTr9MYR5QpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhTlZm4U5WZuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym4W5cpuFuXKbhblym0XYS89a4TaLsJeetcJtFubKbRZhLz1rhdsszJXbLMzJ2ixCiKrNIoSo2ixCiKrNIoRY5tYpRNVmYU7WZmFO1mZhTtZmYU7WZmFO1mZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhTtdmYU7XZmFO12ZhztdmsZzI2iyWE1mbxXIiuy1+OZG1WSwnsjaL5cT3Mo6uzWI5kbVZLCeyNovlVAmdyPanvYm2WRzimldxH+KaN3Ef4qJtFmGueRN3mGvexB3mmjdxh3mVNde8iTvMNdsswlx2goq2WYS57AwVbbMIc9kZKtpmEeayM1S0zSLMZWcouM0iCANOwLZZBGGiCeA2iyAUOMHgBGybRRAqnNDghA4nYNssguBwwkQTwG0WQShwArbNIggdTsDeyXgQwG0WQYB/l8BtFkFwOGGiCeA2iyAUOMHghB1OqHBCgxM6nIBtswiCwwnYNov4OAvbZhGEAicYnIBtswhChRManNDhhAEnYNssgjDRBHCbRRAKnGBwwg4nVDihwQkdTsC2WQTB4QRsm0UcgsC2WQShwAkGJ2DbLIJQ4YQGJ3Q4YcAJDifA35yg2yxqTWizOCDCbRZhr3vDdtjr3rAd9ro3bId9lbbXvWE77HVv2A573Ru2w173hu2w122zOOyF2yzCXnrWCrdZhL30rBVuswh76Vkr3GYR9tKzVrjNIuyp2iwOIa42ixDSvWE77HVv2A573Ru2w75K2+vesB32ujdsh73uDdthr3vDdtjr3rB92Au3WYS99KwVbrMIe+lZK9xmEfbSs1a4zSLspWetcJtF2EvPWq42ixCiarMIIao2ixCiarMIIZa5dQpRtVmEEFWbRQhRtVmEEFWbRQhRtVkcQlxtFiGUvOxfXfcfSmRtFqFEdoFeHNcia7MIJbI2i1Aia7MIJbI2i1Aia7MIJbI2i1Aia7M4lNjaLEKJrM0ilMjaLEKJrM0ilCqfElmbRSiRtVmEElmbRSiRtVmEElmbxaHE1mYRSmRtFqFE1mYRSmRtFqFU+ZTI2ixCiazNIpTI2ixCiazNIpTI2ixWlImszWI5kbVZLCeyNovlRHZb/HIia7NYTmRtFsuJ72UcXZvFciJrs1hOZG0Wy6kSOpHtT60k5IMPiHA+OOx1M0thr5tZCnvdzFLYV2l73cxS2OtmlsJeN7MU9rqZpbDXzQcf9sL54LCXnrXC+eCwl561wvngsJeetcL54LCXnrXC+eCwp8oHH0Jc+eAQ0s0shb1uZinsdTNLYV+l7XUzS2Gvm1kKe93MUtjrZpbCXjezdNgL54PDXnrWCueDw1561grng8NeetYK54PDXnrWCueDw1561nLlg0OIKh8cQlT54BCiygeHEMvcOoWo8sEhRJUPDiGqfHAIUeWDQ4gqH3wIceWDQyh52b8KUIYSWT44lMiOJMZxLbJ8cCiR5YNDiSwfHEpk+eBQIssHhxJZPjiUyPLBhxJbPjiUyPLBoUSWDw4lsnxwKFU+JbJ8cCiR5YNDiSwfHEpk+eBQIssHH0ps+eBQIssHhxJZPjiUyPLBoVT5lMjywaFElg8OJbJ8cCiR5YNDiSwfvKJMZPng5USWD15OZPng5cSXv6PLBy8nsnzwcuJ7GUeXD15OZPng5USWD15OldCJbH/q+5N8cKvj8Vzr48+QDx4YP3yczGeS+TyJWv+gUGETMjahnU2osgk1NqHOJsS2Txe2jbqw7dTGtlMb205tbDu1se3UxrZTG9tObcCd+mSMBMb9/fSDp09DaJIJ7RubUGETMjahnU2osgk1NqHOJjTYhNh26p1tp65sO3Vl26kr205d2XbqyrZTV7adurLt1BW4U58MT2BMPKNtCYySwLAExp7AqAmMlsDoCYyEdd7v/+6+OrQfFEuh3P+5f+ODvD4z/l/GlkJJ+emP+gHKn0/OB6WlUHoKZaRQPIXyifXy55O38XH2lkIpKRRLoewplJpCaSmUnkIZKRRPoXxg7b84ShpHR7YUSkmhWAplT6HUFEpLofQUykihfGDtvzgkHJSZQXl2jPzjmD3j3xZlqzmYloPpOZiZgvnAicBvYUoOxnIwCeumXR+uHedjY7x46Vq3x1nfai+O+vq5V8yt/u+3t7NvvMpt16dwFcSnqvj1KpYwL7LmJmu+y5pXWfMma95lzWUnaJEdoUV2hprsDDXZGWqyM9RkZ6jJzlCTnaEGm6EnYcAJt2dSe3ymWlu9JEw0Yd/ghAInGJxwe2/zx+Kpvl8SKpzQ4IQOJ9xd0217vJBqm18SHE6YaELd4IQCJ9z9bW32+NJm14QOJ9z9Sff9ceqiN7sitA1OgH+X2u01fb5kbm1cEhxOmGhC3+CEAicYnLDDCRVOaHBChxM+uKZ7vyQ4nHB/TZ8737gkjNtr+ty9nxEKnGBwwt013c+Tq32bl4QKJzQ4ocMJA064vaZnexDKdkmYaIJvcEKBEwxO2OGECic0OKHDCeODhMs17Q4n3F/Tj5N03S4J8/aaPl+HPiMUOMHghNtz+tW/RWeFExqc0OGEASc4nAB/c/LkQOnHEOPJabW/vJxye2x+pZZyBSnJ1yt/8Lah8eysk4y9Sdvv0vZV2r5J23dp+yFt79L2U9nepGetSc9ak561Jj1rTXrWmvSsNelZa9Kz1qRnrbHM2ofQzjI+T6HkifjB68HGs1NvMva7tH2Vtm/S9l3afkjbu7T9VLavm7S99Kyt0rO2Ss/aKj1rq/SsrdKztkrP2io9a6v0rG0ss/YUYhmfpxDLRDyFWIbcKcQyt04hllF0CrFMl1OIZWCcQiwz4BRi2dYfQp1tp+7Jy/7VxczjWaLkZ5XI2qnHs6zEj36XhvEp7XxK2Y3wLy7DHs+yEj+r5HxKk07JNz6l9H3pz/c9j2cBkZ9V2vmUKp9S41PqfEqDT8n5lCad0tz4lLJ37xf3go9nUaCfVdr5lCqfUuNT6nxKg0/J+ZQmndKzO/6BTn8uBFhOhdDJCJ0a3QudZ70EP+s0CJ34XsaV7GTgt5yM0GkndKqETmT7k5tom8UhrnkV9yGueRP3IS7aZhHmmjdxh7nmTdxhrnkTd5hXWXPNm7jDXLPNIsxlJ6hom0WYy85Q0TaLMJedoaJtFmEuO0NF2yzCXHaGgtssgjDgBGybRRAmmgBuswhCgRMMTsC2WQShwgkNTuhwArbNIggOJ0w0AdxmEYQCJ2DbLILQ4QTsnYwHAdxmEQT4dwncZhEEhxMmmgBuswhCgRMMTtjhhAonNDihwwnYNosgOJyAbbOIj7OwbRZBKHCCwQnYNosgVDihwQkdThhwArbNIggTTQC3WQShwAkGJ+xwQoUTGpzQ4QRsm0UQHE7AtlnEIQhsm0UQCpxgcAK2zSIIFU5ocEKHEwac4HAC/M0Jus1iloQ2iwMi3GYR9ro3bIe97g3bYa97w3bYV2l73Ru2w173hu2w171hO+x1b9gOe902i8NeuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYS89a4XbLMKeqs3iEOJqswgh3Ru2w173hu2w171hO+yrtL3uDdthr3vDdtjr3rAd9ro3bIe97g3bh71wm0XYS89a4TaLsJeetcJtFmEvPWuF2yzCXnrWCrdZhL30rOVqswghqjaLEKJqswghqjaLEGKZW6cQVZtFCFG1WYQQVZtFCFG1WYQQVZvFIcTVZhFCycv+1XX/oUTWZhFKZBfoxXEtsjaLUCJrswglsjaLUCJrswglsjaLUCJrswglsjaLQ4mtzSKUyNosQomszSKUyNosQqnyKZG1WYQSWZtFKJG1WYQSWZtFKJG1WRxKbG0WoUTWZhFKZG0WoUTWZhFKlU+JrM0ilMjaLEKJrM0ilMjaLEKJrM1iRZnI2iyWE1mbxXIia7NYTmS3xS8nsjaL5UTWZrGc+F7G0bVZLCeyNovlRNZmsZwqoRPb/uQZ+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBzpYPdrZ8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WCXzge7dD7YpfPBLp0Pdul8sEvng106H+zS+WBnywc7Wz7Y2fLBzpYPdrZ8sLPlg50tH+xs+WBnywc7Wz7Y2fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7Xz7Y+fLBzpcPdr58sPPlg50vH+x8+WDnywc7YT7YCfPBTpgPdsJ8sBPmg50wH+yE+WAnzAc7YT7YCfPBTpgPdrp8sG39n7s9znV76FR7YePnBj63+utL7e8/HQ9xVxWfquJlkzUvsuYma77LmldZ8yZr3mXNZSdokR2hRXaGmuwMNdkZarIz1GRnqMnOUJOdoQaboSdhwAm3Z1J7nNSprV4SJpqwb3BCgRMMTri9t/lj8VTfLwkVTmhwQocT7q7pto1/v7RtfklwOGGiCXWDEwqccPe3tdnjS5tdEzqccPcn3ffHUbfe7IrQNjgB/l1qt9d0PX+X2rgkOJww0YS+wQkFTjA4YYcTKpzQ4IQOJ3xwTfd+SXA44f6aPne+cUkYt9f0uXs/IxQ4weCEu2u6n3mIvs1LQoUTGpzQ4YQBJ9xe0/Nx+XMv2yVhogm+wQkFTjA4YYcTKpzQ4IQOJ4wPEi7XtDuccH9NP060dLskzNtr+nwd+oxQ4ASDE27P6Vf/Fp0VTmhwQocTBpzgcAL8zcmTo9MfQ5SOb7MIiG6bxbKXvWF72cvesL3sZW/YXvZV2l72hu1lL3vD9rKXvWF72cvesL3sZdsswl63zWLZS89a3TaLZS89a3XbLJa99KzVbbNY9tKzVrfNYtkztVmEEFWbxRKSvWF72cvesL3sZW/YXvZV2l72hu1lL3vD9rKXvWF72cvesL3sZW/YDnvdNotlLz1rddsslr30rNVts1j20rNWt81i2UvPWt02i2UvPWup2iyWEFObxRJiarNYQkxtFkuIZW6dQo1NiKnNYgkxtVksIaY2iyXE1GYRQlRtFksoedm/uO5/KTU+Ja4L9NZxLa42i6XE1WaxlLjaLJYSV5vFUuJqs1hKXG0WS4mrzSKUyNoslhJXm8VS4mqzWEpcbRZLqfIpNT4lrjaLpcTVZrGUuNoslhJXm0UokbVZLCWuNoulxNVmsZS42iyWUuVTanxKXG0WS4mrzWIpcbVZLCWuNouvKBNXm8WXE1ebxZcTV5vFl1Oje6HD1mbx5cTVZvHlxPcyjq3N4suJq83iy4mrzeLLqRI6ke1Ptou2WRzimldxH+KaN3Ef4qJtFmGueRN3mGvexB3mmjdxh3mVNW+y5pptFmEuO0FF2yzCXHaGirZZhLnsDBVtswhz2Rkq2mYR5rIzFNxmEYQBJ2DbLIIw0QRwm0UQCpxgcAK2zSIIFU5ocEKHE7BtFkFwOGGiCeA2iyAUOOHub+ufWxSC0OEE7J2MBwHcZhEE+HcJ3GYRBIcTJpoAbrMIQoETDE7Y4YQKJzQ4ocMJ2DaLIDicgG2ziI+zsG0WQShwgsEJ2DaLIFQ4ocEJHU4YcAK2zSIIE00At1kEocAJBifscEKFExqc0OEEbJtFEBxOwLZZxCEIbJtFEAqcYHACts0iCBVOaHBChxMGnOBwAvzNCbrNYreENosDItxmEfa6N2yHve4N22Gve8N22Fdp+yZtr3vDdtjr3rAd9ro3bIe9bpvFYS/cZhH20rNWuM0i7KVnrXCbRdhLz1rhNouwl561wm0WYU/VZnEIcbVZhJDuDdthr3vDdtjr3rAd9lXanuVa0/fsdW/YDnvdG7bDXveG7bDXvWH7sBduswh76Vkr3GYR9tKzVrjNIuylZ61wm0XYS89a4TaLsJeetVxtFiFE1WYRQlRtFiFE1WYRQixz6xSiarMIIao2ixCiarMIIao2ixCiarM4hLjaLEIoedm/uu4/lMjaLEKJ7AK9OK5F1mYRSmRtFqFE1mYRSmRtFqFE1mYRSmRtFqFE1mZxKLG1WYQSWZtFKJG1WYQSWZtFKFU+JbI2i1Aia7MIJbI2i1Aia7MIJbI2i0OJrc0ilMjaLEKJrM0ilMjaLEKp8imRtVmEElmbRSiRtVmEElmbRSiRtVmsKBNZm8VyImuzWE5kbRbLiey2+OVE1maxnMjaLJYT38s4ujaL5UTWZrGcyNosllMldGLbn2ZGPnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54MnWz54suWDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eErng6d0PnhK54OndD54SueDp3Q+eLLlgydbPniy5YMnWz54suWDJ1s+eLLlgydbPniy5YMnWz54suWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ18+ePLlgydfPnjy5YMnXz548uWDJ2E+eBLmgydhPngS5oMnYT54EuaDJ2E+eBLmgydhPngS5oMnYT540uWD29Oj/aM8IGP8+my6WPv13HjzOX/zufnec9fnvb/xXHnzOXvzucsl5OffK25PnqtvPtfefK6/+dx48zl/87n53nPXBxzdH+//fdr1c+XN5+zN5/Y3n6tvPtfefK6/+dzl78tvH3yW7fo5f/O5+d5z14d0vvFcefM5e/O5/c3nLn9fpj3W0dyv19H1OY9vPNfffG68+Zy/+dx877nrowLfeK68eK5e//y6vfnc/uZz178v7bHeZ79e79fHA77xXH/zufHmc/7mc/O958b25nPXvy++na+Km//nwf/3N198UiyFsqdQagqlpVB6CmWkUDyFMjMo15/sf5ySsvY9Ze17ytr3lLXvKWvfU9a+p6x9T1n7nrL2Z8ra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j6h4RMMjOh4x8Ahw/0YgJh4B7t+IsxTg/o1AFDzC8Ahw/0YgGh7R8YiBRzgeMfEI/Mcs8P6NaRn9GzeKcv9G6AvfBB76wjeBh77wTeCh37T1hW8CD33hm8BDX/gm8NAXvgk89IX7N276yv0boa+9dZX7N0Jfe+sq92+EvvbWVe7fCH3travcvxH6XP0bNyOy/o0wEr4JPPSFbwIPfeGbwEO/aesL3wQe+sI3gYe+8E3goS98E3joC98EftNX7t8Ife2tq9y/EfraW1e5fyP0tbeucv9G6GtvXeX+jdDX3rpk/RthxNW/EUZc/RthxNW/EUYsG+xpxNW/EUZc/RthxNW/EUZc/RthxNW/cTMi698Io+S3/203QTix9W+EE9uFfnHKi61/I5zY+jfCia1/I5zY+jfCia1/I5zY+jfCia1/4+ZE178RTmz9G+HE1r8RTmz9G+HUCJ3Y+jfCia1/I5zY+jfCia1/I5zY+jduTnT9G+HE1r8RTmz9G+HE1r8RTo3Qia1/I5zY+jfCia1/I5zY+jfCia1/Y2ej2Po3thRb/8aWYuvf2FJs99pvKbb+jS3F1r+xpQg/ruPr39hSbP0bW4qtf2NLNUYpujm1UtLHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vOjSx4sufby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008dLO328tNPHSzt9vLTTx0s7fby008eLLn286NLHiy59vOjSx4sufbzo0seLLn286NLHiy59vOjSx4sufbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwI08eLMH28CNPHizB9vAjTx4swfbwY08eLMX28GNPHizF9vBjTx4sxfbwY08eLMX28GNPHizF9vBjTx4swfbz8r6s91O24+zR7ozMfo3wd7fml9snv1G/mU9Z8yZqXQ1e96KqbrnrVVW+66l1Xfeiq6+7SortMi+42Nd1tarrb1HS3qeluU9Pdpqa7TQ22TZ8IxyMub6d+P+PTejtHLDiiHnhEwSMMj7g85eb9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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":3,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"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","debug_symbols":"7d3RjiS3eYbhe9ljIShW/WSxfCtBECi2HAgwJMOSAwSG7z2jeKp3ZLHdI/LTN+yt92xtd8+yH9dU/y9np/m3T3/45r/++t//+e13f/z+h0+/+/e/ffrT97//+sdvv//u5T/97dPyb2v9///2hz9//d1P/8UPP379lx8//S6n/atP33z3h5c/Hcvfv/r0x2//9M2n320l//0/vvrpSUfHk7a19aQa+fVJNbeetPU8KXqelHueVHqetPc8qfY86eh4Uiw9T0o9T+q5IqLnioieKyJ6rojouSKi54qInisieq6I3HNF5J4rIvdcEbnnisg9V0TuuSJyzxWRe66I3HNF5J4rovRcEaXniig9V0TpuSJKzxVReq6I0nNFlJ4rovRcEaXnith7roi954rYe66IveeK2HuuiL3nith7roi954rYe66IveeKqD1XRO25ImrPFVF7rojac0XUniui9lwRteeKqD1XRO25Io6eK+LouSKOnivi6Lkijp4r4ui5Io6eK+LouSKOnivi6Lki0rJ0PSt1PWvtetbW9azoelbuelbpetbe9aza9ayuayN1XRup69pIXddG6ro2Ute1kbqujdR1baSuayN1XRup69pYu66NtevaWLuujbXr2li7ro2169pYu66NtevaWLuujbXr2ti6ro2t69ro2tRMXbuaqWtbM3Xta6aujc3UtbOZurY2U9feZura3Exdu5upa3szde1vpq4NztS1w5m6tjhT1x5n6trkTF27nKlrmzN17XOmro3O1LXTmbq2OlPXXmfq2uxM7YAvaXl91l7rz5711S8eGy/3ntcHR9qP26NfxtzGo4+8ptdHH7nm26PX7ThXtE23ophuRXm6FZXpVrRPt6I63YqO2VbU3qj60BWl6VY03T37mO6efUx3zz6mu2cf092zj+nu2cd09+xjtnv2usx2z16X2e7Z6zLbPXtdZrtnr8ts9+x1me2evS6z3bPXZbZ79rrMds9el+nu2cn83Z/z8frgvKfP61nTuZ6YbD3mqzrX9VzPm6/8Zj11svUcc61nXSZbT5psPetk69kmW4/g/pM+r6cuD9bz8mOe1we/bBK/+crlXE+ebD1lsvXsk62nTraeY671bMtk60nm9ZR6rqeW1nrWydazTbaemGw9ebL1lMnWs0+2HvP9+SX5Xh/88lbVWs8x13pimWw9abL1rJOt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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(noinitcheck)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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u32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu32CtdsnWLt9grXbJ1i7fYK12ydYu30Za7cvY+32Zazdvoy125cXqFM5Y+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Za7cvY+32Zazdvoy125exdvsy1m5fxtrty1i7fRlrty9j7fZlrN2+jLXbl7F2+zLWbl/G2u3LWLt9GWu3L2Pt9mWs3b6MtduXsXb7MtZuX8ba7ctYu30Fa7evYO32FazdvoK121cWqFO5YO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVrt69g7fYVrN2+grXbV7B2+wrWbl/B2u0rWLt9BWu3r2Dt9hWs3b6CtdtXsHb7CtZuX8Ha7StYu30Fa7evYO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVrt69g7fYVrN2+grXbV7B2+wrWbl/B2u0rWLt9BWu3r2Dt9hWs3b6CtdtXsHb7CtZuX8Ha7StYu30Fa7evYO32FazdvoK121ewdvsK1m5fwdrtK1i7fQVr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+iJmlFrJSB0dG66o1EpG6sNh4etPfrCDYu7ls9Kw/n13gzCtee4LnqoPp38r1z8c561dfyCvP5LXn8jrF/L6M3n9hbz+Sl4/ef8N5P03kvffSN5/I3n/jeT9dzg8Wbt+8v4byftvJO+/kbz/RvL+m8j7byLvv4m8/yby/juckatdP3n/TeT9N5H330TefxN5/xXy/ivk/VfI+6+Q99/h/FXt+sn7r5D3XyHvv0Lef4W8/2by/pvJ+28m77+ZvP8OZ3tq10/efzN5/83k/TeT999M3n8Lef8t5P23kPffQt5/h3Mjtesn77+FvP8W8v5byPtvIe+/lbz/VvL+W8n7byXvv8OZhNr1k/ffSt5/K3n/reT9t5L330befxt5/23k/beR99/hvDvt+sn7byPvv428/zby/tvI+28n77+dvP928v7byfvvcJaadv3k/beT999O3n87ef/t1P03Lwt1/13rp+6/a/3U/Xetn7r/rvVT99+1fur+u9ZP3X/X+qn771o/df9d6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6yfvv9z8q7V+8v7Lzb9a6wfvv73Xx4/uy6v6wfvvYf3g/fewfvD+e1g/eP89rB+8/x7WD95/D+sH77+H9WP33770stUfavtSPzj/6rh+7P57XD92/z2uH7v/9vj073f9L7/Wj91/j+vH7r+99+3Ty5K+np/g/Kvj+rH773H90P13rTnv9Yclfa0fuv8e1h+w+Vcn6ofuvyfqh+6/J+qH7r8n6ofuvyfqh+6/a80x7vWXF/VD998T9UP33xP1g/ffWPtWf5L6tX7w/pu2+7dxkdi/1I/NvzpRP3j/Pawfu/+u/Sk9Pr3WunytH7v/HteP3X9DyNv5E2LOX+vH7r/H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XXx6P74mjvmaNOZrZMzX5DFfU8Z8TR3zNW3M1/QhX5OWMV8z5hRIY06BNOYUSGNOgTTmFEhjToE05hRIY06BNOYUkDGngIw5BVQewM9tWyoq/2bn78WnD4E0WeVxffWiBLGojFhUQSyqIhbVEIvq1xb1+2tUVhhOfE0Y8zVxzNekMV+jcdYd/6aprDCc+Joy5mvqmK9pY75mCBcwl2XM14QxXxPHfE0a8zVjToEy5hQoY06BMuYUKGNOgTLmFKhjToE65hSoY06BOuYUqGNOgTrmFKhjToE65hSoY06BOuYUaGNOgTbmFGhjToE25hRoY06BNuYUaGNOgTbmFGhjToE25hToY06BPuYU6GNOgT7mFOhjToE+5hToY06BPuYU6GNOgT7kFCjLMuZrwpiviWO+Jo35GhnzNXnM15QxX1PHfE0b8zVjToEw5hQIY06BMOYUCGNOgTDmFAhjToEw5hQIY06BMOYUCGNOgTjmFIhjToE45hSIY06BOOYUiGNOgTjmFIhjToE45hSIY06BNOYUSGNOgTTmFEhjToE05hRIY06BNOYUSGNOgTTmFBjzHsEy5j2CZcx7BMuY9wiWMe8RLDLmFJAxp4CMOQVkzCkgY04BGXMK5DGnQB5zCuQxp0AecwqMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjHl2sIx5drCMeXawjnl2sI55drCOeXawjnl2sC4y5mvymK8pY76mjvmaNuZrxpwCY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54drGOeHaxjnh2sY54d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+VeZnH+VyflXmZx/lRfu/pvJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V5mcf5XJ+VeZnH+VyflXmZx/lcn5V4Wcf1XI+VeFnH9VyPlXZeHuv4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcj5V4Wcf1XI+VeFnH9VyPlXhZx/Vcn5V5Wcf1XJ+VeVnH9VF+7+W8n5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXlZx/Vcn5V5Wcf1XJ+VeVnH9VyflXjZx/1cj5V42cf9XI+Vdt4e6/jZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyPlXjZx/1cj5V42cf9XI+VeNnH/VyflXnZx/1cn5V52cf9UX7v7byflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VednH/VyflXnZx/1cn5V52cf9XJ+VdrodwN+Feh7AK4W/BaKHcPXgvlbsJrodxdeC2Uuw2vhXL34bVQ7ka8FsreiclRWKsA9k5MDsNaBbB3YnIc1iqAvROTA7FWAeydmByJtQpg78TkUKxVAHsnJsdirQLYOzE5GGsVwN6JydFYqwD2TkwOx1oFsHdicjzWKoC9E5MDslYB7J2YHJG1CmDvxOSQrFUAeycmx2StAtg7MTkoa62OvROTo7LW6tg7MTksa62OvROT47LW6tg7MTkwa62OvROTI7NWAeydmByatQpg78Tk2KxVAHsnJgdnrQLYOzE5OmsVwN6JyeFZqwD2TkyOz1oFsHdicoDWKoC9E5MjtFYB7J2YHKK1CmDvxOQYrVUAeycmB2mtAtg7MTlKaxXA3onJYVqrAPZOTI7TWgWwd2JyoNYqgL0TkyO1VgHsnZgcqrUKYO/E5FitVQB7JyYHa60C2DsxOVprFcDeicnhWqsA9k5MjtdaBbB3YnLA1iqAvROTI7ZWAeSdOLAztgI7YyuwM7YCO2NrLY9dAHknDuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztgK7IytwM7YCuyMrcDO2ArsjK3AztiK7IytyM7YiuyMrcjO2IoLeSeO7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3IztiK7IytyM7YiuyMrcjO2IrsjK3EzthK7IytxM7YSuyMrbSQd+LEzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2ErsjK3EzthK7IytxM7YSuyMrcTO2BJ2xpawM7aEnbEl7IwtWcg7sbAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YEnbGlrAztoSdsSXsjC1hZ2wJO2NL2Blbws7YyuyMrczO2MrsjK3MztjKC3knzuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7IytzM7YyuyMrczO2MrsjK3MztjK7Iytws7YKuyMrcLO2CrsjK2ykHfiws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztgq7Iytws7YKuyMrcLO2CrsjK3Cztiq7Iytys7YquyMrcrO2KoLeSeu7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Kztiq7Iytys7YquyMrcrO2KrsjK3Gzthq7Iytxs7YauyMrbaQd+LGzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2GrsjK3Gzthq7Iytxs7YauyMrcbO2OrsjK3Oztjq7Iytzs7Y6gt5J+7sjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uyMrc7O2OrsjK3Oztjq7Iytzs7Y6uSMrbiQM7ZWAdydeBXA3YlXAdydeBXA3YlXAdydeBXA3YlXAdydeBXA3YlXAeydmJyxtQpg78TkjK1VAHsnJmdsrQLYOzE5Y2sVwN6JyRlbqwD2TkzO2FoFsHdicsbWKoC9E5MztlYB7J2YnLG1CmDvxOSMrVUAeycmZ2ytX8HeickZW+tXsHdicsbW+hXsnZicsbV+BXsnJmdsrV/B3onJGVurAPZOTM7YWgWwd2JyxtYqgL0TkzO2VgHsnZicsbUKYO/E5IytVQB7JyZnbK0C2DsxOWNrFcDeickZW6sA9k5MzthaBbB3YnLG1iqAvROTM7ZWAeydmJyxtQpg78TkjK1VAHsnJmdsrQLYOzE5Y2sVwN6JyRlbqwD2TkzO2FoFsHdicsbWKoC9E5MztlYB7J2YnLG1CmDvxOSMrVUAeycmZ2ytAtg7MTljaxXA3onJGVurAPZOTM7YWgWwd2JyxtYqgL0TkzO2VgHsnZicsbUKYO/E5IytVQB5Jw7sjK3AztgK7IytwM7YWstjF0DeiQM7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2AjtjK7AztgI7YyuwM7YCO2MrsDO2IjtjK7IztiI7YyuyM7biQt6JIztjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjtjK7IztiI7YyuyM7YiO2MrsjO2IjbhKUv8/dks7wRA94EzAqBPoZzbQ0CpbwRAn0JnBECfQmcEQJ9CZwRAzwMnBGDzhc4IgO4DJZTfny0pvhEA3QfOCICeB84IEHYB0J34jADoTnxGAHQnPiMAuhOfEQDdiU8IwOYLnRHA3omx+UJnBLB3Ymy+0BkB7J0Ymy90RgB7J8bmC50RML4Tv71d+PWzrfZHHa0F2eso7Wc3Im+gEd0qN9iSG23JTaxydwnCLyHzSyj8Eiq/hMYvgTZNbBIqbULYJdB2/V0CbSffJWB351aXx4f7cRjp209e+v7Z9iwXu5Ory8Xu+t+Tq/uwR8VOE7dag51SbrUGO/3cag12qrrTmoad1m61BjsF3moNdrq81ZqZUquyNeLWvLPG0/BbazwNv7XG0/BbazwNv7XG0/A7a7qn4bfWeBp+a42n4bfWeBp+a424Ne+s8TT81hpPw2+t8TT81hpPw2+t8TT8xpq0eBp+a42n4bfWeBp+a42n4bfWiFvzzhpPw2+t8TT81hpPw2+t8TT81hpPw++sCZ6G31rjafitNZ6G31rjafitNeLWvLPG0/BbazwNv7XG0/BbazwNv7XG0/A7a6LRXHNMikzRaK45Y43RDnVM9kvRaIc6Y43RDnXGGqMd6oQ1yej9mjPWGL1fc8Yao7nmmHSUktFcc8YacWveWWP0fs0Za4ym4TPWGE3DZ6wxmobPWGM0DZ+wRoym4TPWGE3DZ6zxNPzWGk/Db62Riaz5xk8OrchD4fot+6fDq0/HnB8Ca3hj5EzZ+VYjZ0ratxo5Uy6/1ciZUrySkbs5M+V4bXPyTEle3ZyZsry6OTOleXVzZsrz6uaIm/PeHE/pH8yxmrx7efzk0Gv6w5wfDdXZavJWN9Jq8v6WkTFuAiW/MdJqStc2EvydOkRGWk3/6kZanRTUjbQ6VagbKW6kjpFWp5XvGXl8Bxf8nU9ERhqdbNbaHn92jctzzT+dbMDff0VkpNHJ5ntGnmg24O8CIzLS6GSjb6TRyUbfSKOTjb6R4kbqGGl0stE30uhk800jjyebqd5Wd6uRViebEDZvQmx/f7KZ6k14dxo51XvzLjPyRLOZ6i17txppdbJRN9LqZKNupLiROkZanWzUjbQ62agbaXWy+Z6Rx5PNVO8pvNVIs3+zaWU3sh8YWfv2k5f9s6G13cip3oF4q5Fm/2ajbaTZyaaEzcgqf/+mxVRvY7zVSHEjj408kSOnetPjrUaanWy0jTQ72WgbaXay0TbS7N9sdI2Uqd5neauRZv9m8y0jD29ayFTvyrzVSJ9sYmh/PmmxmyNuzntzfAL5YI7VqWK9cbXVHPPfvmEgU72N81YjrU4V3zLyTIazOlVoGznVe0FvNdLqVKFupNWpQt1Iq1OFupHiRuoYaXVa+Z6RxzcMpnpX6q1G+mSz/rtNr+fnqd6tqm6OTyDvzYlmp4rStppb+Ps3DKLZqULbSLNTxXeMPJHhpno/8K1GihupY6TZqULbSLNThbaRZqcKbSPNTiDaRpqdVr5l5PENg6ney32rkT7ZKBnpk42SkT7ZKBkpbqSOkT7ZKBnpk42SkT7ZrEb+ufC9m+PTygdzfAJ5b85U7zd/+5N3uSay/y4XO6H3DXfY+tNP/rlc7BytLlfmkXviThL4W73V5WInR3W52PlOXS52YlOXi53BtOWCv2v6e3KPZzPwt0ery50oVZ2RO1GqOiNXbMmdKVWdkAueqto+APb090cE8Lcfq8sFT1XfkXsmZoCnKmW54O/7VZcLnqq05YKnKm254KlKW65MJPc4ZoC/LVZd7kSp6ozciVLVGbkzpaoTcmdKVcdysd812hd5/OS+5PL3RwTsN4Lqy4VOVd+TeyJmYL9dU1+u2JILnar05UKnKn250KlKXy50qvqm3BMxAzpVqcvFfs+hvtyJUtUZuTOlqhNyZ0pVJ+QKjdzy5wC4S+BJSm8l8KSftxLAE01/1NHXQv7+rIn9TjZ9ueCJ5jtyT+RV7Peb6csFTzTacsETjbZc8ESjLVdsyQVPP9+Se5xXsd9hpS93olR1Ru5EqeqM3JlS1aHcjP1uJX25M6WqE3KJUlV/OcNm7DcEnZMg0BKC7BKe1nRf/9K1+GCgtqeaYwhPcrHTj7pc7PTzLbm1bU+7h3jwk4/vUGTst+fcaw12qrrVGuwEdqc12O+sudca7GR3qzXYKfBWa7DT5a3WiFvzzpqJEq62NZ6G31rjafitNZ6G31rjafidNdjvWrnXGk/Db63xNPzWGk/Db60Rt+adNZ6G31rjafitNZ6G31rjafitNZ6G31mD/X6Oe63xNPzWGk/Db63xNPzWGnFr3lljNNdkeTwpkeWdNUZzzQlrsLnwF1qTH68IyKW+scZohzpjjdEOdcYaox3qjDVG79ecscbo/Zoz1hjNNcdvWM/YLP17rTF6v+aENdiM/nutMZqGz1hjNA2fscZoGj5jjbg176wxmobPWGM0DZ+xxtPwW2s8Db+1xtPwO2uw363wTWu+8ZNrfSzx1j9ekfq0YIj9HoZ7rZkpDStbM1MaVrZG3Jp31syUhpWtmSkNK1szUxr+mTW9vLFmpjSsbM1MaVjXGvB3YlxmzRNuI+U31hhNw2esMZqGz1hjNA2fsUbcmnfWGE3DZ6wxmobPWGM0DZ9gZYG/c+RWa4ym4RPWgL/LRMmaXa6JhLvLxU6tMT4+3FPqB3LD0uRR9apg/3R9/nXGzqIXCBZrgrFz4wWCsdPgBYKxM94FgrGT2wWCsfOYvmDw96tcIBg7Z10g2FrSAn/LygWCxZpga0kL/F0rFwi2lrTA37dygWBjSauAv3PlAsHGklYBf+/KBYKNJa2yiDXBxpJWAX+vywWCjSWtAv4OlgsEW0ta4O9LuUCwtaQF/m6TCwRbS1rg7yG5QLC1pAX+zpALBFtLWuDv97hAsLWkBf4ujgsEW0ta4O/NuECwtaQF/o6LCwRbS1rg76O4QLC1pAX+7ogLBFtLWuDvebhAsLWkBf5OhgsEW0ta4O9PuECwtaSVrCUt8PdeXCDYWtJK1pKWWEta4G8huUCwtaQF/saQCwSLNcHWkhb4OzsuEGwtaYG/X+MCwdaSFvi7MC4QbC1pgb+34gLB1pIW+DsmLhBsLWmBvw/iAsHWkhb4uxsuEGwtaYG/Z+ECwdaSFvg7ES4QbC1pgb+/4ALB1pIW+LsGLhBsLWmBvxfgAsHWkhY4w/8CwdaSFjhv/wLB1pIWOBv/AsHWkhY4x/4CwdaSFjhz/gLB1pIWOB/+AsHWkpY1Rnyxxogv1hjxxRojvlhjxBdrjPhijRFfrDHiizVGfLHGiC/WGPHFGiO+WGPEF2uM+GKNEV+sMeKLNUZ8scaIr9YY8dUaI75aY8RXa4z4uog1wcaSVrXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRHfrDHimzVGfLPGiG/WGPFtEWuCjSWtZo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxbSaCeK/x8eH650/e5U7Uhc/IneiE7q09PtzrG7kTnc9n5E50Op+RO9HZfEbuRDPwCbkzEaXPyJ2p756QO1PfPSF3otn3jFyxJddWqpqJIn1GLm2q2iXQJqVdAnb6SXX7PZK+aAzi4JznCwRjJ6ALBGNnoAsEY6egCwSLNcHYSegCwdhZ6ALB2GnoAsHY2ekCwdaSFjjn+QLB1pIWOOf5AsHWkhY45/kCwdaSFjjn+QLB1pIWOOf5AsHGklYH5zxfINhY0urgnOcLBBtLWn0Ra4KNJa0Oznm+QLCxpNXBOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0wDnPFwi2lrTAOc8XCLaWtMA5zxcItpa0irWkBU7yvkCwtaRVrCWtItYEW0ta4MT2CwRbS1rg1PYLBFtLWuDk9gsEW0ta4PT2CwRbS1rgBPcLBFtLWuAU9wsEW0ta4NT3CwRbS1rWGPHdGiO+W2PEd2uM+G6NEd+tMeK7NUZ8t8aI79YY8d0aI75bY8R3a4z4bo0R360x4rs1Rny3xojv1hjx3RojvltjxHdjjPi0GGPEr4JtJa1VsK2ktQq2lbRWwWJNsK2ktQq2lbRWwbaS1irYVtJaBVtLWsYY8atga0nLGCN+FWwtaRljxK+CrSUtY4z4VbC1pGWMEb8Ktpa0jDHiV8HWkpYxRvwq2FrSMsaIXwVbS1rGGPGrYGtJyxgjfhVsLWkZY8Svgq0lLWOM+FWwtaRljBG/CraWtIwx4lfB1pKWMUb8Ktha0jLGiF8FW0taxhjxq2BrScsYI34VbC1pGWPEr4KtJS1jjPhVsLWkZYwRvwq2lrSMMeJXwdaSljFG/CrYWtIyxohfBVtLWsYY8atga0nLGCN+FWwtaRljxK+CrSUtY4z4VbC1pGWMEb8Ktpa0jDHiV8HWkpYxRvwq2FrSMsaIXwVbS1rGGPGrYGtJyxgjfhVsLWkZY8Svgq0lLWOM+FWwtaRljBG/CraWtIwx4lfB1pKWMUb8Ktha0jLGiF8FW0taxhjxq2BrScsYI34VbC1pGWPEr4KtJS1jjPhVsLWkZYwRvwo2lrSCNUZ8sMaID9YY8cEaI36VY02wsaQVrDHigzVGfLDGiA/WGPHBGiM+WGPEB2uM+GCNER+sMeKDNUZ8sMaID9YY8cEaIz5YY8QHa4z4YI0RH6wx4oM1RnywxogP1hjxwRojPlhjxAdrjPhgjREfrDHigzVGfLDGiA/WGPHBGiM+WGPEB2uM+GCNER+sMeKDNUZ8sMaID9YY8cEaIz5YY8QHa4z4YI0RH6wx4oM1RnywxogP1hjxwRojPlhjxAdrjPhgjREfrDHigzVGfLDGiA8zEcR7jY8P1z9/8iZ3Jn74GbkTndC9bR/u9Y3cic7nM3InOp3PyJ3obD4jd6IZ+IzciSbgM3Jn6rvHcmeiSZ+RO9Hse0buRJPvGbm2UtVMFOkzcmlT1S6BNintErDTT5bHaN1Lb0eDeH6Usd5BevNLh51+1OVipx9tueCEZ3W52OlHXS52+lGXi51+1OWKLbnY6UddLnZSUpdrK1WBE53V5dpKVeA0Z3W5tlIVOMlZXa6tVAVOcVaXaytVgROc1eXaSlXg9GZ1uaZSVQQnN6vLNZWqIji1WV2uqVQVF7El11SqiuC0ZnW5plJVBCc1q8u1larAKc3qcm2lKnBCs7pcW6kKnM6sLtdWqgInM6vLtZWqwKnM6nJtpSpwIrO6XFupCpzGrC7XVqoCJzGry7WVqsApzOpybaUqcAKzulxbqQqcvqwu11aqAicvq8u1larAqcvqcm2lKnDisrpcW6kKnLasLtdWqgInLavLtZWqwCnL6nJtpSpwwrK6XFupCpyurC7XVqoCJyury7WVqsCpyupybaUqcKKyulxbqQqcpqwu11aqAicpq8u1laqyrVQFTsnWlgtOyVaXaytVFVupCpyBri5XbMm1larAGejqcm2lKnAGurpcW6kKnIGuLtdWqgJnoKvLtZWqwBno6nJtpSpwXrq6XFupyhZbPdpiq0dbbPVoi60ebbHVoy22erTFVo+22OrRFls92mKrR1ts9WiLrR5tsdWjLbZ6tMVWj7bY6tEWWz3aYqtHW2z1aIutHm2x1aMttnqyxVZPttjqyRZbPdliq6dFbMk1laqSLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1ts9WSLrZ5ssdWTLbZ6ssVWT7bY6skWWz3ZYqsnW2z1ZIutnmyx1ZMttnqyxVZPttjqyRZbPdliqydbbPVki62ebLHVky22erLFVk+22OrJFls92WKrJ1tsdbHFVhdbbHWxxVYXW2x1WcSWXFOpSmyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWyx1cUWW11ssdXFFltdbLHVxRZbXWbCUfcaHx+u6Y3ciRrRCbkzAYt7a48P9/pG7kRH1Rm5Ex1VZ+SKLbkTDYBn5E40AJ6RO1PfPSF3pr57Qu5EA+AJuTMBi8/ItZWqZgIWn5FLm6p2CcIvATv91NgfElqsR2P40suj6hCeqi75STB2/rlAMHYCukAwdga6QDB2CtIXDI4YvkAwdhK6QDB2FrpAMHYaukCwWBNsLWmB44YvEGwtaYEjhy8QbC1pgWOHLxBsLWmBo4cvEGwtaYHjhy8QbC1pgSOILxBsLWmBY4gvEGwsaWVwFPEFgo0lrQyOI75AsLGklRexJthY0srgWOILBBtLWhkcTXyBYGtJCxxPfIFga0kLHFF8gWBrSQscU3yBYGtJCxxVfIFga0kLHFd8gWBrSQscWXyBYGtJCxxbfIFga0kLHF18gWBrSQscX3yBYGtJCxxhfIFga0kLHGN8gWBrSQscZXyBYGtJCxxnfIFga0kLHGl8gWBrSQsca3yBYGtJCxxtfIFga0kLHG98gWBrSQsccXyBYGtJCxxzfIFga0kLHHV8gWBrSQscd3yBYGtJCxx5fIFga0krizXB1pJWtpa0wEneFwi2lrSytaRVrCUtcF77BYKtJS1wZvsFgsWaYGtJC5zcfoFga0kLnN5+gWBrSQuc4H6BYGtJC5zifoFga0kLnPp+gWBrScsaIz5bY8Rna4z4bI0Rn60x4rM1Rny2xojP1hjx2RojPltjxGdrjPhsjRGfrTHiszVGfLbGiM/WGPHZGiM+W2PEZ2uM+GyNEZ+tMeKzNUZ8tsaIz9YY8cUaI75YY8QXa4z4Yo0RXxaxJthY0irWGPHFGiO+WGPEF2uM+GKNEV+sMeKLNUZ8scaIL9YY8cUaI75YY8QXa4z4Yo0RX6wx4os1Rnyxxogv1hjxxRojvlhjxJeZCOLrpx8frn/+5F3uRF34hNyZ2NK9tceHe30jd6Lz+YzciU7nM3InOpvPyJ1oBj4jd6IJ+IzcmfruCbkz9d0TcieafU/InYkkfUaurVQ1E0X6jFzaVLVLEH4J2Omn5br9HuVyNIhL3AZxSXn/dO1PgrHzzwWCsRPQBYKxM9AFgrFTkL5gcM7zBYKxk9AFgrGz0AWCsdPQBYLFmmBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGtJC5zzfIFga0kLnPN8gWBrSQuc83yBYGNJq4Jzni8QbCxpVXDO8wWCjSWtuog1wcaSVgXnPF8g2FjSquCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWuCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWuCc5wsEW0ta4JznCwRbS1rgnOcLBFtLWtFa0gIneV8g2FrSitaSVrKWtMB57RcItpa0wJntFwgWa4KtJS1wcvsFgq0lLXB6+wWCrSUtcIL7BYKtJS1wivsFgq0lLXDq+wWCrSUta4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjx1RojvlpjxFdrjPhqjRFfrTHiqzVGfLXGiK/WGPHVGiO+WmPEV2uM+GqNEV+tMeKrNUZ8tcaIr9YY8dUaI75aY8RXa4z4ao0RX60x4qs1Rny1xoiv1hjxzRojvlljxDdrjPhmjRHfFrEm2FjSatYY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R36wx4ps1Rnyzxohv1hjxzRojvlljxDdrjPhmjRHfrDHimzVGfLPGiG/WGPHNGiO+WWPEN2uM+GaNEd+sMeKbNUZ8s8aIb9YY8c0aI75ZY8Q3a4z4Zo0R32YiiPcaHx+uf/7kXe5EXfiM3IlO6N7a9uH6Ru5E5/MZuROdzmfkTnQ2n5E70Qx8Qu5MROkzcmfquyfkztR3T8idaPY9I1dsybWVqmaiSJ+RS5uqdgm0SWmXgJ1++vaTwxJiOJrE8/bpLK9/68Axz/p6sfOPvl7sAKSvFzsB6esVY3qxM5C+XuwQpK8XOwXp68WOTPp6jeUrcLizvl5j+Qoc7ayv11i+Agc76+s1lq/Asc76eo3lK3Cos75eW/mqgyOd9fXaylcdHOisr9dWvuqLGNNrK191cJizvl5b+aqDo5z19RrLV+AgZ329xvIVOMZZX6+xfAUOcdbXayxfgSOc9fUay1fgAGd9vcbyFTi+WV+vsXwFDm/W12ssX4Gjm/X1GstX4OBmfb3G8hU4tllfr7F8BQ5t1tdrLF+BI5v19RrLV+DAZn29xvIVOK5ZX6+xfAUOa9bXayxfgaOa9fUay1fgoGZ9vcbyFTimWV+vsXwFDmnW12ssX4EjmvX1GstX4IBmfb3G8hU4nllfr7F8BQ5n1tdrLF+Bo5n19RrLV+BgZn29xvJVMZavwLnb+nqN5atiLF8VMabXWL4CR6vr6zWWr8Dh6vp6jeUrcLy6vl5j+QocsK6v11i+Akes6+s1lq/AIev6eo3lK3Aku75eY/nKGL+9G+O3d2P89m6M396N8du7MX57N8Zv78b47d0Yv70b47d3Y/z2bozf3o3x27sxfns3xm/vxvjt3Ri/vdvit8syFd/78M3pq96Z+u8ZvTOdz4dv+Vz1znQ+n9E70/l8Ru9M5/MZvTPNv2f0zjT/ntA7Ff/5jN6p+u8JvTPNv2f0zjT/ntErxvQay1fE/OddA29m2jVA56C18LIXEmM8+MV7/7N3wdBB6ALB2KTmKwRDR6ErBENnoSsEQ4ehKwSLNcHQcegKwdB56ArB0OHpCsHWkhY2svkCwdjM5isEW0ta2NTmKwRbS1rY3OYrBFtLWtjk5isEW0ta2OzmKwRbS1rY9OYrBFtLWtj85isEW0ta2ATnKwRbS1rYDOcrBFtLWtgU5ysEW0ta2BznKwRbS1rYJOcrBFtLWtgs5ysEW0ta2DTnKwRbS1rYPOcrBFtLWthE5ysEW0ta2EznKwRbS1rYVOcrBFtLWthc5ysEW0ta2GTnKwRbS1rYbOcrBFtLWth05ysEW0ta2HznKwRbS1rYhOcrBFtLWtiM5ysEW0ta2JTnKwRbS1rYnOcrBFtLWtik5ysEW0ta2KznKwRbS1rYtOcrBFtLWti85ysEW0ta2MTnKwRbS1rYzOcrBFtLWtjU5ysEW0ta3VrS6saSVsAme18h2FjSWn+KNcFTtaUsD3p7lneCp2pLJwRj45C/LTg/+KK51DeCpzq0zgie6tA6I3iq8fCMYLEmeKrx8IzgqfpwCeX3p0uKbwRP1YfPCJ5qPDwjeKrx8ITguXDLZwRPlbTOCJ4qaZ0RPFXSOiNYrAmeKmmdEWwtac2FWz4jmDhp7SKI09MmAh2LHEvdRbTl4FfvxO1UdCyyvmDwRPQ9wTFuhUh+Ixg8EekLFmuCwRORvmDwRKQvGDwR6QsGT0TfFJzzo5Aa3ggGT0/qgtGxyPqCp0paZwTPlbROCJ4raZ0QLNYEz5W0TggGT1oppKdC0oHgdRZ63ItZQ/NTJevtgF0yeNa6QjJ42rpCMnjeukAyOh75CsngmesKyeCp6wrJ4LnrCsliTzJ49rpCsr30hQ5LvkKyvfSFDky+QDI6MvkKyfbSFzo2+QrJ9tIXOjr5Csn20hc6PvkKyfbSFzpC+QrJ9tIXOkb5Csn20hc6SvkKyfbSFzpO+QrJ9tIXOlL5Csn20hc6VvkKyfbSFzpa+QrJ9tIXOl75Csn20hc6YvkKyfbSFzpm+QrJ9tIXOmr5Csn20hc6bvkKyfbSFzqQ93uSe31g4nr982fvgqfqymcET3Va9/ZATPX+BjGFjmvVFhzRca36gqc6p88InmpGPiN4qgn5jOC5+vAJwXP14ROCp5qNzwieajI+I9hY0oqLtaSFzpj+JHgXQZyedhHgiUiK7IXUevCrdwwgiugsaH3BYk0weCL6nuBjWktEZ0HrCwZPRPqCwRORvmDwRKQuGJ0FrS8YPD3pC54qaR3DSyI6C1pfsFgTPFfSOiF4rqR1QvBcSeuE4LmS1gnBTEmryeu7GOjc6HMimBLRWxHgKSfH/aZYTuXv321A5zvrC5aZBJ8I7uh8Z33B4ClHXzB4ytEXDJ5y9AWDpxx1weh8528KPs6x6HxnfcFTJa0zgqdKWmcEizXBcyWtE4LnSlonBDMlLXnzzAQ6r/mcCKZE9E4EOlM5t7wVUvrRg1Mty/L44TmXp0rKk2T0nHOBZPSkc4Fk9KxzgWSxJxk971wgGT3xXCAZPfNcIBk9IV0gGT1P6UtGZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+kJnKl8h2V76QmcqXyHZXvpCZypfIdle+ur20le3l77QydlXSLaXvrq99NXtpS90RvoVks2lr4TOSb9Csrn0ldBZ6VdINpe+0iL2JJtLXwmdmX6FZHPpK6Fz06+QbC99obPTr5BsL32hc9mvkGwvfaGz2a+QbC99ofPZr5BsL32hM9qvkGwvfaFz2q+QbC99obPar5BsL32h89qvkGwvfaEz26+QbC99oXPbr5BsL32hc96vkGwvfcEz5C+QbC99wXPkL5BsL33Bs+QvkGwvfcHz5C+QbC99wTPlL5BsL33Bc+UvkGwvfcGz5S+QbC99wfPlL5BsL33B8+gvkGwvfdlj3Sd7rPtkj3Wf7LHukz3WfbLHuk/2WPfJHus+2WPdJ3us+2SPdZ/sse6TPdZ9sse6T/ZY98ke6z7ZY90ne6z7ZI91n+yx7pM91n2yx7pP9lj3yR7rPtlj3Sd7rPtkj3Wf7LHukz3WfbLHuk/2WPfJHus+2WPdJ3us+2SPdZ/sse6TPdZ9sse6T/ZY98ke6z7ZY90ne6z7ZI91n+yx7pM91n2yx7pP9lj3yR7rPtlj3Sd7rHuxx7oXe6x7sce6F3use1nEnmRz6Uvsse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rXuyx7sUe617sse7FHute7LHuxR7rPttj3Wd7rPtsj3Wf7bHu8yL2JJtLX9ke6z7bY91ne6z7bI91n+2x7rM91n22x7rP9lj32R7rPttj3Wd7rPtsj3Wf7bHusz3WfbbHus/2WPfZHus+22PdZ3us+2yPdZ/tse6zPdZ9nouC3mv8/ele//zZu+CpuvIZwVOd1r21h+Be3wie6qw+I3iqk/qM4KnO6TOCp5qRzwieakI+IXguHvYZwXP14ROCp5qNzwieajI+I1isCbaWtJgZ2LsI4vS0iwBPRDUtWyFNjn71foFrf3/8Fzju9aiOzqm+QDI6p/oKyeC56ArJ4MnoCsng2egKyWJPMng+ukIyeEK6QjJ4nrpCsr30hc6pvkAyOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyfbSFzqn+grJ9tIXOqf6Csn20hc6p/oKyebSV0HnVF8h2Vz6Kuic6iskm0tfZRF7ks2lr4LOqb5Csrn0VdA51VdItpe+0DnVV0i2l77QOdVXSLaXvtA51VdItpe+0DnVV0i2l77QOdVXSLaXvtA51VdItpe+0DnVV0i2l77QOdVXSLaXvtA51VdItpe+or30Fe2lL3Qa+RWS7aWvZC99JXvpC51K/j3Jx6D9gk4lVxeMzqz+puBD/GtBZ1brC57qpD4jeKpz+oxgsSZ4qgn5jOC5+vAJwXP14ROCp5qNzwieajI+IXguDvYZwdaSFjMDexdBnJ52EYItorW4FdJrP/jVC6lvmlPvr0d1dE71FZLBU9EVksFz0RWSwZPRFZLBs9EFktE51VdIBs9HV0gGT0hXSAbPU1dIFnuS7aUvdE71FZLtpS90TvUVku2lL3RO9RWS7aUvdE71FZLtpS90TvUVku2lL3RO9RWS7aUvdE71FZLtpS90TvUVku2lL3RO9RWS7aUvdE71FZLtpS90TvUVku2lL3RO9RWS7aUvdE71FZLtpS90TvUVku2lL3RO9RWS7aUvdE71FZLtpS90TvUVks2lr4rOqb5Csrn0VdE51VdINpe+6iL2JJtLXxWdU32FZHPpq6Jzqq+QbC99oXOqr5BsL32hc6qvkGwvfaFzqq+QbC99oXOqr5BsL32hc6qvkGwvfaFzqq+QbC99oXOqr5BsL32hE4y/J/kYHFjR+cXqgtG5tt8UfIizqehUW33BU53UZwRPdU6fESzWBE81IZ8RPFcfPiF4rj58QvBUs/EZwVNNxicEozOp9QVbS1roTOpPgncRxOlpFyHQIsISNhFhyeHgVy9vknNr+8+O4UkwdiK6QDB2Ivqm4Nr69rPjwc9+X8duDnZ6utkc7KR1sznYqexec8BZ1zebg532bjYHOxnebA524rzZHHFz3pszVerVNscT8gdzPCF/MMcT8gdzPCG/Nwecd36zOZ6QP5jjCfmDOZ6QP5gjbs57czwhfzDHE/IHczwhfzDHE/IHczwhvzcHnEl/szmekD+Y4wn5gzmekD+YI27Oe3M8IX8wxxPyB3M8IX8wxxPyB3M8Ib83B/y9ATeb4wn5gzmekD+Y4wn5gzni5rw3xxPyB3M8IX8wxxPyB3M8IX8wxxPye3PA3+1wszmekD+Y4wn5gzmekD+YI27Oe3M8IX8wxxPyB3M8IX8wxxPyB3M8Ib81p4G/f+NmczwhfzDHE/IHczwhfzBH3Jz35nhC/mCOJ+QP5nhC/mCOJ+QP5nhCfm8O+DtSbjbHE/IHczwhfzDHE/IHc8TNeW+OJ+QP5nhC/mCOJ+QP5nhC/mCOJ+T35oC/x+ZmczwhfzDHE/IHczwhfzBH3Jz35nhC/mCOJ+QP5nhC/mCOJ+QP5nhCfm8O+LvDbjbHE/IHczwhfzDHE/IHc8TNeW+OJ+QP5nhC/mCOJ+QP5nhC/mCOJ+T35oC/8+1mczwhfzDHE/IHczwhfzBH3Jz35nhC/mCOJ+QP5nhC/mCOJ+QP5nhCfm+Ov1PvkzmekD+Y4wn5gzmekD+YI27Oe3M8IX8wxxPyB3M8IX8wxxPye3Psvvwry/ame3lnjtlWfsYcswdyzu1hTqlvzDF7IJ8xx+yBfMYcs7csTphj9xVOZ8wxe8vijDlmc04J5fdnS4pvzDGbc86YI27Oe3PM3rI4Y47ZhHzGHLMJ+Yw5ZhPyGXPMJuQT5th9hdMZc8wm5DPmeEL+YI4n5A/miJvz3hxPyB/M8YT8wRxPyB/M8YT8wRxPyO/NmewVTt/52aU87pOu/7Pvn07tyZ65MrK6PXOlZHV75srJ6vaI2/PJnrmy8nd+dl0ejSvU+qc9L/7e1banM1rbPxvDk5VzJetbrZwrh99q5Vyp/VYr58r4N1rZJ3tl1a1W2p0e1K20O2moW2l3KlG3UtxKLSt92lGz0qcdNSt92lGz0qcdNSt92tGycrLXj91qpU87alb6tKNmpU87alaKW6llpU87alb6tKNmpefKc1bmxzM4uYbXVk720q5brfQOrvUPfLLXOt1qpXdwNSu9g6tZ6fcr1az0+5UvrNzt8az4yZ7JXkmlbo/he4V9e/SzpXf2GL7/d8YewxPBGXvE7flkj+HkfsYew2n8jD12E3bbQnPo0v6w50cJe7LXWd1qpd00rm3lZK/KutVKuylf3Uq7E4G6lXanB3Urxa3UstLuVKJupd0JRt1Kn3bUrPRpR81Kn3a0rJzstWe3WunTjpqVPu2oWenTjpqV4lZqWenTjpqVPu2oWenTjpqVPu2oWenTjpaVxacdNSt92lGz0qcdNSt92lGzUtxKLSt92lGz0qcdLSsne33kdVYeryhO9rLJW630tqP2D9zbjpqV3nbUrPSbbGpW+k02NSv9JtsLKzd7JnuRoro9nv8+2mP3Blcvjw/HVe4be+zetDplj7g9n+yxm/JP2WM3uZ+yx24aP2WP2YS9Vhc2e7r8Yc+LhF1kS9hPn136k5VmE7a6lXZf2qhvpdnkrm+l2ZSvb6XZiUDfSnErtaw0O2noW2l2KtG30uwEo2+lTztqVvq0o2NlXuy+kFLfSp921Kz0aUfNSp921KwUt1LLSp921Kz0aUfNSp921Kz0aUfNSp92tKy0+0JKfSt92lGz0qcdNSt92lGzUtxKLSt92lGz0qcdNSt92lGz0qcdNSt92tGy0u5rUvWt9GlHzUqfdtSs9GlHzUpxK7Ws9GlHzUqfdtSs9GlHzUqfdtSs9GlHy0q7LwXWt9KnHTUrfdpRs9KnHTUrPQyds/IIqbZa6WFIy0q7b7T8ppVHxKXVSm87alZ621GzUtxKLSv9JpualX6T7YWVuz2eFT/a4/nvoz12b3CFsFUd5I09dt8Qec4euxPBKXvspvxT9thN7qfsEbfnkz12E3Zoeata+h/2/Oh2o923KOpbaTeNq1tpN7mrW2k45StbafctivpWGp4etK00PGloW2l4KtG2UtxKLSt92lGz0qcdNSt92lGz0qcdNSt92tGy0u5rUvWt9GlHzUqfdtSs9GlHzUpxK7Ws9GlHzUqfdtSs9GlHzUqfdtSs9GlHy0q7L/rVt9KnHTUrfdpRs9KnHTUrxa3UstKnHTUrfdpRs9KnHTUrfdpRs9KnHS0rDb9IWd1Kn3bUrPRpR81Kn3bUrBS3UstKn3bUrPRpR81Kn3bUrPRpR81Kn3aUrAyGX6SsbqW4laesPESqBcPvWVW30tvOOSsPiUvB8Bstta00/EZLdSv9JpualX6TTc1Kv8n2wsrdHnF7Ptnj+e+jPXZvcMXSHlWnZXljj92bVqfssTsRnLLHbso/Y4/htzOessduGj9lj92EneJuj5Q39thNzafsEbfnkz12U/Mpe+ym5lP22E3Np+yxm5pTf/zoKNL+sOfFvaG43RtK+Unh0x/KDL89UNtKw28PVLfSbnJXt9Jwyte20vBEoG2luJVaVhqeNL5l5f7UUK1vrDQ8lWhbaXiC0bbSpx01K33a0bJSfNpRs9KnHTUrfdr5rpXvHqE2/NJadSvFrdSy0u60I9uTfjGno8cC22ZIC89vJ8tPVtqddtSttDvtqFtpd9pRt9LutKNtpeGX7KpbaXfa+Z6V8ghDLdc3VtqddtSttDvtqFspbqWWlT7tqFnp046alT7tnLOyPh5laz28sdKnHTUrfdrRstLwC4TVrfRpR81Kn3bUrPRpR81KcSvPWNnDQ2KP5Y2VPu2oWenTjpqVPu2oWenTjpqVPu1oWWn4BcLqVtqddnJZHlWXJRxYGdaushVSnh6LkactR8OvEL7ATLsTzwVmipupZ6bdqed7Zsbw+MtEiK3+YebXT5/A4hl+7fDNxtudqG423u78dbPxdqe1e403/Lrkm433SfAm431qvMl4nzBvMl7c+HuM98n1JuN9cr3JeJ9cbzLeJ9ebjPfJ9R7jDb/6+mbjfXK9yXifXG8y3ifXm4wXN/4e431yvcl4n1xvMt5z/BXGH77zNRp+qfPNxnuqueWoiYu48fcY76nmJuM91dxkvN+Pv8l4vx//t43fzfRsrmem4bfZX2Cm3ws/Z2ZayqOQJO/M9Pvbimb6dKdopriZemb6FKZopk9Wimb6tHTSzPq4uxgkL3+Y+eLTVTbrmzxVIsuT9T4v3Wa9T1d3WR99FrvNep/cbrPe57zbrPep8Dbrxa2/y3qfOG+z3ufT26z3afY2632avc16n2bvsj75NHub9T7N3ma9T7O3We/T7G3Wi1t/l/U+zd5mvU+zt1nv0+xt1vs0e5v1Ps3eZb34NHub9T7N3ma9T7O3We/T7G3Wi1t/l/U+zd5mvU+zt1nv0+xt1vs0e5v1Ps3eZX32afY2632avc16n2Zvs96n2dusF7f+Lus9XF5g/QmYWfZoeY/xxVvsFcYfE4aKN9ibjPf2epPxfqv4JuP9RvFNxvtt4r9t/G6mZ3NFMz1vnzMzh4fGkGs7OhLidiSk/ORH342vfiP3JuP9Nu5NxvuEeZPxPmHeZLy48fcY7xPmTcb7hHmF8UW227f1jfE+Yd5kvE+jNxnvk+s9xjefXG8y3ifXm4z3yfUm431yvdb4Jm+MFzf+HuN9cr3JeJ9czxlfdkfKUx1vHrbLsr18J+dnXP/Tw3bNZ9fbrPfp9TbrfX69y/ruE+xt1vsMe5v1PsVeYv32bPUaROMb632Ovc16cevvst5n2dus92n2Nut9mr3Nep9mr7Be+rJZ3/4Mlz+61dZ98iW4TGnxKZniMvlEfcVlKnX/9LP1T/0mLT5R32a9T9S3WS9u/V3W+0R9m/U+Ud9mvU/Ut1nvE/Ul1rcNQVR6f2O9T8l3WR988r3Nep9mb7Pep9nbrPdp9jbrxa2/y3qfZi+xPjwKCTX8met/dIM5+ORLcZl8Sqa4TD5RX3GZ2rL9Ve2PSv7oNz5R32V99In6Nut9or7Nep+ob7PeJ+rbrBe3/i7rfaK+xPqQN+tje2O9T8m3We+T723W+zR7m/U+zd5lffJp9jbrfZq9zXqfZq+w/sPryH50gzn55EtxmcQvE8NlsjtRl7RVvf41//AyhW0/szw7Ul//CjzaTXx+H1157jZ25+mbjbc7Td9svN1Z+mbj7U7SasZvZord2fgCM+1OuxeYaXd+vcBMu1PmBWaKm6lnpk9simb6FKZopk9WJ83sWyF1yX+Y+aKO3H5/uPanmzjxyXcfrO7x3eeqC3yPcfvRkl8PtNlnsJuM93ntJuN9trvJeJ8DbzJe3Ph7jPf58grjj2/TZ59FbzLe59ZzxtfYNuMl/O35Kfvceo/vPrde4PuJ1lp8br3JeJ9bbzLe59abjPe59SbjxY2/x3ifW68w/nh8Kj633mS8z60njS/bH69rO3qg8nh+Kj633uO7z60X+H6itVafW28y3ufWm4z3ufUm431uvcl4cePvMd7n1iuMPx6fqs+tNxnvc+s549uysXlbXP72/FR9br3Hd59bL/D9RGttPrfeZLzPrTcZ73PrTcb73HqT8eLG32O8z61XGH88PjWfW28y3ufWHxhf/zB+N9OHUUUzfcLUM7P71HjSzCqbma3+69+9TdJ9aLzHd58ZL/D9RILuPjPeZLy48fcY7zPjTcb7zHiT8T4z3mS8z5dXGH98l6T7LHqL8bL43HrS+Bx249uB8T09Hn7p5ek97+1Hs5YsPuPiXyOfh/GvkY/O+NdI/BrBXyMfyPGvkc/u+NfIx3z8a+R3BPCvkd88gL9Gwe8z4F8jv89w7hp12Qrp+W8j4SX4vYN7fPf7ARf4fvxnFgnixt9jvE/uNxnv4/hNxvuMfZPxPjjfZLxPw1cYf/yn9Ogj7k3G+9x6k/E+uN5kvE+uJ41vy+PTy+E236dP79aLW3+X9T69XmB9bX2rIx7U8b7m/SL5pEtwkXwqJrhIPkETXCSftvEvUvLJnOAi+RRPcJF84ie4SH53gOAiiV8k/IvkdxwILpLfcSC4SH7HgeAi+R0HgovkdxzwL5L4HQeCi+R3HAgukt9xILhIfseB4CKJXyT8i+R3HAgukt9xILhIfseB4CL5HQeCi+R3HPAvUvY7DgQXye84EFwkv+NAcJH8jgPBRfI56eaLlLfFo/UPR28uks9J+BepeLq7+yJtOJlc6puL5OmO4CJ5uiO4SJ7uCC6S+EXCv0j+9ySCi+Rz0s0XqYTy+7MlxTcXyeckgovkf08iuEj+9yT8i1T9jgPBRfI7DgQXye84EFwkv+NAcJHELxL+RfI7DgQXye84EFwkv+NAcJH8jgPBRfI7DldcpG/UsRNw/wDglrJfpOZ3HAgukt9xILhIfseB4CL5HQeCiyR+kfAvkt9xILhIfsfh7ouUH5/tdXlzkfyOA8FF8jsOBBfJ7zjgX6TudxwILpLfcSC4SH7HgeAi+R2HoRdpN17c+HuM9zsDNxnv0/5NxvsEf5PxPpXfZLxP2rcYnxcj0/Mu2Mgkugs2MtXtgo1MSLtgsSbYyESwCzaSxHfB6Al4+3RY/79+IDjkRyEhyxvB6MlTXTB64vuWYF3mWg7oqexWc9AT3K3moKe9W81BT4a3miNuzntz0BPnreagp9NbzZkqyWqbM1Xq1TbHE/J7c6In5A/meEL+YI4n5A/meEL+YI64Oe/N8YT8wRxPyB/M8YT8wRxPyB/M8YT83pzkCfmDOZ6QP5jjCfmDOZ6QP5gjbs57czwhfzDHE/IHczwhfzDHE/IHczwhvzdHPCF/MMcT8gdzPCF/MMcT8gdzxM15b44n5A/meEL+YI4n5A/meEL+YI4n5PfmZE/IH8zxhPzBHE/IH8zxhPzBHHFz3pvjCfmDOZ6QP5jjCfmDOZ6QP5jjCfm9OcUT8gdzPCF/MMcT8gdzPCF/MEfcnPfmeEL+YI7ZnJM3uP3696k35pjNOSfMgX//7XXm5PYwp9Q35pjtVmfMMdutzphjtludMcfs/Zwz5pi9n3PGHLM55/g9mhn+PZp3mgP//spbzTF7P+eMOWYT8hlzzCbkM+aIm/PeHLMJ+Yw5ZhPyGXPMJuQz5nhC/mCOJ+T35sC/b+1WczwhfzDHE/IHczwhfzBH3Jz35nhC/mDOXAn5Oz875w3Kv/6dYf+0vNSY80NiDW+snCtP32rlXOn7Vivnyuo3Wlng3wV1i5W7PXNle3V75kr36vbMle/V7RG355M9c2V8dXs85X+0x5P7R3vspvESH9N2KE8aX0fI43G7TPZWrzutnOwdYJdZGeMmUfIbK+0md3Ur7aZ8dSvtTgTqVopbqWWl3UlD3Uq7U4m6lXYnmO9ZeXyXd7J3rt1qpeFpp+TNytr+/rQz2fvcbrXS8LTzHStPtJ3J3hV3q5WGpx1tK8Wt1LLS8LSjbaXhaUfbSsPTjraVhqedb1l5PO1M9ra9O62c7N18t1rp046alXannbo8xupQ83JgZcgPiSHLGyvtTjvqVopbecZKXVRcmexthTS2252ibrXd7sR1q+12p7Nbbbc7yd1p+2Tvm6Sx3e6EeKvtPk3eYrtPnrfYLm77Hbb7lHqL7T6l3mK7T6m32O5T6i22+5R6h+2TvfOVxnafUm+x3afUW2z3KfUW28Vtv8N2n1Jvsd2n1Fts9yn1Ftt9Sr3Fdp9S77B9svcu09juU+ottvuUeovtPqXeYru47XfY7lPqLbb7lHqL7T6l3mK7T6m32O5T6h22V59Sb7Hdp9RbbPcp9RbbfUq9xXZx2++w3afUW2z3KfUW231KvcV2n1Jvsd2n1Dtsbz6l3mK7T6m32O5T6i22e25Xtz3L4+VWWd7Z7rn9Fts9yejbntvD9lJf2949ydxiuyeZW2z3JHOL7X6//RbbxW2/w3bP7eq2n3iJS/fcfovtfr/9Ftv9fvsttvuUeoPtdfEp9RbbfUq9xXafUm+x3afUW2wXt/0O231KvcV2n1Jvsd2n1Fts9yn1Ftt9Sr3D9uBT6i22+5R6i+0+pd5iu0+p52z/xk+OMS27H/unQ5dv/eT9IolfJPyL5BMwwUXyeZngIvl0PfQi7cb7fH2T8T5h32N89Bn7JuN9yr7JeJ+zbzLeJ+2bjBc3/h7jfSK+yXifcm8y3ifXC4xvm/EplD+Mf1GHNHnUkdPTp0t6ukw+51JcJp+Kb75MugiCmnzanuyC+hQ/2QX1uwOTXVC/6zDZBRW/oHNdUL9LMtkF9bsvk11Qv6sz2QX1+z+TXVC/UzTXBRW/UzTZBfU7RZNdUL9TNNkF9TtFk11Q8Qs61wX1O0WTXVC/UzTZBfU7RZNdUL9TNNkF9TtFc13Q7HeKJrugfqdosgvqd4omu6B+p2iyCyp+Qee6oH6naLIL6neKJrugfqdorgtafA4luqDHb5CsxefQyS6o+AUluqCHb0arxVPuZBfUU+5kF9RT7mQX1P8eOtkF9b+HznVBq8+hRBf0BKG9+hw62QX1v4dOdkH976GTXVDxCzrXBfU7RZNdUL9TNNkF9TtFk11Qv1M02QX1O0VzXdDmd4omu6B+p2iyC+p3iia7oH6n6O4L+p2aZXM65OUNpLyJX9LZLqnfLZrukvr9oukuqd8xmu6S+j2j6S6p3zWa7ZJ2v2/EekmfPv3nJfU7R9NdUr93NN0l9btHTJc0h7xd0tjeXFLxSzrbJfW7R9NdUr97NN0l9btH011Sv3s03SX1u0eTXdK2+N0j1kua8ptL6nePprukfvdoukvqd49gL+l+kcQvEv5F8js8+hcphbZdpCwHFylIk/3AK28OPL9rQ3GZ/E7MzZdJl4TZFr8PM9kF9bswc13Q4PdgJrugfgdmsgvq918mu6B+92WyCyp+Qee6oH5XZ7IL6vd/Jrugfqdosgvqd4omu6B+p2iuCxr9TtFkF9TvFE12Qf1O0WQX1O8UTXZBxS/oXBfU7xRNdkH9TtFkF9TvFE12Qf1O0WQX1O8UzXVBk98pmuyC+p2iyS6o3yma7IL6naLJLqj4BZ3rgvqdoskuqM+hRBc0S/z92SzvLqjPoXNdUPGUy3RBD19o3sRT7mQXVPyCznVBPeVOdkH976GTXVD/e+hkF9TnUKILevxmwCY+h851QbP/PXSyC+p/D53sgvqdoskuqN8pmuyCil/QuS6o3yma7IL6naLJLqjfKZrsgvqdoskuqN8pmuuCFr9TNNkF9TtFd1/Q79R84p3Xrfi9oukuqd8tmu6Sil/S2S6p3zGa7pL6PaPpLqnfNZrukvp9I9ZL+vTpPy+p3zma7ZJWv3c03SX1u0dMl/TMO6+r3z2a7pL63aPpLqn4JZ3tkvrdo+kuqd89mu6S+t2j6S6p3z1ivaQpv7mkfvdotkva/O7RdJfU7x7BXtL9Ivn9IIKL5Hd4LrhIuWwXqZeDi9Tj47HMXsOTvvJ0kcQvEv5F8rswN18kZQpm83swk11QvwMz2QX1+y+TXVC/+zLXBe1+72WyC+p3Xia7oH6XZrIL6nd0Jrug4hd0rgvqd4omu6B+p2iyC+p3iia7oH6naLIL6neKprqgffE7RZNdUL9TNNkF9TtFk11Qv1M02QUVv6BzXVC/UzTZBfU7RZNdUL9TNNkF9TtFk11Qv1M01wUNfqdosgvqd4omu6B+p2iyC+p3iia7oD6HEl3QLPH3Z7O8u6A+h851QaOnXKYLevgy8x495U52QT3lTnZBPeVOdkHFL+hcF9T/HjrZBfU5lOiCHr8VsEefQye7oP730MkuqP89dK4LmvxO0WQX1O8UTXZB/U7RZBfU7xRNdkHFL+hcF9TvFE12Qf1O0WQX1O8UTXZB/U7R3Rf0Gz+5b4+g9Pz8loXydEH9TtFcF1T8TtFkF9TvFE12Qf1O0WQX1O8UTXZBxS/oXBfU7xQxXdD8+Gyvy5sL6neKJrugfqdosgvqd4omu6B+p2iuC5r9TtFkF9TvFE12Qf1OEewF3S+S3/0huEjiF0n/IvXtPdUSwsFFirGk/dPxj0/vl8nv01BcJr/7cvtl2q9SfnPk+R0Vgovkd0kILpLf+cC/SMXvZhBcJL9DQXCR/K7D3Rcp58eHa3hzkfyuA8FFEr9I+BfJ7zkQXCS/40BwkfyOA8FF8jsOBBfJ7zjgX6TqdxwILpLfcSC4SH7HgeAi+R0HgoskfpH+3kXarfT7AmpW+vSuZqXP2GpW+iSsZqXPq1pWNp8q1az02U/NSp/Q1Kz0OUrNSnErtaz0aUfNSp92Xli522N4gqlxs6fVg9+0tRLZCkny5nfN8Ayjb6bhKUbdzG54jtE30/Ako2+m4VlG30zD04y+meJm6plpeKLRN9PwTKNvpk9Aimb6BKRopk9AWmaWZfEJSNFMn4AUzfQJSNFMn4AUzRQ3U89Mn4AUzfQJSNFMn4AUzfQJSNFMn4D0zAw+ASma6ROQopk+ASma6ROQopniZuqZ6ROQopk+ASma6ROQopk+ASma6ROQnpnRJyBFM30CUjTTJyBFM30CUjRT3Ew9M30CUjTTJyBFM30CUjTTJyBFM30C0jMz+QSkaKZPQIpm+gSkaKZPQIpmipupZ6ZPQIpm+gSkaKZPQIpm+gSkaKZPQHpmik9Aimb6BKRopk9Aimb6BKRopriZemb6BKRopk9Aimb6BKRopk9Aimb6BKRnZvYJSNFMn4AUzfQJSNFMn4AUzRQ3U89Mn4AUzfQJSNFMn4AUzfQJSNFMn4D0zCw+ASma6ROQopk+ASma6ROQopniZuqZ6ROQopk+ASma6ROQopk+ASma6ROQnpnVJyBFM30CUjTTJyBFM30CUjRT3Ew9M30CUjTTJyBFM30CUjTTJyBFM30C0jOz+QSkaKZPQIpm+gSkaKZPQIpmipupZ6ZPQIpm+gSkaKZPQIpm+gSkaKZPQHpmdp+AFM30CUjRTJ+AFM30CUjRTHEz9cz0CUjRTJ+AFM30CUjRTJ+AFM30CUjNzNU1N1PPTJ+AFM30CUjRTJ+AFM0UN1PPTJ+AFM30CUjRTJ+AFM30CUjRTJ+A9MwMPgEpmukTkKKZPgEpmukTkKKZ4mbqmekTkKKZPgEpmukTkKKZPgEpmukTkJ6Z0ScgRTN9AlI00ycgRTN9AlI0U9xMPTN9AlI00ycgRTN9AlI00ycgRTN9AtIzM/kEpGimT0CKZvoEpGimT0CKZoqbqWemT0CKZvoEpGimT0CKZvoEpGimT0B6ZopPQIpm+gSkaKaRCWgXbGRK2QWLNcFG0v4u2Egi3wUbSc27YCPJdhdsJH1ugrORhLgLNpLidsHWkpaV98PvgoVX8C6COD3tIogT0S6COOXsIoiTyy6COI1sIpjfSb2LIE4NuwjiJLCLIO7uu4gZOjbzu353ETN0bOZ32+4iZujYzO9y3UQwv0N1FzFDx2Z+Z+guYoaOzfyOzF3EDB2b+Z2Quwjwjr3+sXsXkcsfIn74F1/0NyZeIRk8DVwgGf3tg1dIBk8aV0gGzyVXSAZPMVdIFnuSwRPSFZLB89QVku2lL/S3tV0h2V76Qn/z2RWS7aUv9LeIXSHZXvpCfyPXFZLtpS/0t1tdIdle+kJ/U9QVks2lr4j+1qUrJJtLXxH9DUZXSDaXvuIi9iSbS18R/c06V0g2l74i+ltqrpBsL32hv/HlCsn20hf621OukGwvfaG/ieQKyfbSF/pbPa6QbC99ob8h4wrJ9tIX+tsmrpBsL32hv7nhCsn20hf6WxCukGwvfaG/UeAKyfbSFzqd/wrJ9tIXOun+Csn20hc6Nf4KyfbSFzqB/QrJ9tIXOs38Csn20hc6GfwKyfbSFzpl+wrJ9tIXOrH6Csn20hc6tfoKyfbSFzq5+grJ9tIXOr36Csn20hc6wfoKyfbSFzrF+grJ9tIXOsn6Csn20hc6JfsKyfbSFzqB+wrJ9tIXOt37Csn20hc6OfwKyfbSFzqV/ArJ9tIXOvH8Csn20hc6Tf0KyfbSFzqp/QrJ9tIXOgX+Csn20hc6Yf4KyfbSFzq9/grJ9tKXPdZ9tMe6j/ZY99Ee6z7aY91He6z7aI91H+2x7qM91n20x7qP9lj30R7rPtpj3Ud7rPtoj3Uf7bHuoz3WfbTHuo/2WPfRHus+2mPdR3us+2SPdZ/sse6TPdZ9sse6T4vYk2wufSV7rPtkj3Wf7LHukz3WfbLHuk/2WPfJHus+2WPdJ3us+2SPdZ/sse6TPdZ9sse6T/ZY98ke6z4hse73ooDy0V4UUILZixLEooBSwF4UUJ/eiwLqpHtRQL1uLwqoG21FIdG596IQT3QkwvVeFOKJjkSJ3otCPNGRSMt7UYgnOhKteC8K8URHIv7uRSGe6EjU3L0oxBMdiTy7F4V4oiPRW/eiEE90JALqXhTiiY5EEd2LQjzRkUice1GIJzoSzXIv6uITff+iMuqL6qgvaqO+qA/6oqvpffsXhVFfFEd9URr1RTLqi0adDGXUyVBGnQxl1MlQRp0MddTJUEedDHXUyVBHnQx11MlQR50MddTJUEedDHXUyVBHnQxt1MnQRp0MbdTJ0EadDG3UydBGnQxt1MnQRp0MbdTJ0EadDH3UydBHnQx91MnQR50MfdTJ0EedDH3UydBHnQx91MnQB50MorItGqtsX9T6H1/0s6faRGWj84KyImZZCbMswSwrY5ZVMMuqmGU1zLI6ZFkB85QPmKd8wDzlA+YpHzBP+YB5ygfMUz5gnvIB85QPmKd8xDzlI+YpHzFP+Yh5ykfMUz5invIR85SPmKd8xDzlI+YpnzBP+YR5yifMUz5hnvIJ85RPmKd8wjzlE+YpnzBP+YR5ygvmKS+Yp7xgnvKCecoL5ikvmKe8YJ7ygnnKC+YpL5infMY85TPmKZ8xT/mMecpnzFM+Y57yGfOUz5infMY85TPmKV8wT/mCecoXzFO+YJ7yBfOUL5infME85QvmKV8wT/mCecpXzFO+Yp7yFfOUr5infMU85SvmKV8xT/mKecpXzFO+Yp7yDfOUb5infMM85RvmKd8wT/mGeco3zFO+YZ7yDfOUb5infMc85TvmKd8xT/mOecp3zFO+Y57yHfOU75infMc85TvkKZ8xd18z5u5rxtx9zZi7r3mBPOUz5u5rxtx9zZi7rxlz9zVj7r5mzN3XjLn7mjF3XzPm7mvG3H3NmLuvGXP3NWPuvmbM3deMufuaMXdfM+bua8bcfc2Yu68Zc/c1Y+6+Zszd14y5+5oxd18z5u5rxtx9zZi7rxlz9/X/Z++PslvZkWVLtC+vATUYEY4A0J/bjdf34hl3k+KqsyII7XQk3NzsftSoD6WSNj2PYObSMi8x/+1riflvX0vMf/taYv7b1xLz376WmP/2tcT8t68l5r99LTH/7WuJ+W9fS8x/+3rOrlz+31/9uwvhj/dXb8//9yP57xfCf/W96+N8fetaHj9fbft/+J33o7y+8370j6vm3f72nVt/f+f9y3d+/o/7n699/u/p7wOdXW2tgf63BxrotJoG6jHQQGfpNFCPgQY66aeBegzUNNBcAw10HFgD9RhooMPKGqjHQAMdpdZAPQYa6KC3BuoxUG2KUg20PrQpQhpoe7wG2svFQLUpSjZQbYqSDVSbomQDNQ0UaKD1Z6DnxUC1KUo2UG2Kkg1Um6JkA9WmKNlAtSnKNdBNmyKkgZb2GuhZLwaqTVGygWpTlGyg2hQlG6hpoLkGqk1RsoFqU5RsoNoUJRuoNkXJBqpNUa6B7toUJRuoNkXJBqpNUbKBalOUbKCmgeYaqDZFyQaqTVGygWpTlGyg2hQlG6g2RbkGemhTlGyg2hQlG6g2RckGqk1RsoGaBpproNoUJRuoNkXJBqpNUbKBalOUbKDaFOUaqGlTlGyg2hQlG6g2RckGqk1RsoGaBpproNoUJRuoNkXJBqpNUbKBalOUa6BFOXTCQLf2Hmgxz4F+b7QuyqHJBqocmmygpoHmGqhyaLKBKocmG6hyaLKBKocmG6j+YiHXQE/9xUKygWpTlGyg2hQhDfT7IZ5Tm6JkAzUNNNdAtSlKNlBtipAG+v3Mx6lNUbKBalOUbKDaFOUaaNWmKNlAtSlKNlBtipAG+v2v/qo2RckGahporoFqU5RsoNoUJRuoNkXJBqpNUbKBalOUa6BNm6JkA9WmKNlAtSlKNlBtipIN1DTQXAPVpijZQLUpSjZQbYqSDVSbomQD1aYo10C7NkXJBqpNUbKBalOUbKDaFCUbqGmguQaqTVGygWpTlGyg2hQlG6g2RckGqk1RqoG2hzZFyQaqTVGygWpTlGyg2hQlG6hpoLkGqk1RsoFqU5RsoNoUJRuoNkXJBqpNUa6BbtoUJRuocqj/QPd3aeZztq7H7L42WrfNNNBcA1UOTTZQ5dBkA1UOTTZQ5dBkA1UOzTXQXTk02UD1FwvJBqq/WEg2UG2Kkg3UNFCggX49xNN2bYqSDVSbomQD1aYo2UC1KUIa6NczH23XpijXQA9tipINVJuiZAPVpijZQLUpSjZQ00CBBvr9r/4ObYqSDVSbomQD1aYo2UC1KUo2UG2Kcg3UtClKNlBtipINVJuiZAPVpijZQE0DzTVQbYqSDVSbomQD1aYo2UC1KUo2UG2Kcg20aFOUbKDaFCUbqDZFyQaqTVGygZoGmmug2hQlG6g2RckGqk1RsoFqU5RsoNoU5RroqU1RsoFqU5RsoNoUJRuoNkXJBmoaaK6BalOUbKDaFCUbqDZFyQaqTVGygWpTlGugVZuiZAPVpijZQLUpSjZQ5dCxgfr2TlelxSXYlemWYFfyWoJd+WgF9qYUswS7ssYS7EoES7DrN7xLsJuwr8CulLoEu1KqP/bvBzWaUuoS7EqpS7Arpa7A3pVS/bF/r5HvSqlLsCulLsGulLoEuwn7CuxKqUuwK6X6Y//+lwNdKXUJdqXUJdiVUhdg7w+l1CXYlVKXYFdKXYJdKXUJdhP2FdiVUpdgV0pdgl0pdQl2pdQl2JVSV2DflFKXYFdKXYJdKXUJdqXUJdhN2FdgV0pdgl0pdQl2pdQl2JVSl2BXSl2BfVdKXYJdKXUJdqXUJdiVUpdgN2FfgV0pdQl2pdQl2JVSl2BXSl2CXSl1BfZDKXUJdqXUJdiVUpdgV0pdgt2EfQX2XL7dteOoH7nctTOcXB7YF47lcqrOcHL5SWc4uVyfM5xc3swZjgnONZxc23hnOLl25s5w5JBv4PA65K81et14HfJ3OIXXIQ/A4XXIA3B4HfLXwqteeB3yABwTnGs4vA55AA6vQx6Aw+uQB+DwOuTvv30ovA75O5yT1yEPwOF1yANweB3yABxehzwAxwTnGg6vQx6Aw+uQB+DwOuQBOHLIN3DkkK/hVDnkGzhyyDdw5JBv4Mgh38AxwbmGI4d8A0cO+QaOHPINHDnkGzhyyNdwmhzyDRw55Bs4csg3cOSQb+CY4FzDkUO+gSOHfANHDvkGjhzyDRw55Gs4yW6dO8ORQ76BI4d8A0cO+QaOCc41HDnkGzhyyDdwovucbX/DeZTtG5xffO/9PN6f+mwff4l8/O07b/39j2z2x/5TOLLVx386pG//YrA+wl/t1ZCeQ4ru+zSk55Ci+08N6Tmk6D5YQ3oOyTSk+EOKngs0pOeQoucTDek5pOi/SdCQnkOK/hsNDek5JG0c4g8p/AXm/EP6VuryHJI2DgBD0sYBYEjaOAAMyTSkxUP6Vt3yHJI2DgBD0sYBYEjaOAAMSRsHgCFp4xB/SOGvaecf0re/FnoOSRsHgCFp4wAwJG0cAIZkGlL8IWnjADAkbRwAhqSNA8CQtHEAGJI2DvGHFP4yuob0HJI2DgBD0sYBYEjaOAAMyTSk+EPSxgFgSNo4AAxJGweAIWnjADAkbRziD8m0cQAYkjYOAEPSxgFgSNo4AAzJNKT4Q9LGAWBI2jgADEkbB4AhaeMAMCRtHOIPqWjjADAkbRwAhqSNA8CQtHEAGJJpSPGHpI0DwJC0cQAYkjYOAEPSxiH+kE7enFTON/bzsX0b0lFf3DcrP0Parf0V/OuLS/34zvv2AZ43+ywGz5tnFoM3gV8Dnjd3LAbPmyVmgu/lny8+H+UCPG8+WAye1/MvBs/7m8O14CvvbwOngt/e4M8L8Equi8AruS4Cr+S6CLwJ/BrwSq6LwCu5zgDf3keCWrsAr+S6CLyS6yLwSq5rwDcl10XglVwXgVdyXQReyXUReBP4NeCVXBeBV3JdBF7JdRF4JddF4JVc14DvSq6LwCu5LgKv5LoIvJLrIvAm8GvAK7kuAq/kugi8kusi8Equi8AruS4B/yQs8GvAK7kuAq/kugi8kusi8Cbwa8AruS4Cr+S6CLyS6yLwSq6LwCu5rgG/KbkuAq/kugi8kusi8Equi8CbwK8BLx8/Bn7f7PVB9la/gf/a0LRt8vGLwMvHrwG/y8cvAi8fvwi8fPwM8F9LJLZdPn4ReBP4NeD1G6hF4PUbqEXglVwXgVdynQH++65mV3JdA/5Qcl0EXsl1EXgl10XglVwXgTeBXwNeyXUReCXXReCVXBeBV3JdBF7JdQ14U3JdBF7JdRF4JddF4JVcF4E3gV8DXsl1EXgl10XglVwXgVdyXQReyXUN+KLkugi8kusi8Equi8AruS4CbwK/BryS6yLwSq6LwCu5LgKv5LoIvJLrGvCnkusi8Equi8AruS4Cr+S6CLwJ/BrwSq6LwCu5LgLP6+O3Vt6f2voX8AN9HJXXmbuj5PXa7ih53bM7Sl4/7I7ShHIIZX998fkoFyh5Pas7Sl4X6o6S9zci7ih5f8fxS5Rfy2Wq0o4Xyqa044ZSaccNpdKOG0qlHTeUJpRDKL/vK5vSjhtKpR03lEo7biiVdtxQKu14oexKO24olXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXacUO4PpR03lEo7biiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7Xig3pR03lEo7biiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7Xih3pR03lEo7biiVdtxQ8vrKx/HS+NyP2TeUX1sK9p3XV7qj5PWV7ih5faU7Sl5f6Y3y4PWVv0P5tfBhP3h9pTtKXl/pjpJ3i+6O0oRyDOW3f1q/H0o7biiVdtxQKu24oVTacUOptOOF0pR2xlB+31ea0o4bSqUdN5RKO24oTSi9UCrtuKFU2nFDqbTjhlJpxw2l0o4XyqK044ZSaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLJfGFdXeUSjtuKJV23FAq7bihNKH0Qqm044ZSaccNpdKOG0qlHTeUSjteKImv1rujVNpxQ6m044ZSaccNpQmlF0qlHTeUSjtuKJV23FAq7Xih5L0PvrU3na1b+4bye0sB731wf5S0vtIfpQmlF0paX+mPktZX/hLl98IH3vvg/ihpfaU/StotujtK3vvgv0X59Z/W894H90eptOOGUmnHDaUJpRdKpR03lEo7Yyi/7yt574P7o1TacUOptOOE8uC9D+6PUmnHDaXSjhtKpR03lCaUXiiVdtxQKu24oVTacUOptOOGUmnHCyXvfXB/lEo7biiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7Xih574P7o1TacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8ULJe7XeH6XSjhtKpR03lEo7bihNKL1Q8vrK+jhf37rW/g3l15aCg/c+uD9KXl/pjZL3Prg/Sl5f6Y6S11f+DuXXfy568N4H90dpQumFkneL7o6Sd4vujlJpxw2l0s4Yyu8ZnPc+uDtK3vvg/iiVdtxQKu24oVTacUNpQumFUmnHDaXSjhtKpR03lEo7biiVdrxQ8t4H90eptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOFkvc+uD9KpR03lEo7biiVdtxQmlB6oVTacUOptOOGUmnHDaXSjhtKpR0vlE1pxw2l0o4bSqUdN5RKO24oTSi9UCrtuKFU2nFDmctXtv7+3vuX713sDcf+/BxvOMkufjvDyeX9nOHkcnPOcHL5M2c4JjjXcHJ5KGc4uVyRM5xcW11nOLn2tM5w5JAv4ViyK9G/gdMeLzi9XMDhdcgDcHgd8gAcXoc8AMdo4dQfOOcFHF6HPACH1yEPwOF1yANweB3yABxeh/wdTrLLwr+BU9oLzlkv4PA65AE4vA55AA6vQx6AY4JzDYfXIQ/A4XXIA3B4HfIAHF6HPACH1yF/h5PsGq0zHDnkGzhyyDdw5JBv4JjgXMORQ76BI4d8A0cO+QaOHPINHDnkazjJLpg6w5FDvoEjh3wDRw75Bo4JzjUcOeQbOHLIN3DkkG/gyCHfwJFDvoaT7BarMxw55Bs4csg3cOSQb+CY4FzDkUO+gSOHfANHDvkGjhzyNZzgdxUf7V3HsT36R3nH3+H0+vrqXi/+9V3w64cTBMf2IxMEG5vg2L5hguDYXuCXgp+f+/H+8r1/+e69vX6m9371Mz22G1iOJ7YfWI4n9s5sNZ7gV+6W40nlJ/3xpHKf/nhSedXf4flNsLv+1D8oTSi9UKby12tREjt3b5TELt8bJXEi8EZJnB6cUQa/MAeFkjiVeKMkTjDeKJV23FCaUHqhVNpxQ6m044ZSaccNpdKOG0qlHS+UwS/MQaFU2nFDqbTjhlJpxw2lCaUXSqUdN5RKO24olXbcUCrtuKFU2vFCGfxKIhRKpR03lEo7biiVdtxQmlB6oVTacUMpMzSE8vtBvBL8IB4USj07Yyi//svY8tCz44ZSz44bSi3Z3FBqyeaGUku2/+OFUr5yCOW5nf987Xnsf0cZ/IwcFEot2dxQasnmhlJpxw2lCaUXSqUdN5RKO24olXbcUCrtuKFU2vFCGfwkIBRKpR03lMxp5zef5Njf3/n4/M6P8wMmc95xh2mC6QeTOfO4w2ROPe4wmXOPO0zm5OMOkzn7/ApmeX+Q49z+DjP4uUcwmMz5xx2mEpAjTCUgR5gmmH4wlYAcYSoB/QuY7QKmEpAjTCUgR5hKQIMw+0+c7BdxMvg5TzCYSkCOMJWAHGEqATnCNMH0g6kE5AhTCej/XP/r2xL84OlyPEopt3iUO+7wFCWJWzzKBrd45PZv8eQ6x/v1pltJdo53QHCuc7wDglN51RHBqdzniOBUfnJEcCqHOCA411nbEcGpXNyI4FS+bEQwm9PKdfJ1RDCb08p1PnVEMJvTynWKdEQwm9PKddZzRDCb08p1InNEMJvTynVuckQwm9PKdbpxRDCb08p1BnFEMJvTynVScEQwm9PKdZ5vRDCb08p16m5EMJvTynU2bkQwm9PKdYJtRDCb08p1zmxEMJvTynUabEQwm9PKdWZrRDCb0+psTquzOa3O5rRyXWH7LvjMdSttRDCZ0zofZE7rzHWzbkSwsQkmc1pnrittI4LJnNaZ6+LZiGA2p5XretiIYDanlesS14hgNqeV66rViGA2p5XrQtSIYDanleva0ohgNqeV63LRiGA2p5XrCtCIYDanleuazohgNqeV6yrNiGA2p5XrusuIYDanletKyohgNqeV69rIiGA2p5XraseIYDanlev6xYhgNqeV64rEiGA2p5XrGsOIYDanleuqwYhgNqeV6zrAiGA2p5WrZX9EMJvTytWEPyKYzWnlaqsfEczmtHI1yo8IZnNabB3xJ1tH/MnWEX+ydcSfbB3xJ1tH/MnWEX+ydcSfbB3xJ1tH/MnWEX/mahD/5Tmq1t+fZP/ytcVen6PYcYGS+aqgM0rmC4S+KHP1qa9FyXzZ0Bkl8xVEZ5TMF8+dUZpQeqFkvnbujJL51rkzSqUdN5RKO2Mo2+sbl14uUCrteKHMddNgLUqlHTeUSjtjKOsPyvMCpdKOG0oTSi+USjtuKJV23FAq7bihVNoZQ1lev3Es58VvHHNd/1iKMtddkbUolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXacUNZct33WolTacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8UKZ677WWpRKO24olXbcUCrtuKE0ofRCqbTjhlJpxw2l0o4bSqUdN5RKO14oc924W4tSaccNpdKOG0qlHTeUJpReKJV23FAq7bihDO4r6/HDpn30A1yU0NUX+F7/3iVQo9/d8xcc3KP5Cw7upPwFB/c7/oItk+Df/fz/3rNZo1/pW40nuHtYjSf4/nM1nuA7zdV4UvlJdzzRbxGuxpPKq84Ldtef+gdlKhe8FmUqf70WpQmlF0pil++NkjgReKMkTg/eKImThjdK4lTijDL6jU8klEo7biiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7Xiij39lFQqm044ZSaccNpdKOG0oTSi+USjtuKJV23FAq7bihVNpxQ6m044Uy+v1uJJRKO24olXbcUCrtuKE0ofRCqbTjhlJpxw2l0o4XyujnfaOg/H4KvUY/74uEUs/OGMrvLQLRD6kiodSz44ZSSzY3lFqyeaGMfkgVCaV85RDKczv/+drz2C9Qyle6odSSzQ2lCaUXSqUdN5RKO24olXbcUCrtuKFU2nFC2aIfUkVCqbTjhlJpxw2l0o4bSiNG+YtPYoe9VkN2lI/d0OP8gMmcd9xhMiced5jMmccdJnPqcYfJnHu8YUY/qooFkzn7/Apme7xhtn4Bkzn9uMNkzj/uME0w/WAqATnCVAJyhKkE5AhTCej3MPt5AVMJyA9m9EOrWDCVgMZg2vaOk7ZfxMnox1axYCoBOcI0wfSDqQTkCFMJyBGmEpAjTCWgQZjleMM89wuYSkB+MHMdG14NUwnIEaYSkCNMJSBHmCaYfjCVgP7PdTFJYz4FPYJHKeUWj3LHLR4liTs8zKegR/DI7d/iSeXfv58Gb7mOMI8INjbBqbzqiOBU7nNEcCo/OSI4lUMcEZzK8w0IznUOd0RwKl82IpjNaeU6ADsi2NgEszmtXCdPRwSzOa1c50NHBLM5rVynOEcEszmtXGctRwSzOa1cJyJHBLM5rVznFkcEszmtXKcLRwSzOa1cZwBHBLM5rVwn9UYEszmtXOfpRgSzOa1cp95GBLM5rcrmtCqb02psTivXJcARwWxOq7E5rWZsgtmcVq7rhiOC2ZxWrkuBI4LZnFauq3sjgtmcVq4LdiOC2ZxWrmtwI4LZnFauy2ojgtmcVq4rZSOCyZxWz3Xxa0QwmdPqua5njQgmc1r9YWyCyZxWz3XRaUQwmdPquS4jjQhmc1q5LgyNCGZzWrku9YwIZnNauS7ejAhmc1q5LseMCGZzWrkusIwIZnNauS6ZjAhmc1q5LoKMCGZzWrkua4wIZnNauS5UjAhmc1q5Lj2MCGZzWrkuJowIZnNauS4PjAhmc1q5GvxHBLM5rVy9+SOC2ZxWrm77EcFsTitX//yIYDanxdYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8T1Xg/jzc/98+d6/fPfa+vuT7F++ttj+z9cWO/6OMlc3+VqUqbzDWpSpXMlalKn8zlqUJpReKFN5tLUoU7m/tShTbfDWoky1G1yLUmnHB2V75LoPMBFle33j0ssFSqUdN5RKO24olXbcUJpQDqGsPyjPC5RKO24olXbcUCrtuKFU2nFDqbTjhTLXjY6JKMvrN47lrBcolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UOa6k7MWpdKOG0qlHTeUSjtuKE0ovVAq7bihVNpxQ6m044ZSaccNpdKOF8pct6rWolTacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8UKZ617cWpRKO24olXbcUCrtuKE0ofRCqbTjhlJpxw2l0o4bSqUdL5TR7+6VVt4f5OzfUPb66hLo9bgQHNz9+QsO7tH8BRub4OB+x19wcFfyO8G/+/n/tWfziSe401iNJ7h7WI0n+P5zMZ7o9wJX40nlJ/3xpHKf/nhSedV5we76U/+gNKH0QpnKX69FSezcvVESu3xvlMSJwBslcXpwRhn9XiYSSuJU4o2SOMF4o1TacUNpQumFUmnHDaXSjhtKpR03lEo7biiVdrxQRr9Zi4RSaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLZfT73UgolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXacUG7Rz/tGQfn9FPoTlFB6odSzM4bya4vAFv2QKhJKPTteKKMfUkVCqSWbG0ot2dxQylcOoTy385+vPY/9AqUJpRdKLdncUGrJ5oZSaccNpdKOG0qlHS+U0Q+pIqFU2nFDqbTjhlJpxw2lCaUXSqUdN5TMaecXn6TZ/loNNTs+dkOP8wMmc95xh8mceNxhMmceb5jRD6piwWTOPe4wmZOPO0zm7PMrmOfjDfPsFzBNMP1gMucfd5hKQI4wlYAcYSoBOcJUAvKDGf3IakiY9byAqQTkCFMJyBGmEtAgzP6Ok+VxESejH1vFgqkE5AhTCcgRphKQI0wlIEeYSkB+MIsS0BjMYm+fWewiTuY6CLwaphKQI0wlIEeYJph+MJWAHGEqATnCVAL6PcxysYJjPhztD1MJyA8m81Hqgf4h5qPUI3iUUm7xKHfc4jHhucOjbHCLR27/Fk8q/97ba5nb+0WlS65TzCOCU/ngAcG5zhqPCE7lPkcEp/KTI4JTOcQRwcYmOJWLGxGcypeNCGZzWrnOwI4IZnNauU6qjghmc1q5zpOOCGZzWrlOfY4IZnNauc5mjghmc1q5TlCOCGZzWrnOOY4IZnNauU4jjghmc1q5zgyOCGZzWrlO9o0IZnNauc7fjQgmc1r7g8xp7Q8yp7U/yJzWnus64ohgYxNM5rT2B5nT2nPdkhwRTOa09lx3GQcE57qeOCKYzWnlukQ4IpjNaeW66jcimM1p5bqQNyKYzWnlujY3IpjNaeW63DYimM1p5bqCNiKYzWnluig2IpjNaeW6zjUimM1p5bpyNSKYzWnluhY1IpjNaeW6ujQimM1p5bpeNCKYzWnlugI0IpjNaeW6pjMimM1p5bpKMyKYzWnluu4yIpjNaeW6kjIimM1p5bo2MiKYzWnlutoxIpjNaeW6fjEimM1p5boiMSKYzWnlusYwIpjNaeW6ajAimM1p5boOMCKYzWnlatkfEczmtHI14Y8IZnNaudrqRwSzOa1cjfIjgtmcFltH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xO1tH/M7WEb+zdcTvbB3xB1tH/MHWEX+wdcQfbB3xx8PYBJM5rYOtI/5g64g/2DriD7aO+IOtI/5g64g/cjWIPz/34/3le//y3Wvr70+yf/naYvs/X1vsuECZ6oVfizKVd1iLMpUrWYsyld9ZizKVk1qKMle7/FqUqdzfWpSpNnhrUabaDa5FaULphVJpZwxle33j0ssFSqUdN5RKO24olXbcUCrtjKGsPyjPv6PMdeFhLUqlHTeUSjtuKJV23FCaUHqhVNoZQ1lev3Es58VvHHNd/1iLUmnHDaXSjhtKpR0vlLmurKxFqbTjhlJpxw2l0o4bShNKL5RKO24olXbcUCrtuKFU2nFDqbTjhTLXpaO1KJV23FAq7bihVNpxQ2lC6YVSaccNpdKOG0qlHTeUSjtuKJV2vFDmuja2FqXSjhtKpR03lEo7bihNKL1QKu24oVTacUOptOOGUmnHDaXSjhfKXBf/1qJU2nFDqbTjhlJpxw1lcF95bMfHB/mGstdXl0Cvx4Xg4O7PX3Bwj+YvOLiTchcc/e6ev+DgruR3gn/383+gZzP6lb7VeIK7h9V4THju8ATfaa7Gk8pP+uNJ5T798aTyqvOC3fWn/kGZygUvRRn92iISSmLn7o2S2OV7oyROBN4oTSi9UBInDW+UxKnEGyVxgvFGqbTjhlJpxwmlRb94ioRSaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLZfSrw0golXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UEa/342E0oRy6N8gfj3va9HP+yKh1LMzhvLrv4y16IdUgVBGP6SKhFJLNjeUWrK5odSSzQ2lCeUIynM7//na89gvUMpXuqHUks0NpZZsbiiVdtxQKu14oYx+SBUJpdKOG0qlHTeUSjtuKE0ovVAq7bihVNpxQ8mcdn7zSfb6JrK3x89X7/sHTOa84w6TOfF4w4x+ThULJnPqcYfJnHvcYTInH3eYJphjMK39wNz+gPm/v7ofL//az49P0f76Kd6/jqvdPr7vx4yYQxXKjJjTGsqMFAPjz0jpMv6MFFrDzyj6sV3N6DkjRez4M1Jyjz8jLQTiz8g0o/Az0p5h7JMcD3t95+Pzq/+AqYWAI0wld0eYitiOMJWF/WBGv5mMBVPp0hGmYuAgzON8w7RyAVN5zRGmCaYfTCUgR5hKQI4wlYAcYSoBOcJUAvo9zE+NnzBzXVFfDVMJyBGmEtD/uWliY77nPoLHhOcOj3LHLR4liVs8yga3eOT2b/Gk8u+9vX7L3ftFuVWuS+ojglP54BHBqbzqiOBU7nNEsLEJTuUQRwSn8nwjglO5uBHBqXzZiGAyp1VyXXEeEUzmtEqui8gjgsmcVnkYm2Ayp1VyXeodEUzmtEquq7cjgtmcVq4LsiOC2ZxWrmusI4LZnFauy6YjgtmcVq4roSOC2ZxWroubI4LZnFau65Ujgtmc1s7mtHY2p5XrbOqIYDantbM5rZ3NaeU6MjsimM1p5TrYOiKYzWnlOn46IpjNaeU6JDoimM1p5TrKOSKYzWnlOnA5IpjNaeU6FjkimM1p5Tq8OCKYzWnlOmI4IpjNaeU6CDgimM1p5TqtNyKYzWnlOlE3IpjNaeU69TYimM1p5TqZNiKYzWnlOuY1IpjNaeU6MzUimM1p5TqANCKYzWnlOs0zIpjNaeU6GjMimM1p5bqSMiKYzWnlujYyIpjNaeW62jEimM1p5bp+MSKYzWnluiIxIpjNaeW6xjAimM1p5bpqMCKYzWnlug4wIpjNaeVq2R8RzOa0cjXhjwhmc1q52upHBLM5rVyN8iOC2ZwWW0d8YeuIL2wd8YWtI76wdcQXto74wtYRX9g64gtbR3xh64g/2Triz1wN4r88R9X6+5PsX7622P7P1xY7LlCmeuHXomS+QOiMkvlaoTNK5suGziiZryA6o2S+eO6LMldv/VqUzNfOnVEy3zp3Rqm044bShHIIZXt94+dG9AKl0o4bSqUdN5RKO24olXbGUNYflOcFSqUdL5S5bkesRam044ZSaccNpdKOG0oTyiGU5fUbx3Je/MYx1/WPtSiVdtxQKu24oVTacUOptOOFMtf9lrUolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UOa6obQWpdKOG0qlHTeUSjtuKE0ovVAq7bihVNpxQ6m044ZSaccNpdKOF8pcd8zWolTacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8UKZ65bgWpRKO24olXbcUAb3ldv580H2ff+CcqBLIPrdPX/BwT2av+DgTspfcHC/4y44+t09f8HBvYO/4OAvvL/g4FtHf8HGJpjNaUW/u/dLwd+rV6Lf3fMXnMtpDQjO5bS+C45+d++Xgr+XL0S/u+cvOJfTGhCcy2kNCDY2wbmc1oDgXE7r+9Yy+t09f8G5nNaA4FxO67vg6Hf3/AXncloDgnM5rQHBuZzWgGBjE5zLaQ0IZnNa0e/u+Qtmc1rR7+55C67R7+75CyZzWvVB5rRq9MuK/oKNTTCZ06rRbwn6CyZzWjX6XT5/wWxOK/qNO3/BbE4r+r04f8FsTiv67TV/wWxOK/odM3/BbE4r+k0wf8FsTiv6fS1/wWxOK/qtKn/BbE4r+t0nf8Gh3+He+8+/4tz27YveXl9/EN/rcaE39DM8QW/oV9hfb+yzLxP0hn6DJ+gN/QT/Uu/v/tV5b6+f5r1f/DSPfRNlOZ3Qj/tyOqF3LsvphF7QLKeTyUX608nkOf3pZHKo83pkrj/0m2TsIyBQJDO56rUkef26N0leb+9N0kTSiSRvZvAmyZsvvEnyZhFvkry5xZukMo4TydinP6BIKuN4kVTG8SKpjONF0kTSiaQyjhdJZRwvkso4XiSVcbxIKuM4kYx98AOKpDKOF0llHC+SyjheJE0knUgq43iRVMbxIqmM40VSGceLpDKOE8nY54OgSCrjeJFUxvEiqYzjRdJE0omkMo4XSWUcL5LKOF4klXG8SCrjOJGMfbgLiqQyjhdJZRwvkso4XiTlgkZIfj/3WmOfqEIiGfsyUhyS3xumYp9cgiKpF8eLpImkE0lt1bxIaqvmRVJ+coTkuZ3/fO157Bck5Se9SGqr5kOyxT4dBkVSGceLpDKOF0llHC+SJpJOJJVxvEgq43iRVMbxIqmM40VSGceJZOyjfVAklXG8SCrjeJFUxvEiaSLpRJI44/zig+zbG+W+HeXnc7T+t68u5fXFdbvgTpyIlnInzk9LuROnraXcibOZE/c3y9iHPsFYEuczd5bECc2dJXFGc2dpYunGUjnNj6Wylx9L5akxlv1t1fdH+4Plv9rbpLpnjMRdecqf+76/eVj5O/dU952RuCunreGuTLeGu/LfGu4m7ku4K1eu4a4MOoH799+HEF8sX8tdeXUNd+XVJdyZb7L/hvt+tLfEZl+4b+X9qYtdcFdeXcNdedWfu2/fUmO+JA8zI9OMws9ImTn+jJSv489IWTz+jJTb489IGT/8jIr2AfFnpN1B/BlpzxB/RtozxJ+RaUbhZ6Q9Q/wZac8Qf0baM8SfkfYM8WekPUP4GZ3aM8SfkfYM8WekPUP8GWnPEH9GphmFn5H2DPFnpD1D/BlpzxB/RtozxJ+R9gzhZ1S1Z4g/I+0Z4s9Ie4b4M9KeIf6MTDMKPyPlo7Uz+n7/vFXlo/AzavJ1i2f09RZxa/J18WckXxd/RqYZhZ+Rfn8Uf0b6/VH8GSkfrZ3RQP9vUz6KPyP9/ij8jLp+fxR/RtozxJ+R9gzxZ6Q9Q/wZmWYUfkbaM8SfkfYM8WekPUP8GWnPEH9G2jNEn1F/aM8Qf0baM8SfkfYM8WekPUP8GZlmFH5G2jNMmNEvvvPWfz5z3z4+88P+5US1lcg2Ue0wsk1UG49sE9V+JO5E31PatCFBmJJ2JAhT0pYEYUrakyBMyTQlgClpV4IwJe0/EKaknQbClLSnQJiSdg+rp1RfqPfHdv4xpb98jq8X1fuuPUW2iWqngTRR3zagvmtXwjx97WCYp2+aPvH0tTNinr52UczT146LefranTFPXzs54ukf2t8xT1+7Pubpa9fHPH3t+pinb5o+8fS162OevnZ9zNPXro95+tr1MU9fuz7i6Zt2fczT166Pefra9TFPX7s+5umbpk88fe36mKevvJ91+t9v0nZT3ieefpHnTzv9r3cLe5HnZ56+afrE05fnZ56+fr/PPH39fp95+sr7Wac/0O1blPeJp3/q9/vM09fv95mnr10f8/S162Oevmn6xNPXro95+tr1MU9fuz7m6WvXxzx97fqIp1+162OevnZ9UNP/zXfe+uszb/vj47d8bfuYv7Z93PPXvo97/qb5U89fOz/u+Wvrxz1/7f2456/NX475/0xU27xkE23a0K2d6P4oj/dEe/ky0YHLeE1bt2wT1R4NaaLO3QhNWzTm6ZumTzx9bdCYp6/9GfP0tT1jnr52Z8zT156NePpdOznm6Wt/xzx97fqYp69dH/P0TdMnnr52fczT166Pefra9TFPX7s+5ulr10c7/f7EpekTT1+7Pubpa9fHPH3t+pinb5o+8fS162OevnZ9zNNX3s86/a/X7vpjU95nnr48f9rpf7t685y+afrE05fnZ56+PD/z9PX7febp6/f7zNNX3s86/a8dyP2xK+8zT1+/32eevn6/zzx97fqYp2+aPvH0tetjnr52fczT166Pefra9TFPX7s+4ukf2vUxT1+7Pqjp/+I7D1y7eM5f2z7u+Wvfxz1/0/yp56+dH/f8tfXjnr/2ftzz1+Yvx/x/JqptXrKJmjZ0iyf6/FH6+s7bUb9MdHuO46VwO+xiptq75ZupdmlIM7X3F9vx+PKdP7+2XUxfmzTm6Zumn3T6z8/8+sZWLqavLRrz9LVDY56+NmjM09f+jHn62rURT79oL5d2+qW8vnHdLqavDR7z9LXrY56+dn3M0zdNn3j62vUxT1+7Pubpa9eHOv2L39sV7e+yTVQ7uWQTPbVnyzZR7c6yTVT7sGwT1Y4r20RNE002Ue2isk1U+6VsE9XOaPVEf/491nZ++/dYQ//S49TWKN9MtTdKN9OqzVG+mWp3lG+m2h7lm6n2R/lmapppuplqh5Rvptoi5Zup9kj5Zqo9Ur6Zao+UbqZNe6R8M9UeKd9MtUfKN1PtkfLN1DTTdDPVHinfTLVHyjdT7ZHyzVR7pHwz1R4p3Uy79kj5Zqo9Ur6Zao+Ub6baI+WbqWmm6WaqPVK+mWqPlG+m2iPlm6n2SPlmqj1Stpk+KWim6WaqPVK+mWqPlG+m2iPlm6lppulmqj1Svplqj5Rvptoj5Zup9kj5Zqo9UrqZbtoj5Zup9kj5Zqo9Ur6Zao+Ub6ammaabqfZI+WaqPVK+mWqPlG+m2iPlm6n2SOlmumuPlG+m2iPlm6n2SPlmqj1SvpmaZppuptoj5Zup9kj5Zqo9Ur6Zao+Ub6baI6Wb6aE9Ur6Zao+Ub6baI+WbqfZI+WZqmmm6mWqPlG+m2iPlm6n2SPlmqj1Svplqj5RupqY9Ur6Zao+Ub6baI+WbqfZI+WZqmmm6mWqPlG+m2iPlm6n2SPlmqj1Svplqj5RupkV7pHwz1R4p30y1R8o3U+2R8s3UNNN0M9UeKd9MtUfKN1PtkfLNVHukfDPVHindTE/tkfLNVHukfDPVHinfTLVHyjdT00zTzVR7pHwz1R4p30y1R8o3U+2R8s1Ue6R0M63aI+WbqfZI+WaqPVK+mWqPlG+mppmmm6n2SPlmqj1Svplqj5Rvptoj5Zup9kjpZtq0R8o3U+2R8s1Ue6R8M9UeKd9MTTNNN1PtkfLNVHukfDPVHinfTLVHyjdT7ZHSzbRrj5Rvptoj5Zup9kj5Zqo9Ur6ZmmaabqbaI+WbqfZI+WaqPVK+mWqPlG+m2iNlm+n+0B4p30y1R8o3U+2R8s1Ue6R8MzXNNN1MtUfKN1PtkfLNVHukfDPVHinfTLVHSjfTTXukfDPVHinfTLVHyjdT7ZHyzdQ003Qz1R4p30y1R8o3U+2R8s1Ue6R8M9UeKd1Md+2R8s1Ue6R8M9Ue6b850x/u2vWs4W7ivoS7diZruGuvsYa7dg9ruGs/sIa7MvwQ92MvL4nHJ5C/ch9y8IeS9iryysP+5A97feqj2JfvfG7nP197HvvFjJRv489IWTj+jEwzWjqjp2N7fWMrFzNSxo4/I+Xx+DNSdo8/I+X8+DPSTiD8jEzbg/gz0p5h8YzK+xvX7WJG2jPEn5H2DPFnZJpR+BlpzxB/RtozxJ+R9gxTZ3RecdfuYA137QOWcC/K+Gu4K7ev4a4sPsa9bW/uvX3hPvQXMUUJexV5E3l38s5/Q1GUm+PPSLl57YwGfh9SlJvjz0gZO/6MlMfDz+hUdo8/I+X8+DPSTmDxjL7/PuTU9iD+jEwzCj8j7Rniz0h7hvgz0p4h/oy0Z4g/I+0Zps7o6vegVbuDNdy1D1jDXRl/DXfl9jXcTdyXcFe+XsNdmXkNd+XgNdyVbddwV14d4m5bf0m041uH4NBfMTYl1lXklVlXkVdqXUVeuXUVeRP5ReSVXVeRV3pdRV75dRV5JdhV5JVhF5HvyrCryCvDriKvDLuKvDLsKvIm8ovIK8OuIq8Mu4q8Muwq8sqwq8grw64hfzyUYVeRV4ZdRV4ZdhV5ZdhV5E3kF5FXhl1FXhl2FXll2FXklWFXkVeGXUR+U4ZdRV4ZdhV5ZdhV5JVhV5E3kV9EXhl2FXll2FXklWFXkVeGXUVeGXYR+V0ZdhV5ZdhV5JVhV5FXhl1F3kR+EXll2FXklWFXkVeGXUVeGXYVeWXYReQPZdhV5JVhV5FXhl1FXhl2FXkT+UXklWFXkVeGXUVeGXYVeWXYVeSVYReRN2XYVeSVYVeRV4ZdRV4ZdhV5E/lF5JVhV5FXhl1FXhl2FXll2FXklWEXkS/KsKvIK8OuIq8Mu4q8Muwq8ibyi8grw64irwy7irwy7CryyrCryCvDLiJ/KsOuIq8Mu4q8Muwq8sqwq8ibyC8irwy7irwy7CryyrCryCvDriKvDLuIfFWGXUVeGXYVeWXYVeSVYVeRN5FfRF4ZdhV5ZdhV5JVhV5FXhl1FXhl2EfmmDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7CLyXRl2FXll2FXklWFXkVeGXUXeRH4ReWXYVeSVYVeRV4ZdRV4ZdhV5Zdg15O2hDLuKvDLsKvLKsKvIK8OuIm8iv4i8Muwq8sqwq8grw64irwy7irwy7CLymzLsKvLKsKvIK8OuIq8Mu4q8ifwi8sqwq8grw64irwy7irwy7CryyrCLyO/KsKvIK8OuIq8Mu4q8Muz//iA/dEx0bugoC97RUV67o6NMdUdHueeOjrLJDZ1D+eGOjjz+HR358Ds68sp3dEx0buhk8sq9tX++uvd6oTeT+x3Rm8nPjujN5FBH9GbynAN6LZOLHNGbyReO6M3k9Eb0ZvJuI3qNTC+ZvzIyf2Vk/srI/JWR+atC5q8Kmb8qZP6qkPmrYmR6yfxVIfNXhcxfFTJ/Vcj81Unmr04yf3WS+auTzF+dRqaXzF+lulA/opfMX6W6xj6il8xfpbo8PqKXzF+lurI9opfMX6W6KD2il8xfpbqePKKXzF+luhQ8opfMX6W6ijuil8xfpboAO6KXzF+lunY6opfMX6W67Dmil8xfpbpiOaKXzF+lutg4opfMX6W6Tjiil8xfpbrEN6KXzF+lujo3opfMX6W6sDail8tflVTXxEb0cvmrkupy1oheLn9VHkaml8tflVQXkUb0cvmrkur6z4heMn+V6tLNiF4yf5XqqsuIXjJ/leqCyYheMn+V6lrHiF4yf5XqMsWIXjJ/leoKw4heMn+V6uLAiF4yf5WquX9EL5m/StWuP6KXzF+lasAf0Uvmr1K11I/oJfNXqZrkR/SS+atUbe8jesn8FVl/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj620+y/vaTrL/9JOtvP8n628+Hkenl8lcnWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e1nqn7v58d+vL9871+++W8+yL4f7S2x2c/naP0//c6P8vrM+6OXD3j2t+/c+vs771++c7H9n68tdlxMP5Mb0fR/Of1U3e+a/m+nn8mpavq/nX4m367p/3b6mVKMpv/b6ZumTzz9TAlX0//t9DP9PkXT/+30M/12SdP/7fS162OevnZ9aaffXt+4fH7fz+mnukOk6f92+tr1MU9fuz7m6WvXl3b69Wf658X0TdMnnr52fczT166Pefra9TFPX7s+5ulr15d2+uX1kct58Te9qW5iavq/nb52fczT166Pefra9TFP3zR94ulr18c8fe36mKev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Z5ihmM5zHXSeK/hljRmK6TzXQee5jM5zBb90MkMxnecKfpVkhmKjU0znuYLfBZmhmM5zBb/hMUMxnecKfm9jhmI6zxX8NsYMxXSeK/gdixmK6TxX8JsTMxTTea7g9yFmKKbzXMFvOcxQTOe5gt9dmKGYznMFv5EwQzGd5wp+z2CGYjrPFfz2wAzFdJ4r+J2AGYrpPFfwTv8Ziuk8V/D+/RmK6TxX8K78GYrpPFfwXvsZiuk8V/AO+hmK6TwXXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDf9L10J90PfQnXQ/9SddDX+l66CtdD32l66GvdD309WF0itk8V6Xroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Pf6HroG10PfaProW90PfTtYXSK2TxXo+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76lqmjvNf99cX1z+/8oTfRazykN9HP6d7a64t7vdKb6Kf0kN5EP6OH9Cb6CT2kN1EmHtGbqbF6SG+m93dEb6b3d0Rvoiw8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zpvhVyim81zO2+FXKKbzXM4b4lcopvNczlviVyim81zOm+JXKKbzXM6b5VcopvNcdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPth76dGProb8rJvNcd8VknuuumMxz3RVnOsVknuuumMxz3RWTea67YjLPdVdM57nYeujviuk8F1sP/V0xnedi66G/K6bzXGw99HfFdJ6LrYf+rpjOc7H10N8V03kuth76u2I6z8XWQ39XTOe52Hro74rpPBdbD/1dMZ3nYuuhvyum81xsPfR3xXSei62H/q6YznOx9dDfFdN5LrYe+rtiOs/F1kN/V0znudh66O+K6TwXWw/9XTGd52Lrob8rpvNcbD30d8V0nouth/6umM5zsfXQ3xXTeS62Hvq7YjrPxdZDf1dM57nYeujviuk8F1sP/V0xnedi66G/K6bzXGw99HfFdJ6LrYf+rpjOc7H10N8V03kuth76u2I6z8XWQ39XTOe52Hro74rpPBdbD/1dMZ3nYuuhvyum81xsPfR3xXSei62H/q6YznOx9dDfFdN5LrYe+rtiOs/F1kN/V0znudh66O+K6TwXWw/9XTGd52Lrob8rpvNcbD30d8V0nouth/6umM1zHXQ99AddD/1B10N/0PXQ3/XQKWbzXAddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH5E6ykc7Hy9uf//kL72RGsqn9AZap0d/vni0d3oDrdJTegOt0VN6A63QU3oDZeIpvYES8ZTeSPvvhN5IbdVTegNl4Sm9gZLwlF4yfxWppXpKL6y/etEA65leNPj2QSU/svaoo3+XzMvjMe6HSu9+73z7IHu9vn2QuV7nDdL2en37IHu9vn2QvV7fPshebybT69sH2ev17Zns9ZL5K+eN0fZ6yfyV87Zoe71k/sp5U7S9XjJ/5bwl2l4vmb9y3hBtr5fMXzlvh7bXy+WvTufN0PZ6ufzV6bwV2l4vl786b5lML5e/Op23Qdvr5fJXp/MmaHu9ZP7KeQu0vV4yf+W8AdpeL5m/ct7+bK+XzF85b36210vmr5y3PtvrJfNXzhuf7fWS+Svnbc/2esn8lfOmZ3u9ZP7KecuzvV4yf+W84dleL5m/ct7ubK+XzF85b3a210vmr5y3OtvrJfNXzhud7fWS+Svnbc72esn8lfMmZ3u9ZP7KeYuzvV4yf+W8wdleL5m/ct7ebK+XzF85b26210vmr5y3NtvrJfNXzhub7fWS+Svnbc32esn8lfOmZnu9ZP6qkPkr5z3c5nqd93Db6yXzV5XMXznvWbfXm8n0kvkr5z3r9nrJ/JXznnV7vWT+ynnPur1eMn/lvGfdXi+Zv3Les26vl8xfOe9kt9dL5q/I+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72RNbfnsj62xNZf3si629Pt0yml8tfJbL+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2JrL89kfW3J7L+9kTW357I+tsTWX97IutvT2T97Ymsvz2R9bcnsv72RNbfnsj62xNZf3si629PZP3tiay/PZH1tyey/vZE1t+eyPrbE1l/eyLrb09k/e2ZrL89k/W3Z7L+9kzW355vmUwvl7/KZP3tmay/PZP1t2ey/vZM1t+eyfrbM1l/eybrb89k/e2ZrL89k/W3Z7L+9kzW357J+tszWX97Jutvz2T97Zmsvz2T9bdnsv72TNbfnsn62zNZf3sm62/PZP3tmay/PZP1t2ey/vZM1t+eyfrbM1l/eybrb89k/e2ZrL89k/W3Z7L+9kzW357J+tszWX97Jutvz2T97Zmsvz2T9bdnsv72TNbfnsn62zNZf3sm62/PkfquRzsfL27pnd5A+9GM3kh9yKP3x4tHe6c30Ho1pTfQejWlN5PpDZQHp/QGyoNTeiPtvzN6I+2/M3oD5cEZvZH6kKf0kvmrSH3IU3ph/dWLhhxAg28f1M7x0NDP9l0uv436eOrjeHnqWl4V+3ZCKxT79kIrFPt2QysU+/ZDCxQ7bzBeodi3J1qh2LcrWqHYty9aoTjTKabzXM7bjFcopvNczhuNVyim81zOW41XKKbzXM6bjVcopvNcztuNVyim81zOG45XKKbzXM5bjlcoZvNcxXnT8QrFbJ6rOG87XqGYzXOVW6ZTzOa5ivPW4xWK2TxXcd58vEIxnedy3n68QjGd53LegLxCMZ3nct6CvEIxnedy3oS8QjGd53LehrxCMZ3nct6IvEIxnedy3oq8QjGd53LejLxCMZ3nct6OvEIxnedy3pC8QjGd53LekrxCMZ3nct6UvEIxnedy3pa8QjGd53LemLxCMZ3nct6avEIxnedy3py8QjGd53LenrxCMZ3nct6gvEIxnedy3qK8QjGd53LepLxCMZ3nct6mvEIxnedy3qi8QjGd5yqZTjGd5yp0nst5V/gKxXSeq9B5rkrnuZx3wq9QTOe5nPfCr1Cc6RTTeS7n7fArFNN5LucN8SsU03ku5y3xKxTTeS7nTfErFNN5LufN8isU03kuuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dBXuh76StdDX+l66CtdD329ZTrFbJ6r0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10NfI3WU31/9eHH7+ye/6A20G8/ojdRdPXp/vHi0d3oDrdJTegOt0VN6A63QU3oDZeIpvYES8ZTeSPvvjN5I+++M3kBZeEZvpKbqKb1k/ipSS/WUXlh/9aIhB9Dg2wf10p6/SqV+l8zz+UzmOZWvV7fxqti3E1qh2LcXWqHYtxtaodi3H1qg2HmP9ArFvj3RCsW+XdEKxb590QrFmU4xnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGd53LeI71CMZ3nct4jvUIxnedy3iO9QjGb52rOe6RXKGbzXM15j/QKxWyeq90ynWI2z9Wc90ivUMzmuZrzHukViuk8l/Me6RWK6TyX8x7pFYrpPJfzHukViuk8l/Me6RWK6TyX8x7pFYrpPJfzHukViuk8l/Me6RWK6TyX8x7pFYrpPNdJ57mcd4WvUEznuU46z5XoPJfzTvgViuk8l/Ne+BWKM51iOs/lvB1+hWI6z+W8IX6FYjrP5bwlfoViOs/lvCl+hWI6z+W8WX6FYjrPRddD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtP10He6HvpO10Pf6Xro+y3TKWbzXJ2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66HukjvLRzseL298/+UVvoN14Sm+gdXr0/nxxe6c30Co9pTfQGj2lN9AKPaU3UCae0RupsXpKb6T9d0ZvpP13Rm+gLDylN5PpJfNXkVqqp/TC+qsXDbCe6UWDbx80nj/5uB3n8V00L89Xl/zmF895jfQCwb6d0ALBvq3QAsG+vdACwZlNsG83tECwbzu0QLBvP7RAsG/ztEAwm9NyXh69QDCb03JeHb1AMJvTcl4cvUAwm9NyXhu9QDCb03JeGr1AMJnTGs4roxcIJnNaw3lh9ALBZE5r3DKbYDKnNZyXRS8QTOa0hvOq6AWC2ZyW86LoBYLZnJbzmugFgtmclvOS6AWC2ZyW84roBYLZnJbzgugFgtmclvN66AWC2ZyW83LoBYLZnJbzaugFgtmclvNi6AWC2ZyW81roBYLZnJbzUugFgtmclvNK6AWC2ZyW80LoBYLZnJbzOugFgtmclvMy6AWC2ZyW8yroBYLZnJbzIugFgtmclvMa6AWC2ZyW8xLoBYLZnJbzCugFgtmclvMC6AWC2ZyW8/rnBYLZnJbz8ucFgtmclvPq5wWC2ZyW8+LnBYLZnFZlc1rOm70XCGZzWpXNadXMJpjNaTmvb18gmM1pOS9wXyCYzWk5r3BfIJjNaTkvcV8gmM1pOa9xXyCYzWk5L3JfIJjNaTmvfV8gmM1psXXED7aO+MHWET/YOuIHW0f8YOuIH2wd8YOtI36wdcQPto74wdYRP9g64gdbR/xg64gfbB3xg60jfrB1xA+yjvh8C9Ug/v397XfBkfbhKcGRVunvbxi9C460Sk8JjrRKTwmOtEpPCY6Uh6cER8rDM4JD9UtPCQ61D88IjpSHpwRHysNTgjObYDanBdwv/SIC1z29iHDtiO5PXr8e5DzPb3733v/sF8WuLdEKxb6boJcodm2Klih27YqWKHZti5YoznSKXRujJYpdO6Mlil3bqCWK6TyX70roFYp9d0IvUUznuXy3Qi9RTOe5fPdCL1FM57l8N0MvUUznuXx3Qy9RTOe5fLdDL1FM57l890MvUUznuXw3RC9RTOe5fHdEL1FM57l8t0QvUUznuXz3RC9RTOe5fDdFL1FM57l8d0UvUUznuXy3RS9RTOe5fPdFL1FM57l8N0YvUUznuXx3Ri9RTOe5fLdGL1FM57l890YvUUznuXw3Ry9RTOe5fHdHL1FM57l8t0cvUUznuXz3Ry9RTOe5fDdIL1FM57l8d0gvUUznuXy3SC9RTOe5fPdIL1FM57l8N0kvUUznuXx3SS9RTOe5fLdJL1FM57l890kvUUznuXw3Si9RTOe5fHdKL1FM57l8t0ovUUznuQad5xpsnuvw3R2+RDGb57r/GDrFoXankh8N8SW/VRxqd5pR7Ltt+ceKy6O5tNT2TnGolWtKcaiVa0pxqLQ4pTjTKQ6VFqcUh9qP61H/vLqm853iUPvxlOJQaXFKcai0OKM4VpvzlOJQnmtKcSjPNaU4lOeaUpzpFIfyXFOK6TxXrDbnKcXAnutFBbCP+lLhvXX5rO1LRb9989s3c8rqvXV5gWLn3uhnis/z+SC5vFPs3BstUJzpFDv3RgsUO/dGCxQ790YLFDv3Rj9UXMrjQdrxTrFzH2Wv2Hvr8gLFoTzXlOJYnmtGcSzPNaM40ymO5blmFDv3XOlILw+SvlF8D0aP45m7f355kvv5wItm565riWbnvmuJZufOa4Vm7+3LSzQ7d19LNDv3X0s0O3dgSzRnQs3OXdgSzYQ+zHsX8xLNhD7Mex/zCs3eG5mXaCb0Yd5bmZdoJvRh3puZl2gm9GHe25mXaCb0Yd4bmpdoJvRh3lual2gm9GHem5qXaCb0Yd7bmpdoJvRh3hubl2gm9GHeW5uXaCb0Yd6bm5doJvRh3tubl2gm9GHeG5yXaCb0Yd5bnJdoJvRh3pucl2gm9GHe25yXaCb0Yd7bfn+mebRH89xof//sF8WhducpxaHW7NEfjVVjvGus8t4Ea6749N4Eu0BxqNV6SnGozDylOFRinlIcaz+eURxrP55RHCorTykOlZSnFLN5rvNG57m8d1h/UvyiAthHvahw7o1yzV8P0to3v30TbUan967pBYoznWLn3uhniid6X07vXdMLFDv3RgsUO/dGCxQ790b2ir13TS9Q7NxHLVAcynNNtKCc3rumFyjOdIpjea4ZxbE814ziWJ5rRnEszzWjGMlz9fzmXMN7L/WkCiRv9F6Fc79Tzq+TspKqwfmD9/7oBYpzJMUzLt57f/QCxc79zgLFzv3OAsXO/c4Cxc79jr1i7/3RP1Q84Wm990cvUBzKc00pDuW5phRnOsWxPNeM4liea0YxkufK7z5X4b0PelIFkjd6q8J7Z3Pp5fkgdXz3Cate8u3xw0upL09SXzV7dzwrNHv3PCs0e3c9KzRnQs3enc8Kzd69zwrN3t3PCs3evdIKzd6d1QLN3jubl2gm9GHeO5uXaCb0Yd47m5doJvRh3jubl2gm9GHeO5uXaCb0Yd47m5doJvRh3jubl2gm9GHeO5uXaCb0Yd47m5doJvRh3jubl2gm9GHeO5uXaCb0Yd47m5doJvRh3jubl2gm9GHeO5uXaCb0Yd47m5doJvRh3jubl2gm9GGD0IcNQh/mvZt7iWZCHzYIfdgg9GHee9iXaObzYcl7F/sSzXw+LHnvY1+imc+HpVsm1Mznw5L3XvYlmvl8WPLezb5EM6EP897PvkQzoQ/z3v2+RDOhD/Pe/75EM6EP894Bv0QzoQ/z3gO/RDOhD/PeBb9EM6EP894Hv0QzoQ/z3gm/RDOhD/PeC79EM6EP894Nv0QzoQ/z3iW/RDOhD3PfU79CM6EPc99Vv0IzoQ9z31e/QjOhD3PfWb9CM6EPc99bv0IzoQ9z312/QjOhD3PfX79CM6EPc99hv0IzoQ9z33m/QjOhDyPs00+EffqJsE8/EfbpJ8I+/UTYp58I+/QTYZ9+IuzTT4R9+omwTz8R9uknwj79RNinnwj79BNhn34i7NNPhH36ibBPPxH26SfCPv1E2KefCPv0E2GffiLs00+EffqJsE8/EfbpJ8I+/UTYp58I+/QTYZ9+IuzTT4R9+omwTz8R9uknwj79RNinnwj79BNhn34i7NNPhH36ibBPPxH26SfCPv1E2KefCPv0E2GffiLs00+EffqZsE8/E/bpZ8I+/UzYp59vmVAznw/LhH36mbBPPxP26WfCPv1M2KefCfv0M2Gffibs08+EffqZsE8/E/bpZ8I+/UzYp58J+/QzYZ9+JuzTz4R9+pmwTz8T9ulnwj79TNinnwn79DNhn34m7NPPhH36mbBPPxP26WfCPv1M2KefCfv0M2Gffibs08+EffqZsE8/E/bpZ8I+/UzYp58J+/QzYZ9+JuzTz4R9+pmwTz8T9ulnwj79TNinnwn79DNhn34m7NPPhH36mbBPPxP26WfCPv1M2KefCfv0M2Gffibs08+EffqZsE8/E/bpZ8I+/UzYp58J+/QzYZ9+JuzTz4R9+pmwTz8T9ulnwj79TNinnwn79DNhn34m7NPPhH36mbBPPxP26WfCPv1M2KefCfv0M2Gffibs08+EffqZsE8/E/bpZ8I+/UzYp58J+/QzYZ9+JuzTz4R9+pmwTz8T9ulnwj79TNinnwn79Athn34h7NMvhH36hbBPv9wyoWY+H1YI+/QLYZ9+IezTL4R9+oWwT78Q9ukXwj79QtinXwj79Athn34h7NMvhH36hbBPvxD26RfCPv1C2KdfCPv0C2GffiHs0y+EffqFsE+/EPbpl1g966Odf1492t8/+0VxqN15SnGoNXv0/lA82jvFoVbsKcWh1uspxaFW6ynFoTLzlOJQiXlGcay+7SnFsfbjGcWhsvKU4lBJeUpxplNM57mQO7ZfVAD7qBcVzr1RS7fng/T83W/ffzpx/7z8P1V0b7K79x7sFZq992Av0ezcIS3R7NwjLdHs3CUt0ZwJNTt3Sks0O/dKSzQ7d1ZLNBP6MO892Cs0e+/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnQh3nvwV6imdCHee/BXqKZ0Id578FeopnPh1XvPdhLNPP5sOq9B3uJZj4fVm+ZUDOfD6vee7CXaObzYdV7D/YSzYQ+zHsP9hLNhD7Mew/2Es2EPsx7D/YSzYQ+zHsP9hLNhD7Mew/2Es2EPsx7D/YSzYQ+zHsP9hLNhD7Mew/2Es2EPsx7D/YSzYQ+7CT0YSehD/Ped75EM6EPS4Q+LBH6MO+95z/TPNHmX733ntsr9t6J/UPF3zfLVu+d2AsUh1qvpxSHWq2nFGc6xaES85TiWPvxjOJY+/GM4lBZeUpxqKQ8ozhWz/aUYjrPhdyx/aIC2Ee9qMi+VfR+Ph9ktPHNb9+RxlN0GuNNdvfeg71Es3N/tESzc4e0RLNzj7REs3OXtEKz9x7sJZqdO6Ulmp17pSWanTurJZozoWZCH+a9B3uJZkIf5r0He4lmQh/mvQd7iWZCH+a9B3uJZkIf5r0He4lmQh/mvQd7iWZCH+a9B3uJZkIf5r0He4lmQh/mvQd7iWZCH+a9B3uJZkIf5r0He4lmQh/mvQd7iWZCH+a9B3uJZkIf5r0He4lmQh/mvQd7iWZCH+a9B3uJZkIf5r0He4lmPh/WvPdgL9HM58Oa9x7sJZr5fFi7ZULNfD6see/BXqKZz4c17z3YSzQT+jDvPdhLNBP6MO892Es0E/ow7z3YSzQT+jDvPdhLNBP6MO892Es0E/ow7z3YSzQT+jDvPdhLNBP6MO/9yD/TPNFG2Ly3I9sr9t6Z+0PF3zfjNO+NuQsUh1qvpxSHWq2nFGc6xaES85TiWPvxjOJY+/GM4lBZeUpxqKQ8o9h75/UCxXSey3vn9SfFLyqAfdSLiuxaxXE7niqOWzm++e0rT82l96+ffR6vin17oxWKfXujHypufTx/9vnNz37/HC90fPuo3XR8e67ddHz7s810nHdp76bj2/ftpuPbI+6m49t77qaTRecDnVD+15yOvPInOvLKn+jIK3+iI6/8gY7zPvXddOSVP9GRV/5ER175E50sOh/oyCt/oiOv/ImOvPInOvLKn+jIK3+g47zzfjcdeeVPdOSVP9GRV/5EJ4vOBzryyp/oyCt/oiOv/ImOvPInOvLKH+g4v5dgNx155U905JU/0ZFX/kQni84HOvLKn+jIK3+iI6/8iY688ic68sof6Di/O2I3HXnlT3TklT/RkVf+RCeLzgc68sqf6Mgrf6Ijr/yJjrzyJzryyu/pdOf3e+ymI6/8iY688ic68sqf6GTR+UBHXvkTHXnlT3TklT/RkVf+REde+QMd53ew7KYjr/yJjrzyJzryyp/oZNH5QEde+RMdeeVPdOSVP9GRV/5ER175Ax3n9+TspiOv/ImOvPInOvLKn+hk0flAR175Ex155U905JU/0ZFX/kRHXvkDHef3k+2mI6/8iY688ic68sqf6GTR+UBHXvkTHXnlT3TklT/RkVf+REde+QMd5/fK7aYjr/yJjrzyJzryyp/oZNH5QEde+RMdeeVPdOSVP9GRV/5ER175Ax3d2/eRjrzyJzryyp/oyCt/opNF5wMdeeVPdOSVP9GRV/5ER175Ax3e28VKfvzkkt/Sod3Rp+jQrsql9Aed2t7RoV2Vp+jQrspTdGhPMGbo8N4QNUWH9gRjig6t36lH/fPams53dGj9zhSdLDof6NCeYEzRofXKU3RovfIUHVqvPEWH1ivP0OG9IWqKDq1XnqIjr/yJjrzyJzpZdD7QkVf+REde+RMdeeVPdOSVP9GRV/5AJ9gNUT/52bU+jk7v/3d8vTr1Vz6x3LI9n1h+2Z5PLMdszyeLz0c+sVzzT352uz22r6O1v/n84+9g/fnZjd6/Xnseryxjeey9LGM58r0sY/n3vSxjuf2dLEewG7H2suTNEfYseTOHPUvefGLPMoulGUvlHjuWyj12LJV77Fgq99ixVO4xYxnsdrO9LJV77Fgq99ixVO6xY5nF0oylco8dS+UeO5byl3Msy+PzOaUdb1gGuxFsL0vt42b/jQe7MWovS+3jdiy1j9ux1PmlHUudX/6D5QsfecaPfILddmXPh/jscDw/G9rTWz7E54FTfIizwRSfLD4f+RB7+Ck+xL58ig+v1+5P+3yM3P/i8zuvHeymrL0seX25Octgt3DtZcnr9+1Z8mYDe5a8OcKeZRZLM5a8+cSeJW+WsWep3GPHUrnHjqVyjxnLYDeq7WWp3GPHUrnHjqVyjx3LLJZmLJV77Fgq99ixVO6xY6ncY8dSuceMZVXusWOp3GPHUrnHjqVyjx3LLJZmLJV77Fgq95ixDHY35TqWE99nDHaT5V6W2nvs/hvX3mPHUnuPHUududmx1JmbHUuduf2D5RefYHc02vORD/zMh/e8a9THi8+73Hd8eM+w5vhk8fnIh9fvz/Hh9fBzfHh9+RwfWq99f7rjyWfkv/j8w2vX/PTaL6+9jVeWtF7bniXvfZALWNJ6+AUsaf3+Apa02WAByyyWZixpM8cClrT5ZAFL2iyzgKVyjx1L5R4jluXGe9flApbKPXYslXvsWCr32LHMYmnGUrnHjqVyjx1L5R47lso9diyVe8xY8t51uYClco8dS+UeO5bKPXYss1iasVTusWOp3GPHUrnHjqVyjx1L5R4zlrx3sC5gqdxjx1K5x46lco8dyyyWZiyVe+xYKvfYsVTusWOp3GPHUrnHjCXvncMLWCr32LFU7rFjqdxjx1KeaI7lt31sd5byRGYsee/K/CHLb7ua7iy199ix1N5jxzKLpRlLnbnZsdSZ2z9YvvCRZ/zMRz7wMx/e867jeD71kd/x4b17cpIPbzaY48Pr9+f48Hr4OT5ZfD7y4fXaRy/Pp87jLz6/O3/kvZ9xAUteX27PktfD27Mk9vvWLHnvZ1zAkjhHmLMkzhzmLInziTnLLJZmLJV77Fgq99ixVO6xY6ncY8dSuceMJe8drAtYKvfYsVTusWOp3GPHMoulGUvlHjuWyj12LJV77Fgq99ixVO4xY8l7j/AClso9diyVe+xYKvfYscxiacZSuceOpXKPHUvlHjuWyj12LJV7zFgS39Nsz1K5x46lco8dS+UeO5ZZLM1YKvfYsVTusWOp3GPHUrnHjqVyjxXLg/ieZnuWWSynWH7fx3YQ3+Fqz1J7zxzL77uaDuK7Ms1ZEt+Vac9SZ252LHXmZsdSZ27/YPnCJ4vPRz7ygZ/58J53nbU/njrdbu/48J5hzfHhzQZzfHj9/hQf4nsf5/jw+vI5PrxeO51ffHJ9x4fXP8/xyeLzkQ+vf57jw+uf5/jw+uc5Prz+OY3Hjz5z7n/x+cdZ0fk8K0rlReHr38+I7yU0Z0l8L6E9S14Pb8+S2O+bsyTOBuYss1iasSTOHD9i+fWZotbesSTOJ+YsibOMOUvlHjuWyj1mLLNyjx1L5R47lso9P2X59nPWxHfi2rPMYmnGkjf35OdHAc+SvvvcYH8C6cfrnWfllSVv7rFnyZt77Fny5h57lry5x5wl8R2+9ix5c8/PWOaHJ+qlvWPJm3vsWfLmHnuWWSzNWCr32LFU7rFjqdwzx7I9PujWx/GOpXKPHUvlHjOWxPcT27NU7rFjqdxjx1K5x45lFssZluN4SBxnfcdSuceOpXKPHUvlHjuWyj12LJV7zFgS309sz5I395R6ezx1vR3fsDzuO8vzQerLJ2by6zciiW8oXkGTN/usoJlF05Amb/75Gc3zePyx4jh7+4vmf796plWP+Fbj3eR5s9Vu8rxJbDd53ty2mTzxbcy7ySsT7iKv/LiLvLLmLvJZ5DeRV4bdRV4Zdhd5Zdhd5JVhd5FXht1Envhm7d3klWF3kVeG3UVeGXYX+Szym8grw+4irwy7i7z8/Ary398mexLfGL2bvLzNntXmvGWR30Re3mYXeXmbXeR1Pr+LvM7n/2fyLzTl0Q1pHvLdljR1Nj5HM93q40FSfktT592WNJXzLGlm0TSkqTxmSVMZy5KmctMkzfY4bDxyuf1F8x+vbvnJvueXJ8m3V/ZKTvvYK2dtY38qle1jrwy3j70S3z72yof72Gex38Ze2XMfeyXVfeyVa/exV67dx165dhv7pFy7j71y7T72yrX72CvX7mOfxX4be+XafeyVa/exV67dx165dh975dpt7LNy7T72yrX72CvX7mOvXLuPfRb7beyVa/exV67dx165dh975dp97JVrt7EvyrX72CvX7mOvXLuPvXLtPvZZ7Lexl8dcwH6mAa3IYW4iX7XPriA/0UlUtcvuIq89dhd5nRzvIq9z413kdWr8P5N/oSmPbklTvnuOZjkeGo/S+nerwvlcFVJ54TFeyDed6+4ir1PdXeSVNXeRV9bcRT6L/Cbyypq7yCtrriBf8/M0t70jr6y5i7xy6S7yyrCbyHdl2F3klWF3kVeG3UVeGXYt+Z7fkc8iv4m8Muwu8sqwc+TrF5H68hxvPodX8vMOn1Je+/5fP4fXlWL3sVeO3cdeSXYb+6Esu4+90uw+9sqzS9g/P3p996PnO/ZKtPvYZ7Hfxl6pdh975dp97JVr97FXrl3BPo/bk33/22P+7txtKAMjzCndlJcx5qRsvWJOtX29+pX9656TbsrW+9grW+9jn8V+G3tl633sla33sVe23sde2XoJ+/7sLKpjvGOvvLyN/aEMvI+9cu0+9sq1+9gr1+5jn8V+G3vl2iXsj8eDHO3429//7rz5UAbGmJPyMsaclK1XzKnfnn9n++tJ/t5zlK23sT+VrfexV7bex17Zeh97Zet97LPYb2OvbL2E/VGe7M/+jr3y8j72ysD72CvX7mOvXLuNfVKu3cdeuXYfe+XaFew/3Gv2u/PmpAyMMaesOUHMiTdb1/R86vuf+L+d0/H8Fmd9JdL+/Tvw2HLO15vt6l87Dm+y3k2eN1fvJs+bqneT583UZuS/aGbelLyCJm/uXUGTN8muoMmbN1fQzKJpSFPZzZKm8pglTWWsSZrj+SDtVv6i+Y/nKP3Pi9t4OdE5X8ErYm0Cr4S1APx5Pn90Lm+ybVEa20VeyW0XeaW8XeSVCHeRzyK/ibyS5gryE+f2Ral0F3kl2Dny7exP8vn434NUUYLdBF4JdgH4mf21KsHuIq8Eu4u8Euwu8kqwu8hnkd9EXgl2BfmJHFWVYHeRV4KdJF+ff9Fu/btPW04EqaoEuwm8EuwC8DP7a1OC3UVeCXYXeSXYXeSVYHeRzyK/ibwS7AryEzmqKcHuIq8EO0e+3569vv28/e9BqinBbgKvBLsA/Mz+2pVgd5FXgt1FXgl2F3kl2F3ks8hvIq8Eu4L8RI7qSrC7yCvB/oJ8+4v8C03FUkuaypqGNIfy4yTNlp80e/v//89HJkPxcRN4pccF4Gec9FB63EU+i/wm8kqPu8grPe4ir/S4i7yS5gryEycmQ6l0D/l8U4KdJF+OL/L9G/IjPT4UM+rL7fH9d6Er35R2AYakZAwwJIVogCFlDcn/kBTNAYakFA8wJAV+gCHpbABgSDpG8D+kQycOAEPSicPckEZ+Psgo/3ujfD50irAJvE4GFoCf+LNLPrLIbyKvDL+LvIL5LvJK27vIK0LvIq9cvIL8xJ/XT4XdXeSVYHeRV4TdRV4ZdpJ8vz1effv2K3+fXv3CPov9NvbKsQvYtz6ez3F+8xzvn/llSsq8CFNSPkaYkrI0wpSUu/8f9v4uO5Zl19FEe1Qj3J3215/sfxtu7JsrpJh5VrhM+9CmEQTyoUY9aGsFPs7jDlASCDClSxkdYUrK8whTUvZHmJL2BAhTMk0JYEraPSBMSbsHhClp94AwJe0eEKak3QPAlEy7B4QpafeAMCXtHhCmpN0DwpRMUwKYknYPCFPS7gFhSto9IExJuweEKWn3ADClot0DwpS0e0CYknYPCFPS7gFhSspLm6dUvv4w6flzpE9TUl4CmFKVx9s9pa/qmVLbpynJ4yFMSR4PYUryeAhTMk0JYEr6+RLClJSXNk+pHvWfr63X+WlKyksIU9LPlxCmpJ8vAUypafeAMCXtHhCmpN0DwpS0e0CYkmlKAFPS7gFhSto9IExJuweEKWn3gDAl7R5WTOkXn+O7NveP1txa36bUtXtAmJJ2DwhT0u4BYUraPSBMyTQlgClp94AwJe0edk+pvL52tMenKWn3gDAl7R4QpqTdA8CUhnYPCFPS7gFhSto9IExJu4e/OqU38ibym8hrR7CLvHL/LvLK8rvIK5/vIq/MvYd8eZDk6DfFJJn0TTFJvntTTJKV3hQbnWKSbPCmmMSTvymO7oW/vvp4/r/xg+KjvD7IUeyT4uge1F9xdO/3K8XOPW3liO7P9tKJ7uX20onu+/bSie4R99Ix0bmhE9177qUT3afupZPK07rTSeV/3enIK9/QOeWV7+jIK9/RkVe+oyOvfEfHROeGjrzyHR155Ts68sp3dOSV7+jIK9/QueSV7+jIK9/RkVe+oyOvfEfHROeGjrzyHR155Ts68sp3dOSV7+jIK9/QMXnlOzryynd05JXv6Mgr39Ex0bmhI698R0de+Y6OvPIdHXnlOzryyjd0irzyHR155Ts68sp3dOSV7+iY6NzQkVe+oyOvfEdHXvmOjrzyHR155Rs6VV75jo688h0deeU7OvLKd3RMdG7oyCvf0aH1O+WrLf/5Y6tPdGj9zgyd8Pd119Ep/UWntk90aN9ZU3Ro31lTdGjfWVN0aPc7U3Ro9ztTdGj9zsSdzhL+TudWOuHvY+6lQ7vfmaJD65Wn6NB65Sk6Jjo3dGi98hQdWq88RYfWK0/RkVe+oyOvfEMn/D23vXTkle/oyCvf0ZFXvqNjonNDR175jk4ur/yb713KV9X/84cP319t/6qxlJfEdnximctZ72WZy4fvZZnLte9kWcPfmtrC8o1PLpfvzyeXz/fnk8vp+/Mx8bnlk8vt+/OR37/nIw9/z4fXl9fzFb2P+qbx373kRPauya6GbWWZ7MbYMpbn+SXRyieWvB7enyWv3/dnyZsN/FmaWLqx5M0c/ix584k/S94s8zuWE3vfZDfd9rIkzj21fLFs3SH3JLsXt5clce75DcuZd0+yW3R7WRLnHneWJpZuLIlzjztL4tzjzpI497izJM49v2I5kXuSXfPbyjLZ7b+9LJV7/Fjy5p72eEXso5XHDyyP8pJ4FPvEkjf3+LM0sZxh6dw1V5NdQ8Thzpun9nLnzV57ufPmtL3ceTPdVu7J7lnicOfNinu5K1fu4a4Muoe7ifsW7sqre7grr+7hrry6h7vy6h7uyqtbuCe7KYvDXXl1D3fl1T3clVf3cDdx38JdeXUPd+XVPdyVV/dwV17dw115dQv3ZHedcbgrr+7hrry6h7vy6h7uJu5buCuv7uGuvLqHu/LqHu7Kq3u4K69u4d6UV/dwV17dw115dQ935dU93E3ct3BXXt3DXXl1D3fl1T3clVf3cFde3cK9K6/u4a68uoe78uoe7vLv7tyLvQ5lFfvIXf59D3f5GX/upb+41/aB+5Cf2cNdfmYPd/mZPdy1f9/D3cR9C3f5d3fuM7dghvz7Hu7av+/hrv37Hu7Kqzu4t4fy6h7uyqt7uCuv7uGuvLqHu4n7Fu7Kq3u4K6/u4a68uoe78uoe7sqrW7gfyqt7uCuv7uGuvLqHu/LqHPdffOfzvB7fPL6/+hj2q+/8NiXTlACmpCyMMCUlZ4QpKWf/1Sm9kVfS3kVeWXsT+VNpexd55e1d5JW4d5FX5t5F3kR+E3ll413klXd3kVeGXUC+f5G/jvoH+X/5HNbt9TnK9fbV9XqfkxIvxpyUjzfPybmtoF3K3dkmqjyfbaLaE2SbqPYP2SZqmmiyiWpfkm2i2sNkm6j2O9kmqk1QtolqZ5RsoqadUbaJameUbaLaGWWbqHZG2SZqmmiyiWpnlG2i2hllm6h2Rtkmqp1RtolqZ5RsokU7o2wT1c4o20S1M8o2Ue2Msk3UNNFkE9XOKNtEtTPKNlHtjJJNtCqPAk104g5lq8qj2SZqmijQRH++rdaqvG62icrrZpuovG62ierno9kmqp+PJptoUx4FmuhMr3tTHs02Uf18NNtE9fPRbBM1TTTZRLUzyjZR7YyyTVQ7o2wT1c4o20S1M0o20a6dUbaJameUbaLaGWWbqHZGuyf6m89sX6SP8vjUa95NM003U+2N8s1Um6N8M9XuKN9MtT3KN1Ptj9LNdGiDhDrTt6/+f2aqHVK+mWqLlG+m2iMhzbQc5WumZ/80U9NM081Ue6R8M9UeKd9MtUfKN1PtkfLNVHukbDPtD+2RUGd6lU8z1R4p30y1R8o3U+2Rws70bUqmKQFMSbse/yldR/+aUrEfpnRYt+9nXv30zNP+BmNO2slsnpNzb2Z/aCOTbaLaxySb6KFtTLaJaheTbaLaxGSbqPYw2SZqmmiyiWq/k22i2gRlm6h2Rtkmqp1RtolqZ5Rsoqd2Rtkmqp1RtolqZ5RtotoZZZuoaaLJJqqdUbaJameUbaLaGWWbqHZG2SaqnVGyiV7aGWWbqHZG2SaqnVG2iWpnlG2ipokmm6h2RtkmqjwKNNFi5z9fW+zjRJVHk03U5HWRJvrzVfRu8rrZJmqaaLKJyutmm6h+Ppptovr5aLaJKo8CTXTirmA35dFkEy36+Wi2ierno9kmqp1RtolqZ5RtoqaJJpuodkbZJqqdUbaJameUbaLaGWWbqHZGySZatTPKNlHtjHZP9DefeeZudq/aGuWbqfZG+WZqmmm6mWp3lG+m2h7lm6n2R/lmqg0S6kzfvvr/mal2SOlm2rRFyjdT7ZGQZjp1N7tpj5Rvptoj5ZupaabpZqo9Ur6Zao+Ub6baI+WbqfZIqDO9yqeZao+UbqZde6R8M9UeKexM36akzRDClLTrWTClUr+mNOoPUxrn67c1Rzve9NX3KZmmBDAl7WM2T8m7M7NrG5NtotrFZJuoNjHZJqo9TLKJDm1hsk1UO5hsE9W+JttEtdvJNlHTRJNNVDujbBPVzijbRLUzyjZR7YyyTVQ7o1wTHQ/tjLJNVDujbBPVzijbRLUzyjZR00STTVQ7o2wT1c4o20S1M8o2Ue2Msk1UO6NkEz20M8o2Ue2Msk1UO6NsE9XOKNtElUeBJlrs/Odri32cqPJosome8rpIE/35Ivo45XWzTVReN9tE5XWzTdQ00WQT1c9Hs01UeRRoohM3BcepPJptovr5aLaJ6uejySZ6aWeUbaLaGWWbqHZG2SaqnVG2iZommmyi2hllm6h2Rtkmqp1RtolqZ7R7or/4zuPrt1JGeb/NUN8nqp1RsomadkbZJqqdUbaJameUbaLaGWWbqGmiySaqnRHSRMvra0d7fJqodkbZJqqdUbaJameUbaLaGSWbaNHOKNtEtTPKNlHtjMJO9G1K2gMhTMk0Jf8pja9b13YcP0zpPOv1/dXnH1/9NidtbDDmpD3M9jl9j6l8euppt4IwJe1LEKakHQjAlKr2GghT0q4CYUraP+yeUimvL27Hpylp/4AwJdOUAKak7QPClLR7QJiSdg8IU9LuAWFK2j0ATKlp94AwJe0eEKak3QPClLR7QJiSaUr/uym9sdSGwI+lcrwfS6VtP5bKxH4slVzdWHblSz+WSoF+LJXV/FgqUfmxNLF0Y6nc48dSuedfWL7xIc4y7fzi09sP/9aen8S+Pshln/61EaeZBTSJ84w/zUGcaBbQJM40C2gSp5oFNIlzzQKaJpqONImzzQKaxOlmAU1lIU+aykKeNJWF3GjWx0NZyJOmspAnTWUhT5rKQp40TTQdaSoLedJUFvKkqSzkSVNZyJOmspAjzUNZyJOmspAnTWUhT5rKQp40TTQdaSoLedJUFvKkqSzkSVNZyJOmspAjzVNZyJOmspAnTWUhT5rKQp40TTQdaSoLedJUFvKkqSzkSVNZyJOmspAjzUtZyJOmspAnTWUhT5rKQp40TTQdaSoLedJUFvKkqSzkSVNZyJOmspAjTVMW8qSpLORJU1nIk6aykCdNE01HmspCnjSVhTxpKgt50lQW8qSpLORIsygLedJUFvKkqSzkSVNZyJOmiaYjTWUhT5rKQp40lYU8aSoLedJUFnKkWZWFPGkqC3nSVBbypKks5EnTRNORprKQJ01lIU+aykKeNJWFPGkqCznSbMpCnjSVhTxpKgt50lQW8qRpoulIU1nIk6aykCdNZSFPmspCnjSVhRxpdmUhT5rKQp40lYU8aSoLedI00XSkqSzkSVNZyJOmspAnTWUhT5rKQo40h7KQJ01lIU+aykKeNJWFPGmaaDrSVBbypKks5ElTWciTprKQJ01lIT+aT2yi6UhTWciTprKQJ01lIU+aJpqONJWFPGkqC3nSVBbypKks5ElTWciR5qEs5ElTWciTprKQJ01lIU+aJpqONJWFPGkqC3nSVBbypKks5ElTWciR5qks5ElTWciTprKQJ01lIU+aJpqONJWFPGkqC3nSVBbypKks5ElTWciR5qUs5ElTWciTprKQJ01lIU+aJpqONJWFPGkqC3nSVBbypKks5ElTWciRpikLedJUFvKkSZKF3hST5JU3xUanmMT3vykm8eZvikn885tiEo/7ppjEh34rLiRe8U0xiZ97U0znuVhu0L8pNlzFbyqAfdSbCmBv9KYC2O+8qQD2MG8qgH3Jtwrku9dvKoD9w5sKYE/wpgL4Pf+mIsW7G/me8JuKFO9u5Pu5bypSvLuR78V+q0C+0/qmIsW7G/ku6ZuKFO9u5DucbypSvLuR706+qQj+7n7+QPxbRal/qPhvfyoc/SrjEs3BfcEKzdEvHC7RHNxzLNEc3KEs0RzczyzRbISag3ulJZqDO6slmgl9WPSLcEs0E/qw6NfVlmgm9GHRL5Ut0Uzow6Jf/VqimdCHRb+gtUQzoQ+Lfo1qiWY+H3ZGv+y0RDOfDzujX0laopnPh50PI9TM58PO6Nd7lmjm82Fn9Es4SzQT+rDoV2WWaCb0YdEvtCzRTOjDol87WaKZ0IdFvxyyRDOhD4t+hWOJZkIfFv2ixRLNhD4s+nWIJZoJfVj0SwtLNBP6sOhXC5ZoJvRh0S8ALNFM6MOit+kv0Uzow6I30y/RTOjDore8L9FM6MOiN6Yv0Uzow6K3jy/RTOjDojd5L9FM6MOit2Iv0Uzow6I3Yy/RTOjDordjL9FM6MOiN2Qv0Uzow6K3ZC/RTOjDojdlL9FM6MOit2Uv0Uzow6I3cS/RTOjDord8L9FM6MOiN4gv0Uzow6K3ky/RTOjDojefL9FM6MOit6ov0Uzow6I3ti/RTOjDorfBL9FM6MOiN80v0Uzow6K32C/RTOjDojfkL9FM6MMI+/RPwj79k7BP/yTs0z8J+/RPwj79k7BP/yTs0z8J+/RPwj79k7BP/yTs0z8J+/RPwj79k7BP/yTs0z8J+/RPwj79k7BP/yTs0z8J+/RPwj79i7BP/yLs078I+/Qvwj7962GEmvl82EXYp38R9ulfhH36F2Gf/kXYp38R9ulfhH36F2Gf/kXYp38R9ulfhH36F2Gf/kXYp38R9ulfhH36V6Q+/bdPFcgpvX2qQF7m7VNZyE8VyA+8fapAb+y3TxXonfr2qQK99d4+VaD30venitQA/vapQj7bI7Vov32qkM/2SE3Ub58q5LM9Upvz26cK+WyP1Ij89qlCPtsjtQq/faqQz/ZIzbxvnyrksz1Su+3bpwr5bI/UEPv2qUI+2yO1rL59qpDP9khNpW+fKuSzPVLb59unCvlsj9SY+fapFj/b3/5L9a/9l9pf+y/1v/ZfGn/rv7S6IfDtv3T8tf/S+df+S9df+y/ZX/sv/bVnRP1rz4j6154R9a89I+pfe0a0v/aMaH/tGdH+2jOi/bVnRPtrz4j2154R7a89I9pfe0a0v/aMaH/tGdH/2jOi/7VnRP9rz4j+154R/a89I/pfe0b0v/aM6H/tGdH/2jOi/7VnxPhrz4jx154R4689I8Zfe0aMv/aMGH/tGTH+2jNi/LVnxPhrz4jxt54R5vIXqWezr/9SH3/8l/7L35Izl78aXfG5zqCf6wr6uSzo5ypBP1cN+rla0M/Vg36uEfNzHUGf90fQ5/0R9Hl/BH3eH0Gf90fQ5/0R9Hl/BH3eH0Gf90fQ5/0Z9Hl/Bn3en0Gf92fQ5/0Z9Hl/Bn3en0Gf92fQ5/0Z9Hl/Bn3eX0Gf91fQ5/0V9Hl/BX3eX0Gf91fQ5/0V9Hl/BX3eX0Gf91fQ570Ffd5b0Oe9BX3eW9DnvQV93lvQ570Ffd5b0Oe9BX3eW9DnfQn6vC9Bn/cl6PO+BH3el6DP+xL0eV+CPu9L0Od9Cfq8L0Gf9zXo874Gfd7XoM/7GvR5X4M+72vQ530N+ryvQZ/3NejzvgZ93regz/sW9Hnfgj7vW9DnfQv6vG9Bn/ct6PO+BX3et6DP+xb0ed+DPu970Od9D/q870Gf9z3o874Hfd73oM/7HvR534M+73vQ5/0I+rwfQZ/3I+jzfgR93o+gz/sR9Hk/gj7vR9Dn/Qj6vB8xn/cl6N/XlqB/X1uC/n1tCfr3teUR83lfgv59bQn697Ul6N/XlqB/X1uC/n1tCfr3tSXo39eWoH9fW4L+fW0J+ve1Jejf15agf19bgv59bQn697Ul6N/XlqB/X1uC/n1tCfr3tSXo39eWoH9fW4L+fW0J+ve1Jejf15agf19bgv59bQn697Ul6N/XlqB/X1uC/n1tCfr3tSXo39eWoH9fW4L+fW0J+ve1Jejf15agf19bgv59bQn697Ul6N/X1tVt0P/zq393Af3x9dXH8/99a/73C+i/+t7tUV/fupXH91fb+b/8zudVXt/5vMbb1fZh//ad+/j6zucP3/n5z/ufr33+g/ow0dWt25roX59ooOtwmqjLRANd1tNEXSYa6CqhJuoyUdNEk0000KVjTdRlooGuRGuiLhMNdGFbE3WZaKDr5Jqoy0S1M8o10fbQzghpov3xmugonyaqnVG2iWpnlG2i2hllm6hpokATbd8TrZ8mqp1RtolqZ5RtotoZZZuodkbZJqqdUbKJHtoZIU209NdEa/s0Ue2Msk1UO6NsE9XOKNtETRNNNlHtjLJNVDujbBPVzijbRLUzyjZR7YySTfTUzijbRLUzyjZR7YyyTVQ7o2wTNU002US1M8o2Ue2Msk1UO6NsE9XOKNtEtTNKNtFLO6NsE9XOKNtEtTPKNlHtjLJN1DTRZBPVzijbRLUzyjZR7YyyTVQ7o2wT1c4o2URNO6NsE9XOKNtEtTPKNlHtjLJN1DTRZBPVzijbRLUzyjZR7YyyTVQ7o2QTLcqjCyZ69K+JFvOc6EQHdlEezTZR5dFsEzVNNNlElUezTVR5NNtElUezTVR5NNtE9TsMySZa9TsM2SaqnVG2iWpnhDTRiQs+VTujbBM1TTTZRLUzyjZR7YyQJjpxHaRqZ5RtotoZZZuodkbJJtq0M8o2Ue2Msk1UOyOkiU78LmDTzijbRE0TTTZR7YyyTVQ7o2wT1c4o20S1M8o2Ue2Mkk20a2eUbaLaGWWbqHZG2SaqnVG2iZommmyi2hllm6h2Rtkmqp1RtolqZ5RtotoZJZvo0M4o20S1M8o2Ue2Msk1UO6NsEzVNNNlEtTPKNlHtjLJNVDujbBPVzijbRLUzyjXR/tDOKNtEtTPKNlHtjLJNVDujbBM1TTTZRLUzyjZR7YyyTVQ7o2wT1c4o20S1M0o20UM7o2wTVR71n+j5VbH5HK7rJbyfO7D7YZposokqj2abqPJotokqj2abqPJotokqjyab6Kk8mm2i+h2GbBPV7zBkm6h2Rtkmapoo0ER/vuDTT+2Msk1UO6NsE9XOKNtEtTNCmujP10H6qZ1Rsole2hllm6h2Rtkmqp1RtolqZ5RtoqaJAk104ncBL+2Msk1UO6NsE9XOKNtEtTPKNlHtjJJN1LQzyjZR7YyyTVQ7o2wT1c4o20RNE002Ue2Msk1UO6NsE9XOKNtEtTPKNlHtjJJNtGhnlG2i2hllm6h2Rtkmqp1RtomaJppsotoZZZuodkbZJqqdUbaJameUbaLaGSWbaNXOKNtEtTPKNlHtjLJNVDujbBM1TTTZRLUzyjZR7YyyTVQ7o2wT1c4o20S1M0o20aadUbaJameUbaLaGWWbqPLo3ESdm6qbUuMe7sp2e7grge3hrpy0hXtXmtnDXZljD3clgz3c9TPfPdxN3LdwV17dw1151Z/7xCWOrry6h7vy6h7uyqtbuA/lVX/uE+3zQ3l1D3fl1T3clVf3cDdx38JdeXUPd+VVf+4Tv08wlFf3cFde3cNdeXUH9/FQXt3DXXl1D3fl1T3clVf3cDdx38JdeXUPd+XVPdyVV/dwV17dw115dQv3Q3l1D3fl1T3clVf3cFde3cPdxH0Ld+XVPdyVV/dwV17dw115dQ935dUt3E/l1T3clVf3cFde3cNdeXUPdxP3LdyVV/dwV17dw115dQ935dU93JVXt3C/lFf3cFde3cNdeXUPd+XVPdxN3Ldwz+XffVuRxpXLZXvTyeWFnelYLsfqTSeXr/Smk8v9edPJ5dG86Zjo3NDJtZ/3ppNri+5NR175jg6vV/65f28Yr1eeoFN4vfIMHV6vPEOH1yv/3JM1Cq9XnqFjonNDh9crz9Dh9cozdHi98gwdXq888TOJwuuVJ+hUXq88Q4fXK8/Q4fXKM3R4vfIMHROdGzq8XnmGDq9XnqHD65Vn6Mgr39GRV76h0+SV7+jIK9/RkVe+oyOvfEfHROeGjrzyHR155Ts68sp3dOSV7+jIK9/Q6fLKd3Tkle/oyCvf0ZFXvqNjonNDR175jo688h0deeU7OvLKd3TklW/oJLum7k1HXvmOjrzyHR155Ts6Jjo3dOSV7+jIK9/Rie53jvOLzqMcP9H5xfc+6/X1qWt/+43l69++8zG+/iTnfJzfbSVHe/xvp/Tj3xi2R/irwJrSf6YU3f9pSv+ZUnQfqin9Z0rR/bCm9J8pmaYEMKXo+UBT+s+UoucUTek/U4r+swVN6T9Tiv4zDk3pP1PS7gFgSuEvPOef0o9tMM8pafeAMCXtHhCmpN0DwpRMU9o8pR8bX55T0u4BYUraPSBMSbsHhClp94AwJe0eAKYU/lp3/in9+DtEzylp94AwJe0eEKak3QPClExTApiSdg8IU9LuAWFK2j0gTEm7B4QpafcAMKXwl9c1pf9MSbsHhClp94AwJe0eEKZkmhLAlLR7QJiSdg8IU9LuAWFK2j0gTEm7B4ApmXYPCFPS7gFhSto9IExJuweEKZmmBDAl7R4QpqTdA8KUtHtAmJJ2DwhT0u4BYEpFuweEKWn3gDAl7R4QpqTdA8KUTFMCmJJ2DwhT0u4BYUraPSBMSbsHgClV3rxU6hf3+jh+mtLVXuAPK99TOq3/K/nXF5f29p3P4508bwbaTZ431+wmbyK/iTxv/thNnjdTrCQ/yj9fXB/lE3nenLCbPK/3302e92eJm8k33p8PLiV/fJGvn8grw+4irwy7i7wy7C7yJvKbyCvD7iKvDLuCfP+6MtT7J/LKsLvIK8PuIq8Mu4l8V4bdRV4Zdhd5Zdhd5JVhd5E3kd9EXhl2F3ll2F3klWF3kVeG3UVeGXYT+aEMu4u8Muwu8sqwu8grw+4ibyK/ibwy7C7yyrC7yCvD7iKvDLuLvDLsHvJPxCK/ibwy7C7yyrC7yCvD7iJvIr+JvDLsLvLKsLvIK8PuIq8Mu4u8Muwm8ocy7C7yyrC7yCvD7iKvDLuLvIn8JvLy83Pkz8NeH+Ts7SfyP3c6HYf8/C7y8vObyJ/y87vIy8/vIi8/v4L8z40Txyk/v4u8ifwm8vqZ1C7y+pnULvLKsLvIK8OuID+xtzmVYTeRv5Rhd5FXht1FXhl2F3ll2F3kTeQ3kVeG3UVeGXYXeWXYXeSVYXeRV4bdRN6UYXeRV4bdRV4Zdhd5Zdhd5E3kN5FXht1FXhl2F3ll2F3klWF3kVeG3US+KMPuIq8Mu4u8Muwu8sqwu8ibyG8irwy7i7wy7C7yyrC7yCvD7iKvDLuJfFWG3UVeGXYXeWXYXeSVYXeRN5HfRF4Zdhd5Zdhd5Hn9/NHL16e28QP5mfaOxuvQ/Vnyem5/lrwu2p8lry/2Z2liOcVyvL64Psonlrze1Z8lrxv1Z8n7MxJ/lrw/9fgly5/baJpyjxvLrtzjx1K5x4+lco8fS+UeP5YmllMsJ/aXXbnHj6Vyjx9L5R4/lso9fiyVe9xYDuUeP5bKPX4slXv8WCr3+LE0sXRjqdzjx1K5x4+lco8fS+UeP5bKPV4sz4dyjx9L5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lodyjx9L5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lqdyjx9L5R4/lso9fix5/eXjeml8bsvsJ5Y/9xqcJ6+/9GfJ6y/9WfL6S3+WvP7y4c3y4vWXv2P5c0fEefH6S3+WvP7SnyXvXt2fpYnlHMsf/xb/vJR7/Fgq9/ixVO7xY6nc48dSuceNpSn3zLGc2F+aco8fS+UeP5bKPX4sTSzdWCr3+LFU7vFjqdzjx1K5x4+lco8by6Lc48dSucePpXKPH0vlHj+WJpZuLJV7/Fgq9/ixVO7xY6nc48dSuceNJfEFd3+Wyj1+LJV7/Fgq9/ixNLF0Y6nc48dSucePpXKPH0vlHj+Wyj1uLJtyjx9L5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6VyjxtL3vvjR//CcwzrP7Gc6DXgvT++gCWtv1zA0sTSjSWtv1zAktZf/pLlREcE7/3xBSxp/eUClrR7dX+WvPfHf8vy57/F570/voClco8fS+UeP5Ymlm4slXv8WCr3zLGc2F/y3h9fwFK5x4+lco8Xy4v3/vgClso9fiyVe/xYKvf4sTSxdGOp3OPHUrnHj6Vyjx9L5R4/lso9bix5748vYKnc48dSucePpXKPH0sTSzeWyj1+LJV7/Fgq9/ixVO7xY6nc48aS9/74ApbKPX4slXv8WCr3+LE0sXRjqdzjx1K5x4+lco8fS+UeP5bKPW4sL+UeP5bKPX4slXv8WCr3+LE0sXRjyesv26O+vnVr4yeWP/caXLz3xxew5PWX7ix5748vYMnrL/1Z8vrL37H8+W9LL9774wtYmli6seTdq/uz5N2r+7NU7vFjqdwzx3Iij/PeH/dnyXt/fAFL5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lrz3xxewVO7xY6nc48dSucePpYmlG0vlHj+Wyj1+LJV7/Fgq9/ixVO5xY8l7f3wBS+UeP5bKPX4slXv8WJpYurFU7vFjqdzjx1K5x4+lco8fS+UeN5ZducePpXKPH0vlHj+Wyj1+LE0s3Vgq9/ixVO7xY5nLX/bx9b3PH753sS869ufn+KaT7KK4N51cHtCbTi5X500nl0/zpmOic0Mnl5fyppPLHXnTybXn9aaTa3PrTUde+TMdS3aF+jd0+uNFZ5RPdHi98gwdXq88Q4fXK8/QMVo67ZtO/USH1yvP0OH1yjN0eL3yDB1erzxDh9crT9BJdrn4N3RKf9Gp7RMdXq88Q4fXK8/Q4fXKM3RMdG7o8HrlGTq8XnmGDq9XnqHD65Vn6PB65Qk6ya7detORV76jI698R0de+Y6Oic4NHXnlOzryynd05JXv6Mgr39GRV76hk+xCqjcdeeU7OvLKd3Tkle/omOjc0JFXvqMjr3xHR175jo688h0deeUbOsmuvXrTkVe+oyOvfEdHXvmOjonODR155Ts68sp3dOSV7+jIK9/QCX638dG/ujyOx3hr/vh3OqO9vnq0T3+vF/y64grFsX3JCsVGpzi2f1ihOLYn+KXi5+d+fH35OX747qO/nuxjfHyyx3YF+/nE9gX7+cTeom3nE/yK3n4+qZzlAj6pfOgCPqlc6+/4/Cblff7UbyxNLN1YpnLam1kSe3h3lsR+350lcTZwZ0mcI7xZBr9gh8WSOJ+4syTOMu4slXv8WJpYurFU7vFjqdzjx1K5x4+lco8fS+UeN5bBL9hhsVTu8WOp3OPHUrnHj6WJpRtL5R4/lso9fiyVe/xYKvf4sVTucWMZ/A4jFkvlHj+Wyj1+LJV7/FiaWLqxVO7xYylPNMVy4t5eCX5vD4ul3j1zLH/+S9ry0LvHj6XePX4stXPzY6mdmx9L7dz8WMpfTrGsR/3na+t1fmAZ/EYdFkvt3PxYaufmx1K5x4+liaUbS+UeP5bKPX4slXv8WCr3+LFU7nFjGfzeIBZL5R4/lsy55zef5Dq/vvP1/p0f9Z0mc/Lxp2mi6UiTOf3402TOP/40mROQP03mDORPkzkF/Ypm+fogVz0+0Ax+SxKNJnMS8qepLORJU1nIk6aJpiNNZSFPmspC/wXN/ommspAnTWUhT5rKQpM0x3eyHJ+SZfBboWg0lYU8aSoLedJUFvKkaaLpSFNZyJOmstD/uflb3RL8mup+Psor93yUQG75FGWKez5KCfd85Pvv+eS69vvzpbiS7NrvjOJc135nFKdyrVOKU/nQKcWpnOWU4lRecUZxrqu5U4pT+bkpxakc2pRiOs+V66LslGI6z5XrOuuUYjrPlevS6ZRiOs+V62rolGI6z5XrAueUYjrPleua5ZRiOs+V6zLklGI6z5XryuKUYjrPleti4ZRiOs+V6/rflGI6z5Xrkt6UYjrPlesq3ZRiOs+V68LblGI6z5XrWtqUYjrPlevy2JRiOs+V64rXlGI6zzXoPNeg81yDznPluvM2objmusY2pZjNc9UHm+eque7iTSk2OsVsnqvmugQ3pZjNc9VcV9WmFNN5rlwXyqYU03muXNe+phTTea5cl7OmFNN5rlxXqKYU03muXBedphTTea5c15GmFNN5rlyXhqYU03muXBd7phTTea5cl2+mFNN5rlwXZKYU03muXJdYphTTea5cF02mFNN5rlyXQaYU03muXBc2phTTea5clyqmFNN5rlwXH6YU03muXJcTphTTea5cFwimFNN5rlxN/lOK6TxXrrb9KcV0nitXI/6UYjrPlau1fkoxneei66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+5uoo/+X9qz6+Psn5w9cWe32OYtcnlsy3DL1ZMt89dGaZq7F9M0vme4reLJlvL3qzZL647s3SxNKNJfO1dW+WzLfWvVkq9/ixVO6ZY9lf37iM8omlco8by1xXEzazVO7xY6ncM8eyfbOsn1gq9/ixNLF0Y6nc48dSucePpXKPH0vlnjmW5fVzyFI//Rwy132RvSxzXS7ZzFK5x4+lco8fS+UeP5Ymlm4slXv8WCr3+LFU7vFjqdzjx1K5x4tly3U9aDNL5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lrkueG1mqdzjx1K5x4+lco8fSxNLN5bKPX4slXv8WCr3+LFU7vFjqdzjxjLXFb3NLJV7/Fgq9/ixVO7xY2li6cZSucePpXKPH8vg/rJd33D6W6PAhwa79iI/2of2gRb9rt8CxcG92gLFwR3VAsXBfc8CxZZJ8e/eAhNNnS36FcDtfIK7iO18gm9Et/MJvuXczieVs/TnE/3W4XY+qVzrupT3+VO/sUzlhzezTOW0N7M0sXRjSez33VkSZwN3lsQ5wp0lceZwZ0mcT7xZRr8hCsVSucePpXKPH0vlHj+WJpZuLJV7/Fgq9/ixVO7xY6nc48dSuceNZfQ7vlAslXv8WCr3+LFU7vFjaWLpxlK5x4+lco8fS+UeP5bKPX4slXvcWEa/EA7FUrnHj6Vyjx9L5R4/liaWbiyVe/xYKvf4sVTucWMZ/XpwFJYT19Zb9OvBUCz17pljOdE8EP1KKxRLvXv8WGrn5sdSOzc3ltGvtEKxlL+cYlmP+s/X1uv8xFL+0o+ldm5+LE0s3Vgq9/ixVO7xY6nc48dSucePpXKPF8se/UorFEvlHj+Wyj1+LJV7/FgaMctffBK77LUosqu8bYoe9Z0mc/Lxp8mcffxpMqcff5rM+cefJnMCcqcZ/WIrGE3mFPQrmv3xRbOPTzSZc5A/TeYk5E/TRNORprKQJ01lIU+aykKeNJWFfk9z1E80lYUcaUa/4gpGU1lojqYdX8nSzk/JMvolVzCaykKeNE00HWkqC3nSVBbypKks5ElTWWiSZrm+aNbzE01lIUeauW4Zb6epLORJU1nIk6aykCdNE01HmspC/+emzaQzX5qe4qO8cs9HCeSejzLFLR/mS9NTfOT77/mkcvITt8d7rhvPU4qNTnEq1zqlOJUPnVKcyllOKU7lFacUp3J/M4pzXdudUpzKoU0ppvNcue7LTik2OsV0nivXRdUpxXSeK9d10inFdJ4r16XPKcV0nivX1cwpxXSeK9cFyinFdJ4r1zXHKcV0nivXZcQpxXSeK9eVwSnFdJ4r18W+KcV0nivX9bspxXSeK9cluSnFdJ6r0XmuRue5Op3nynVrcEoxnefqdJ6rG51iOs+V64LilGI6z5XrGuGUYjrPleuy35RiOs+V60relGI6z5Xr4tyUYjrPlet625RiOs+V6xLalGI2zzVyXRWbUszmuUauC11Titk813gYnWI2zzVyXY2aUszmuUau60tTiuk8V64rRlOK6TxXrmtAU4rpPFeuqzpTiuk8V67rNFOK6TxXrisvU4rpPFeuaylTiuk8V66rI1OK6TxXrusdU4rpPFeuKxhTiuk8V65rElOK6TxXrqsMU4rpPFeu6wZTiuk8V64rAVOK6TxXrm7+KcV0nitXf/6UYjrPlavjfkoxneei66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76kauj/Pm5v7/8HD9899bH1yc5f/jaYuc/X1vs+sAyV/v5ZpapPMRmlqncyWaWqXzPZpYmlm4sU3m1zSxTucDNLFPt9DazTLUt3MxSuceJZX/kukCwkGV/feMyyieWyj1+LJV7/Fgq9/ixNLGcYtm+WdZPLJV7/Fgq9/ixVO7xY6nc48dSuceNZa4rIAtZltfPIUttn1gq9/ixVO7xY6nc48fSxNKNpXKPH0vlHj+Wyj1+LJV7/Fgq97ixzHWJZzNL5R4/lso9fiyVe/xYmli6sVTu8WOp3OPHUrnHj6Vyjx9L5R43lrmuYW1mqdzjx1K5x4+lco8fSxNLN5bKPX4slXv8WCr3+LFU7vFjqdzjxjLXRbrNLJV7/Fgq9/ixVO7xY2li6cZSucePpXKPH0vlHj+Wyj1uLKPf9Su9fH2QOn5iOdqrfWC065Pi4C5wgeLgXm2BYqNTHNz3LFAc3J38TvHv3gI/N3U++QR3HNv5BHcR2/kE34ju5hP9HuF2Pqmc5QI+qXzoAj6pXOu6lPf5U7+xNLF0Y5nKaW9mSezh3VkS+313lsTZwJ0lcY7wZhn9HicUS+J84s6SOMu4s1Tu8WNpYunGUrnHj6Vyjx9L5R4/lso9fiyVe9xYRr+JC8VSucePpXKPH0vlHj+WJpZuLJV7/Fgq9/ixVO7xY6nc48dSuceNZfQL4VAslXv8WCr3+LFU7vFjaWLpxlK5x4+lco8fS+UeP5bKPX4slXu8WB7RrwdHYTlxbf1JSizdWOrdM8fy5+aBI/qVViiWeve4sYx+pRWKpXZufiy1c/NjKX85xbIe9Z+vrdf5iaWJpRtL7dz8WGrn5sdSucePpXKPH0vlHjeW0a+0QrFU7vFjqdzjx1K5x4+liaUbS+UeP5bMuecXn6Tb+VoUdbveNkWP+k6TOfn402TOPv40mdOPO83o11rBaDInIH+azBnInyZzCvoVzfr4olnHJ5ommo40mZOQP01lIU+aykKeNJWFPGkqCznSjH7BNSTNVj/RVBbypKks5ElTWWiS5vhKluXxKVlGv+QKRlNZyJOmspAnTWUhT5rKQp40lYUcaRZloTmaxb78ZrFPyTLXveHtNJWFPGkqC3nSNNF0pKks5ElTWciTprLQ72mWTxs55rvUC2gqCznSZL55PdNbxHzzeoqP8so9HyWQez4mPrd8lBLu+cj33/NJ5eRHf613x/jUBJPr0vOU4lSOeEZxrqvJU4pT+dApxamc5ZTiVF5xSrHRKU7l56YUp3JoU4rpPFeuK7NTiuk8V66LrVOK6TxXruunU4rpPFeuS6JTiuk8V66rnFOK6TxXrguXU4rpPFeua5FTiuk8V67Li1OK6TxXriuGU4rpPFeui4BTiuk8V67relOK2TzX+WDzXOeDzXOdDzbPdea6vzil2OgUs3mu88Hmuc5c9yqnFLN5rjPX7ccZxbkuNE4ppvNcua4dTimm81y5LgdOKabzXLmu8E0ppvNcuS7aTSmm81y5rsNNKabzXLkurU0ppvNcua6WTSmm81y5LoBNKabzXLkuaU0ppvNcuS5STSmm81y5LjtNKabzXLkuJE0ppvNcuS4NTSmm81y5LvZMKabzXLku30wppvNcuS7ITCmm81y5LrFMKabzXLkumkwppvNcuS6DTCmm81y5LmxMKabzXLkuVUwppvNcuS4+TCmm81y5LidMKabzXLkuEEwppvNcuZr8pxTTea5cbftTiuk8V65G/CnFdJ4rV2v9lGI6z0XXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UnXQ3/S9dCfdD30J10P/UXXQ3/R9dBfdD30F10P/fUwOsVsnuui66G/6HroL7oe+ouuh/6i66G/6Hror1wd5c/P/fj68nP88N1bH1+f5Pzha4ud/3xtsesTy1Rv+s0sU3mIzSxTuZPNLFP5ns0sUzmqvSxz9ddvZpnKBW5mmWqnt5llqm3hZpYmlm4slXvmWPbXNy6jfGKp3OPHUrnHj6Vyjx9L5Z45lu2bZf3AMtcNic0slXv8WCr3+LFU7vFjaWLpxlK5Z45lef0cstRPP4fMdV9kM0vlHj+Wyj1+LJV73FjmuuOymaVyjx9L5R4/lso9fixNLN1YKvf4sVTu8WOp3OPHUrnHj6VyjxvLXLeUNrNU7vFjqdzjx1K5x4+liaUbS+UeP5bKPX4slXv8WCr3+LFU7nFjmeue2WaWyj1+LJV7/Fgq9/ixNLF0Y6nc48dSucePpXKPH0vlHj+Wyj1uLHPdFNzMUrnHj6Vyjx9L5R4/lsH95XVcbx/kJ5ajvdoHRrs+KQ7uAhcoDu7VFigO7qj8FUe/67dAcXB38jvFv3sLzDR1Rr8CuJ1PcBexnY+Jzy2f4FvO7XxSOcsFfFL50AV8UrnWdSnv86d+Y5nKD+9lGf2aIxRLYg/vzpLY77uzJM4G7ixNLN1YEmcOd5bE+cSdJXGWcWep3OPHUrnHi6VFv6gKxVK5x4+lco8fS+UeP5Ymlm4slXv8WCr3+LFU7vFjqdzjx1K5x41l9KvGUCyVe/xYKvf4sVTu8WNpYunGUrnHj6Vyjx9L5R4/lso9fiyVe9xYRr8QDsXSxHLqLxZ/vh5s0a8HQ7HUu2eO5c9/SWvRr7QisYx+pRWKpXZufiy1c/NjqZ2bH0sTyxmW9aj/fG29zk8s5S/9WGrn5sdSOzc/lso9fiyVe9xYRr/SCsVSucePpXKPH0vlHj+WJpZuLJV7/Fgq9/ixZM49v/kkZ/sicvbH91ef5ztN5uTjT5M5+7jTjH6rFYwmc/7xp8mcgPxpMmcgf5ommnM0rX/TPP6g+T+/elwvHzvq26fo//opvn5G14a9fd/3ITHHK5ghMec2mCEpEAIMSTkTYEiKr/GHFP2Sr4b0nyEpbAMMSRkeYEhaDQAMyTSk+EPSxmHuk1wPe33n6/2r/6Sp1YAnTWV4T5oK2540lYodaUY/yAxGUznTk6YC4STNq37RtPKJppKbJ00TTUeaykKeNJWFPGkqC3nSVBbypKks9Hua7xr/oJnrSPt2mspCnjSVhf7PXYUb87n4KT4mPrd8lEDu+ShT3PNRSrjnI99/zyeVkx/99ePvMT6VYuU61D6lOJUjnlKcyrVOKU7lQ6cUG53iVF5xSnEq9zelOJWfm1KcyqFNKWbzXCXXkegpxWyeq+Q6uDylmM1zlYfRKWbzXCXXIeApxWyeq+Q6qjulmM5z5TpQO6WYznPlOvY6pZjOc+U6nDqlmM5z5TpCOqWYznPlOug5pZjOc+U6jjmlmM5znXSe66TzXLkOs04ppvNcJ53nOuk8V65DtlOK6TxXrqOwU4rpPFeuA6tTiuk8V65jpVOK6TxXrsOfU4rpPFeuI5pTiuk8V66DlFOK6TxXruOOU4rpPFeuQ4lTiuk8V66jg1OK6TxXrvN9U4rpPFeuM3hTiuk8V65zclOK6TxXrrNsU4rpPFeug2FTiuk8V65TVlOK6TxXriNLU4rpPFeu8z9Tiuk8V67DNFOK6TxXrkssU4rpPFeuiyZTiuk8V67LIFOK6TxXrgsbU4rpPFeuSxVTiuk8V66LD1OK6TxXrssJU4rpPFeuCwRTiuk8V64m/ynFdJ4rV9v+lGI6z5WrEX9KMZ3nytVaP6WYznPR9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpK10Nfc3WU//L+VR9fn+T84WuLnf98bbHrE8tUb/rNLJnvHnqzZL6R6M2S+Z6iN0vm24veLJkvrjuzzNWMv5kl87V1b5bMt9a9WSr3+LE0sZxi2V/f+Lki/cRSucePpXKPH0vlHj+Wyj1zLNs3y/qJpXKPG8tc1yk2s1Tu8WOp3OPHUrnHj6WJ5RTL8vo5ZKmffg6Z677IZpbKPX4slXv8WCr3+LFU7nFjmetCzGaWyj1+LJV7/Fgq9/ixNLF0Y6nc48dSucePpXKPH0vlHj+Wyj1uLHNdadrMUrnHj6Vyjx9L5R4/liaWbiyVe/xYKvf4sVTu8WOp3OPHUrnHjWWuS2mbWSr3+LFU7vFjqdzjx9LE0o2lco8fS+UeP5bKPX4slXv8WCr3uLHMda1wM0vlHj+Wyj1+LIP7y6N+f5DzPH9gOdM+EP2u3wLFwb3aAsXBHdUCxcF9j7/i6Hf9FigO7iEWKA7+pl+gOPgecoFio1NM57mi3/X7peKJzpbod/0WKM7luWYU5/JcE4qj3/X7peKJzobod/0WKM7luWYU5/JcM4qNTnEuzzWjOJfnmthlRr/rt0BxLs81oziX55pQHP2u3wLFuTzXjOJcnmtGcS7PNaPY6BTn8lwziuk8V/S7fgsU03mu6Hf93BW36Hf9Fihm81ztwea5WvTbjQsUG51iNs/Vol8rXKCYzXO16Jf/Fiim81zRr+gtUEznuaJfpFugmM5zRb/utkAxneeKfiltgWI6zxX96tgCxXSeK/oFrwWK6TxX9GtYCxTTea7ol6UWKA79Ph5jfP8J6HEePwge7fUr9KNdnwSHfh2vEBz6bbxAcOyzMisEh34XrxAc+lX8S8G/+7v10V/P9DE+PdNj31zZjyf0S34/ntBbmP14Qq9s9uPJ5CcX4MnkPhfgyeRV1xXSfP7Q3yhjHxnBQpnJX29Gyevc3VHyunx3lCaUXih504M7St6k4Y6SN5W4o+RNMO4olXa8UMY+LYKFUmnHDaXSjhtKpR03lCaUXiiVdtxQKu24oVTacUOptOOGUmnHC2XsgyJYKJV23FAq7bihVNpxQ2lC6YVSaccNpdKOG0qlHTeUSjtuKJV2vFDGPlCEhVJpxw2l0o4bSqUdN5QmlF4olXbcUCrtuKFU2nFDqbTjhlJpxwtl7NNgWCiVdtxQKu24oVTacUMpMzSDcuKybIt9AQsKZeyzS3FQTrRTxb7nhIVSrx03lCaUXii1ZHNDqSWbG0r5yhmU9aj/fG29zk8o5SvdUGrJ5oSyx75LhoVSaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLZeyLgFgolXbcUCrtuKFU2nFDaULphZI47fzig5zHF8vzuMr35+jj3766lNcXt+MTeOJstBc8cZLaC544d+0FT5zSnMB/w4x9RRQNJnFS84dJnNX8YRKnNX+YJph+MJXYHGEqhTnCVLKagzm+PPv56H/A/O+WOKnOJUOBV7LyB3+eXzysfACf6nw0FHgltk3gle42gVcS3ATeBH4PeCXMTeCVRheAn/gJCfFB9M3glVw3gVdy3QOe+eT7b8CfV/+S2O0H8Ef5+tTFPoFXct0EXsnVH7xzS1NnPlSPMyTTkOIPSekZYEhK2gBDUioHGJISPMCQlPbjD6loMwAwJG0RAIakjQPAkLRxABiSaUjxh6SNA8CQtHEAGJI2DgBD0sYBYEjaOMQfUtXGAWBI2jgADEkbB4AhaeMAMCTTkOIPSRsHgCFp4wAwJG0cAIakjQPAkLRxiD+kpo0DwJC0cQAYkjYOAEPSxgFgSKYhxR+SctLeIU0cVe9NOSn+kLrc3eYh/XzcuHe5O4Ahyd0BDMk0pPhD0s+TAIaknycBDEk5ae+QZmqDu3ISwJD086T4Qxr6eRLAkLRxABiSNg4AQ9LGAWBIpiHFH5I2DgBD0sYBYEjaOAAMSRsHgCFp4xB+SOOhjQPAkLRxABiSNg4AQ9LGAWBIpiHFH5I2DguG9IvvfIzvzzyOt8/8sP92pNpPpBupthnpRqrdR7qRalMSd6TfYzq0K4EYk7YlEGPSvgRiTNqYQIzJNCaEMWlrAjEmbUIgxqTtBsSYtLGAGJO2ELvH1F6oz8dR/xjTv3yOn6+zj1Mbi3Qj1XYDaaTOxUHj1NaEevzaxlCP3zR+5vFre0Q9fm2lqMevbRf1+LVFox6/tnPM47+0yaMev7Z+1OPX1o96/Nr6UY/fNH7m8WvrRz1+bf2ox6+tH/X4tfWjHr+2fszjN239qMevrR/1+LX1ox6/tn7U4zeNn3n82vpRj1+5P+v4J67aDlPuZx5/kfNPO/6frx6OIudPPX7T+JnHL+dPPX79vJ96/Pp5P/X4lfuzjn+mCbgo9zOPv+rn/dTj18/7qcevrR/1+LX1ox6/afzM49fWj3r82vpRj19bP+rxa+tHPX5t/ZjH37T1ox6/tn5Q4//Ndz7G6zMf5+PtZ379eP8HoL0f+T8Abf7I/wGY/gFw/wPQ9o/8H4D2f+T/ALQBJP8HoB1gjn8AbyPVXi/bSLt2dXtHej7K42uko/ww0pmLel37t3Qj1UYNaaTe5Qld+zTq8ZvGzzx+7dKox69NGvX4tUejHr+2aNTj18aNefxD2znq8WuTRz1+bf2ox6+tH/X4TeNnHr+2ftTj19aPevza+lGPX1s/6vFr68c7/vHkpfEzj19bP+rxa+tHPX5t/ajHbxo/8/i19aMev7Z+1ONX7s86/p+v5I3HodxPPX45/7Tj//FSznP8pvEzj1/On3r8cv7U49fP+6nHr5/3U49fuT/r+H8uTB6PU7mfevz6eT/1+PXzfurxa+tHPX7T+JnHr60f9fi19aMev7Z+1OPX1o96/Nr6MY//0taPevza+kGN/xffeeY+xvMfgPZ+5P8AtPkj/wdg+gfA/Q9A2z/yfwDa/5H/A9AGkPwfgHaAOf4BvI1Ue71sIzXt6jaP9Pk0fX3n42o/jPR4juOl8Ljs01C1gUs4VG3VkIZqX19s1+OH7/z+tf3T+LVTox6/afxJx//8zK9vbOXT+LVPox6/tmnU49cujXr82qRRj19bN+bxF23o0o6/lNc3bsen8WuXRz1+bf2ox6+tH/X4TeNnHr+2ftTj19aPevza+qGO/9NP8Yo2eelGqu1ctpFWbdzSjVRbtHQj1WYs3Ui17Uo3UtNIs41UW6l0I9WmKd1ItT3aPdLvv9U66k9/qzX3NyBV+6OEQ9UGKd9Qm3ZICYeqLVLCoWqPlHCo2iQlHKppqPmGqm1SwqFqn5RwqNooJRyqNkoJh6qNUr6hdm2UEg5VG6WEQ9VGKeFQtVFKOFTTUPMNVRulhEPVRinhULVRSjhUbZQSDlUbpXxDHdooJRyqNkoJh6qNUsKhaqOUcKimoeYbqjZKCYeqjVLCoWqjlHCo2iglHKo2SumG+sSgoeYbqjZKCYeqjVLCoWqjlHCopqHmG6o2SgmHqo1SwqFqo5RwqNooJRyqNkr5hnpoo5RwqNooJRyqNkoJh6qNUsKhmoaab6jaKCUcqjZKCYeqjVLCoWqjlHCo2ijlG+qpjVLCoWqjlHCo2iglHKo2SgmHahpqvqFqo5RwqNooJRyqNkoJh6qNUsKhaqOUb6iXNkoJh6qNUsKhaqOUcKjaKCUcqmmo+YaqjVLCoWqjlHCo2iglHKo2SgmHqo1SvqGaNkoJh6qNUsKhaqOUcKjaKCUcqmmo+YaqjVLCoWqjlHCo2iglHKo2SgmHqo1SvqEWbZQSDlUbpYRD1UYp4VC1UUo4VNNQ8w1VG6WEQ9VGKeFQtVFKOFRtlBIOVRulfEOt2iglHKo2SgmHqo1SwqFqo5RwqKah5huqNkoJh6qNUsKhaqOUcKjaKCUcqjZK+YbatFFKOFRtlBIOVRulhEPVRinhUE1DzTdUbZQSDlUbpYRD1UYp4VC1UUo4VG2U8g21a6OUcKjaKCUcqjZKCYeqjVLCoZqGmm+o2iglHKo2SgmHqo1SwqFqo5RwqNoo5Rvq0EYp4VC1UUo4VG2UEg5VG6WEQzUNNd9QtVFKOFRtlBIOVRulhEPVRinhULVRSjfU86GNUsKhaqOUcKjaKCUcqjZKCYdqGmq+oWqjlHCo2iglHKo2SgmHqo1SwqFqo5RvqIc2SgmHqo1SwqFqo5RwqNooJRyqaaj5hqqNUsKhaqOUcKjaKCUcqjZKCYeqjVK+oZ7aKCUcqjZKCYeqjdLfHOobeG19NoE3gd8DXtuTTeC14dgEXluITeC1KdgEXml+Cvx1lpfE6x3Iv4Kfc/KXMvc29ErG/ugve33qq9gP37ke9Z+vrdf5aUhKugBDUioGGJJpSFuH9PRtr29s5dOQlLYBhqRkDjAkpXiAISnxAwxJ24H4QzLtEQCGpI3D5iGVr2/cjk9D0sYBYEjaOAAMyTSk+EPSxgFgSNo4AAxJG4elQ6ofwWuLsAm8NgN7wBel/U3gleA3gVcqnwPfjy/wo/8Afu73ZIqy9jb0JvTu6L1/saIoQQMMSQl675Bmfj5SlKABhqS0DTAkJfP4Q6pK8QBDUuIHGJK2A5uHNPHzkao9AsCQTEOKPyRtHACGpI0DwJC0cQAYkjYOAEPSxmHpkD7+ZLRpi7AJvDYDm8Ar7W8CrwS/CbwJ/B7wStqbwCs9bwKvRLwJvFLuJvBKrlPg7RgviXb9VDs49/uNXdl1G3ql123olV+3oVeC3YbehH4XeqXYbeiVY7ehV5Ldhl5Zdht6pdld6IfS7Db0SrPb0CvNbkOvNLsNvQn9LvRKs9vQK81uQ680uw290uw29Eqzm9BfD6XZbeiVZrehV5rdhl5pdht6E/pd6JVmt6FXmt2GXml2G3ql2W3olWZ3oT+UZrehV5rdhl5pdht6pdlt6E3od6FXmt2GXml2G3ql2W3olWa3oVea3YX+VJrdhl5pdht6pdlt6JVmt6E3od+FXml2G3ql2W3olWa3oVea3YZeaXYX+ktpdht6pdlt6JVmt6FXmt2G3oR+F3ql2W3olWa3oVea3YZeaXYbeqXZXehNaXYbeqXZbeiVZrehV5rdht6Efhd6pdlt6JVmt6FXmt2GXml2G3ql2V3oi9LsNvRKs9vQK81uQ680uw29Cf0u9Eqz29ArzW5DrzS7Db3S7Db0SrO70Fel2W3olWa3oVea3YZeaXYbehP6XeiVZrehV5rdhl5pdht6pdlt6JVmd6FvSrPb0CvNbkOvNLsNvdLsNvQm9LvQK81uQ680uw290uw29Eqz29Arze5C35Vmt6FXmt2GXml2G3ql2W3oTeh3oVea3YZeaXYbeqXZbeiVZrehV5rdhX4ozW5DrzS7Db3S7Db0SrPb0JvQ70KvNLsNvdLsNvRKs9vQK81uQ680uwm9PZRmt6FXmt2GXml2G3ql2W3oTeh3oVea3YZeaXYbeqXZbeiVZrehV5rdhf5Qmt2GXml2G3ql2W3olWa3oTeh34VeaXYbeqXZbeiVZrehV5rdhl5pdhf6U2l2G3ql2W3olWa3oVea/Z8f5A2PCc8dHqXCWzxKbrd4lK5u8SgB3eJRSrnDcylJ3OKR27/FI0d+i0eu+RaPCc8dnkyuefT+z1eP0T4JzuSDpwRncrZTgjN51SnBmdznjGDL5CenBGdyiFOCM3m+KcGZXNyUYGMTzOa0jM1pGZvTMjanZWxOq7A5rcLmtAqb0ypsTqsYm2A2p1XYnFZhc1qFzWkVNqdV2ZxWZXNalc1pVTanVY1NMJvTqmxOK9Xt+SnBbE4r1Z31GcGprptPCWZzWqkueU8JZnNaqa5WTwlmc1qpLjRPCWZzWqmuEU8JZnNaqS7vTglmc1qprsxOCWZzWqkuqk4JZnNaqa6HTglmc1qpLmVOCWZzWqmuQk4JZnNaqS4gTglmc1qprv1NCWZzWqku200JZnNaqa64TQkmc1ol1cWyKcFkTqukus41JZjMaZWHsQkmc1ol1dWlKcFkTqukujA0JZjNaaW6pjMlmM1ppbocMyWYzWmlupIyJZjNaaW6CDIlmM1ppbp+MSWYzWmluvQwJZjNaaW6ajAlmM1ppboOMCWYzWmlavCfEszmtFK17E8JZnNaqZrwpwSzOa1UbfVTgtmcVqpG+SnBbE6LrSO+sHXEF7aO+MLWEV/YOuILW0d8YeuIL2wd8YWtI76wdcQXto74wtYRX9g64gtbR3xh64gvbB3xha0jvrB1xBe2jvjC1hFf2DriC1tHfGHriC9sHfGFrSO+sHXEF7aO+MLWEV/YOuILW0d8YeuIL2wd8YWtI76wdcQXto74wtYRX9g64gtbR3xh64gvbB3xha0jvrB1xBe2jvjC1hFf2DriC1tHfGHriC9sHfGFrSO+sHXEF7aO+MLWEV/YOuILW0d8YeuIL2wd8YWtI76wdcQXto74wtYRX9g64gtbR3xh64gvbB3xla0jvrJ1xFe2jvjK1hFfH8YmmMxpVbaO+MrWEV/ZOuIrW0d8ZeuIr2wd8ZWtI76ydcRXto74ytYRX9k64itbR3xl64ivbB3xla0jvrJ1xFe2jvjK1hFf2TriK1tHfGXriK9sHfGVrSO+snXEV7aO+MrWEV/ZOuIrW0d8ZeuIr2wd8ZWtI76ydcRXto74ytYRX9k64itbR3xl64ivbB3xla0jvrJ1xNdUDeLPj/34+vJz/PDNf/NBzvPqXxK7fX+OPv633/lRXp/5fIzyBs/+7Tv38fWdzx++c7Hzn68tdn0afyZXovH/dvyp2uU1/l+PP5Nj1fh/Pf5M/l3j//X4M6UZjf/X4zeNn3n8mZKuxv/r8Wf6CYvG/+vxZ/p5k8b/6/Fr60c9fm390o6/v75xef++f4w/1aUjjf/X49fWj3r82vpRj19bv7Tjb9/jr5/Gbxo/8/i19aMev7Z+1OPX1o96/Nr6UY9fW7+04y+vj1zqp9/0TXV1U+P/9fi19aMev7Z+1OPX1o96/KbxM49fWz/q8WvrRz1+bf2ox6+tH/X4tfVjHn+qC/Aa/6/Hr60f9fi19aMev7Z+1OM3jZ95/Nr6UY9fWz/q8WvrRz1+bf2ox6+tH/P4h7Z+1OPX1o96/Nr6UY9fWz/q8ZvGzzx+bf2ox6+tH/X4tfWjHr+2ftTj19aPePztoa0f9fi19aMev7Z+1OPX1o96/KbxM49fWz/q8WvrRz1+bf2Yx38o9+8d//Gcwdf4j+o5/p+vebRDuZ96/Mr91ONX7qcev2n8zONX7qcev3I/9fiV+6nHr9/2oR6/ftuHefyntn7U49fWL+34fz7j2E5t/ajHr60f9fhN42cev7Z+acf/8yG3dmrrRz1+bf2ox6+tH/X4tfVjHv+lrR/1+LX1Szv+id/0vbT1ox6/tn7U4zeNn3n82vpRj19bP+rxa+tHPX5t/ajHr60f8/hNWz/q8WvrRz1+bf2ox6+tH/X4TeNnHr+2ftTj19aPevza+lGPX1s/6vFr68c8/qKtH/X4tfWjHr+2ftTj19aPevym8TOPX1s/6vFr60c9fm39qMevrR/1+LX1Yx5/1daPevza+lGPX1s/6vFr60c9ftP4mcevrR/1+LX1ox6/tn7U49fWj3r82voxj78p9y8Yv/PNjaZ0DjAk05DiD0lJF2BIyqMAQ1JqBBiSsh3AkJTA4g+p67cjAIak32EAGJI2DgBD0sZh85AmzrF105DiD0kbB4AhaeMAMCRtHDYPaeJQUNfGAWBI2jjEH9LQxgFgSNo4AAxJGweAIWnjsHlIE78tNExDij8kbRwAhqSNA8CQtHEAGJI2DgBD0sYh/JD6QxsHgCFp4wAwJG0cAIakjQPAkExDij8kbRwAhqSNA8CQtHEAGJI2DgBD0sYh/pAObRwAhqSNA8CQtHEAGJI2DgBDMg0p/pC0cQAYkjYOAEPSxgFgSNo4AAxJG4f4Qzq1cQAYkjYOAEPSxgFgSNo4AAzJNKT4Q9LGAWBI2jgADEkbB4AhaeMAMCRtHOIP6dLGAWBI2jgADMl4h+Tb79gv4jTjjZI4c3ijJE4G3iiJ/bs3SmKX7YzSiL2wN0pix+qNkvgnWd4oiX/e5I3ShNILpdLOFMqfS5i7Ke24oVTacUOptOOGUmlnCuXPlaa9KO24oVTacUOptOOGUmnHDaUJpRdKpR2vnzgWpR03lEo7biiVdtxQKu14oaxKO24olXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5RKO24olXa8UDalHTeUSjtuKJV23FAq7bihNKH0Qqm044ZSaccNpdKOG0qlHTeUSjteKLvSjhtKpR03lEo7biiVdtxQmlB6oVTacUOptOOGUmnHDaXSjhtKpR0vlENpxw2l0o4bSqUdN5RKO24oY/vKXl5fPEapP5Ac7VUlMNqnKoER2/z5643t0Pz1xrZR3nrHI7bX8dcb25D8Su/vnvzPiPD1rdsnOrE9xm46sW3DbjomOjd0Yq8yd9NJ5CIX0EnkORfQSeRQ12W5z5/5jWQi77uX5JHIVW8mSevX3UnSent3krQ5wJ2kiaQTSdp84U6SNou4k6TNLe4klXG8SCrjOJEMfkkdiaQyjhdJZRwvkso4XiRNJJ1IKuN4kVTG8SKpjONFUhnHi6QyjhPJ4LebkUgq43iRVMbxIqmM40XSRNKJpDKOF0llHC+SyjheJJVxvEgq4ziRDH6TG4mkiaTLwd4R/GAvEkm9cXz+0nUEP4wKRDL4XVQkktqqeZHUVs2LpLZqXiRNJH8mWY/6z9fW6/xEUn7Si6S2al4ktVXzIqmM40VSGceJZPBrqEgklXG8SCrjeJFUxvEiaSLpRFIZx4ukMo4XSd6M84vPcVzlq/Dzqm882nhnyZty/Fny5hx3lsEvoWKx5M06/ix5044/S96848/SxHKGZS9fLId9YsmbefxZ8qYef5bKPX4slXv8WCr3uLEMfhMVi6Vyzy9Z2uP4xFK5x4+lco8fSxPLCZZ21i+WV/nEUrnHj6Vyjx9L5R4/lso9fiyVe9xYBr+OisVSuefm72mDXzzdTUfZ5I6Oic4NHeWHOzpKBHd05PHv6GS6lztxfS3Vvdwf9f7n30umg7lTghN51DnBiWznnOBETnJOsLEJTuT35gQnsnBzghO5sjnBVEbrP4LZnFamI6pzgtmcVqaTpHOC2ZxWpgOfc4LZnFamc5lzgtmcVqbjk3OC2ZxWplOOc4LZnFamw4hzgtmcVqYzg3OC2ZxWpqN9c4LZnFamE3hzgtmcVqaDcnOC2ZxWpvNsc4LZnFamY2dzgtmcVqbTYXOC2ZxWpkNcc4LZnFams1ZzgtmclrE5LWNzWpkOqs0JZnNaxua0jM1pZTpANyeYzWllOuc2J5jNaWU6jjYnmM1pZTo1NieYzWllOtw1J5jNaWU6gzUnmM1pZToqNSeYzWllOtE0J5jNaWU6eDQnmM1pZTofNCeYzWllOsUzJ5jNaWU6ajMnmM1pZToPMyeYzWllOrQyJ5jNaWU6WTInmM1pZTr+MSeYzWllOqMxJ5jNaWU6SDEnmM1pZTrtMCeYzWllOpIwJ5jNaWU6NzAnmM1pZSrunxPM5rQyFebPCWZzWplq7ecEszmtTOXzc4LZnBZXRfx/BJM5rYOtI/5g64g/2DriD7aO+KccNsFkTutg64g/2DriD7aO+IOtI/7I1CB+/O4YVR9fn+P84WuLnf98bbHrI0ree4LuKE0ovVDyXip0R8l71tAdJe8NRHeUvGfO3VHyXjn3RpmpEX83St4b5+4olXbcUCrtzKDsr29cRvmI0oTSC6XSjhtKpR03lEo7MyjbN8r6EaXSjhtKpR0vlJmuUuxGqbTjhlJpxw2l0s4MyvL6iWOpH3/imOn6x26USjtuKJV23FAq7bihVNpxQ6m044Uy02WY3SiVdtxQKu24oVTacUNpQumFUmnHDaXSjhtKpR03lEo7biiVdrxQZrrOtBul0o4bSqUdN5RKO24oTSi9UCrtuKFU2nFDqbTjhlJpxw2l0o4XykwX0najVNpxQ6m044ZSaccNpQmlF0qlHTeUSjtuKJV23FAq7bihVNrxQpnpSuFulEo7bigtNMp2vvSOfrYfUD6/+vXF7WOXQPC7ewsEx/ZoCwTHdlILBMf2OwsEx3YlvxL8u+f/VM9m8Ct92/HEdg/b8cTef27HE3unuR2PCc8dnkTucwWeRF51XbD7/JnfUSZywbtRJvLXu1HSOnd3lMEvREKhpE0E/ihp04M/Stqk4Y/ShNILJW2C8UeptOOGUmnHDaXSjhtKpR0nlGfwK61QKJV23FAq7bihVNpxQ2lC6YVSaccNpdKOG0qlHTeUSjtuKJV2vFAeSjtuKJV23FAq7bihVNpxQ2lC6YVSZmjm72omTlaewc/7IqEMfkg1CsqJv/Y6gx9ShUKp144bSi3Z3FBqyeaGUks2N5TylRMo61H/+dp6nR9Ryld6oQx+SBUKpZZsbiiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7XiiDH1KFQsmbdn7xOY5Hta/v/NbldNTyB0zevLMAJm/iWQDTBNMPJm/qWQCTN/csgMmbfBbA5M0+v4I5XjbzOB7lI0ze9OMPM/hpVTCYSkCOMJWAHGEqATnCNMH0g6kE9FuYb+u6/xemEpAjTCUgR5hKQHd/YhL8fOpuPMFPom7Ho9xxi0dJ4haPssEtHhOeOzyZDkdNlPGfwY97LhCc6XDUlOBMh6OmBCdyn1OCgx+dXCA4kUOcE5zI880JTuTi5gQbm2A2p5XqROeUYDanlepE55RgNqeV6ejmnGA2p5XpMOacYDanlel45ZxgNqeV6cDknGA2p5XpWOOcYDanlenw4ZxgNqeV6YjgnGA2p5XpIN+cYDanlem43ZxgNqeV6VDcnGAyp3VlOro2J5jMaV2ZDpjNCSZzWtfD2ASTOa0r02GtOcFkTuvKdKRqTjCb08p08GlOMJvTynQ8aU4wm9PKdIhoTjCb0zrYnNbB5rQyXcCaE8zmtE42p3WyOa1M98LmBLM5rUy3t+YEszmtTHes5gSzOa1MN6HmBLM5rUz3leYEszmtTLeK5gSzOa1Md3/mBLM5rUw3dOYEszmtTPdo5gSzOa1Mt13mBLM5rUxXUuYEszkt4psOvzk3bec/X1vs+ohSt+zcUOqWnRtK3bLzQkl8y8EdpS53u6HU5W43lLrc7YbShNILpS53u6FU2nFDqbQzg7K/vnEZ5SNKpR03lEo7XiiJb0K4o1TamUHZvlHWjyiVdtxQKu24oTSh9EKptOOGUmnHDaXSzgzK8vqJY6kff+KY6frHbpRKO14oM10s2Y1SaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLZaarQbtRKu24oVTacUOptOOG0oTSC6XSjhtKpR03lEo7biiVdtxQKu14ocx0uWs3SqUdN5RKO24olXbcUJpQeqFU2nFDqbTjhlJpxw2l0o4bSqUdJ5SW6XrebpRKO24olXbcUCrtuKE0ofRCqbTjhjK2ryxmL5R19B9QPsG/vrhdHwXHdn/+goPf3VsgOLaTWiA4tt9ZIDi2K/mV4N89/2d6Ni34lb7teGK7h+14Yu8/t+OJvdPcjieRn1yBJ5H7XIAn+OXChXh+E+w+f+Z3lIlc8G6Uifz1bpS0zt0fpQmlF0raROCPkjY9+KOkTRr+KGlTiT9K2gTjjjL49VAolEo7biiVdtxQKu24oTSh9EKptOOGUmnHDaXSjhtKpR03lEo7XiiDX/CFQqm044ZSaccNpdKOG0oTSi+USjtuKJV23FAq7bihVNpxQ6m044Uy+P1uKJRKO24olXbcUCrtuKE0ofRCqbTjhlJpxwtl8PO+QVDOnEK34Od9oVDqtTODcqZFIPghVSiUeu24odSSzQ2llmxuKLVk80IZ/JBqEJT1qP98bb3OjyjlK91QasnmhlJLNjeUJpReKJV23FAq7bihVNpxQ6m044ZSaccLZfBDqlAolXbcUCrtuKFU2nFDaULphVJpxw2l0o4bSqUdN5S8aecXn+OwL5aHXeX7czT7r8HzZqO94IMfaU0Mnjd3bQbPm9KcwL/D5M1pC2CaYPrB5M1qC2DyprUFMHnz2gKYSmyOMJXC3GCW4AdhwWAqLTnCVAKagtlfCo9y1T9g/stXH/baRR5HefvUrfyBXnlpG3oTem/03n8eWYKfs9WQ/v9DUhoEGJJSJsCQlF4BhqRUHH9ImU575x2SUjzAkLQdABiS9ggAQzINKf6QtHEAGJI2DgBD0sYBYEjaOAAMSRuH+EM6tXEAGJI2DgBD0sYBYEjaOAAMyTSk+EPSxgFgSNo4AAxJGweAIWnjADAkbRziD+nSxgFgSNo4AAxJGweAIWnjADAk05DiD0kbB4AhaeMAMCTlpK1DmrlmVkw5CWBIcnd7hzRxVegJQUOKPyS5O4Ahyd0BDEk/TwIYkn6eBDAk5aStQ5ppQi1FOQlgSPp5EsCQ9PMkgCFp4wAwJNOQ4g9JGweAIWnjADAkbRwAhqSNA8CQtHGIP6SqjQPAkLRx8B/Sb77z8fhq8T6O9xbvP/qMq3YOEGPS1gFiTKYxIYxJmweIMWn3ADEmbR8gxqT9w+YxHe1rTGf9OCZtIBDG1LSDgBiTthAQY9IWAmJM2kJAjMk0JoQxaQuxeUxTF/+athAQY9IWAmJM2kJAjElbCIQxdW0hIMakLQTEmLSF+ItjegevvcIm8CbwE+CfPzv7At+PH8A/fxxnXw+byz6iV/rfhl6J3h39eX7hsPIRvDL6JvBK3ZvAK0fvAT+UjDeBV9bdBF7p1R98KS8c7fgIXul1E3gT+D3glV03gVdy3QReyXUTeCXXTeCVXLeArw8l103glVw3gVdy3QReyXUTeBP4CfDPJ8PrO9ej/QB+7od/9aHsug290us29Mqv29ArwW5Drwy7C/2hFLsNvXLsNvRKstvQK8tuQ29Cvwu90uw29Eqz29ArzW5DrzS7Db3S7C70p9LsNvRKs9vQK81uQ680uw29Cf0u9Eqz29ArzW5DrzS7Db3S7Db0SrO70F9Ks9vQK81uQ680uw290uw29Cb0u9ArzW5DrzS7Db3S7Db0SrPb0CvN7kJvSrPb0CvNbkOvNLsNvdLsNvQm9LvQK81uQ680uw290uw29Eqz29Arze5CX5Rmt6FXmt2GXml2G3ql2W3oTeh3oVea3YZeaXYbeqXZbeiVZrehV5rdhb4qzW5DrzS7Db3S7Db0SrPb0JvQ70KvNLsNvdLsNvRKs9vQK81uQ680uwt9U5rdhl5pdht6pdlt6JVmt6E3od+FXml2G3ql2W3olWa3oVea3YZeaXYX+q40uw290uw29Eqz29ArzW5Db0K/C73S7Db0SrPb0CvNbkOvNLsNvdLsLvRDaXYbeqXZbeiVZrehV5rdht6Efhd6pdlt6JVmt6FXmt2GXml2G3ql2U3o20Npdht6pdlt6JVmt6FXmt2G3oR+F3ql2W3olWa3oVea3YZeaXYbeqXZXegPpdlt6JVmt6FXmt2GXml2G3oT+l3olWa3oVea3YZeaXYbeqXZbeiVZnehP5Vmt6FXmt2GXml2G3ql2W3oTeh3oVea3YZeaXYbeqXZbeiVZrehV5rdhf5Smt2GXml2G3ql2W3olWa3oTeh34VeaXYbeqXZbeiVZrehV5rdhl5pdhd6U5rdhl5pdht6pdlt6JVmt6E3od+FXml2G3ql2W3olWa3oVea3YZeaXYX+qI0uw290uw29Eqz29ArzW5Db0K/C73S7Db0SrPb0CvNbkOvNLsNvdLs//gcb3iqEuctHqXCWzxKbrd4lK5u8Zjw3OFRSrnFoyRxi0du/xaPHPktHrnmOzxNrvkWTyLXPHp/ffFoHwUn8sFzghM52znBxiY4kfucE5zIT84JTuQQ5wQn8nxzghO5uCnBPZEvmxPM5rQ6m9PqbE6rG5tgNqfV2ZxWZ3Nanc1pdTanNdic1mBzWoPNaQ02pzWMTTCb0xpsTmuwOa3B5rQGmdPqDzKn1R9kTqs/yJxWz3R7fk6wsQkmc1o903XzOcFkTqtnuuQ9J5jNaWW6Wj0nmM1pZbrQPCeYzWllukY8J5jNaWW6vDsnmM1pZboyOyeYzWlluqg6J5jNaWW6HjonmM1pZbqUOSeYzWllugo5J5jNaWW6gDgnmM1pZbr2NyeYzWllumw3J5jNaWW64jYnmM1pZbpYNieYzWllus41J5jNaWW6RDUnmM1pZbq6NCeYzWllujA0J5jNaWW6pjMnmM1pZbocMyeYzWllupIyJ5jNaWW6CDInmM1pZbp+MSeYzWlluvQwJ5jNaWW6ajAnmM1pZboOMCeYzWllavCfE8zmtDK17M8JZnNamZrw5wSzOa1MbfVzgtmcVqZG+TnBbE6LrSO+s3XEd7aO+M7WEd/ZOuI7W0d8Z+uI72wd8Z2tI76zdcR3to74ztYR39k64jtbR3xn64jvbB3xna0jvrN1xHe2jvjO1hHf2TriO1tHfGfriO9sHfGdrSO+s3XEd7aO+M7WET/YOuIHW0f8YOuIH2wd8eNhbILJnNZg64gfbB3xg60jfrB1xA+2jvjB1hE/2DriB1tH/GDriB9sHfEjU4P481M/vj71OX743r/5HIf1l8KjXPX7czT7t+/cx9d3Pn/4zsXOf7622PVxSIm8Q9ohZWpqzzukRB4t75AS+cq8Q0rkhfMOyTSk+ENKlDnyDinRRjrvkBJt0fMOSRsHgCFp47B3SP31kcson4aU6WJJ3iFp4wAwJG0cAIakjcPeIbXvIdWPQzINKf6QtHEAGJI2DgBD0sYBYEjaOAAMSRuHvUMqr98WKvXjbwtlutyVd0jaOAAMSRsHgCFp4wAwJNOQ4g9JGweAIWnjADAkbRwAhqSNA8CQtHGIP6RMFyzzDkkbB4AhaeMAMCRtHACGZBpS/CFp4wAwJG0cAIakjQPAkLRxABiSNg7xh5TpknPeIWnjADAkbRwAhqSNA8CQTEOKPyRtHACGpI0DwJC0cQAYkjYOAEPSxiH+kJo2DgBD0sYBYEjaOAAMSRsHgCGZhhR/SNo4AAxJGweAIWnjEH9InTcnefc7dt40446SN3O4o+RNBu4oTSi9UPK6bHeUvF7YHSWvY3VHyfuTLHeUvD9v8kY5lHbcUCrtzKCcKWEeSjtuKJV23FCaUHqhVNqZQTlTaTqUdtxQKu24oVTacUOptOOD8j//caH0Qqm04/MTx+d/XGnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOF8lDacUOptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOF8lTacUOptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOF8lLacUOptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUOptOOF0mL7yqu9NAwbjx9QjvbqEhjt+ig4tvtbINjYBMd2UgsEx/Y7CwTHdiW/Evy75//oX996fH6mx3Ya2/HEdg+78ZTY+8/teGLvNLfjSeQnV+BJ5D5X4DFWPL8Jdp8/8zvKRC54N8pE/no3Slrn7o+S1uX7o6RNBO4oK2168EdJmzT8UdKmEn+UtAnGH6UJpRdKpR03lEo7biiVdtxQKu24oVTa8UIZ/PI3FEqlHTeUSjtuKJV23FCaUHqhVNpxQ6m044ZSaccNpdKOG0qlHS+Uwe93Q6FU2nFDqbTjhlJmaObvan4+WflEKTPkhTL4IdUoKGf+2iv4IVUolHrtuKHUks0NpQmlF0ot2dxQyldOoKxH/edr63V+RClf6YZSSzY3lFqyOaE8gh9ShUKptOOGUmnHDaXSjhtKE0ovlEo7biiVdtxQKu24oVTacUPJm3Z+8Tn+0wXy9Z3r8f052vEOM/gpVTCYvIlnAUzezLMAJm/qWQDTBNMPJm/yWQCTN/v8Cma3r+88ro8wedPPApi8+WcBTCUgP5jBz6uCwVQCcoSpBOQIUwnolzCf/5WPME0w/WAqATnCVAK6+ROTI/j51O14lFJu8Sh33OEJfrp0Ox5lg1s8cvu3eDIdjpoo4z+CH/dcIDjT4agpwZkOR00JTuQ+5wQn8pNzghM5xCnBlsjzzQlO5OLmBGc60TklmM1ppTrROSWYzWmlOtE5JZjNaWU6ujknmM1pZTqMOSeYzWllOl45J5jNaWU6MDknmM1pZTrWOCeYzWllOnw4J5jNaWU6IjgnmM1pZTrINyeYzWllOm43J5jNaWU6FDcnmM1pZTq6NieYzWllOmA2J5jNaWU6BjYnmM1pZTqsNSeYzWllOlI1J5jNaWU6+DQnmM1pZTqeNCeYzWllOkQ0J5jNaXVjE8zmtDJdwJoTzOa0OpvT6mxOK9O9sDnBbE4r0+2tOcFsTivTHas5wWxOK9NNqDnBbE4r032lOcFkTuvMdKtoTjCZ0zoz3f2ZE0zmtM6HsQkmc1pnpns0c4LJnNaZ6bbLnGA2p5XpSsqcYDanRXzT4Tfnpu11haDY9RGlbtm5odQtOzeUumXnhlK37NxQ6nK3F0riOw7uKHW52w2lLne7odTlbjeUJpReKJV2ZlD21zcuo3xEqbTjhlJpxw2l0o4bSqWdGZTtG2X9hJL41oQ7SqUdN5RKO24olXbcUJpQeqFU2plBWV4fo9SPP3HMdP1jN0qlHTeUSjtuKJV2vFBmurKyG6XSjhtKpR03lEo7bihNKL1QKu24oVTacUOptOOGUmnHDaXSjhfKTJeOdqNU2nFDqbTjhlJpxw2lCaUXSqUdN5RKO24olXbcUCrtuKFU2vFCmena2G6USjtuKJV23FAq7bihNKH0Qqm044ZSaccNpdKOG0qlHTeUSjteKDNd/NuNUmnHDaXSjhtKpR03lLF95Xm+vnhc1/gB5WivLoHRPnYJBL+7t0BwbI+2QHBsJ+UvOPjdvQWCY7uSXwn+3fN/qmcz+JW+7Xhiu4fteEx47vDE3mlux5PIT67Ak8h9rsCTyKuuC3afP/M7ykQueDPK4NcWoVDSOnd/lLQu3x8lbSLwR2lC6YWSNmn4o6RNJf4oaROMP0qlHTeUSjtOKK/gF0+hUCrtuKFU2nFDqbTjhtKE0gul0o4bSqUdN5RKO24olXbcUCrteKEMfnUYCqXSjhtKpR03lEo7bihNKL1QKu24oVTa8UIZ/LxvEJQzJyuv4Od9oVDqteP0115X8EOqUCj12nFDqSWbG0ot2dxQasnmhTL4IdUgKOtR//naep0fUcpXuqHUks0NpZZsbihNKL1QKu24oVTacUOptOOGUmnHDaXSjhfK4IdUoVAq7bihVNpxQ8mbdn7xOY5HOb++cz2+P0c7/oBpgukHkzfxLIDJm3kWwORNPQtg8uaeBTB5k48/zOBnVcPA7Pb1ncf1ESZv+lkAkzf/LICpBOQI0wTTD6YSkCNMJSBHmEpAv4T5/K98hKkE5AhTCcgPZvBTq1tgvuNRprnFo5Ryi0e54xaPCc8dHmWDWzxy+7d4Mh2Omijjv4If91wgONPhqBnBwQ9lLhCcyH3OCU7kJ+cEJ3KIc4KNTXAiFzcnONOJzinBbE4r1YnOKcFsTivVic4pwWxOK9PRzTnBbE4r02HMOcFsTivT8co5wWxOK9OByTnBbE4r07HGOcFsTivT4cM5wWxOK9MRwTnBbE4r00G+OcFsTivTcbs5wWROyzIdipsTTOa0LNPRtTnBZE7LHsYmmMxpWaZjYHOCyZyWZTqsNSeYzWllOlI1J5jNaWU6+DQnmM1pZTqeNCeYzWllOkQ0J5jNaR1sTutgc1qZLmDNCWZzWieb0zrZnFame2FzgtmcVqbbW3OC2ZxWpjtWc4LZnFamm1BzgtmcVqb7SnOC2ZxWpltFc4LZnFamuz9zgtmcVqYbOnOC2ZxWpns0c4LZnFam2y5zgtmcVqYrKXOC2ZwW8U2H35ybttcVgmLXR5S6ZeeFkviegztK3bJzQ6lbdm4odbnbDaUJpRdKXe52Q6nL3W4odbnbDaXSjhtKpZ0ZlP31jcson1AS325wR6m044ZSaccNpdLODMr2jbJ+RGlC6YVSaccNpdKOG0qlHTeUSjtuKJV2ZlCW108cS/34E8dM1z92o1TacUOptOOGUmnHDaUJpRdKpR03lEo7biiVdtxQKu24oVTa8UKZ6QLPbpRKO24olXbcUCrtuKE0ofRCqbTjhlJpxw2l0o4bSqUdN5RKO14oM13B2o1SaccNpdKOG0qlHTeUJpReKJV23FAq7bihVNpxQ6m044ZSaccJZcl0iW43SqUdN5RKO24olXbcUJpQeqFU2nFDqbTjhlJpxwtl8Lt7h70+xzh6/wGld+9ACX6jbzOc2N5vM5zYbm4zHBOcz3BiO67NcGJ7qM1wYruizXBib3U3w4m9p90LJ/i9xM1wWB3yRBVPCX6HcTMcVoc8BccE5zMcVoc8UR5Sgt+N3AyH1SFPwWF1yFNwWB3yDJzgdy43w2F1yDM/fQh+P3MzHFaHPAXHBOczHFaHPAWH1SFPwWF1yFNwWB3yFBxWhzwDJ/h90s1w5JBv4Mgh38CRQ76BY4LzGY4c8g0cOeQbOHLIN3DkkG/gyCF/hhP8Cu9mOHLIN3DkkG/gyCHfwDHB+QxHDvkGjhzyDRw55Bs4csg3cOSQP8MJfrl1Mxw55Bs4csg3cOSQb+CY4HyGI4d8A0cO+QaOHPINHDnkGzhyyJ/hxL6r2PvXrwv3JyhPODN/qRf7UuJuOCY4n+GE9jm74YT2ObvhhPY5u+GE9jm74YT2OZvhxL7ztxtO6E3gbjhyyDdwWB3yzB/dx76XtxsOq0OegsPqkKfgsDrkmT+djn13bjccVoc8Ayf2bbjdcFgd8hQcVoc8BYfVIc/89CH2jbXdcFgd8hQcVoc8BYfVIU/BYXXIU3BYHfIEnBr7nthuOKwOeQoOq0OegiOHfAPHBOczHDnkGzhyyDdw5JBv4Mgh38CRQ/4MJ/ZltN1w5JBv4Mgh38CRQ76BY4LzGY4c8g0cOeQbOHLIN3DkkG/gyCF/hhP7MtpuOHLIN3DkkG/gyCHfwDHB+QxHDvkGjhzyDRw55Bs4csg3cOSQP8OJfRltNxw55Bs49tfhOP89Xd1whcpdQsWX0PAldHwJA17ChhtG7hIOfAknvoQLXwL+29liv50n/ni2Wuy385SE2G/nKQmx385TEmK/nSf+NK+W2G/nKQmx385TEmK/nackxH47T0mI/XaekhD77TyzwSix385TEmK/nackxH47T0mI/XaekVBjv52nJMR+O09JiP12npIQ++08JSH223lKAv7bueK/nSv+27niv50r/tu54b+dG/7bueG/nRv+23lDE767BPy3c8N/Ozf8t3PDfzs3/Ldzx387d/y3c8d/O3f8t/OGFm53Cfhv547/du74b+eO/3bu+G/ngf92Hvhv54H/dh74b2efHtfj9anOo5qnhJnfCvNpW90roeNLGOgSmk+/6F4JB76EE1/ChS/B8CUUfAnwb+f2iP12nvhV2/aI/XaekhD77Twj4Yj9dp6SEPvtPPFLnu2I/XaekhD77TwlIfbbeUpC7LfzlITYb+cpCbHfzhMbjHbEfjtPSYj9dp6RcMZ+O09JiP12npIQ++08JSH223lKQuy385SE2G/nKQmx385TEvDfzif+2/nEfztf+G/nC//tfOG/nS/8t7NPS9VeCfhv5wv/7Xzhv50v/Lfzhf92Nvy3s+G/nQ3/7Wz4b2eflqq9EvDfzob/djb8t7Phv50N/+1c8N/OBf/tXPDfzgX/7ezTUrVXAv7b2aUf6WHlJeExHp4SZn4rzKUfaa8El36kzRIOfAknvoQLX4LhSyj4Eiq+hIYvAf/tXGO/nWd+1bbFfjtPSYj9dp6SEPvtPCUh9tt55pc8XfqRNkuI/XaekhD77TwlIfbbeUpC7LfzlITYb+eZDUaP/XaekhD77TwlIfbbeUpC7LfzlITYb+cpCbHfzlMSYr+dpyTEfjtPSYj9dp6SgP92Hvhv54H/dh74b+eB/3Ye+G/ngf92Hvhv54H/dh74b+cB/3buD/i3c3/Av537A/7t3B/wb+f+gH879wf827k/4N/O/QH/du4P+Ldzf+C/nQ/8t/OB/3Y+8N/OB/7b2aWlarME/Lfzgf92PnDfztdR7f/7UILRzvb6/OMYb5+/ff8vx3/7v/xQ+TDzvzz+6//l+d/8L6/r8f+d/97i9cwo//wvx7A/Bvz9Pxz/5f/w3xurZv6Hx3/7Pzz/2//h9d/+D+2//R86PPeOUa+vuff6w//F1aP+88X1Ov/H/xX93w9VI36oFvFD9Ygfaqz9UF//IY+2m7n/0PG3/kPn3/oPXX/rP2R/6z9U/tZ/qP6t/1D7W/+h/rf+Q3899//nl9xf3/t89O+v7sf3x7JHzI8VOp+31r6+9vr3F4GFTuczAkJn8xkBhi4gdC6fERA6lc8ICJ3JZwSE3pfPCAi9LZ8QUELvymcEoL+JC/qbuKC/iV0aNbYKQH8TF/Q3cUF/E8fuM5kRgP4mjt1lMiMA/U0cu8dkRgD6mzh2h8mMAPQ3MXBzxj8CcFut/q+A4H0Ntz9o/78CcH9r5h8BoZ9CMwJwf2PmHwG4vy/zjwDg35b5vwJCvwcmftIdu6FhQkDsfoYZAaHzwIyA0G/iGQGh38QzAkK/iWcEhH4TzwgI/SaeERD6TTwjAP1NHLuNYUJA7C6GGQF//038cdPwP7/2OMbLjh7n482Pvv/CzYYmBncJF74Ew5dQ8CVUfAkNX0KPI+H7Q414H+p6/PXrLcfx/ecuh739Dudhbx/riPmxQl9ZmRl36BsrMwIMXUDo+yozAkLfPpsREPry2YyA0HfPZgSEvno2IeB4oAsIffFsRgD6m/hAfxO7tBdsFYD+Jj7Q38QH+pv4QH8TH+hv4hP9TXyiv4lP9Dfxif4mPtHfxCf6m/hEfxOf6G/iE/1NfKK/iS/0N/EV+/70j7+dfF2h3wMzAkI/hX7+zczrCv0UmhEQ+ik0IcBCP4VmBITOAzMCQueBGQGh3wM//0rRZaHfAzMCQueBGQGh88CMgNBv4hkBod/EMwJCv4knBJTQb+IZAaHfxDMCQr+JZwSgv4ld2ku2CkB/E5e//yb+zS8zPvr3L5093n6d7/2XzkrDl9DxJQx4CfWBL+HAl3DiS7hiS/jK+E8Jxx8S/uU7j6/v/Hjr3u/9Ta5xyS1ccmM7hD9+Lf3T/z3GdghTEmI7hCkJsR3CjIQW2yFMSYjtEKYkxHYIUxJiO4SZv/VxaRraLCH2m3xKQqC38/eHCvS+/f5QLm/Q8bpGcZ7l/OFDHeXrdEWxDx9qBPxQLu09v/pQzr+p4tLes1XAiS7gQhdg6AIKuoCKLqChC+joAga4gIH+Jh7ob+KB/iYe6G9il96erQLQ38QD/U080N/EA/1NPMDfxPYAfxPbA/xNbA/wN7E9wN/E9gB/E9sD/E1sD/A3sT3A38T2AH8T2wP9TXygv4kP9Dfxgf4mPtDfxD7dQjsFoL+JD/Q38YH+Jj7Q38QH+pv4RH8Tn+hv4hP9TXyiv4l9uoV2CkB/E5/ob+IT/U18or+JT/Q38YX+Jr7Q38QX+pv4Qn8T+7Q77RSA/ia+0N/EF/qb+EJ/E1/ob2JDfxMb+pvY0N/Ehv4m9unX2ikA/U1s6G9iQ38TG/qb2NDfxAX9TVzQ38QF/U1c0N/EPv1aOwWgv4kL+pu4oL+JC/qbuKC/iSv6m7iiv4kr+pu4or+JfTqydgpAfxNX9DdxRX8TV/Q3cUV/Ezf0N3FDfxM39DdxQ38T+/RW7RSA/iZu6G/ihv4mbuhv4ob+Jkbv2DL0ji1D79gy9I4tQ+/YMvSOLUPv2DL0ji1D79gy9I4tQ+/YMvSOLUPv2DL0ji1D79gy9I4tQ+/YMvSOLUPv2DL0jq2C3rFV0Du2CnrHVkHv2CoP8DdxQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YKesdWQe/YKugdWwW9Y6ugd2wV9I6tgt6xVdA7tgp6x1ZB79gq6B1bBb1jq6B3bBX0jq2C3rFV0Du2CnrHVkHv2CroHVsFvWOroHdsFfSOrYLesVXQO7YqesdWRe/YqugdWxW9Y6s+wN/EFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79iq6B1bFb1jq6J3bFX0jq2K3rFV0Tu2KnrHVkXv2KroHVsVvWOrondsVfSOrYresVXRO7YqesdWRe/YqugdWxW9Y6uid2xV9I6tit6xVdE7tip6x1ZF79hq6B1bDb1jq6F3bDX0jq32AH8TN/SOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOroXdsNfSOrYbesdXQO7YaesdWQ+/YaugdWw29Y6uhd2w19I6tht6x1dA7thp6x1ZD79hq6B1bDb1jq6F3bDX0jq2G3rHV0Du2GnrHVkPv2GroHVsNvWOro3dsdfSOrY7esdXRO7b6A/xN3NE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tjt6x1dE7tjp6x1ZH79jq6B1bHb1jq6N3bHX0jq2O3rHV0Tu2OnrHVkfv2OroHVsdvWOro3dsdfSOrY7esdXRO7Y6esdWR+/Y6ugdWx29Y6ujd2x19I6tgd6xNdA7tgZ6x9ZA79gaD/A38UDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2BnrH1kDv2BroHVsDvWNroHdsDfSOrYHesTXQO7YGesfWQO/YGugdWwO9Y2ugd2wN9I6tgd6xNdA7tgZ6x9ZA79ga6B1bA71ja6B3bA30jq2B3rE10Du2np8U/FX8n08KrwD8Zfz8pOBv4+cnBX8dPz8p+Pv4+UnBX8jPTwr+Rn5+UvBX8vOTwr+T0eu2ngrg38nohVtPBfDvZPTKracC+HcyeunWUwH8Oxm9duupAP6djF689VQA/05Gr956KoB/J6OXbz0VwL+T0eu3ngrg38noBVxPBfDvZPQKrqcC+HcyegnXUwH8Oxm9huupAP6djF7E9VQA/05Gr+J6KoB/J6OXcT0/Hvw7Gb2O6/nx4N/J6IVcz48H/05Gr+R6fjz4dzJ6Kdfz48G/k9FruZ4K4N/J6MVcTwXw72T0aq6nAvh3Mno511MB/DsZvZ7rqQD+nYxe0PVUAP9ORq/oeiqAfyejl3Q9FcC/k9Frup4K4N/J6EVdTwXw72T0qq6nAvh3MnpZ11MB/DsZva7rqQD+nYxe2PVUAP9ORq/seiqAfyejl3Y9FcC/k9Fru54K4N/J6MVdTwXw72T06q6nAvh3Mnp511MB/DsZvb7rqQD+nYxe4PVUAP9ORq/weiqAfyejl3g9FcC/k9FrvJ4K0N/JB3yP1wHf43XA93gd8D1ez88HrwD9nXzA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eB3yP1wHf43XA93gd8D1eJ3yP1wnf43XC93id8D1e5wP9nXzC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wnf43XC93id8D1eJ3yP1wXf43XB93hd8D1eF3yP1/VAfydf8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd8D1eF3yP1wXf43XB93hd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necKfsthhWI6zxX87sIKxXSeK/iNhBWK6TxX8HsGKxTTea7gtwdWKKbzXMHvBKxQTOe5gnf6r1BM57mC9++vUEznuYJ35a9QTOe5gvfar1BM57mCd9CvUEznueh66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99o+uhb3Q99I2uh77R9dC3h9EpZvNcja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32n66HvdD30na6HvtP10PeH0Slm81ydroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peuh7po7y0c7XF7c/v/Ob3kRv4ym9iZ7To/fXF4/2SW+ip/SU3kTP6Cm9iZ7QU3oTZeIZvZkaq6f0Znr/zujN9P6d0ZsoC0/pNTK9ZP4qU0v1lF5Yf/WmAdYzvWmI7YOu9vVPycbDJZkH75FeoTi2F1qhOLYbWqE4th9aodjoFMf2RCsUx3ZFKxTH9kUrFMd2USsU03mu4D3SKxTTea7gPdIrFNN5ruA90isU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3CMt0RzcJa3QHL0He4nm4E5piebgXmmJ5uDOaolmI9RM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RTOjDovdgL9FM6MOi92Av0Uzow6L3YC/RzOfDWvQe7CWa+XxYi96DvUQznw9rDyPUzOfDWvQe7CWa+XxYi96DvUQzoQ+L3oO9RDOhD4veg71EM6EPi96DvUQzoQ+L3oO9RDOhD4veg71EM6EPi96DvUQzoQ+L3oO9RDOhD4vej/w7zRNthC16O7K/4uidub9U/HMzTovemLtAcarn9ZTiVE/rKcVGpzhVYp5SnOt9PKM41/t4RnGqrDylOFVSnlEcvfN6gWI6zxW98/pO8ZsKYB/1psJCqzgex5eK41GOH/71lS/Npffv730e74pje6MVimN7o18qbn18fe/zh+/9+XO80Ynto3bTie25dtOJ7c820wnepb2bTmzft5tObI+4m05s77mbjonODZ1U/tedjrzyHR155Ts68sp3dOSVb+gE71PfTUde+Y6OvPIdHXnlOzomOjd05JXv6Mgr39GRV76jI698R0de+YZO8M773XTkle/oyCvf0ZFXvqNjonNDR175jo688h0deeU7OvLKd3TklW/oBL9LsJuOvPIdHXnlOzryynd0THRu6Mgr39GRV76jI698R0de+Y6OvPINneC3I3bTkVe+oyOvfEdHXvmOjonODR155Ts68sp3dOSV7+jIK9/RkVf+TKcHv++xm4688h0deeU7OvLKd3RMdG7oyCvf0ZFXvqMjr3xHR175jo688g2d4DdYdtORV76jI698R0de+Y6Oic4NHXnlOzryynd05JXv6Mgr39GRV76hE/xOzm468sp3dOSV7+jIK9/RMdG5oSOvfEdHXvmOjrzyHR155Ts68so3dILfJ9tNR175jo688h0deeU7OiY6N3Tkle/oyCvf0ZFXvqMjr3xHR175hk7wu3K76cgr39GRV76jI698R8dE54aOvPIdHXnlOzryynd05JXv6Mgr39DR3b5bOvLKd3Tkle/oyCvf0THRuaEjr3xHR175jo688h0deeUbOrzXxYq9vnOxj3Ro3+hT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FYpjO64Viuk8V/ArLisUG51iOs8V/JbLCsV0niv4PZcVitk8Vw1+02WFYjbPVYPfdVmhmM1z1YfRKWbzXDX43ZgVitk8Vw1+42WFYjrPFfweywrFdJ4r+O2UFYrpPFfwOycrFNN5ruA3SVYopvNcwe+HrFBM57mC3/pYoZjOcwW/y7FCMZ3nCn5DY4ViOs8V/N7FCsV0niv4bYoViuk8V/A7EisU03mu4DcfViim81zB7zOsUEznuS46zxX8ssYKxXSe66LzXEbnuYJfOlmhmM5zBb9KskKx0Smm81zB74KsUEznuYLf8FihmM5zBb+3sUIxnecKfhtjhWI6zxX8jsUKxXSeK/jNiRWK6TxX8PsQKxTTea7gtxxWKKbzXMHvLqxQTOe5gt9IWKGYznMFv2ewQjGd5wp+e2CFYjrPFfxOwArFdJ4reKf/CsV0nit4//4KxXSeK3hX/grFdJ4reK/9CsV0nit4B/0KxXSei66HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dA3uh76RtdD3+h66BtdD317GJ1iNs/V6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10He6HvpO10Pf6XroO10PfX8YnWI2z9Xpeug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7X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k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//SLrb7/I+tsvsv72i6y//XoYmV4uf3WR9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tRtbfbmT97UbW325k/e32MDK9XP7KyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dMvVdj3a+vrhdn/Qmeh/N6M3Uhzx6f33xaJ/0JnpeTelN9Lya0mtkehPlwSm9ifLglN5M798ZvZnevzN6E+XBGb2Z+pCn9JL5q0x9yFN6Yf3VmwZLoCG2D2rneGnoZ/sulz9GfX3q43j71LW8K47thFYoju2FViiO7YZWKI7thxYoDt5gvEJxbE+0QnFsV7RCcWxftEKx0Smm81zB24xXKKbzXMEbjVcopvNcwVuNVyim81zBm41XKKbzXMHbjVcopvNcwRuOVyim81zBW45XKGbzXCV40/EKxWyeqwRvO16hmM1zlYfRKWbzXCV46/EKxWyeqwRvPl6hmM5zBW8/XqGY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E7S/XjJ/FbwF2l8vmb8K3gDtr5fMXwVvf/bXS+avgjc/++sl81fBW5/99ZL5q+CNz/56yfxV8LZnf71k/ip407O/XjJ/Fbzl2V8vmb8K3vDsr5fMXwVvd/bXS+avgjc7++sl81fBW5399ZL5q+CNzv56yfxV8DZnf71k/ip4k7O/XjJ/FbzF2V8vmb8K3uDsr5fMXwVvb/bXS+avgjc3++sl81fBW5v99ZL5q+CNzf56yfxV8LZmf71k/ip4U7O/XjJ/Vcj8VfAebne9wXu4/fWS+atK5q+C96z76zUyvWT+KnjPur9eMn8VvGfdXy+Zvwres+6vl8xfBe9Z99dL5q+C96z76yXzV8E72f31kvkrsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//SLrb7/I+tsvsv72i6y//XoYmV4uf3WR9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tRtbfbmT97UbW325k/e32MDK9XP7KyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrbjay/3cj6242sv93I+tuNrL/dyPrb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do/Y/9g9Yv9j94j9j90j9j92j9j/2D1i/2P3iP2P3SP2P3aP2P/YPWL/Y/eI44/dI44/do84/tg94vhj94jjj90jjj92jzj+2D3i+GP3iOOP3SOOP3WPaJJfpM5be/5L+/Hbv/QPvyXXJL8aveK65k6v697pdbVOr2vp9LrWTq9r6/S69k6v6+jzuqZO7/dTp/f7qdP7/dTp/X7q9H4/dXq/nzq930+d3u+nTu/3U6f3+7nT+/3c6f1+7vR+P3d6v587vd/Pnd7v507v93On9/u50/v93On9/t7p/f7e6f3+3un9/t7p/f7e6f3+3un9/t7p/f7e6f3+3un9/t7p/b51er9vnd7vW6f3+9bp/b51er9vnd7vW6f3+9bp/b51er9vnd7vl07v90un9/ul0/v90un9fun0fr90er9fOr3fL53e75dO7/dLp/f7tdP7/drp/X7t9H6/dnq/Xzu936+d3u/XTu/3a6f3+7XT+/3a6f1+6/R+v3V6v986vd9vnd7vt07v91un9/ut0/v91un9fuv0fr91er/fO73f753e7/dO7/d7p/f7vdP7/d7p/X7v9H6/d3q/3zu93++d3u+PTu/3R6f3+6PT+/3R6f3+6PR+f3R6vz86vd8fnd7vj07v90ef9/ul09/XLp3+vnbp9Pe1S6e/r11ufd7vl05/X7t0+vvapdPf1y6d/r526fT3tUunv69dOv197dLp72uXTn9fu3T6+9ql09/XLp3+vnbp9Pe1S6e/r106/X3t0unva5dOf1+7dPr72qXT39cunf6+dun097VLp7+vXTr9fe3S6e9rl05/X7t0+vvapdPf1y6d/r526fT3tUunv69dOv197dLp72uXTn9fu3T6+9ql09/XLp3+vnbp9Pe1S6e/r106/X3tevVp0P/66p9tQL89Xz19/ed75r/fgP6j995u6+Ott+X2/eo2/5vvPN+XxzvP9+Nla/vR/u6d9+P5zvOHd/768/712q8/qDeKXn3qNor+cUU72g6HohJFO9qsh6ISRTvaSoiiEkUbihZTtKNNxygqUbSjLdEoKlG0ow3bKCpRtKPt5CgqUZTOqJai243OaCRF99tD0WN5pyidUTVF6YyqKUpnVE3RhqIDKbp9K7q+U5TOqJqidEbVFKUzqqYonVE1RemMiik60RmNpOiyPxRdt3eK0hlVU5TOqJqidEbVFG0oWkxROqNqitIZVVOUzqiaonRG1RSlMyqm6ExnVE1ROqNqitIZVVOUzqiaog1FiylKZ1RNUTqjaorSGVVTlM6omqJ0RsUUvdMZVVOUzqiaonRG1RSlM6qmaEPRYorSGVVTlM6omqJ0RtUUpTOqpiidUTFFG51RNUXpjKopSmdUTVE6o2qKNhQtpiidUTVF6YyqKUpnVE1ROqNiii7k0QsUnfanoktTKho4A3shj1ZTlDxaTdGGosUUJY9WU5Q8Wk1R8mg1Rcmj1RTlOwzFFF35DkM1RemMqilKZzSSooENPiudUTVFG4oWU5TOqJqidEYjKRrYDrLSGVVTlM6omqJ0RsUU3eiMqilKZ1RNUTqjkRQNfBdwozOqpmhD0WKK0hlVU5TOqJqidEbVFKUzqqYonVExRXc6o2qK0hlVU5TOqJqidEbVFG0oWkxROqNqitIZVVOUzqiaonRG1RSlMyqm6EFnVE1ROqNqitIZVVOUzqiaog1FiylKZ1RNUTqjaorSGVVTlM6omqJ0RrUU3W90RtUUpTOqpiidUTVF6YyqKdpQtJiidEbVFKUzqqYonVE1RemMqilKZ1RM0YnOqJqi5FG9ovPziM0vcaWb8D6fgb1PDUWLKUoeraYoebSaouTRaoqSR6spSh4tpuhMHq2mKN9hqKYo32GopiidUTVFG4oOpOjnDT77TGdUTVE6o2qK0hlVU5TOaCRFP28H2Wc6o2KK3umMqilKZ1RNUTqjaorSGVVTtKHoQIoGvgt4pzOqpiidUTVF6YyqKUpnVE1ROqNiijY6o2qK0hlVU5TOqJqidEbVFG0oWkxROqNqitIZVVOUzqiaonRG1RSlMyqm6EJnVE1ROqNqitIZVVOUzqiaog1FiylKZ1RNUTqjaorSGVVTlM6omqJ0RsUUXemMqilKZ1RNUTqjaorSGVVTtKFoMUXpjKopSmdUTVE6o2qK0hlVU5TOqJiiG51RNUXpjKopSmdUTVHyaExR8UnVG6kxhzvZLoc7CSyHOzkphftOmsnhTubI4U4yyOHOZ7453BvcU7iTV3O4k1f13AObOHbyag538moOd/JqCveDvKrnHjh9/iCv5nAnr+ZwJ6/mcG9wT+FOXs3hTl7Vcw98n+Agr+ZwJ6/mcCevZnA/buTVHO7k1Rzu5NUc7uTVHO4N7incyas53MmrOdzJqzncyas53MmrKdwn8moOd/JqDnfyag538moO9wb3FO7k1Rzu5NUc7uTVHO7k1Rzu5NUU7jN5NYc7eTWHO3k1hzt5NYd7g3sKd/JqDnfyag538moOd/JqDnfyagr3O3k1hzt5NYc7eTWHO3k1h3uDewr3Wv5deyrSca/lstV0anlhMZ1Wy7Gq6dTylWo6tdyfmk4tj6am06BzQqdWP6+mU6tFV9PBK5/R8fXKn8/fO5qvVw7QWXy9coSOr1eO0PH1yp/PyToWX68codOgc0LH1ytH6Ph65QgdX68coePrlQOfSSy+XjlAZ/X1yhE6vl45QsfXK0fo+HrlCJ0GnRM6vl45QsfXK0fo+HrlCB288hkdvPIJnQ2vfEYHr3xGB698RgevfEanQeeEDl75jA5e+YwOXvmMDl75jA5e+YTOjlc+o4NXPqODVz6jg1c+o9Ogc0IHr3xGB698RgevfEYHr3xGB698QqfYNnU1HbzyGR288hkdvPIZnQadEzp45TM6eOUzOr37nWl+0rkt0yc6P3jveb0/r3rdX76xfP+7d56O509y5tt8+76O7fbvqvTxN4bbrfutwKj0l0q9+z9U+kul3n0oKv2lUu9+GJX+Uqmh0gAq9Z4PUOkvlXrPKaj0l0q9f7aASn+p1PtnHKj0l0p0DwOo1P2G5/oqfTwN5ksluocRVKJ7GEEluocRVGqolKzSxxNfvlSiexhBJbqHEVSiexhBJbqHEVSiexhApe63dddX6eN3iL5UonsYQSW6hxFUonsYQaWGSgOoRPcwgkp0DyOoRPcwgkp0DyOoRPcwgErdb15Hpb9UonsYQSW6hxFUonsYQaWGSgOoRPcwgkp0DyOoRPcwgkp0DyOoRPcwgEqN7mEElegeRlCJ7mEElegeRlCpodIAKtE9jKAS3cMIKtE9jKAS3cMIKtE9DKDSQvcwgkp0DyOoRPcwgkp0DyOo1FBpAJXoHkZQie5hBJXoHkZQie5hAJVW37y0rE/u6236pNJ9e4Cf2vKt0tz2vyX/ePGyvbzzPL2S981A2eR9c002+Qb5JPK++SObvG+muJL8sfx68Xpb3pH3zQnZ5H29fzZ5388Sk8lvvp8PXkp+epJf35Enw2aRJ8NmkSfDZpFvkE8iT4bNIk+GvYL8/twytO/vyJNhs8iTYbPIk2GTyO9k2CzyZNgs8mTYLPJk2CzyDfJJ5MmwWeTJsFnkybBZ5MmwWeTJsEnkDzJsFnkybBZ5MmwWeTJsFvkG+STyZNgs8mTYLPJk2CzyZNgs8mTYHPJfiCGfRJ4Mm0WeDJtFngybRb5BPok8GTaLPBk2izwZNos8GTaLPBk2ifxEhs0iT4bNIk+GzSJPhs0i3yCfRB4/HyM/T+1xIfO+fSL/+UynacLPZ5HHzyeRn/HzWeTx81nk8fNXkP984sQ04+ezyDfIJ5HnM6ks8nwmlUWeDJtFngx7BflAbzOTYZPI38mwWeTJsFnkybBZ5MmwWeQb5JPIk2GzyJNhs8iTYbPIk2GzyJNhk8g3MmwWeTJsFnkybBZ5MmwW+Qb5JPJk2CzyZNgs8mTYLPJk2CzyZNgk8gsZNos8GTaLPBk2izwZNot8g3wSeTJsFnkybBZ5MmwWeTJsFnkybBL5lQybRZ4Mm0WeDJtFngybRb5BPok8GTaLPBk2i7yvn5/25XnV7fhAPnJ6x+br0PUsfT23nqWvi9az9PXFepYNliGWx+PF6215x9LXu+pZ+rpRPUvfz0j0LH0/9fghy8+n0WzkHhnLndyjY0nu0bEk9+hYknt0LBssQywD/eVO7tGxJPfoWJJ7dCzJPTqW5B4Zy4Pco2NJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktyjYjnfyD06luQeHUtyj44luUfHssFSxpLco2NJ7tGxJPfoWJJ7dCzJPTKWE7lHx5Lco2NJ7tGxJPfoWDZYyliSe3QsyT06luQeHUtyj44luUfGcib36FiSe3QsyT06lr7+8nZ/zPjVlrVPLD+fazDPvv5Sz9LXX+pZ+vpLPUtffylneff1lz9j+fmMiPnu6y/1LH39pZ6lb6+uZ9lgGWP58bf4853co2NJ7tGxJPfoWJJ7dCzJPTKWjdwTYxnoLxu5R8eS3KNjSe7RsWywlLEk9+hYknt0LMk9OpbkHh1Lco+M5ULu0bEk9+hYknt0LMk9OpYNljKW5B4dS3KPjiW5R8eS3KNjSe6RsTTe4K5nSe7RsST36FiSe3QsGyxlLMk9OpbkHh1Lco+OJblHx5LcI2O5kXt0LMk9OpbkHh1Lco+OZYOljCW5R8eS3KNjSe7RsST3yFj67h+f9iee6Wj7J5aBcw18949fwNLWX17AssFSxtLWX17A0tZf/pBl4IwI3/3jF7C09ZcXsLTt1fUsffeP/5Tl59/i++4fv4AluUfHktyjY9lgKWNJ7tGxJPfEWAb6S9/94xewJPfoWJJ7VCzvvvvHL2BJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktwjY+m7f/wCluQeHUtyj44luUfHssFSxpLco2NJ7tGxJPfoWJJ7dCzJPTKWvvvHL2BJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktwjY3kn9+hYknt0LMk9OpbkHh3LBksZS19/ud3Wx1tv2/GJ5edzDe6++8cvYOnrL+UsffePX8DS11/qWfr6y5+x/Pzb0rvv/vELWDZYylj69up6lr69up4luUfHktwTYxnI4777x/UsffePX8CS3KNjSe7RsST36Fg2WMpYknt0LMk9OpbkHh1Lco+OJblHxtJ3//gFLMk9OpbkHh1Lco+OZYOljCW5R8eS3KNjSe7RsST36FiSe2QsffePX8CS3KNjSe7RsST36Fg2WMpYknt0LMk9OpbkHh1Lco+OJblHxnIn9+hYknt0LMk9OpbkHh3LBksZS3KPjiW5R8eylr/cj+d7zx/ee2lPOu336/imU2yjuJpOLQ+oplPL1anp1PJpajoNOid0ankpNZ1a7khNp1bPq6ZTq7lV08Erv6fTim2h/gmd/fagcyzv6Ph65QgdX68coePrlSN0mi2d7ZvO+o6Or1eO0PH1yhE6vl45QsfXK0fo+HrlAJ1im4t/QmfZH3TW7R0dX68coePrlSN0fL1yhE6DzgkdX68coePrlSN0fL1yhI6vV47Q8fXKATrFtt2q6eCVz+jglc/o4JXP6DTonNDBK5/RwSuf0cErn9HBK5/RwSuf0Cm2IVVNB698RgevfEYHr3xGp0HnhA5e+YwOXvmMDl75jA5e+YwOXvmETrFtr2o6eOUzOnjlMzp45TM6DTondPDKZ3Twymd08MpndPDKJ3Q639t4259neUy34+Xkj7+nc2yPVx/bu9/rdb5d8YqJ+/YlV0zc7Cbu2z9cMXHfnuCHE39d9+358vn48O7H/rizH8fbO3vfriCfT9++IJ9P3y1aOp/Ot+jl8ynlLC/gU8qHXsCnlGv9GZ+fpLz3V/3CssFSxrKU005maezh5SyN/b6cpXE2kLM0zhFqlp1vsBuLpXE+kbM0zjJyluQeHcsGSxlLco+OJblHx5Lco2NJ7tGxJPfIWHa+wW4sluQeHUtyj44luUfHssFSxpLco2NJ7tGxJPfoWJJ7dCzJPTKWne9hHIsluUfHktyjY0nu0bFssJSxJPfoWOKJQiwD+/aWzvftjcWSZ0+M5edf0i43nj06ljx7dCzp3HQs6dx0LOncdCzxlyGW67T+eu16n9+w7HxH3Vgs6dx0LOncdCzJPTqWDZYyluQeHUtyj44luUfHktyjY0nukbHsfN/gWCzJPTqWzrnnJ1dyn5/vfH9959v6StM5+ehpNmgKaTqnHz1N5/yjp+mcgPQ0nTOQnqZzCvoRzeV5Ifd1ekOz812So9F0TkJ6mmQhJU2ykJJmg6aQJllISZMs9A9o7u9okoWUNMlCSppkoSDN4ztZHu+SZee7QkejSRZS0iQLKWmShZQ0GzSFNMlCSppkof84+a3u0vk21Xw+5JVzPiSQUz4LmeKcDynhnA++/5xPrW2/nzfFLcW2/UYmrrXtNzJxKdcamriUDw1NXMpZhiYu5RUjE9famhuauJSfC01cyqGFJrbzXLU2yoYmtvNctbazhia281y1Np2GJrbzXLW2hoYmtvNctTZwhia281y1tlmGJrbzXLU2Q4YmtvNctbYshia281y1NhaGJrbzXLW2/4UmtvNctTbphSa281y1ttKFJrbzXLU2vIUmtvNctbalhSa281y1No+FJrbzXLW2eIUmtvNch53nOuw812HnuWrteQtMvNbaxhaa2M1zrTc3z7XW2osXmrjZTezmudZam+BCE7t5rrXWVrXQxHaeq9aGstDEdp6r1rav0MR2nqvW5qzQxHaeq9YWqtDEdp6r1kan0MR2nqvWdqTQxHaeq9amodDEdp6r1sae0MR2nqvW5pvQxHaeq9YGmdDEdp6r1iaW0MR2nqvWRpPQxHaeq9ZmkNDEdp6r1oaN0MR2nqvWporQxHaeq9bGh9DEdp6r1uaE0MR2nqvWBoLQxHaeq9ZJ/qGJ7TxXrdP2QxPbea5aJ+KHJrbzXLVOrQ9NbOe57M6hX+3OoV/tzqFf7c6hX+3OoV/tzqFf7c6hX+3OoV/tzqFf7c6hX+3OoV9rnVH+w/1X+/G8kvnDa5f2uI6l3d+xdN5lqGbpvPdQzLLWie3JLJ33KapZOu9eVLN03riuZtlgKWPpvG1dzdJ517qaJblHx5LcE2O5P954OZZ3LMk9Mpa1tiYksyT36FiSe2Ist2+W6zuW5B4dywZLGUtyj44luUfHktyjY0nuibFcHp9DLuu7zyFr7RfJZVlrc0kyS3KPjiW5R8eS3KNj2WApY0nu0bEk9+hYknt0LMk9OpbkHhXLrdb2oGSW5B4dS3KPjiW5R8eywVLGktyjY0nu0bEk9+hYknt0LMk9Mpa1NnglsyT36FiSe3QsyT06lg2WMpbkHh1Lco+OJblHx5Lco2NJ7pGxrLVFL5kluUfHktyjY0nu0bFssJSxJPfoWJJ7dCw795fb/RvO/nKiwJsT7LYH+WN7c/rA1vtevwsm7tyrXTBx547qgok79z0XTNwqTfyzp0DgpM6t9y2A6Xw6dxHpfDpvRNP5dN5ypvMp5Sz1fHrfdZjOp5RrvS7lvb/qF5al/HAyy1JOO5llg6WMpbHfl7M0zgZylsY5Qs7SOHPIWRrnEzXL3neIDsWS3KNjSe7RsST36Fg2WMpYknt0LMk9OpbkHh1Lco+OJblHxrL3Pb5DsST36FiSe3QsyT06lg2WMpbkHh1Lco+OJblHx5Lco2NJ7pGx7H1D+FAsyT06luQeHUtyj45lg6WMJblHx5Lco2NJ7pGx7H17cC8sA9vWt963Bw/FkmdPjGXg5IHet7QOxZJnj44lnZuOJZ2bjGXvW1qHYom/DLFcp/XXa9f7/I4l/lLHks5Nx7LBUsaS3KNjSe7RsST36FiSe3QsyT0qlnvvW1qHYknu0bEk9+hYknt0LJsxyx9cSbu3R1HU7stLU3RbX2k6Jx89Tefso6fpnH70NJ3zj56mcwKS0+x9Y+tgNJ1T0I9o7rcnzf14R9M5B+lpOichPc0GTSFNspCSJllISZMspKRJFvo5zWN9R5MsJKTZ+xbXwWiShWI02/RMlm1+lyx73+Q6GE2ykJJmg6aQJllISZMspKRJFlLSJAsFaS73J811fkeTLCSkWWuXcTpNspCSJllISZMspKTZoCmkSRb6j5PTTHbnTdMhPuSVcz4kkHM+ZIpTPs6bpkN88P3nfEo5+cDu8b3WjufQxM1u4lKuNTRxKR8amriUswxNXMorhiYu5f4iE9fathuauJRDC01s57lq7ZcNTdzsJrbzXLU2qoYmtvNctbaThia281y1Nn2GJrbzXLW2ZoYmtvNctTZQhia281y1tjmGJrbzXLU2I4YmtvNctbYMhia281y1NvaFJrbzXLW234UmtvNctTbJhSa281ybnefa7DzXbue5au0aDE1s57l2O8+1N7uJ7TxXrQ2KoYntPFetbYShie08V63NfqGJ7TxXrS15oYntPFetjXOhie08V63tbaGJ7TxXrU1ooYndPNdRa6tYaGI3z3XU2tAVmtjNcx23Zjexm+c6am2NCk3s5rmOWtuXQhPbea5aW4xCE9t5rlrbgEIT23muWlt1QhPbea5a22lCE9t5rlpbXkIT23muWttSQhPbea5aW0dCE9t5rlrbO0IT23muWlswQhPbea5a2yRCE9t5rlpbGUIT23muWtsNQhPbea5aWwJCE9t5rlpn84cmtvNctc7PD01s57lqnXEfmtjOc9mdQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9idQ3/YnUN/2J1Df9Q6o/zrur9fPh8f3n3bj+eVzB9eu7T512uXdn/Dstbp58ksS3mIZJal3Ekyy1K+J5llg6WMZSmvlsyylAtMZlmq00tmWaotTGZJ7hGx3G+1NhBcyHJ/vPFyLO9Yknt0LMk9OpbkHh3LBssQy+2b5fqOJblHx5Lco2NJ7tGxJPfoWJJ7ZCxrbQG5kOXy+BxyWbd3LMk9OpbkHh1Lco+OZYOljCW5R8eS3KNjSe7RsST36FiSe2Qsa23iSWZJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktwjY1lrG1YyS3KPjiW5R8eS3KNj2WApY0nu0bEk9+hYknt0LMk9OpbkHhnLWhvpklmSe3QsyT06luQeHcsGSxlLco+OJblHx5Lco2NJ7pGx7H2v37IvzwtZj08sj+1x+sCx3d9N3LkLvGDizr3aBRM3u4k79z0XTNy5O/nZxD97Cnw+qfOLT+eOI51P5y4inU/njWg2n973EabzKeUsL+BTyodewKeUa70u5b2/6heWDZYylqWcdjJLYw8vZ2ns9+UsjbOBnKVxjlCz7H0f51AsjfOJnKVxlpGzJPfoWDZYyliSe3QsyT06luQeHUtyj44luUfGsveduEOxJPfoWJJ7dCzJPTqWDZYyluQeHUtyj44luUfHktyjY0nukbHsfUP4UCzJPTqW5B4dS3KPjmWDpYwluUfHktyjY0nu0bEk9+hYkntULKfetwf3wjKwbf2LFCxlLHn2xFh+Pnlg6n1L61AsefbIWPa+pXUolnRuOpZ0bjqW+MsQy3Vaf712vc/vWDZYyljSuelY0rnpWJJ7dCzJPTqW5B4Zy963tA7FktyjY0nu0bEk9+hYNljKWJJ7dCydc88PrmRv86Mo2tv9pSm6ra80nZOPnqZz9tHTdE4/cpq9b2sdjKZzAtLTdM5AeprOKehHNNfbk+Z6vKPZoCmk6ZyE9DTJQkqaZCElTbKQkiZZSEiz9w2uXdLc1nc0yUJKmmQhJU2yUJDm8UyWy+1dsux9k+tgNMlCSppkISVNspCSJllISZMsJKS5kIViNJf29JtLe5csa+0bTqdJFlLSJAspaTZoCmmShZQ0yUJKmmShn9Nc3jVyznupL6BJFhLSdN55HTm3yHnndYgPeeWcDwnknE+DzykfUsI5H3z/OZ9STv7YH/Xucbw7CabWpufQxKUccWTiWluTQxOX8qGhiUs5y9DEpbxiaOJmN3EpPxeauJRDC01s57lqbZkNTWznuWptbA1NbOe5am0/DU1s57lqbRINTWznuWpt5QxNbOe5am24DE1s57lqbYsMTWznuWptXgxNbOe5am0xDE1s57lqbQQMTWznuWpt1wtN7Oa55pub55pvbp5rvrl5rrnW/sXQxM1uYjfPNd/cPNdca19laGI3zzXX2v0YmbjWhsbQxHaeq9a2w9DEdp6r1ubA0MR2nqvWFr7QxHaeq9ZGu9DEdp6r1na40MR2nqvWprXQxHaeq9bWstDEdp6r1gaw0MR2nqvWJq3QxHaeq9ZGqtDEdp6r1man0MR2nqvWhqTQxHaeq9amodDEdp6r1sae0MR2nqvW5pvQxHaeq9YGmdDEdp6r1iaW0MR2nqvWRpPQxHaeq9ZmkNDEdp6r1oaN0MR2nqvWporQxHaeq9bGh9DEdp6r1uaE0MR2nqvWBoLQxHaeq9ZJ/qGJ7TxXrdP2QxPbea5aJ+KHJrbzXLVOrQ9NbOe57M6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3OoZ/tzqGf7c6hn+3Oob/bnUN/tzuH/m53Dv3d7hz6+63ZTezmue5259Df7c6hv9udQ3+3O4f+bncO/d3uHPp7rTPKv6779nz5fHx4920/nlcyf3jt0uZfr13a/R3LUk/6ZJalPEQyy1LuJJllKd+TzLKUo8plWev8+mSWpVxgMstSnV4yy1JtYTLLBksZS3JPjOX+eOPlWN6xJPfoWJJ7dCzJPTqW5J4Yy+2b5fqGZa0dEsksyT06luQeHUtyj45lg6WMJbknxnJ5fA65rO8+h6y1XySZJblHx5Lco2NJ7pGxrLXHJZkluUfHktyjY0nu0bFssJSxJPfoWJJ7dCzJPTqW5B4dS3KPjGWtXUrJLMk9OpbkHh1Lco+OZYOljCW5R8eS3KNjSe7RsST36FiSe2Qsa+0zS2ZJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktwjY1lrp2AyS3KPjiW5R8eS3KNj2bm/vE/3lwv5xPLYHqcPHNv93cSdu8ALJu7cq10wceeOSj9x73v9Lpi4c3fys4l/9hSInNTZ+xbAdD6du4h0Pg0+p3w6bznT+ZRylhfwKeVDL+BTyrVel/LeX/ULy1J+OJdl79sch2Jp7OHlLI39vpylcTaQs2ywlLE0zhxylsb5RM7SOMvIWZJ7dCzJPSqWrfeNqkOxJPfoWJJ7dCzJPTqWDZYyluQeHUtyj44luUfHktyjY0nukbHsfavxUCzJPTqW5B4dS3KPjmWDpYwluUfHktyjY0nu0bEk9+hYkntkLHvfED4UywbL0C8WP28Pbr1vDx6KJc+eGMvPv6RtvW9pHYll71tah2JJ56ZjSeemY0nnpmPZYBlhuU7rr9eu9/kdS/yljiWdm44lnZuOJblHx5LcI2PZ+5bWoViSe3QsyT06luQeHcsGSxlLco+OJblHx9I59/zkSubtSWTeb9+vnudXms7JR0/TOfvIafa+q3Uwms75R0/TOQHpaTpnID3NBs0YzbZ/05x+o/mvrz7uDx97rC9Xsf/tVTw/o9uO9vK+ryI5x6thRHLObcOIRCAcQCRy5gAiEV/7F6n3Tb6I9JdIhO0BRCLDDyAS1cAAIjVE6l8kGofYldxv7fHO99dX/06TakBJkwyvpEnYVtIkFQtp9r6QeTCa5EwlTQJhkOZ9fdJsyzuaJDclzQZNIU2ykJImWUhJkyykpEkWUtIkC/2c5uuMv9GstaQ9nSZZSEmTLPQfZ0e4Oa+LD/Fp8DnlQwI550OmOOdDSjjng+8/51PKyR/74+Pv43h3KFatRe2hiUs54tDEpVxraOJSPjQ0cbObuJRXDE1cyv2FJi7l50ITl3JooYndPNdSa0l0aGI3z7XUWrgcmtjNcy23Zjexm+daai0CDk3s5rmWWkt1QxPbea5aC2pDE9t5rlrLXkMT23muWotTQxPbea5aS0hDE9t5rloLPUMT23muWssxQxPbea7ZznPNdp6r1mLW0MR2nmu281yzneeqtcg2NLGd56q1FDY0sZ3nqrVgNTSxneeqtaw0NLGd56q1+DM0sZ3nqrVEMzSxneeqtZAyNLGd56q13DE0sZ3nqrUoMTSxneeqtXQwNLGd56q1vi80sZ3nqrUGLzSxneeqtU4uNLGd56q1li00sZ3nqrUwLDSxneeqtcoqNLGd56q1ZCk0sZ3nqrX+JzSxneeqtZgmNLGd56q1iSU0sZ3nqrXRJDSxneeqtRkkNLGd56q1YSM0sZ3nqrWpIjSxneeqtfEhNLGd56q1OSE0sZ3nqrWBIDSxneeqdZJ/aGI7z1XrtP3QxHaeq9aJ+KGJ7TxXrVPrQxPbeS67c+gXu3PoF7tz6Be7c+gXu3PoF7tz6Be7c+gXu3PoF7tz6Be7c+hXu3Po11pnlP9w/9V+PK9k/vDapc2/Xru0+zuWpZ70ySyd9x6qWTrvSFSzdN6nqGbpvHtRzdJ547qYZa2T8ZNZOm9bV7N03rWuZknu0bFssAyx3B9v/FWRvmNJ7tGxJPfoWJJ7dCzJPTGW2zfL9R1Lco+MZa3tFMksyT06luQeHUtyj45lg2WI5fL4HHJZ330OWWu/SDJLco+OJblHx5Lco2NJ7pGxrLUhJpkluUfHktyjY0nu0bFssJSxJPfoWJJ7dCzJPTqW5B4dS3KPjGWtLU3JLMk9OpbkHh1Lco+OZYOljCW5R8eS3KNjSe7RsST36FiSe2Qsa21KS2ZJ7tGxJPfoWJJ7dCwbLGUsyT06luQeHUtyj44luUfHktwjY1lrW2EyS3KPjiW5R8eyc385rd8XMs/zB5aR0wd63+t3wcSde7ULJu7cUV0wcee+Rz9x73v9Lpi4cw9xwcSdP+kvmLjzHvKCiZvdxHaeq/e9fj+cOHBmS+97/S6YuJbnikxcy3MFJu59r98PJw6c2dD7Xr8LJq7luSIT1/JckYmb3cS1PFdk4lqeK9Bl9r7X74KJa3muyMS1PFdg4t73+l0wcS3PFZm4lueKTFzLc0UmbnYT1/JckYntPFfve/0umNjOc/W+108+8db7Xr8LJnbzXNvNzXNtve9uvGDiZjexm+faet9WeMHEbp5r633z3wUT23mu3rfoXTCxnefqfSPdBRPbea7et7tdMLGd5+p9U9oFE9t5rt63jl0wsZ3n6n2D1wUT23mu3rdhXTCxnefqfbPUBRN3/Tw+juP7J6DTPH0Y+NgeX6E/tvu7gbt+HF8xcNdP4wsG7nutzBUDd/0svmLgrh/FPxz4Z79bP/bHPf043t3T+965ko+n64d8Pp6uW5h8PF1XNvl4KvnJC/BUcp8X4KnkVa87kOb9RX+j7HvJyFgoK/nrZJS+zl2O0tfly1E2UKpQ+qYHOUrfpCFH6ZtK5Ch9E4wcJWlHhbLv1SJjoSTtyFCSdmQoSTsylA2UKpSkHRlK0o4MJWlHhpK0I0NJ2lGh7HuhyFgoSTsylKQdGUrSjgxlA6UKJWlHhpK0I0NJ2pGhJO3IUJJ2VCj7XlA0FkrSjgwlaUeGkrQjQ9lAqUJJ2pGhJO3IUJJ2ZChJOzKUpB0Vyr5Xg42FkrQjQ0nakaEk7chQYoYiKAObZbe+N2ANhbLvtUv9oAycTtX3PqexUPLYkaFsoFShpGSToaRkk6HEV0ZQrtP667XrfX6HEl8pQ0nJJkK5972XbCyUpB0ZStKODCVpR4aygVKFkrQjQ0nakaEk7chQknZkKEk7KpR9bwQcCyVpR4aStCNDSdqRoWygVKE0Tjs/uJB5erKcp/vyfR378XevXpbHi7fpHXjjbJQL3jhJ5YI3zl254I1Tmgj8N8y+t4iOBtM4qelhGmc1PUzjtKaH2YCpg0liE8IkhQlhkqxiMI+nZ59v+28w/1mJU2pd8lDgSVZ68PP85NGWN+BLrY8eCjyJLQk86S4JPEkwCXwDfA54EmYSeNLoBeADn5AYL0RPBk9yTQJPcs0B77zy/Sfg5/v+HHFvH8BPy/Oql/YOPMk1CTzJVQ9efErT7ryofhyRGiL1LxLpeQCRSNoDiEQqH0AkEvwAIpH2+xdpoRkYQCRahAFEonEYQCQahwFEaojUv0g0DgOIROMwgEg0DgOIROMwgEg0Dv2LtNI4DCASjcMAItE4DCASjcMAIjVE6l8kGocBRKJxGEAkGocBRKJxGEAkGof+RdpoHAYQicZhAJFoHAYQicZhAJEaIvUvEjkpV6TAUvV9Iyf1L9KOu0sW6fNy433H3Q0gEu5uAJEaIvUvEp8nDSASnycNIBI5KVekyLHBOzlpAJH4PKl/kQ4+TxpAJBqHAUSicRhAJBqHAURqiNS/SDQOA4hE4zCASDQOA4hE4zCASDQO3Yt03GgcBhCJxmEAkWgcBhCJxmEAkRoi9S8SjcMFIv3gnafj+5qP6eWab+2fSko/UU5S2oxyktJ9lJOUpqRfSb9lmuhKhpCJtmQImehLhpCJxmQImRoyjSATrckQMtGEDCET7cYQMtFYDCETLUS2TNsD9Xyb1t9k+pvr+Lyd/ZhpLMpJSrsxkqTig4OOmdbEWn7aGGv5G/I7y097ZC0/rZS1/LRd1vLTolnLTzvnLP+dJs9aflo/a/lp/azlp/Wzlr8hv7P8tH7W8tP6WctP62ctP62ftfy0fs7yN1o/a/lp/azlp/Wzlp/Wz1r+hvzO8tP6WctP7q8qf2Cr7dHI/c7yLzj/svJ/3np4LDh/a/kb8jvLj/O3lp/P+63l5/N+a/nJ/VXlj5wEvJD7neVf+bzfWn4+77eWn9bPWn5aP2v5G/I7y0/rZy0/rZ+1/LR+1vLT+lnLT+vnLP9G62ctP63fUPL/5J2n43HN03x7+cxvn17/AOj9zP8AaP7M/wAafwDefwC0f+Z/APR/5n8ANIDmfwB0gDX+AF4kpderJulOV5cr6Xxbbk9Jj+WDpJGNejv9WzlJadRGklR9eMJOn2Ytf0N+Z/np0qzlp0mzlp8ezVp+WjRr+WncnOU/aOes5afJs5af1s9aflo/a/kb8jvLT+tnLT+tn7X8tH7W8tP6WctP6+cr//HFC/md5af1s5af1s9aflo/a/kb8jvLT+tnLT+tn7X85P6q8n/eknfcJnK/tfw4/7Lyf9yU8yV/Q35n+XH+1vLj/K3l5/N+a/n5vN9afnJ/Vfk/H5h83GZyv7X8fN5vLT+f91vLT+tnLX9Dfmf5af2s5af1s5af1s9aflo/a/lp/Zzlv9P6WctP6zeU/D9458h+jK8/AHo/8z8Amj/zP4DGH4D3HwDtn/kfAP2f+R8ADaD5HwAdYI0/gBdJ6fWqSdro6pIl/bqbPt55um8fJJ2+5HhMON3bO1Fp4AqKSqs2kqjt+eJ2v31459fX7u/kp1Ozlr8hf1H5v6758cZteSc/fZq1/LRp1vLTpVnLT5NmLT+tm7P8Cw1dWfmX5fHG2/ROfro8a/lp/azlp/Wzlr8hv7P8tH7W8tP6WctP6zeq/O8+xVto8spJSjtXTdKVxq2cpLRo5SSlGSsnKW1XOUkbklaTlFaqnKQ0TeUkpT3KlvT7t1rT+um3WrHfgKz0RwVFpUGqJ+pGh1RQVFqkgqLSIxUUlSapoKgNUeuJSptUUFT6pIKi0igVFJVGqaCoNEr1RN1plAqKSqNUUFQapYKi0igVFLUhaj1RaZQKikqjVFBUGqWCotIoFRSVRqmeqAeNUkFRaZQKikqjVFBUGqWCojZErScqjVJBUWmUCopKo1RQVBqlgqLSKJUT9QsDotYTlUapoKg0SgVFpVEqKGpD1Hqi0igVFJVGqaCoNEoFRaVRKigqjVI9UScapYKi0igVFJVGqaCoNEoFRW2IWk9UGqWCotIoFRSVRqmgqDRKBUWlUaon6kyjVFBUGqWCotIoFRSVRqmgqA1R64lKo1RQVBqlgqLSKBUUlUapoKg0SvVEvdMoFRSVRqmgqDRKBUWlUSooakPUeqLSKBUUlUapoKg0SgVFpVEqKCqNUj1RG41SQVFplAqKSqNUUFQapYKiNkStJyqNUkFRaZQKikqjVFBUGqWCotIo1RN1oVEqKCqNUkFRaZQKikqjVFDUhqj1RKVRKigqjVJBUWmUCopKo1RQVBqleqKuNEoFRaVRKigqjVJBUWmUCoraELWeqDRKBUWlUSooKo1SQVFplAqKSqNUT9SNRqmgqDRKBUWlUSooKo1SQVEbotYTlUapoKg0SgVFpVEqKCqNUkFRaZTqibrTKBUUlUapoKg0SgVFpVEqKGpD1Hqi0igVFJVGqaCoNEoFRaVRKigqjVI9UQ8apYKi0igVFJVGqaCoNEoFRW2IWk9UGqWCotIoFRSVRqmgqDRKBUWlUSon6nyjUSooKo1SQVFplAqKSqNUUNSGqPVEpVEqKCqNUkFRaZQKikqjVFBUGqV6ok40SgVFpVEqKCqNUkFRaZQKitoQtZ6oNEoFRaVRKigqjVJBUWmUCopKo1RP1JlGqaCoNEoFRaVR+pOivoCn9UkC3wCfA572JAk8DUcSeFqIJPA0BUngSfMh8Pd5eYx4fwXyt+BjTv5O5k5DTzLWo7+3x1Xfl/bhnddp/fXa9T6/E4mkO4BIpOIBRGqIlCrSl297vHFb3olE2h5AJJL5ACKR4gcQicQ/gEi0A/2L1OgRBhCJxiFZpOX5xtv0TiQahwFEonEYQKSGSP2LROMwgEg0DgOIRONwqUjrW/C0CEngaQZywC+k/STwJPgk8KTyGPh9eoI/9g/gY9+TWcjaaegb6OXo1V+sWEjQA4hEgs4VKfL5yEKCHkAk0vYAIpHM+xdpJcUPIBKJfwCRaAeSRQp8PrLSIwwgUkOk/kWicRhAJBqHAUSicRhAJBqHAUSicbhUpLefjG60CEngaQaSwJP2k8CT4JPAN8DngCdpJ4EnPSeBJxEngSflJoEnuYbAt+l4jNjun44djH2/cSe7pqEnvaahJ7+moSfBpqFvoM9CT4pNQ0+OTUNPkk1DT5ZNQ0+azUJ/kGbT0JNm09CTZtPQk2bT0DfQZ6EnzaahJ82moSfNpqEnzaahJ80mob/fSLNp6EmzaehJs2noSbNp6Bvos9CTZtPQk2bT0JNm09CTZtPQk2az0E+k2TT0pNk09KTZNPSk2TT0DfRZ6EmzaehJs2noSbNp6EmzaehJs1noZ9JsGnrSbBp60mwaetJsGvoG+iz0pNk09KTZNPSk2TT0pNk09KTZLPR30mwaetJsGnrSbBp60mwa+gb6LPSk2TT0pNk09KTZNPSk2TT0pNks9I00m4aeNJuGnjSbhp40m4a+gT4LPWk2DT1pNg09aTYNPWk2DT1pNgv9QppNQ0+aTUNPmk1DT5pNQ99An4WeNJuGnjSbhp40m4aeNJuGnjSbhX4lzaahJ82moSfNpqEnzaahb6DPQk+aTUNPmk1DT5pNQ0+aTUNPms1Cv5Fm09CTZtPQk2bT0JNm09A30GehJ82moSfNpqEnzaahJ82moSfNZqHfSbNp6EmzaehJs2noSbNp6Bvos9CTZtPQk2bT0JNm09CTZtPQk2az0B+k2TT0pNk09KTZNPSk2TT0DfRZ6EmzaehJs2noSbNp6EmzaehJs0no2400m4aeNJuGnjSbhp40m4a+gT4LPWk2DT1pNg09aTYNPWk2DT1pNgv9RJpNQ0+aTUNPmk1DT5pNQ99An4WeNJuGnjSbhp40m4aeNJuGnjSbhX4mzaahJ82moSfNpqEnzf7rhbzgaeA5w0MqPMVDcjvFQ7o6xUMCOsVDSjnDcydJnOLB7Z/iwZGf4sE1n+Jp4DnDU8k1H/v+69XHsb0buJIPDg1cydmGBq7kVUMDV3KfkYFbJT8ZGriSQwwNXMnzhQau5OJCAze3gd2cVnNzWs3NaTU3p9XcnNbi5rQWN6e1uDmtxc1pLc1tYDentbg5rcXNaS1uTmtxc1qrm9Na3ZzW6ua0VjentTa3gd2c1urmtErtng8N7Oa0Su1Zjwxcart5aGA3p1Vqk3doYDenVWprdWhgN6dVakNzaGA3p1VqG3FoYDenVWrzbmhgN6dVastsaGA3p1Vqo2poYDenVWp7aGhgN6dValNmaGA3p1VqK2RoYDenVWoDYmhgN6dVattfaGA3p1Vqs11oYDenVWqLW2hgM6e1lNpYFhrYzGktpbZzhQY2c1rLrbkNbOa0llJbl0IDmzmtpdSGodDAbk6r1Dad0MBuTqvU5pjQwG5Oq9SWlNDAbk6r1EaQ0MBuTqvU9ovQwG5Oq9Smh9DAbk6r1FaD0MBuTqvUdoDQwG5Oq9QJ/qGB3ZxWqVP2QwO7Oa1SJ+GHBnZzWqVOqw8N7Oa0Sp0oHxrYzWm5nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/uJ0Rv7idEb+4nRG/up0Rv7qdEb+6nRG/up0Rv96a28BmTmt1OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+dTsjfnU7I351OyN+LXWC+Ndl354vn48Pb/6TC5nn+/4ccW/f17Ef/+4735bHNc+3Y3mB1/7unffj+c7zh3de2vzrtUu7v5O/kitB/p/KX+p0eeT/sfyVHCvy/1j+Sv4d+X8sf6U0g/w/lr8hv7P8lZIu8v9Y/kqfsCD/j+Wv9HkT8v9Yflo/a/lp/crKvz/eeHl939/kL7XpCPl/LD+tn7X8tH7W8tP6lZV/+5Z/fSd/Q35n+Wn9rOWn9bOWn9bPWn5aP2v5af3Kyr88LnlZ333Tt9TWTeT/sfy0ftby0/pZy0/rZy1/Q35n+Wn9rOWn9bOWn9bPWn5aP2v5af2c5S+1AR75fyw/rZ+1/LR+1vLT+lnL35DfWX5aP2v5af2s5af1s5af1s9aflo/Z/kPWj9r+Wn9rOWn9bOWn9bPWv6G/M7y0/pZy0/rZy0/rZ+1/LR+1vLT+hnLv91o/azlp/Wzlp/Wz1p+Wj9r+RvyO8tP62ctP62ftfy0fs7yT+T+XPmnLw2e8k+rUv7P2zy2idxvLT+531p+cr+1/A35neUn91vLT+63lp/cby0/3/axlp9v+zjLP9P6WctP61dW/s9rHLeZ1s9aflo/a/kb8jvLT+tXVv7Pi9y2mdbPWn5aP2v5af2s5af1c5b/TutnLT+tX1n5A9/0vdP6WctP62ctf0N+Z/lp/azlp/Wzlp/Wz1p+Wj9r+Wn9nOVvtH7W8tP6WctP62ctP62ftfwN+Z3lp/Wzlp/Wz1p+Wj9r+Wn9rOWn9XOWf6H1s5af1s9aflo/a/lp/azlb8jvLD+tn7X8tH7W8tP6WctP62ctP62fs/wrrZ+1/LR+1vLT+lnLT+tnLX9Dfmf5af2s5af1s5af1s9aflo/a/lp/Zzl38j9F8gv3rmxkc4HEKkhUv8ikXQHEIk8OoBIpMYBRCLbDSASCax/kXa+HTGASHyHYQCRaBwGEInGIVmkwDq2vSFS/yLROAwgEo3DACLROCSLFFgUtNM4DCASjUP/Ih00DgOIROMwgEg0DgOIROOQLFLg20JHQ6T+RaJxGEAkGocBRKJxGEAkGocBRKJx6F6k/UbjMIBINA4DiETjMIBINA4DiNQQqX+RaBwGEInGYQCRaBwGEInGYQCRaBz6F2micRhAJBqHAUSicRhAJBqHAURqiNS/SDQOA4hE4zCASDQOA4hE4zCASDQO/Ys00zgMIBKNwwAi0TgMIBKNwwAiNUTqXyQahwFEonEYQCQahwFEonEYQCQah/5FutM4DCASjcMAIjVfkbTnO+534zSjRmmcOdQojZOBGqWxf1ejNHbZYpTN2AurURo7VjVK40+y1CiNP29So2ygVKEk7YRQfj6EeW+kHRlK0o4MJWlHhpK0E0L5+UjTfSHtyFCSdmQoSTsylKQdGcoGShVK0o7qE8eFtCNDSdqRoSTtyFCSdlQoV9KODCVpR4aStCNDSdqRoWygVKEk7chQknZkKEk7MpSkHRlK0o4K5UbakaEk7chQknZkKEk7MpQNlCqUpB0ZStKODCVpR4aStCNDSdpRodxJOzKUpB0ZStKODCVpR4aygVKFkrQjQ0nakaEk7chQknZkKEk7KpQHaUeGkrQjQ0nakaEk7chQ9u0r9+Xx4uNY1g8kj+1xlMCxvTtK4Ojb/Onn7duh6eft20ap5z1ufXsd/bx9G5IfzfuzO/9XRHi+9faOTt8eI5tO37Yhm06DzgmdvqvMbDqFXOQFdAp5zgvoFHKo12W599f8QrKQ980lORVy1ckkbf26nKStt5eTtM0BcpINkiKStvlCTtI2i8hJ2uYWOUkyjookGUdEsvNN6iORJOOoSJJxVCTJOCqSDZIikmQcFUkyjookGUdFkoyjIknGEZHsfHfzSCTJOCqSZBwVSTKOimSDpIgkGUdFkoyjIknGUZEk46hIknFEJDvfyT0SyQZJycLeo/OFvSOR5Imj+aXr0fli1IFIdr4XdSSStGoqkrRqKpK0aiqSDZKfSa7T+uu1631+RxI/qSJJq6YiSaumIknGUZEk44hIdr4NdSSSZBwVSTKOiiQZR0WyQVJEkoyjIknGUZH0zTg/uI7pvjwP/LyvLzy245Wlb8rRs/TNOXKWnW9CHYulb9bRs/RNO3qWvnlHz7LBMsJyX54sj/aOpW/m0bP0TT16luQeHUtyj44luUfGsvOdqGOxJPf8kGW7Te9Yknt0LMk9OpYNlgGWbV6fLO/LO5bkHh1Lco+OJblHx5Lco2NJ7pGx7Hw76lgsyT0nv6ftfONpNh2yyRmdBp0TOuSHMzokgjM6ePwzOpX25Qa2r5Xal/tx3r/+XiotzA0NXMijxgYuZDtjAxdykrGBm9vAhfxebOBCFi42cCFXFhvYymj9NbCb06q0RDU2sJvTqrSSNDawm9OqtOAzNrCb06q0LjM2sJvTqrR8Mjawm9OqtMoxNrCb06q0GDE2sJvTqrRmMDawm9OqtLQvNrCb06q0Ai82sJvTqrRQLjawm9OqtJ4tNrCb06q07Cw2sJvTqrQ6LDawm9OqtIgrNrCb06q01io2sJvTam5Oq7k5rUoL1WIDuzmt5ua0mpvTqrSALjawm9OqtM4tNrCb06q0HC02sJvTqrRqLDawm9OqtLgrNrCb06q0Bis2sJvTqrRUKjawm9OqtKIpNrCb06q08Cg2sJvTqrQ+KDawm9OqtIonNrCb06q01CY2sJvTqrQeJjawm9OqtGglNrCb06q0siQ2sJvTqrT8Izawm9OqtEYjNrCb06q0kCI2sJvTqrTaITawm9OqtCQhNrCb06q0biA2sJvTqnRwf2xgN6dV6cD82MBuTqvSsfaxgd2cVqXD52MDuzktryPi/xrYzGlNbmfET25nxE9uZ8RPbmfEf43jNrCZ05rczoif3M6In9zOiJ/czoifKp0gPv1sGdV+PK9j/vDapc2/Xru0+1uUvvsE5SgbKFUofTcVylH6rjWUo/TdgShH6bvmXI7Sd8u5GmWlE/GzUfruOJejJO3IUJJ2Iij3xxsvx/IWZQOlCiVpR4aStCNDSdqJoNy+Ua5vUZJ2ZChJOyqUlbZSZKMk7chQknZkKEk7EZTL4xPHZX37iWOl7R/ZKEk7MpSkHRlK0o4MJWlHhpK0o0JZaTNMNkrSjgwlaUeGkrQjQ9lAqUJJ2pGhJO3IUJJ2ZChJOzKUpB0VykrbmbJRknZkKEk7MpSkHRnKBkoVStKODCVpR4aStCNDSdqRoSTtqFBW2pCWjZK0I0NJ2pGhJO3IUDZQqlCSdmQoSTsylKQdGUrSjgwlaUeFstKWwmyUpB0ZytY1ym1+zHvs8/YB5derHy/e3p4l0PnevQsG7tujXTBw307qgoH79jsXDNy3K/nRwD+7/4fO2ex8S186nr7dQzqevvvPdDx9d5rpeBp4zvAUcp9X4CnkVa8Ldu+v+RVlIRecjbKQv85Gaevc5Sg73xA5FErbRKBHaZse9Chtk4YeZQOlCqVtgtGjJO3IUJJ2ZChJOzKUpB0RyrnzLa1DoSTtyFCSdmQoSTsylA2UKpSkHRlK0o4MJWlHhpK0I0NJ2lGhnEg7MpSkHRlK0o4MJWlHhrKBUoUSMxT5XU1gZeXc+XrfkVB2vki1F5SBX3vNnS9SHQoljx0ZSko2GUpKNhlKSjYZSnxlAOU6rb9eu97ntyjxlSqUnS9SHQolJZsMJWlHhpK0I0PZQKlCSdqRoSTtyFCSdmQoSTsylKQdFcrOF6kOhdI37fzgOqbb2p7v/HKW07Quv8H0zTsXwPRNPBfAbMDUwfRNPRfA9M09F8D0TT4XwPTNPj+CeTxs5jTdlrcwfdOPHmbnq1UHg0kCEsIkAQlhkoCEMBswdTBJQD+F+VLX/WeYJCAhTBKQECYJ6OwnJp2vT83G0/lK1HQ85I5TPCSJUzxkg1M8DTxneCotjgocxj93vtzzgoErLY4KDVxpcVRo4ELuMzRw50snLxi4kEOMDVzI88UGLuTiYgM3t4HdnFapFZ2hgd2cVqkVnaGB3ZxWpaWbsYHdnFalxZixgd2cVqXllbGB3ZxWpQWTsYHdnFalZY2xgd2cVqXFh7GB3ZxWpSWCsYHdnFalhXyxgd2cVqXldrGB3ZxWpUVxsYHNnNa90tK12MBmTuteaYFZbGAzp3W/NbeBzZzWvdJirdjAZk7rXmlJVWxgN6dVaeFTbGA3p1VpeVJsYDenVWkRUWxgN6c1uTmtyc1pVdqAFRvYzWnNbk5rdnNalfaFxQZ2c1qVdm/FBnZzWpX2WMUGdnNalXZCxQZ2c1qV9ivFBnZzWpV2FcUGdnNalfb+xAZ2c1qVdujEBnZzWpX20cQGdnNalXa7xAZ2c1qVtqTEBnZzWsY7HX6ybrrNv167tPtblOyyk6Fkl50MJbvsVCiNdznIUbK5W4aSzd0ylGzulqFsoFShZHO3DCVpR4aStBNBuT/eeDmWtyhJOzKUpB0VSuOdEHKUpJ0Iyu0b5foWJWlHhpK0I0PZQKlCSdqRoSTtyFCSdiIol8cnjsv69hPHSts/slGSdlQoK20syUZJ2pGhJO3IUJJ2ZCgbKFUoSTsylKQdGUrSjgwlaUeGkrSjQllpa1A2StKODCVpR4aStCND2UCpQknakaEk7chQknZkKEk7MpSkHRXKSpu7slGSdmQoSTsylKQdGcoGShVK0o4MJWlHhpK0I0NJ2pGhJO2IULZK2/OyUZJ2ZChJOzKUpB0ZygZKFUrSjgxl375yae2Bcj32Dyi/wD9evN3fDty3+9MP3PnevQsG7ttJXTBw337ngoH7diU/Gvhn9//IOZut8y196Xj6dg/pePruP9Px9N1ppuMp5CevwFPIfV6Ap/PNhRfi+Umwe3/NrygLueBslIX8dTZKW+euR9lAqUJpmwj0KG3Tgx6lbdLQo7RNJXqUtglGjrLz7aFDoSTtyFCSdmQoSTsylA2UKpSkHRlK0o4MJWlHhpK0I0NJ2lGh7HyD71AoSTsylKQdGUrSjgxlA6UKJWlHhpK0I0NJ2pGhJO3IUJJ2VCg73989FErSjgwlaUeGkrQjQ9lAqUJJ2pGhJO2oUHa+3rcTlJFV6K3z9b5DoeSxE0EZOUWg80WqQ6HksSNDSckmQ0nJJkNJyaZC2fki1U5QrtP667XrfX6LEl8pQ0nJJkNJySZD2UCpQknakaEk7chQknZkKEk7MpSkHRXKzhepDoWStCNDSdqRoSTtyFA2UKpQknZkKEk7MpSkHRlK37Tzg+uY2pPl1O7L93Vs7R+D981GueA7X9JaGLxv7koG75vSROBfYfrmtAtgNmDqYPpmtQtg+qa1C2D65rULYJLYhDBJYTKYS+cLYQeDSVoSwiQBhWDujwmn5b7+BvNvXj21Rxc5TcvLVW/Lb+jJS2noG+jV6NU/j1w6X2eLSP+/SKTBAUQiZQ4gEul1AJFIxf2LVGm1d12RSPEDiEQ7MIBI9AgDiNQQqX+RaBwGEInGYQCRaBwGEInGYQCRaBz6F2mmcRhAJBqHAUSicRhAJBqHAURqiNS/SDQOA4hE4zCASDQOA4hE4zCASDQO/Yt0p3EYQCQahwFEonEYQCQahwFEaojUv0g0DgOIROMwgEjkpFSRItvMlkZOGkAk3F2uSIGtQl8QEKl/kXB3A4iEuxtAJD5PGkAkPk8aQCRyUqpIkZNQl4WcNIBIfJ40gEh8njSASDQOA4jUEKl/kWgcBhCJxmEAkWgcBhCJxmEAkWgc+hdppXEYQCQaB71IP3nn6fY8xXuaXk/x/u0845XOYQiZaB2GkKkh0wgy0TwMIRPdwxAy0T4MIRP9Q7JM0/aUaV7fykQDMYJMGx3EEDLRQgwhEy3EEDLRQgwhU0OmEWSihUiWKbTxb6OFGEImWoghZKKFGEImWogRZNppIYaQiRZiCJloIf6gTK/g6RWSwDfAB8B/fXb2BL9PH8B/fRzXnjebe3uLnvSfhp5EL0c/z08cbXkLnoyeBJ7UnQSeHJ0D/iAZJ4En6yaBJ73qwS/LA8c2vQVPek0C3wCfA57smgSe5JoEnuSaBJ7kmgSe5JoCfr2RXJPAk1yTwJNck8CTXJPAN8AHwH/dGR7vvE7bB/CxD//WG9k1DT3pNQ09+TUNPQk2DT0ZNgv9RIpNQ0+OTUNPkk1DT5ZNQ99An4WeNJuGnjSbhp40m4aeNJuGnjSbhX4mzaahJ82moSfNpqEnzaahb6DPQk+aTUNPmk1DT5pNQ0+aTUNPms1CfyfNpqEnzaahJ82moSfNpqFvoM9CT5pNQ0+aTUNPmk1DT5pNQ0+azULfSLNp6EmzaehJs2noSbNp6Bvos9CTZtPQk2bT0JNm09CTZtPQk2az0C+k2TT0pNk09KTZNPSk2TT0DfRZ6EmzaehJs2noSbNp6EmzaehJs1noV9JsGnrSbBp60mwaetJsGvoG+iz0pNk09KTZNPSk2TT0pNk09KTZLPQbaTYNPWk2DT1pNg09aTYNfQN9FnrSbBp60mwaetJsGnrSbBp60mwW+p00m4aeNJuGnjSbhp40m4a+gT4LPWk2DT1pNg09aTYNPWk2DT1pNgv9QZpNQ0+aTUNPmk1DT5pNQ99An4WeNJuGnjSbhp40m4aeNJuGnjSbhH67kWbT0JNm09CTZtPQk2bT0DfQZ6EnzaahJ82moSfNpqEnzaahJ81moZ9Is2noSbNp6EmzaehJs2noG+iz0JNm09CTZtPQk2bT0JNm09CTZrPQz6TZNPSk2TT0pNk09KTZNPQN9FnoSbNp6EmzaehJs2noSbNp6EmzWejvpNk09KTZNPSk2TT0pNk09A30WehJs2noSbNp6EmzaehJs2noSbNZ6BtpNg09aTYNPWk2DT1pNg19A30WetJsGnrSbBp60mwaetJsGnrSbBb6hTSbhp40m4aeNJuGnjSbhr6BPgs9aTYNPWk2DT1pNg09aTYNPWn2X67jBc9K4jzFQyo8xUNyO8VDujrF08BzhoeUcoqHJHGKB7d/igdHfooH13yGZ8M1n+Ip5JqPfX+8+NjeDlzIB8cGLuRsYwM3t4ELuc/YwIX8ZGzgQg4xNnAhzxcbuJCLCw28F/JlsYHdnNbu5rR2N6e1N7eB3ZzW7ua0djentbs5rd3NaR1uTutwc1qHm9M63JzW0dwGdnNah5vTOtyc1uHmtA4zp7XfzJzWfjNzWvvNzGntlXbPxwZubgObOa290nbz2MBmTmuvtMk7NrCb06q0tTo2sJvTqrShOTawm9OqtI04NrCb06q0eTc2sJvTqrRlNjawm9OqtFE1NrCb06q0PTQ2sJvTqrQpMzawm9OqtBUyNrCb06q0ATE2sJvTqrTtLzawm9OqtNkuNrCb06q0xS02sJvTqrSxLDawm9OqtJ0rNrCb06q0iSo2sJvTqrR1KTawm9OqtGEoNrCb06q0TSc2sJvTqrQ5Jjawm9OqtCUlNrCb06q0ESQ2sJvTqrT9Ijawm9OqtOkhNrCb06q01SA2sJvTqrQdIDawm9OqdIJ/bGA3p1XplP3YwG5Oq9JJ+LGB3ZxWpdPqYwO7Oa1KJ8rHBnZzWm5nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxO9uZ8TvbmfE725nxB9uZ8QfbmfEH25nxB9uZ8Qft+Y2sJnTOtzOiD/czog/3M6IP9zOiD/czog/3M6IP9zOiD/czog/3M6IP9zOiD8qnSD+ddW351XPx4f3/sl1TG1/TDgt9/X7Orb2d++8H893nj+889LmX69d2v2tSIW8Q1mRKp3UXlekQh6trkiFfGVdkQp54boiNUTqX6RCmaOuSIUa6boiFWrR64pE4zCASDQOuSLtj0tejuWdSJU2ltQVicZhAJFoHAYQicYhV6TtW6T1rUgNkfoXicZhAJFoHAYQicZhAJFoHAYQicYhV6Tl8W2hZX37baFKm7vqikTjMIBINA4DiETjMIBIDZH6F4nGYQCRaBwGEInGYQCRaBwGEInGoX+RKm2wrCsSjcMAItE4DCASjcMAIjVE6l8kGocBRKJxGEAkGocBRKJxGEAkGof+Raq0ybmuSDQOA4hE4zCASDQOA4jUEKl/kWgcBhCJxmEAkWgcBhCJxmEAkWgc+hdpo3EYQCQahwFEonEYQCQahwFEaojUv0g0DgOIROMwgEg0Dv2LtPvmJPX5jrtvmpGj9M0ccpS+yUCOsoFShdLXZctR+nphOUpfxypH6ftJlhyl7+dNapQHaUeGkrQTQRk5hPkg7chQknZkKBsoVShJOxGUkSNND9KODCVpR4aStCNDSdrRoPzrHwelCiVpR/OJ49c/TtqRoSTtyFA2UKpQknZkKEk7MpSkHRlK0o4MJWlHhXIi7chQknZkKEk7MpSkHRnKBkoVStKODCVpR4aStCNDSdqRoSTtqFDOpB0ZStKODCVpR4aStCND2UCpQknakaEk7chQknZkKEk7MpSkHRXKO2lHhpK0I0NJ2pGhJO3IUDZQqlCSdmQoSTsylKQdGUrSjgwlaUeFsvXtK+/bY4bj64o/oDy2x1kCx3Z/O3Df7u+CgZvbwH07qQsG7tvvXDBw367kRwP/7P5/7M+3Pt7f0/t2Gul4+nYP2XiWvvvPdDx9d5rpeAr5ySvwFHKfV+Bprnh+EuzeX/MrykIuOBtlIX+djdLWuetR2rp8PUrbRCBHudqmBz1K26ShR2mbSvQobROMHmUDpQolaUeGkrQjQ0nakaEk7chQknZUKDvf/D0UStKODCVpR4aStCND2UCpQknakaEk7chQknZkKEk7MpSkHRXKzvd3D4WStCNDSdqRocQMRX5X83ll5RdKzJAKZeeLVHtBGfm1V+eLVIdCyWNHhpKSTYaygVKFkpJNhhJfGUC5Tuuv1673+S1KfKUMJSWbDCUlmwjl1Pki1aFQknZkKEk7MpSkHRnKBkoVStKODCVpR4aStCNDSdqRofRNOz+4jr/OAnm+8zp9X8c2vcLsfJXqYDB9E88FMH0zzwUwfVPPBTAbMHUwfZPPBTB9s8+PYO7t+c7H/S1M3/RzAUzf/HMBTBKQDmbn61UHg0kCEsIkAQlhkoB+CPPrX3kLswFTB5MEJIRJAjr5icnU+frUdDyklFM85I4zPJ2vLk3HQzY4xYPbP8VTaXFU4DD+qfPlnhcMXGlxVGjgSoujQgMXcp+xgQv5ydjAhRxiaOBWyPPFBi7k4mIDV1rRGRrYzWmVWtEZGtjNaZVa0Rka2M1pVVq6GRvYzWlVWowZG9jNaVVaXhkb2M1pVVowGRvYzWlVWtYYG9jNaVVafBgb2M1pVVoiGBvYzWlVWsgXG9jNaVVabhcb2M1pVVoUFxvYzWlVWroWG9jNaVVaYBYb2M1pVVoGFhvYzWlVWqwVG9jNaVVaUhUb2M1pVVr4FBvYzWlVWp4UG9jNaVVaRBQb2M1p7c1tYDenVWkDVmxgN6e1uzmt3c1pVdoXFhvYzWlV2r0VG9jNaVXaYxUb2M1pVdoJFRvYzWlV2q8UG9jMac2VdhXFBjZzWnOlvT+xgc2c1nxrbgObOa250j6a2MBmTmuutNslNrCb06q0JSU2sJvTMt7p8JN10+2xhWBp97co2WUnQ8kuOxlKdtnJULLLToaSzd0qlMZ7HOQo2dwtQ8nmbhlKNnfLUDZQqlCSdiIo98cbL8fyFiVpR4aStCNDSdqRoSTtRFBu3yjXdyiNd03IUZJ2ZChJOzKUpB0ZygZKFUrSTgTl8riMZX37iWOl7R/ZKEk7MpSkHRlK0o4KZaUtK9koSTsylKQdGUrSjgxlA6UKJWlHhpK0I0NJ2pGhJO3IUJJ2VCgrbTrKRknakaEk7chQknZkKBsoVShJOzKUpB0ZStKODCVpR4aStKNCWWnbWDZK0o4MJWlHhpK0I0PZQKlCSdqRoSTtyFCSdmQoSTsylKQdFcpKG/+yUZJ2ZChJOzKUpB0Zyr595Tw/Xnzc78cHlMf2OEvg2N6eJdD53r0LBu7bo10wcN9OSj9w53v3Lhi4b1fyo4F/dv8PnbPZ+Za+dDx9u4d0PA08Z3j67jTT8RTyk1fgKeQ+r8BTyKteF+zeX/MrykIuOBll59sWh0Jp69z1KG1dvh6lbSLQo2ygVKG0TRp6lLapRI/SNsHoUZJ2ZChJOyKU9843ng6FkrQjQ0nakaEk7chQNlCqUJJ2ZChJOzKUpB0ZStKODCVpR4Wy863DQ6Ek7chQknZkKEk7MpQNlCqUpB0ZStKOCmXn6307QRlZWXnvfL3vUCh57Ih+7XXvfJHqUCh57MhQUrLJUFKyyVBSsqlQdr5ItROU67T+eu16n9+ixFfKUFKyyVBSsslQNlCqUJJ2ZChJOzKUpB0ZStKODCVpR4Wy80WqQ6Ek7chQknZkKH3Tzg+uY7ot8/Od1+n7OrbpN5gNmDqYvonnApi+mecCmL6p5wKYvrnnApi+yUcPs/O1qt3A3NvznY/7W5i+6ecCmL755wKYJCAhzAZMHUwSkBAmCUgIkwT0Q5hf/8pbmCQgIUwSkA5m56tWU2C+4iHTnOIhpZziIXec4mngOcNDNjjFg9s/xVNpcVTgMP5758s9Lxi40uKoyMCdL8q8YOBC7jM2cCE/GRu4kEOMDdzcBi7k4mIDV1rRGRrYzWmVWtEZGtjNaZVa0Rka2M1pVVq6GRvYzWlVWowZG9jNaVVaXhkb2M1pVVowGRvYzWlVWtYYG9jNaVVafBgb2M1pVVoiGBvYzWlVWsgXG9jNaVVabhcb2MxptUqL4mIDmzmtVmnpWmxgM6fVbs1tYDOn1SotA4sNbOa0WqXFWrGB3ZxWpSVVsYHdnFalhU+xgd2cVqXlSbGB3ZxWpUVEsYHdnNbk5rQmN6dVaQNWbGA3pzW7Oa3ZzWlV2hcWG9jNaVXavRUb2M1pVdpjFRvYzWlV2gkVG9jNaVXarxQb2M1pVdpVFBvYzWlV2vsTG9jNaVXaoRMb2M1pVdpHExvYzWlV2u0SG9jNaVXakhIb2M1pGe90+Mm66fbYQrC0+1uU7LJToTTe5yBHyS47GUp22clQsrlbhrKBUoWSzd0ylGzulqFkc7cMJWlHhpK0E0G5P954OZZ3KI13N8hRknZkKEk7MpSknQjK7Rvl+hZlA6UKJWlHhpK0I0NJ2pGhJO3IUJJ2IiiXxyeOy/r2E8dK2z+yUZJ2ZChJOzKUpB0ZygZKFUrSjgwlaUeGkrQjQ0nakaEk7ahQVtrAk42StCNDSdqRoSTtyFA2UKpQknZkKEk7MpSkHRlK0o4MJWlHhbLSFqxslKQdGUrSjgwlaUeGsoFShZK0I0NJ2pGhJO3IUJJ2ZChJOyKUS6VNdNkoSTsylKQdGUrSjgxlA6UKJWlHhpK0I0NJ2lGh7Hzv3tQe13FM+/4BpfrcgaXzHX3JcPr2fslw+nZzyXAacN7D6dtxJcPp20Mlw+nbFSXD6bvVTYbTd0+bC6fzfYnJcFwdcuAonqXzPYzJcFwdcghOA857OK4OOXB4yNL53shkOK4OOQTH1SGH4Lg65AiczvdcJsNxdciRTx8635+ZDMfVIYfgNOC8h+PqkENwXB1yCI6rQw7BcXXIITiuDjkCp/P9pMlwcMgncHDIJ3BwyCdwGnDew8Ehn8DBIZ/AwSGfwMEhn8DBIb+H0/kW3mQ4OOQTODjkEzg45BM4DTjv4eCQT+DgkE/g4JBP4OCQT+DgkN/D6XxzazIcHPIJHBzyCRwc8gmcBpz3cHDIJ3BwyCdwcMgncHDIJ3BwyO/h9L1Xcd+fXxfev0Ap4UR+qdf3psRsOA047+F07XOy4XTtc7LhdO1zsuF07XOy4XTtc5Lh9L3nLxtO101gNhwc8gkcV4cc+dF93/vysuG4OuQQHFeHHILj6pAjP53ue+9cNhxXhxyB0/duuGw4rg45BMfVIYfguDrkyKcPfe9Yy4bj6pBDcFwdcgiOq0MOwXF1yCE4rg45AGfte59YNhxXhxyC4+qQQ3BwyCdwGnDew8Ehn8DBIZ/AwSGfwMEhn8DBIb+H0/dmtGw4OOQTODjkEzg45BM4DTjv4eCQT+DgkE/g4JBP4OCQT+DgkN/D6XszWjYcHPIJHBzyCRwc8gmcBpz3cHDIJ3BwyCdwcMgncHDIJ3BwyO/h9L0ZLRsODvkETvvjcMS/p1sTtlDJR1jHH2Ebf4R9/BGO4UdI2GEkH2Eaf4R5/BHu448w/tO59f10Dvx4dm19P51DI/T9dA6N0PfTOTRC30/nwE/z1qXvp3NohL6fzqER+n46h0bo++kcGqHvp3NohL6fzpEGY+n76Rwaoe+nc2iEvp/OoRH6fjpHRlj7fjqHRuj76Rwaoe+nc2iEvp/OoRH6fjqHRhj/6byO/3Rex386r+M/ndfxn87b+E/nbfyn8zb+03kb/+mccBK+fITxn87b+E/nbfyn8zb+03kb/+m8j/903sd/Ou/jP5338Z/OCadwy0cY/+m8j/903sd/Ou/jP5338Z/Ox/hP52P8p/Mx/tP5GP/prDnHdXpc1TytTTlC5FthmtNWc0fYxx/hGH2ETXO+aO4I0/gjzOOPcB9/hDb+CMv4Iwz/dN5ufT+dA1+13W59P51DI/T9dI6MMPX9dA6N0PfTOfAlz23q++kcGqHvp3NohL6fzqER+n46h0bo++kcGqHvp3Ogwdimvp/OoRH6fjpHRpj7fjqHRuj76Rwaoe+nc2iEvp/OoRH6fjqHRuj76Rwaoe+nc2iE8Z/O8/hP53n8p/N9/Kfzffyn8338p/N9/Kez5pSq3BHGfzrfx38638d/Ot/Hfzrfx386t/Gfzm38p3Mb/+ncxn86a06pyh1h/KdzG//p3MZ/Orfxn85t/KfzMv7TeRn/6byM/3Rexn86a06pyh1h/Kez5HykW1seI9yOm3KEyLfCJOcj5Y4gOR8peYRp/BHm8Ue4jz9CG3+EZfwR1vFH2MYfYfyn89r30znyVdut76dzaIS+n86hEfp+OodG6PvpHPmSp+R8pOQR+n46h0bo++kcGqHvp3NohL6fzqER+n46RxqMve+nc2iEvp/OoRH6fjqHRuj76Rwaoe+nc2iEvp/OoRH6fjqHRuj76Rwaoe+nc2iE8Z/Ox/hP52P8p/Mx/tP5GP/pfIz/dD7Gfzof4z+dj/Gfzsf4T+dj+Kfzfhv+6bzfhn8677fhn877bfin834b/um834Z/Ou+34Z/O+234p/N+G/7pvN/GfzpP4z+dp/GfztP4T+dp/Kez5JSq5BHGfzpP4z+dp1Gfzl//7f/+L//Hf/0v/9P/+r/8n1//F3/9j//Xf/uf//t//d/+26//+t//n//9f/wvX6/9/wA="},{"name":"lookup_validity","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"consumer","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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J0P+nq7yDtadDPl7uso7WFY/Pv7Lfy7vMuj39HUG/Z6+zqDf09cZ9Hv6OoN+T19n0O/p6wz6PX2ZQd7BupNBv6evM2zQ0/IO1p0MG/S0vIN1J8MGPS3vYN3JsEFPyztYNzLIO1h3MmzQ0/IO1p0MG/S0b9DTvkFP63tk1xm+wZBqx8eijuOXL/gfhvA+fnza++dC6mv5lnv5nnv5Jffya+7lR+7lt9zL77mXP3Ivf6Zefs3dujV369bcrVtzt+436E+PLj9369bcrVtzt27N3bo1d+tG7taN3K0buVs3crfuN1hOjy4/d+tG7taN3K0buVs3crduy926LXfrttyt23K37jfITI8uP3frttyt23K3bsvdui136/bcrdtzt27P3bo9d+t+g7P06PJzt27P3bo9d+v23K3bc7fuyN26I3frjtytO3K37jeoSY8uP3frjtytO3K37sjduiN3687crTtzt+7M3bozd+t+g4H06PJzt+7M3bozd+vO3K07U7duHKlbN47UrRtH6taNI3XrxpG6deNI3bpxpG7dOFK3bhypWzeO3K1ruVvXcreu5W5dy9263+ATPbr83K1ruVvXcreu5W5dy926nrt1PXfreu7W9dyt+w3a0KPLz926nrt1PXfreu7W9dytm9umitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVNFbpsqcttUkdumitw2VeS2qSK3TRW5barIbVO13DZVy21Ttdw2VcttU7Ujdeu23DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2VcttU7XcNlXLbVO13DZVy21Ttdw2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CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wv73C/PYK89srzG+vML+9wvz2CvPbK8xvrzC/vcL89grz2yvMb68wvz1gfnvA/PaA+e0B89vjqLC8rP1VwPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN8eML89YH57wPz2gPntAfPbA+a3B8xvD5jfHjC/PWB+e8D89oD57QHz2wPmtwfMbw+Y3x4wvz1gfnvA/PaA+e0B89sD5rcHzG8PmN/eYH57g/ntDea3N5jf3o4Ky8vaXzWY395gfnuD+e0N5rc3mN/eYH57g/ntDea3N5jf3mB+e4P57Q3mtzeY395gfnuD+e0N5rc3mN/eYH57g/ntDea3N5jf3jbz2928/Pi0h9mvPv1KvNcO607ivfZYNxJvprjfSbzXPutO4r12WncS77XXupO44hLvtd+6k3ivHdedxLg912aq+53EuD3XZrL7ncS4PddmuvudxLg912bC+53EuD3XZsr7ncS4Pddm0vudxLg912ba+53EuD3XZuL7ncS4Pddm6vudxLg912by+53EuD3XZvr7ncS4PddmAvydxLg912YK/J3EuD3XZhL8ncS4PddmGvydxLg912Yi/J3EuD3XZir8ncS4PddmMvydxLg912Y6/J3EuD3XZkL8ncS4PddmSvydxLg912ZS/J3EuD3XZlr8ncS4PddmYvydxLg912Zq/J3EuD3XZnL8ncS4PddmevydxLg912aC/J3EuD3XZor8ncS4PddmkvydxLg912aa/J3EtD1X30yUv5OYtufqm6nydxLT9lz9qLjEtD1X30yXv5OYtufqmwnzdxLj9lybKfN3EuP2XJtJ83cS4/Zcm2nzdxLj9lybifN3EuP2XJup83cS4/Zcm8nzdxLj9lyb6fN3EuP2XJsJ9HcS4/Zcmyn0dxLj9lw4h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoe84h77jHPqOc+g7zqHvOIe+4xz6jnPoO86h7ziHvuMc+o5z6DvOoR84h37gHPqBc+gHzqEfR8Ulpu25Bs6hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4Bz6gXPoB86hHziHfuAc+oFz6AfOoR84h37gHPqBc+gHzqEfOId+4hz6iXPoJ86hnziHfh4Vl5i255o4h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHfuIc+olz6CfOoZ84h37iHPqJc+gnzqGfOId+4hz6iXPoJ86hnziHftIcej9oDv2ZGLbnOhPD9lxnYtie60xccYlhe64zMWzPdSaG7bnOxLA915kYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2Lcnovm0J+JcXsumkN/JsbtuWgO/ZkYt+eiOfRnYtyei+bQn4lxey6aQ38mxu25aA79mRi356I59Gdi3J6L5tCfiXF7LppDfybG7bloDv2ZGLfnojn0Z2LanstwDr3hHHrDOfSGc+jtqLjEtD2X4Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nENvOIfecA694Rx6wzn0hnPoDefQG86hN5xDbziH3nAOveEcesM59IZz6A3n0BvOoTecQ284h95wDr3hHHrDOfSGc+gN59AbzqE3nEPvOIfecQ694xx6xzn0flRcYtqey3EOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hd5xD7ziH3nEOveMcesc59I5z6B3n0DvOoXecQ+84h95xDr3jHHrHOfSOc+gd59A7zqF3nEPvOIfecQ694xx6xzn0jnPoHefQO86hLziHvuAc+oJz6AvOoS9HxSWm7bkKzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77gHPqCc+gLzqEvOIe+4Bz6gnPoC86hLziHvuAc+oJz6AvOoS84h77iHPqKc+grzqGvOIe+HhWXmLbnqjiHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6inPoK86hrziHvuIc+opz6CvOoa84h77iHPqKc+grzqGvOIe+4hz6wDn0gXPoA+fQB86hj6PiEtP2XIFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfeAc+sA59IFz6APn0AfOoQ+cQx84hz5wDn3gHPrAOfSBc+gD59AHzqEPnEMfOIc+cA594Bz6wDn0gXPoA+fQB86hD5xDHziHPnAOfcM59A3n0DecQ99wDn07Ki4xbc/VcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59wzn0DefQN5xD33AOfcM59A3n0DecQ99wDn3DOfQN59A3nEPfcA59S+3QvzLUDTLI74t6jI8Mrb/NIL/TuZFBfu9yI4P8buRGBvn9xXUGfUX9Rgb5PcAfZ+j1bQb5Vr+RQb6nb2SQ7+nhHxlGef/zIN/TNzLI9/SNDPI9fSODfE/fyCDf09cZ9FXmEe0jwyhvM8j3w40M6nOpNq8/Pl7PXfbbDOpz6U4G9bl0J4P6XLqRQV6nvZNB6/eH16q0Jv5rVV8+w8+ljPGxLDveL6tqLis0l9U0l9U1lzU0lzUll/X1dOa9ZZnmslxzWZpTfmhO+aE55YfmlB+aU35oTvmhOeWn5pSfmlN+ak75qTnlp+aUn5pTfmpO+ak55afmlJ+SU74fklO+H5JTvh+SU74fklO+H5JTvh+SU74fklO+H5JTvh+SU74fmlPeNKe8aU5505zypjnlTXPKm+aUN80pb5pT3jSnvGlOedec8q455V1zyrvmlHfNKe+aU941p7xrTnnXnPKuOeWL5pQvmlO+aE75ojnli+aUL5pTvmhO+aI55YvmlC+aU75qTvmqOeWr5pSvmlO+ak75qjnlq+aUr5pTvmpO+ao55UNzyofmlA/NKR+aUz40p3xoTvnQnPKhOeVDc8qH5pRvmlO+aU75pjnlm+aUb5pTvmlO+aY55ZvmlG+aU75pTvmuOeW75pTvmlNe8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvnbNu69d8+5r17z72jXvvg7Nu69D8+7r0Lz7OjTvvo5DcsoPzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo0774OzbuvQ/Pu69C8+zo1775OzbuvU/Pu69S8+zoPySk/Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uvUvPs6Ne++Ts27r1Pz7uv8jtuc5uVzWfV4u6zQXNY3/CTa/FyWl/F2WVNyWd9xP/HOskxzWa65rKK5rKfnVjkullXG60vX4/Oz9WNBobagpragrragobagKbagx+8e/qcXZGoLcrUFFbUFqU3qqTap59dP6qivD/d3C+pqCxpqC5pSCyrHcagtyNQWpDWpzwVpTepzQVqT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qZffjtzLt9zL99zLL7mXX3MvP3IvP3frttyt23K3bsvduj136/bcrdtzt27P3bo9d+v23K3bc7duz926PXfr9tytO3K37sjduiN3647crTtyt+7I3bojd+uO3K07crfuyN26M3frztytO3O37szdujN3687crTtzt+7M3bozd+vO1K0bR+rWjSN168aRunXjSN26caRu3ThSt24cqVs3jtStG0fq1o0jd+ta7ta13K1ruVvXcrfu1wM2zy4/d+ta7ta13K1ruVvXcreu525dz926nrt1PXfrfj1W8+zyc7eu525dz926nrt1PXfrltytW3K3bsnduiV36349TPPs8nO3bsnduiV365bcrVtyt27N3bo1d+vW3K1bc7fu14tSzy4/d+vW3K1bc7duzd26NXfrhvTcv4IQI6Tn/vXy30+eaeO1/Nl//Zdyvh7sqw+O1Qffv+fz07s77Hj3oDalcfn/Im1K43r50tV8vXzpar5evnQ1Xy9fuppjvpbRjni7fOlqvly+NqVxvXzpX4ivl6+9MbpcvnbrTvtYfnu7fO3WvVy+duteLl+7dS+Xr926l8sXb92r5Wu37oXPHdqUxvXytVv3cvnarXu5fO3WvVy+duteLl+7dS+Xr926l8vXbt3L5Wu37uXyc7euNqVxvfzcratNaVwvP3fralMa18vP3bralMb18nO3rjalcb381K3btCmN6+Wnbt2mTWlcLz9167Yjdes2bUrjevmpW7dpUxrXy0/duk2b0rhcvjalcb383K2rTWlcLz9362pTGtfLz9262pTG9fJzt+7XYw5P/p3j7esxh2eXr/1Xpl8uX/uvTL9cfs29fO2/Mv3iD4M11/4r0y+XL/RXpq8sX+ivV19Z/ky9/KLduhd/mqoV7da9XL52614uX7t1L5ev3bqXyxdv3avla7fu1a8rRbt1L5ev3bqXy9du3avlV+3WvVy+duteLl+7dS+Xr926l8vXbt3L5Wu37uXyc7duzd26NXfr1tytG7lbN3K3buRu3cjdupG7dSN360bu1o3crRu5Wzdyt27L3botd+u23K3bcrfu1+tIzy4/d+u23K3bcrduy926LXfr/sTnOZfxWr61+NXyXw+W1Qfr6oOx+mBbffD9T5Z9/Mvy6sf7B8fqg3PxwZ94GzcetNUHffXBcvmg2dsH6+qDsfrgT96ccXy8OdPf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"}],"outputs":{"globals":{"notes":[{"fields":[{"kind":"integer","sign":false,"value":"00000000000000000000000000000000000000000000000000000000aad5fd6b"},{"kind":"string","value":"PublicKeyNote"}],"kind":"tuple"}],"storage":[{"fields":[{"name":"signing_public_key","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"signing_pub_key_x","type":{"kind":"field"}},{"name":"signing_pub_key_y","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::constructor_parameters"}}],"kind":"struct","path":"SchnorrAccount::constructor_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"SchnorrAccount::entrypoint_parameters"}}],"kind":"struct","path":"SchnorrAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrAccount::verify_private_authwit_abi"}]}},"file_map":{"100":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/outgoing_body.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, hash::poseidon2_hash\n};\n\nuse dep::std::aes128::aes128_encrypt;\nuse dep::std::println;\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogOutgoingBody {\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint,\n}\n\nimpl EncryptedLogOutgoingBody {\n pub fn new(\n eph_sk: GrumpkinPrivateKey,\n recipient: AztecAddress,\n recipient_ivpk_app: GrumpkinPoint\n ) -> Self {\n Self { eph_sk, recipient, recipient_ivpk_app }\n }\n\n pub fn compute_ciphertext(self, ovsk_app: GrumpkinPrivateKey, eph_pk: GrumpkinPoint) -> [u8; 176] {\n // Again, we could compute `eph_pk` here, but we keep the interface more similar\n // and also make it easier to optimise it later as we just pass it along\n\n let mut buffer: [u8; 160] = [0; 160];\n\n let serialized_eph_sk: [Field; 2] = self.eph_sk.serialize();\n let serialized_eph_sk_high = serialized_eph_sk[0].to_be_bytes(32);\n let serialized_eph_sk_low = serialized_eph_sk[1].to_be_bytes(32);\n\n let address_bytes = self.recipient.to_field().to_be_bytes(32);\n let serialized_recipient_ivpk_app = self.recipient_ivpk_app.serialize();\n let serialized_recipient_ivpk_app_x = serialized_recipient_ivpk_app[0].to_be_bytes(32);\n let serialized_recipient_ivpk_app_y = serialized_recipient_ivpk_app[1].to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = serialized_eph_sk_high[i];\n buffer[i + 32] = serialized_eph_sk_low[i];\n buffer[i + 64] = address_bytes[i];\n buffer[i + 96] = serialized_recipient_ivpk_app_x[i];\n buffer[i + 128] = serialized_recipient_ivpk_app_y[i];\n }\n\n // We compute the symmetric key using poseidon.\n let full_key: [u8; 32] = poseidon2_hash(\n [\n ovsk_app.high, ovsk_app.low, eph_pk.x, eph_pk.y,\n GENERATOR_INDEX__SYMMETRIC_KEY as Field\n ]\n ).to_be_bytes(32).as_array();\n\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(buffer, iv, sym_key).as_array()\n }\n}\n\nmod test {\n use crate::encrypted_logs::outgoing_body::EncryptedLogOutgoingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash\n };\n\n use crate::context::PrivateContext;\n\n #[test]\n fn test_encrypted_log_outgoing_body() {\n let eph_sk = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f096b423017226a18461115fa8d34bb,\n 0x00000000000000000000000000000000d0d302ee245dfaf2807e604eec4715fe\n );\n let recipient_ivsk_app = GrumpkinPrivateKey::new(\n 0x000000000000000000000000000000000f4d97c25d578f9348251a71ca17ae31,\n 0x000000000000000000000000000000004828f8f95676ebb481df163f87fd4022\n );\n let sender_ovsk_app = GrumpkinPrivateKey::new(\n 0x00000000000000000000000000000000089c6887cb1446d86c64e81afc78048b,\n 0x0000000000000000000000000000000074d2e28c6bc5176ac02cf7c7d36a444e\n );\n\n let eph_pk = eph_sk.derive_public_key();\n let recipient_ivpk_app = recipient_ivsk_app.derive_public_key();\n\n let recipient = AztecAddress::from_field(0xdeadbeef);\n\n let body = EncryptedLogOutgoingBody::new(eph_sk, recipient, recipient_ivpk_app);\n\n let ciphertext = body.compute_ciphertext(sender_ovsk_app, eph_pk);\n\n let expected_outgoing_body_ciphertext = [\n 127, 84, 96, 176, 101, 107, 236, 57, 68, 8, 53, 202, 138, 74, 186, 54, 74, 193, 245, 7, 109, 59, 218, 33, 1, 31, 205, 225, 241, 209, 64, 222, 94, 245, 4, 150, 47, 241, 187, 64, 152, 20, 102, 158, 200, 217, 213, 82, 1, 240, 170, 185, 51, 80, 27, 109, 63, 231, 235, 120, 174, 44, 133, 248, 10, 97, 60, 40, 222, 190, 147, 76, 187, 48, 91, 206, 48, 106, 56, 118, 38, 127, 82, 4, 182, 188, 44, 224, 31, 129, 47, 107, 134, 252, 20, 25, 122, 191, 158, 69, 35, 255, 215, 171, 196, 45, 91, 184, 83, 80, 238, 201, 1, 233, 235, 159, 171, 130, 158, 64, 176, 165, 132, 30, 84, 81, 71, 195, 145, 47, 82, 247, 210, 192, 23, 4, 220, 90, 56, 109, 46, 105, 79, 251, 165, 141, 185, 233, 191, 118, 219, 153, 191, 162, 99, 238, 241, 249, 9, 74, 210, 241, 54, 28, 126, 226, 85, 235, 174, 75, 239, 207, 100, 184, 248, 194\n ];\n\n for i in 0..expected_outgoing_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_outgoing_body_ciphertext[i]);\n }\n assert_eq(expected_outgoing_body_ciphertext.len(), ciphertext.len());\n }\n}\n"},"101":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/header.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nuse dep::std::aes128::aes128_encrypt;\n\nstruct EncryptedLogHeader {\n address: AztecAddress,\n}\n\nimpl EncryptedLogHeader {\n fn new(address: AztecAddress) -> Self {\n EncryptedLogHeader { address }\n }\n\n fn compute_ciphertext(self, secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 48] {\n let full_key = point_to_symmetric_key(secret, point);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n\n let input: [u8; 32] = self.address.to_field().to_be_bytes(32).as_array();\n aes128_encrypt(input, iv, sym_key).as_array()\n }\n}\n\n#[test]\nfn test_encrypted_log_header() {\n let address = AztecAddress::from_field(0xdeadbeef);\n let header = EncryptedLogHeader::new(address);\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let ciphertext = header.compute_ciphertext(secret, point);\n\n let expected_header_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 23, 131, 32, 226, 26, 176, 43, 39, 239, 177, 177, 192, 85, 216, 17, 15, 18, 187, 35, 225, 135, 192, 63, 88, 29, 173, 232, 46, 72, 82, 187, 139\n ];\n\n assert_eq(ciphertext, expected_header_ciphertext);\n}\n"},"102":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/incoming_body.nr","source":"use crate::note::note_interface::NoteInterface;\nuse crate::event::event_interface::EventInterface;\nuse dep::protocol_types::{grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint};\n\nuse dep::std::aes128::aes128_encrypt;\nuse crate::keys::point_to_symmetric_key::point_to_symmetric_key;\n\nstruct EncryptedLogIncomingBody {\n plaintext: [u8; M]\n}\n\nimpl EncryptedLogIncomingBody {\n pub fn from_note(note: T, storage_slot: Field) -> Self where T: NoteInterface {\n let mut plaintext = note.to_be_bytes(storage_slot);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn from_event(event: T, randomness: Field) -> Self where T: EventInterface {\n let mut plaintext = event.private_to_be_bytes(randomness);\n EncryptedLogIncomingBody { plaintext }\n }\n\n pub fn compute_ciphertext(self, eph_sk: GrumpkinPrivateKey, ivpk_app: GrumpkinPoint) -> [u8] {\n let full_key = point_to_symmetric_key(eph_sk, ivpk_app);\n let mut sym_key = [0; 16];\n let mut iv = [0; 16];\n\n for i in 0..16 {\n sym_key[i] = full_key[i];\n iv[i] = full_key[i + 16];\n }\n aes128_encrypt(self.plaintext, iv, sym_key)\n }\n}\n\nmod test {\n use crate::encrypted_logs::incoming_body::EncryptedLogIncomingBody;\n use dep::protocol_types::{\n address::AztecAddress, traits::Empty, constants::GENERATOR_INDEX__NOTE_NULLIFIER,\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, traits::Serialize,\n abis::event_selector::EventSelector\n };\n\n use crate::{\n note::{note_header::NoteHeader, note_interface::NoteInterface},\n event::event_interface::EventInterface, oracle::unsafe_rand::unsafe_rand,\n context::PrivateContext\n };\n\n struct AddressNote {\n address: AztecAddress,\n owner: AztecAddress,\n randomness: Field,\n header: NoteHeader,\n }\n\n global ADDRESS_NOTE_LEN: Field = 3;\n global ADDRESS_NOTE_BYTES_LEN = 32 * 3 + 64;\n\n impl NoteInterface for AddressNote {\n fn compute_note_content_hash(self) -> Field {1}\n\n fn get_note_type_id() -> Field {\n 1\n }\n\n fn get_header(self) -> NoteHeader { self.header}\n\n fn set_header(&mut self, header: NoteHeader) {self.header = header; }\n\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n (1, 1)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {(1,1)}\n\n fn serialize_content(self) -> [Field; ADDRESS_NOTE_LEN] { [self.address.to_field(), self.owner.to_field(), self.randomness]}\n\n fn deserialize_content(fields: [Field; ADDRESS_NOTE_LEN]) -> Self {\n AddressNote { address: AztecAddress::from_field(fields[0]), owner: AztecAddress::from_field(fields[1]), randomness: fields[2], header: NoteHeader::empty() }\n }\n\n fn to_be_bytes(self, storage_slot: Field) -> [u8; ADDRESS_NOTE_BYTES_LEN] {\n let serialized_note = self.serialize_content();\n\n let mut buffer: [u8; ADDRESS_NOTE_BYTES_LEN] = [0; ADDRESS_NOTE_BYTES_LEN];\n\n let storage_slot_bytes = storage_slot.to_be_bytes(32);\n let note_type_id_bytes = AddressNote::get_note_type_id().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = storage_slot_bytes[i];\n buffer[32 + i] = note_type_id_bytes[i];\n }\n\n for i in 0..serialized_note.len() {\n let bytes = serialized_note[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n buffer\n }\n }\n\n impl AddressNote {\n pub fn new(address: AztecAddress, owner: AztecAddress, randomness: Field) -> Self {\n AddressNote { address, owner, randomness, header: NoteHeader::empty() }\n }\n }\n\n #[test]\n fn test_encrypted_note_log_incoming_body() {\n let note = AddressNote::new(\n AztecAddress::from_field(0x1),\n AztecAddress::from_field(0x2),\n 3\n );\n\n let storage_slot = 2;\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let body = EncryptedLogIncomingBody::from_note(note, storage_slot);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_note_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 48, 153, 169, 1, 25, 182, 93, 39, 39, 207, 251, 218, 234, 147, 156, 13, 110, 180, 190, 199, 41, 6, 211, 203, 176, 110, 165, 186, 110, 127, 199, 22, 201, 149, 92, 249, 219, 68, 145, 68, 179, 29, 233, 34, 98, 123, 197, 234, 169, 53, 44, 14, 81, 60, 92, 27, 250, 134, 49, 248, 57, 119, 236, 118, 158, 104, 82, 243, 98, 164, 60, 72, 74, 27, 177, 194, 221, 225, 193, 150, 67, 235, 205, 106, 150, 24, 126, 186, 220, 178, 199, 189, 113, 54, 181, 55, 46, 15, 236, 236, 9, 159, 5, 172, 237, 154, 110, 50, 241, 64, 92, 13, 37, 53, 20, 140, 42, 146, 229, 63, 97, 25, 159, 63, 235, 104, 68, 100\n ];\n\n assert_eq(expected_note_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_note_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_note_body_ciphertext[i]);\n }\n }\n\n struct TestEvent {\n value0: Field,\n value1: Field,\n value2: Field,\n }\n\n impl Serialize<3> for TestEvent {\n fn serialize(self) -> [Field; 3] {\n [self.value0, self.value1, self.value2]\n }\n }\n\n global TEST_EVENT_LEN: Field = 3;\n global TEST_EVENT_BYTES_LEN = 32 * 3 + 64;\n global TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS = 32 * 3 + 32;\n\n impl EventInterface for TestEvent {\n fn get_event_type_id() -> EventSelector {\n EventSelector::from_signature(\"TestEvent(Field,Field,Field)\")\n }\n\n fn private_to_be_bytes(self, randomness: Field) -> [u8; TEST_EVENT_BYTES_LEN] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN] = [0; TEST_EVENT_BYTES_LEN];\n\n let randomness_bytes = randomness.to_be_bytes(32);\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = randomness_bytes[i];\n buffer[32 + i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[64 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn to_be_bytes(self) -> [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] {\n let mut buffer: [u8; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS] = [0; TEST_EVENT_BYTES_LEN_WITHOUT_RANDOMNESS];\n\n let event_type_id_bytes = TestEvent::get_event_type_id().to_field().to_be_bytes(32);\n\n for i in 0..32 {\n buffer[i] = event_type_id_bytes[i];\n }\n\n let serialized_event = self.serialize();\n\n for i in 0..serialized_event.len() {\n let bytes = serialized_event[i].to_be_bytes(32);\n for j in 0..32 {\n buffer[32 + i * 32 + j] = bytes[j];\n }\n }\n\n buffer\n }\n\n fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n }\n\n #[test]\n fn test_encrypted_log_event_incoming_body() {\n let test_event = TestEvent { value0: 1, value1: 2, value2: 3 };\n\n let eph_sk = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n\n let ivpk_app = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let randomness = 2;\n\n let body = EncryptedLogIncomingBody::from_event(test_event, randomness);\n\n let ciphertext = body.compute_ciphertext(eph_sk, ivpk_app);\n\n let expected_event_body_ciphertext = [\n 228, 9, 65, 81, 62, 59, 249, 207, 90, 196, 206, 72, 39, 199, 82, 196, 63, 127, 188, 251, 150, 188, 238, 205, 3, 86, 102, 164, 175, 12, 137, 158, 163, 111, 205, 10, 229, 230, 46, 202, 110, 107, 156, 180, 67, 192, 161, 201, 66, 122, 29, 35, 42, 33, 153, 216, 199, 208, 103, 207, 126, 153, 189, 136, 19, 220, 238, 15, 169, 29, 255, 11, 123, 107, 70, 192, 53, 40, 36, 93, 187, 32, 123, 136, 104, 23, 229, 245, 152, 90, 84, 2, 136, 112, 42, 27, 82, 214, 104, 14, 250, 48, 199, 245, 88, 22, 200, 77, 38, 51, 127, 56, 138, 255, 16, 46, 179, 129, 215, 185, 185, 116, 148, 16, 133, 62, 56, 180, 10, 132, 109, 77, 206, 199, 21, 167, 7, 163, 171, 158, 244, 23, 18, 121, 108, 42, 107, 7, 48, 84, 212, 104, 39, 16, 109, 7, 108, 129, 60, 80, 112, 241, 223, 140, 186, 158, 38, 74, 230, 213, 159, 175, 142, 228, 128, 160\n ];\n\n assert_eq(expected_event_body_ciphertext.len(), ciphertext.len());\n\n for i in 0..expected_event_body_ciphertext.len() {\n assert_eq(ciphertext[i], expected_event_body_ciphertext[i]);\n }\n }\n}\n"},"107":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/utils.nr","source":"use crate::{context::PrivateContext, note::{note_header::NoteHeader, note_interface::NoteInterface}};\n\nuse dep::protocol_types::{\n constants::GENERATOR_INDEX__INNER_NOTE_HASH,\n hash::{\n pedersen_hash, compute_unique_note_hash, compute_siloed_note_hash as compute_siloed_note_hash,\n compute_siloed_nullifier as compute_siloed_nullifier_from_preimage\n},\n utils::arr_copy_slice\n};\n\nfn compute_inner_note_hash(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n let note_hash = note.compute_note_content_hash();\n\n pedersen_hash(\n [header.storage_slot, note_hash],\n GENERATOR_INDEX__INNER_NOTE_HASH\n )\n}\n\npub fn compute_siloed_nullifier(\n note_with_header: Note,\n context: &mut PrivateContext\n) -> Field where Note: NoteInterface {\n let header = note_with_header.get_header();\n let (_, inner_nullifier) = note_with_header.compute_note_hash_and_nullifier(context);\n\n compute_siloed_nullifier_from_preimage(header.contract_address, inner_nullifier)\n}\n\nfn compute_note_hash_for_read_request_from_innter_and_nonce(\n inner_note_hash: Field,\n nonce: Field\n) -> Field {\n // TODO(#1386): This if-else can be nuked once we have nonces injected from public\n if (nonce == 0) {\n // If nonce is zero, that means we are reading a public note.\n inner_note_hash\n } else {\n compute_unique_note_hash(nonce, inner_note_hash)\n }\n}\n\npub fn compute_note_hash_for_read_request(note: Note) -> Field where Note: NoteInterface {\n let inner_note_hash = compute_inner_note_hash(note);\n let nonce = note.get_header().nonce;\n\n compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, nonce)\n}\n\npub fn compute_note_hash_for_consumption(note: Note) -> Field where Note: NoteInterface {\n let header = note.get_header();\n // There are 3 cases for reading a note intended for consumption:\n // 1. The note was inserted in this transaction, and is transient.\n // 2. The note was inserted in a previous transaction, and was inserted in public\n // 3. The note was inserted in a previous transaction, and was inserted in private\n\n let inner_note_hash = compute_inner_note_hash(note);\n\n if (header.note_hash_counter != 0) {\n // If a note is transient, we just read the inner_note_hash (kernel will silo by contract address).\n inner_note_hash\n } else {\n // If a note is not transient, that means we are reading a settled note (from tree) created in a\n // previous TX. So we need the siloed_note_hash which has already been hashed with\n // nonce and then contract address. This hash will match the existing leaf in the note hash\n // tree, so the kernel can just perform a membership check directly on this hash/leaf.\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, header.nonce);\n compute_siloed_note_hash(header.contract_address, unique_note_hash)\n // IMPORTANT NOTE ON REDUNDANT SILOING BY CONTRACT ADDRESS: The note hash computed above is\n // \"siloed\" by contract address. When a note hash is computed solely for the purpose of\n // nullification, it is not strictly necessary to silo the note hash before computing\n // its nullifier. In other words, it is NOT NECESSARY for protocol security that a nullifier\n // be computed from a siloed note hash. After all, persistable note hashes and nullifiers are\n // siloed by the kernel circuit. That being said, the siloed note hash computed above CAN be\n // used for nullifier computation, and this achieves the (arguably unnecessary) property that\n // nullifiers are computed from a note hash's fully-computed note hash tree leaf.\n }\n}\n\npub fn compute_note_hash_and_optionally_a_nullifier(\n deserialize_content: fn([Field; N]) -> T,\n note_header: NoteHeader,\n compute_nullifier: bool,\n serialized_note: [Field; S]\n) -> [Field; 4] where T: NoteInterface {\n let mut note = deserialize_content(arr_copy_slice(serialized_note, [0; N], 0));\n note.set_header(note_header);\n\n let inner_note_hash = compute_inner_note_hash(note);\n let unique_note_hash = compute_note_hash_for_read_request_from_innter_and_nonce(inner_note_hash, note_header.nonce);\n let siloed_note_hash = compute_siloed_note_hash(note_header.contract_address, unique_note_hash);\n\n let inner_nullifier = if compute_nullifier {\n let (_, nullifier) = note.compute_note_hash_and_nullifier_without_context();\n nullifier\n } else {\n 0\n };\n // docs:start:compute_note_hash_and_optionally_a_nullifier_returns\n [inner_note_hash, unique_note_hash, siloed_note_hash, inner_nullifier]\n // docs:end:compute_note_hash_and_optionally_a_nullifier_returns\n}\n"},"108":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/lifecycle.nr","source":"use dep::protocol_types::grumpkin_point::GrumpkinPoint;\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::note::{\n note_header::NoteHeader, note_interface::NoteInterface,\n utils::{compute_inner_note_hash, compute_note_hash_for_consumption}, note_emission::NoteEmission\n};\nuse crate::oracle::notes::{notify_created_note, notify_nullified_note};\n\npub fn create_note(\n context: &mut PrivateContext,\n storage_slot: Field,\n note: &mut Note\n) -> NoteEmission where Note: NoteInterface {\n let contract_address = (*context).this_address();\n let note_hash_counter = context.side_effect_counter;\n\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n let serialized_note = Note::serialize_content(*note);\n assert(\n notify_created_note(\n storage_slot,\n Note::get_note_type_id(),\n serialized_note,\n inner_note_hash,\n note_hash_counter\n )\n == 0\n );\n\n context.push_new_note_hash(inner_note_hash);\n\n NoteEmission::new(*note)\n}\n\npub fn create_note_hash_from_public(\n context: &mut PublicContext,\n storage_slot: Field,\n note: &mut Note\n) where Note: NoteInterface {\n let contract_address = (*context).this_address();\n // Public note hashes are transient, but have no side effect counters, so we just need note_hash_counter != 0\n let header = NoteHeader { contract_address, storage_slot, nonce: 0, note_hash_counter: 1 };\n note.set_header(header);\n let inner_note_hash = compute_inner_note_hash(*note);\n\n context.push_new_note_hash(inner_note_hash);\n}\n\npub fn destroy_note(\n context: &mut PrivateContext,\n note: Note\n) where Note: NoteInterface {\n let (note_hash, nullifier) = note.compute_note_hash_and_nullifier(context);\n\n let note_hash_counter = note.get_header().note_hash_counter;\n let note_hash_for_consumption = if (note_hash_counter == 0) {\n // Counter is zero, so we're nullifying a non-transient note and we don't populate the note_hash with real\n // value (if we did so the `notifyNullifiedNote` oracle would throw).\n 0\n } else {\n // A non-zero note hash counter implies that we're nullifying a transient note (i.e. one that has not yet been\n // persisted in the trees and is instead in the pending new note hashes array). In such a case we populate its\n // hash with real value to inform the kernel which note we're nullifyng so that it can find it and squash both\n // the note and the nullifier.\n note_hash\n };\n\n let nullifier_counter = context.side_effect_counter;\n assert(notify_nullified_note(nullifier, note_hash_for_consumption, nullifier_counter) == 0);\n\n context.push_new_nullifier(nullifier, note_hash_for_consumption)\n}\n"},"109":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_emission.nr","source":"/**\n * A note emission struct containing the information required for emitting a note.\n * The exact `emit` logic is passed in by the application code\n */\nstruct NoteEmission {\n note: Note\n}\n\nimpl NoteEmission {\n pub fn new(note: Note) -> Self {\n Self { note }\n }\n\n pub fn emit(self, _emit: fn[Env](Self) -> ()) {\n _emit(self);\n }\n\n pub fn discard(self) {}\n}\n\n/**\n * A struct wrapping note emission in `Option`.\n * This is the struct provided to application codes, which can be used to emit\n * only when a note was actually inserted.\n * It is fairly common to have cases where a function conditionally inserts,\n * and this allows us to keep the same API for emission in both cases (e.g. inserting \n * a change note in a token's transfer function only when there is \"change\" left).\n */\nstruct OuterNoteEmission {\n emission: Option>,\n}\n\nimpl OuterNoteEmission {\n pub fn new(emission: Option>) -> Self {\n Self { emission }\n }\n\n pub fn emit(self, _emit: fn[Env](NoteEmission) -> ()) {\n if self.emission.is_some() {\n _emit(self.emission.unwrap());\n }\n }\n\n pub fn discard(self) {}\n}\n"},"111":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_viewer_options.nr","source":"use dep::std::option::Option;\nuse crate::note::note_getter_options::{PropertySelector, Select, Sort, Comparator, NoteStatus};\nuse dep::protocol_types::traits::ToField;\nuse crate::note::note_interface::NoteInterface;\nuse crate::note::constants::MAX_NOTES_PER_PAGE;\n\n// docs:start:NoteViewerOptions\nstruct NoteViewerOptions {\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>,\n limit: u32,\n offset: u32,\n status: u8,\n}\n// docs:end:NoteViewerOptions\n\nimpl NoteViewerOptions {\n pub fn new() -> NoteViewerOptions where Note: NoteInterface {\n NoteViewerOptions {\n selects: BoundedVec::new(),\n sorts: BoundedVec::new(),\n limit: MAX_NOTES_PER_PAGE as u32,\n offset: 0,\n status: NoteStatus.ACTIVE\n }\n }\n\n // This method adds a `Select` criterion to the options.\n // It takes a field_index indicating which field to select,\n // a value representing the specific value to match in that field, and\n // a comparator (For possible values of comparators, please see the Comparator enum from note_getter_options)\n pub fn select(\n &mut self,\n property_selector: PropertySelector,\n value: T,\n comparator: Option\n ) -> Self where T: ToField {\n self.selects.push(\n Option::some(\n Select::new(\n property_selector,\n value.to_field(),\n comparator.unwrap_or(Comparator.EQ)\n )\n )\n );\n *self\n }\n\n pub fn sort(&mut self, property_selector: PropertySelector, order: u8) -> Self {\n self.sorts.push(Option::some(Sort::new(property_selector, order)));\n *self\n }\n\n pub fn set_limit(&mut self, limit: u32) -> Self {\n assert(limit <= MAX_NOTES_PER_PAGE as u32);\n // By requesting that the limit is a constant, we guarantee that it will be possible to loop over it, reducing\n // gate counts when a limit has been set. This isn't required in unconstrained code, but we still keep this\n // requirement here for API consistency.\n assert_constant(limit);\n self.limit = limit;\n *self\n }\n\n pub fn set_offset(&mut self, offset: u32) -> Self {\n self.offset = offset;\n *self\n }\n\n // This method sets the status value, which determines whether to retrieve active or nullified notes.\n pub fn set_status(&mut self, status: u8) -> Self {\n self.status = status;\n *self\n }\n}\n"},"112":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_getter.nr","source":"use dep::protocol_types::{constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, GET_NOTES_ORACLE_RETURN_LENGTH}};\nuse crate::context::PrivateContext;\nuse crate::note::{\n constants::{GET_NOTE_ORACLE_RETURN_LENGTH, MAX_NOTES_PER_PAGE, VIEW_NOTE_ORACLE_RETURN_LENGTH},\n note_getter_options::{NoteGetterOptions, Select, Sort, SortOrder, Comparator, NoteStatus, PropertySelector},\n note_interface::NoteInterface, note_viewer_options::NoteViewerOptions,\n utils::compute_note_hash_for_read_request\n};\nuse crate::oracle;\n\nmod test;\n\nfn extract_property_value_from_selector(\n serialized_note: [Field; N],\n selector: PropertySelector\n) -> Field {\n // Selectors use PropertySelectors in order to locate note properties inside the serialized note. \n // This allows easier packing and custom (de)serialization schemas. A note property is located\n // inside the serialized note using the index inside the array, a byte offset and a length.\n let value = serialized_note[selector.index].to_be_bytes(32);\n let offset = selector.offset;\n let length = selector.length;\n let mut value_field = 0 as Field;\n let mut acc: Field = 1;\n for i in 0..32 {\n if i < length {\n value_field += value[31 + offset - i] as Field * acc;\n acc = acc * 256;\n }\n }\n value_field\n}\n\nfn check_note_header(\n context: PrivateContext,\n storage_slot: Field,\n note: Note\n) where Note: NoteInterface {\n let header = note.get_header();\n let contract_address = context.this_address();\n assert(header.contract_address.eq(contract_address), \"Mismatch note header contract address.\");\n assert(header.storage_slot == storage_slot, \"Mismatch note header storage slot.\");\n}\n\nfn check_note_fields(serialized_note: [Field; N], selects: BoundedVec, N>) {\n for i in 0..selects.len {\n let select = selects.get_unchecked(i).unwrap_unchecked();\n let value_field = extract_property_value_from_selector(serialized_note, select.property_selector);\n\n // Values are computed ahead of time because circuits evaluate all branches\n let is_equal = value_field == select.value.to_field();\n let is_lt = value_field.lt(select.value.to_field());\n\n if (select.comparator == Comparator.EQ) {\n assert(is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.NEQ) {\n assert(!is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LT) {\n assert(is_lt, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.LTE) {\n assert(is_lt | is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GT) {\n assert(!is_lt & !is_equal, \"Mismatch return note field.\");\n } else if (select.comparator == Comparator.GTE) {\n assert(!is_lt, \"Mismatch return note field.\");\n }\n }\n}\n\nfn check_notes_order(\n fields_0: [Field; N],\n fields_1: [Field; N],\n sorts: BoundedVec, N>\n) {\n for i in 0..sorts.len {\n let sort = sorts.get_unchecked(i).unwrap_unchecked();\n let field_0 = extract_property_value_from_selector(fields_0, sort.property_selector);\n let field_1 = extract_property_value_from_selector(fields_1, sort.property_selector);\n let eq = field_0 == field_1;\n let lt = field_0.lt(field_1);\n if sort.order == SortOrder.ASC {\n assert(eq | lt, \"Return notes not sorted in ascending order.\");\n } else if !eq {\n assert(!lt, \"Return notes not sorted in descending order.\");\n }\n }\n}\n\npub fn get_note(\n context: &mut PrivateContext,\n storage_slot: Field\n) -> Note where Note: NoteInterface {\n let note = get_note_internal(storage_slot);\n\n check_note_header(*context, storage_slot, note);\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n\n context.push_note_hash_read_request(note_hash_for_read_request);\n note\n}\n\npub fn get_notes(\n context: &mut PrivateContext,\n storage_slot: Field,\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let opt_notes = get_notes_internal(storage_slot, options);\n\n constrain_get_notes_internal(context, storage_slot, opt_notes, options)\n}\n\nfn constrain_get_notes_internal(\n context: &mut PrivateContext,\n storage_slot: Field,\n opt_notes: [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n options: NoteGetterOptions\n) -> BoundedVec where Note: NoteInterface {\n let mut returned_notes = BoundedVec::new();\n\n // The filter is applied first to avoid pushing note read requests for notes we're not interested in. Note that\n // while the filter function can technically mutate the contents of the notes (as opposed to simply removing some),\n // the private kernel will later validate that these note actually exist, so transformations would cause for that\n // check to fail.\n let filter_fn = options.filter;\n let filter_args = options.filter_args;\n let filtered_notes = filter_fn(opt_notes, filter_args);\n\n let mut prev_fields = [0; N];\n for i in 0..filtered_notes.len() {\n let opt_note = filtered_notes[i];\n if opt_note.is_some() {\n let note = opt_note.unwrap_unchecked();\n let fields = note.serialize_content();\n check_note_header(*context, storage_slot, note);\n check_note_fields(fields, options.selects);\n if i != 0 {\n check_notes_order(prev_fields, fields, options.sorts);\n }\n prev_fields = fields;\n\n let note_hash_for_read_request = compute_note_hash_for_read_request(note);\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1410): test to ensure\n // failure if malicious oracle injects 0 nonce here for a \"pre-existing\" note.\n context.push_note_hash_read_request(note_hash_for_read_request);\n\n // The below code is used to collapse a sparse array into one where the values are guaranteed to be at the \n // front of the array. This is highly useful because the caller knows that the returned array won't have\n // more than option.limits notes, and can therefore loop over this limit value instead of the entire array,\n // resulting in a smaller circuit and faster proving times.\n // We write at returned_notes[num_notes] because num_notes is only advanced when we have a value in \n // filtered_notes.\n returned_notes.push(note);\n };\n }\n\n assert(returned_notes.len() <= options.limit, \"Got more notes than limit.\");\n assert(returned_notes.len() != 0, \"Cannot return zero notes\");\n\n returned_notes\n}\n\nunconstrained fn get_note_internal(storage_slot: Field) -> Note where Note: NoteInterface {\n let placeholder_note = [Option::none()];\n let placeholder_fields = [0; GET_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n oracle::notes::get_notes(\n storage_slot,\n 0,\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n [],\n 1, // limit\n 0, // offset\n NoteStatus.ACTIVE,\n placeholder_note,\n placeholder_fields,\n placeholder_note_length\n )[0].unwrap() // Notice: we don't allow dummies to be returned from get_note (singular).\n}\n\nunconstrained fn get_notes_internal(\n storage_slot: Field,\n options: NoteGetterOptions\n) -> [Option; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL] where Note: NoteInterface {\n // This function simply performs some transformations from NoteGetterOptions into the types required by the oracle.\n\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL];\n let placeholder_fields = [0; GET_NOTES_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n )\n}\n\nunconstrained pub fn view_notes(\n storage_slot: Field,\n options: NoteViewerOptions\n) -> BoundedVec where Note: NoteInterface {\n let (num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order) = flatten_options(options.selects, options.sorts);\n let placeholder_opt_notes = [Option::none(); MAX_NOTES_PER_PAGE];\n let placeholder_fields = [0; VIEW_NOTE_ORACLE_RETURN_LENGTH];\n let placeholder_note_length = [0; N];\n\n let notes_array = oracle::notes::get_notes(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n options.limit,\n options.offset,\n options.status,\n placeholder_opt_notes,\n placeholder_fields,\n placeholder_note_length\n );\n\n let mut notes = BoundedVec::new();\n for i in 0..notes_array.len() {\n if notes_array[i].is_some() {\n notes.push(notes_array[i].unwrap_unchecked());\n }\n }\n\n notes\n}\n\nunconstrained fn flatten_options(\n selects: BoundedVec, N>,\n sorts: BoundedVec, N>\n) -> (u8, [u8; N], [u8; N], [u8; N], [Field; N], [u8; N], [u8; N], [u8; N], [u8; N], [u8; N]) {\n let mut num_selects = 0;\n let mut select_by_indexes = [0; N];\n let mut select_by_offsets = [0; N];\n let mut select_by_lengths = [0; N];\n let mut select_values = [0; N];\n let mut select_comparators = [0; N];\n\n for i in 0..selects.len {\n let select = selects.get(i);\n if select.is_some() {\n select_by_indexes[num_selects] = select.unwrap_unchecked().property_selector.index;\n select_by_offsets[num_selects] = select.unwrap_unchecked().property_selector.offset;\n select_by_lengths[num_selects] = select.unwrap_unchecked().property_selector.length;\n select_values[num_selects] = select.unwrap_unchecked().value;\n select_comparators[num_selects] = select.unwrap_unchecked().comparator;\n num_selects += 1;\n };\n }\n\n let mut sort_by_indexes = [0; N];\n let mut sort_by_offsets = [0; N];\n let mut sort_by_lengths = [0; N];\n let mut sort_order = [0; N];\n for i in 0..sorts.len {\n let sort = sorts.get(i);\n if sort.is_some() {\n sort_by_indexes[i] = sort.unwrap_unchecked().property_selector.index;\n sort_by_offsets[i] = sort.unwrap_unchecked().property_selector.offset;\n sort_by_lengths[i] = sort.unwrap_unchecked().property_selector.length;\n sort_order[i] = sort.unwrap_unchecked().order;\n };\n }\n\n (\n num_selects, select_by_indexes, select_by_offsets, select_by_lengths, select_values, select_comparators, sort_by_indexes, sort_by_offsets, sort_by_lengths, sort_order\n )\n}\n"},"113":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/note/note_header.nr","source":"use dep::protocol_types::address::AztecAddress;\nuse dep::protocol_types::traits::{Empty, Eq, Serialize};\n\nstruct NoteHeader {\n contract_address: AztecAddress,\n nonce: Field,\n storage_slot: Field,\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)\n // Check the nonce to see whether a note is transient or not.\n note_hash_counter: u32, // a note_hash_counter of 0 means non-transient\n}\n\nimpl Empty for NoteHeader {\n fn empty() -> Self {\n NoteHeader { contract_address: AztecAddress::zero(), nonce: 0, storage_slot: 0, note_hash_counter: 0 }\n }\n}\n\nimpl Eq for NoteHeader {\n fn eq(self, other: Self) -> bool {\n (self.contract_address == other.contract_address) & \n (self.nonce == other.nonce) & \n (self.storage_slot == other.storage_slot)& \n (self.note_hash_counter == other.note_hash_counter)\n }\n}\n\nimpl NoteHeader {\n pub fn new(contract_address: AztecAddress, nonce: Field, storage_slot: Field) -> Self {\n NoteHeader { contract_address, nonce, storage_slot, note_hash_counter: 0 }\n }\n}\n\nimpl Serialize<4> for NoteHeader {\n fn serialize(self) -> [Field; 4] {\n [self.contract_address.to_field(), self.nonce, self.storage_slot, self.note_hash_counter as Field]\n }\n}\n"},"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"118":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/initializer.nr","source":"use dep::protocol_types::{\n address::AztecAddress, hash::{compute_siloed_nullifier, pedersen_hash},\n constants::GENERATOR_INDEX__CONSTRUCTOR, abis::function_selector::FunctionSelector\n};\n\nuse crate::{\n context::{PrivateContext, PublicContext}, oracle::get_contract_instance::get_contract_instance,\n oracle::get_contract_instance::get_contract_instance_avm\n};\n\npub fn mark_as_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn mark_as_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier((*context).this_address());\n context.push_new_nullifier(init_nullifier, 0);\n}\n\npub fn assert_is_initialized_public(context: &mut PublicContext) {\n let init_nullifier = compute_unsiloed_contract_initialization_nullifier(context.this_address());\n assert(context.nullifier_exists(init_nullifier, context.this_address()), \"Not initialized\");\n}\n\npub fn assert_is_initialized_private(context: &mut PrivateContext) {\n let init_nullifier = compute_contract_initialization_nullifier(context.this_address());\n let header = context.get_header();\n header.prove_nullifier_inclusion(init_nullifier);\n}\n\nfn compute_contract_initialization_nullifier(address: AztecAddress) -> Field {\n compute_siloed_nullifier(\n address,\n compute_unsiloed_contract_initialization_nullifier(address)\n )\n}\n\nfn compute_unsiloed_contract_initialization_nullifier(address: AztecAddress) -> Field {\n address.to_field()\n}\n\npub fn assert_initialization_matches_address_preimage_public(context: PublicContext) {\n let address = context.this_address();\n let instance = get_contract_instance_avm(address).unwrap();\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn assert_initialization_matches_address_preimage_private(context: PrivateContext) {\n let address = context.this_address();\n let instance = get_contract_instance(address);\n let expected_init = compute_initialization_hash(context.selector(), context.get_args_hash());\n assert(instance.initialization_hash == expected_init, \"Initialization hash does not match\");\n assert(\n (instance.deployer.is_zero()) | (instance.deployer == context.msg_sender()), \"Initializer address is not the contract deployer\"\n );\n}\n\npub fn compute_initialization_hash(init_selector: FunctionSelector, init_args_hash: Field) -> Field {\n pedersen_hash(\n [init_selector.to_field(), init_args_hash],\n GENERATOR_INDEX__CONSTRUCTOR\n )\n}\n"},"120":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_nullifier_membership_witness.nr","source":"use dep::protocol_types::{\n abis::nullifier_leaf_preimage::{NullifierLeafPreimage, NULLIFIER_LEAF_PREIMAGE_LENGTH},\n constants::NULLIFIER_TREE_HEIGHT, hash::pedersen_hash, utils::arr_copy_slice\n};\n\n// INDEX_LENGTH + NULLIFIER_LEAF_PREIMAGE_LENGTH + NULLIFIER_TREE_HEIGHT\nglobal NULLIFIER_MEMBERSHIP_WITNESS: Field = 24;\n\nstruct NullifierMembershipWitness {\n index: Field,\n leaf_preimage: NullifierLeafPreimage,\n path: [Field; NULLIFIER_TREE_HEIGHT],\n}\n\nimpl NullifierMembershipWitness {\n pub fn deserialize(fields: [Field; NULLIFIER_MEMBERSHIP_WITNESS]) -> Self {\n let leaf_preimage_fields = arr_copy_slice(fields, [0; NULLIFIER_LEAF_PREIMAGE_LENGTH], 1);\n Self {\n index: fields[0],\n leaf_preimage: NullifierLeafPreimage::deserialize(leaf_preimage_fields),\n path: arr_copy_slice(\n fields,\n [0; NULLIFIER_TREE_HEIGHT],\n 1 + NULLIFIER_LEAF_PREIMAGE_LENGTH\n )\n }\n }\n}\n\n#[oracle(getLowNullifierMembershipWitness)]\nunconstrained fn get_low_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_low_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_low_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n\n#[oracle(getNullifierMembershipWitness)]\nunconstrained fn get_nullifier_membership_witness_oracle(\n _block_number: u32,\n _nullifier: Field\n) -> [Field; NULLIFIER_MEMBERSHIP_WITNESS] {}\n\n// Nullifier here refers to the nullifier we are looking to get non-inclusion proof for (by proving that a lower\n// nullifier's next_value is bigger than the nullifier)\nunconstrained pub fn get_nullifier_membership_witness(block_number: u32, nullifier: Field) -> NullifierMembershipWitness {\n let fields = get_nullifier_membership_witness_oracle(block_number, nullifier);\n NullifierMembershipWitness::deserialize(fields)\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"126":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/key_validation_request.nr","source":"use dep::protocol_types::{\n grumpkin_point::GrumpkinPoint,\n abis::validation_requests::{KeyValidationRequest, key_validation_request::KEY_VALIDATION_REQUEST_LENGTH}\n};\n\n#[oracle(getKeyValidationRequest)]\nunconstrained fn get_key_validation_request_oracle(\n _pk_m_hash: Field,\n _key_index: Field\n) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {}\n\nunconstrained fn get_key_validation_request_internal(npk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n let result = get_key_validation_request_oracle(npk_m_hash, key_index);\n KeyValidationRequest::deserialize(result)\n}\n\npub fn get_key_validation_request(pk_m_hash: Field, key_index: Field) -> KeyValidationRequest {\n get_key_validation_request_internal(pk_m_hash, key_index)\n}\n\n"},"130":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/unsafe_rand.nr","source":"#[oracle(getRandomField)]\nunconstrained fn rand_oracle() -> Field {}\n\n// Called `unsafe_rand` because we do not constrain in circuit that we are dealing with an actual random value.\n// Instead we just trust our PXE.\nunconstrained pub fn unsafe_rand() -> Field {\n rand_oracle()\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"133":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/keys.nr","source":"use crate::keys::PublicKeys;\nuse dep::protocol_types::{address::{AztecAddress, PartialAddress}, grumpkin_point::GrumpkinPoint};\n\n#[oracle(getPublicKeysAndPartialAddress)]\nunconstrained fn get_public_keys_and_partial_address_oracle(_address: AztecAddress) -> [Field; 9] {}\n\nunconstrained fn get_public_keys_and_partial_address_oracle_wrapper(address: AztecAddress) -> [Field; 9] {\n get_public_keys_and_partial_address_oracle(address)\n}\n\nfn get_public_keys_and_partial_address(address: AztecAddress) -> (PublicKeys, PartialAddress) {\n let result = get_public_keys_and_partial_address_oracle_wrapper(address);\n\n let keys = PublicKeys {\n npk_m: GrumpkinPoint::new(result[0], result[1]),\n ivpk_m: GrumpkinPoint::new(result[2], result[3]),\n ovpk_m: GrumpkinPoint::new(result[4], result[5]),\n tpk_m: GrumpkinPoint::new(result[6], result[7])\n };\n\n let partial_address = PartialAddress::from_field(result[8]);\n\n (keys, partial_address)\n}\n"},"135":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/notes.nr","source":"use crate::note::{note_header::NoteHeader, note_interface::NoteInterface};\n\nuse dep::protocol_types::{address::AztecAddress, utils::arr_copy_slice};\n\n#[oracle(notifyCreatedNote)]\nunconstrained fn notify_created_note_oracle(\n _storage_slot: Field,\n _note_type_id: Field,\n _serialized_note: [Field; N],\n _inner_note_hash: Field,\n _counter: u32\n) -> Field {}\n\nunconstrained pub fn notify_created_note(\n storage_slot: Field,\n note_type_id: Field,\n serialized_note: [Field; N],\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_created_note_oracle(\n storage_slot,\n note_type_id,\n serialized_note,\n inner_note_hash,\n counter\n )\n}\n\n#[oracle(notifyNullifiedNote)]\nunconstrained fn notify_nullified_note_oracle(_nullifier: Field, _inner_note_hash: Field, _counter: u32) -> Field {}\n\nunconstrained pub fn notify_nullified_note(\n nullifier: Field,\n inner_note_hash: Field,\n counter: u32\n) -> Field {\n notify_nullified_note_oracle(nullifier, inner_note_hash, counter)\n}\n\n#[oracle(getNotes)]\nunconstrained fn get_notes_oracle(\n _storage_slot: Field,\n _num_selects: u8,\n _select_by_indexes: [u8; N],\n _select_by_offsets: [u8; N],\n _select_by_lengths: [u8; N],\n _select_values: [Field; N],\n _select_comparators: [u8; N],\n _sort_by_indexes: [u8; N],\n _sort_by_offsets: [u8; N],\n _sort_by_lengths: [u8; N],\n _sort_order: [u8; N],\n _limit: u32,\n _offset: u32,\n _status: u8,\n _return_size: u32,\n _placeholder_fields: [Field; S]\n) -> [Field; S] {}\n\nunconstrained fn get_notes_oracle_wrapper(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; N],\n select_by_offsets: [u8; N],\n select_by_lengths: [u8; N],\n select_values: [Field; N],\n select_comparators: [u8; N],\n sort_by_indexes: [u8; N],\n sort_by_offsets: [u8; N],\n sort_by_lengths: [u8; N],\n sort_order: [u8; N],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_fields: [Field; S]\n) -> [Field; S] {\n let return_size = placeholder_fields.len() as u32;\n get_notes_oracle(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n return_size,\n placeholder_fields\n )\n}\n\nunconstrained pub fn get_notes(\n storage_slot: Field,\n num_selects: u8,\n select_by_indexes: [u8; M],\n select_by_offsets: [u8; M],\n select_by_lengths: [u8; M],\n select_values: [Field; M],\n select_comparators: [u8; M],\n sort_by_indexes: [u8; M],\n sort_by_offsets: [u8; M],\n sort_by_lengths: [u8; M],\n sort_order: [u8; M],\n limit: u32,\n offset: u32,\n status: u8,\n mut placeholder_opt_notes: [Option; S], // TODO: Remove it and use `limit` to initialize the note array.\n placeholder_fields: [Field; NS], // TODO: Remove it and use `limit` to initialize the note array.\n _placeholder_note_length: [Field; N] // Turbofish hack? Compiler breaks calculating read_offset unless we add this parameter\n) -> [Option; S] where Note: NoteInterface {\n let fields = get_notes_oracle_wrapper(\n storage_slot,\n num_selects,\n select_by_indexes,\n select_by_offsets,\n select_by_lengths,\n select_values,\n select_comparators,\n sort_by_indexes,\n sort_by_offsets,\n sort_by_lengths,\n sort_order,\n limit,\n offset,\n status,\n placeholder_fields\n );\n let num_notes = fields[0] as u32;\n let contract_address = AztecAddress::from_field(fields[1]);\n for i in 0..placeholder_opt_notes.len() {\n if i < num_notes {\n // lengths named as per typescript.\n let return_header_length: u32 = 2; // num_notes & contract_address.\n let extra_preimage_length: u32 = 2; // nonce & note_hash_counter.\n let read_offset: u32 = return_header_length + i * (N + extra_preimage_length);\n let nonce = fields[read_offset];\n let note_hash_counter = fields[read_offset + 1] as u32;\n let header = NoteHeader { contract_address, nonce, storage_slot, note_hash_counter };\n let serialized_note = arr_copy_slice(fields, [0; N], read_offset + 2);\n let mut note = Note::deserialize_content(serialized_note);\n note.set_header(header);\n placeholder_opt_notes[i] = Option::some(note);\n };\n }\n placeholder_opt_notes\n}\n\n// Only ever use this in private!\n#[oracle(checkNullifierExists)]\nunconstrained fn check_nullifier_exists_oracle(_inner_nullifier: Field) -> Field {}\n\n// Only ever use this in private!\nunconstrained pub fn check_nullifier_exists(inner_nullifier: Field) -> bool {\n check_nullifier_exists_oracle(inner_nullifier) == 1\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"154":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress, header::Header};\n\nuse crate::context::PrivateContext;\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_delay_change::ScheduledDelayChange, scheduled_value_change::ScheduledValueChange}\n};\n\nstruct SharedMutablePrivateGetter {\n context: &mut PrivateContext,\n // The contract address of the contract we want to read from\n other_contract_address: AztecAddress,\n // The storage slot where the SharedMutable is stored on the other contract\n storage_slot: Field,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numberic value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\n// We have this as a view-only interface to reading Shared Mutables in other contracts.\n// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date\nimpl SharedMutablePrivateGetter {\n pub fn new(\n context: &mut PrivateContext,\n other_contract_address: AztecAddress,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n assert(other_contract_address.to_field() != 0, \"Other contract address cannot be 0\");\n Self { context, other_contract_address, storage_slot, _dummy: [0; INITIAL_DELAY] }\n }\n\n pub fn get_value_in_private(self, header: Header) -> T where T: FromField {\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(header);\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // If our context has the same header as the one we pass in via the parameter, we are trying to read the \"current\" value\n // and thus need to set the tx max block number below. If the context header is not the same as the one we pass in, this means\n // we are trying to read a historical value and thus have no constraint on the max block number that this transaction can be included in.\n if (self.context.historical_header.global_variables.block_number.eq(header.global_variables.block_number)) {\n self.context.set_tx_max_block_number(block_horizon);\n }\n\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n header: Header\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n self.other_contract_address\n );\n }\n\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, self.other_contract_address)];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"159":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/private_immutable.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint,\n constants::GENERATOR_INDEX__INITIALIZATION_NULLIFIER, hash::pedersen_hash\n};\n\nuse crate::context::{PrivateContext, UnconstrainedContext};\nuse crate::note::{\n lifecycle::create_note, note_getter::{get_note, view_notes}, note_interface::NoteInterface,\n note_viewer_options::NoteViewerOptions, note_emission::NoteEmission\n};\nuse crate::oracle::notes::check_nullifier_exists;\nuse crate::state_vars::storage::Storage;\n\n// docs:start:struct\nstruct PrivateImmutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:struct\n\nimpl Storage for PrivateImmutable {}\n\nimpl PrivateImmutable {\n // docs:start:new\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n // docs:end:new\n\n // The following computation is leaky, in that it doesn't hide the storage slot that has been initialized, nor does it hide the contract address of this contract.\n // When this initialization nullifier is emitted, an observer could do a dictionary or rainbow attack to learn the preimage of this nullifier to deduce the storage slot and contract address.\n // For some applications, leaking the details that a particular state variable of a particular contract has been initialized will be unacceptable.\n // Under such circumstances, such application developers might wish to _not_ use this state variable type.\n // This is especially dangerous for initial assignment to elements of a `Map` type (for example), because the storage slot often also identifies an actor. \n // e.g. the initial assignment to `my_map.at(msg.sender)` will leak: `msg.sender`, the fact that an element of `my_map` was assigned-to for the first time, and the contract_address.\n pub fn compute_initialization_nullifier(self) -> Field {\n pedersen_hash(\n [self.storage_slot],\n GENERATOR_INDEX__INITIALIZATION_NULLIFIER\n )\n }\n}\n\nimpl PrivateImmutable {\n // docs:start:initialize\n pub fn initialize(\n self,\n note: &mut Note\n ) -> NoteEmission where Note: NoteInterface {\n // Nullify the storage slot.\n let nullifier = self.compute_initialization_nullifier();\n self.context.push_new_nullifier(nullifier, 0);\n\n create_note(self.context, self.storage_slot, note)\n }\n // docs:end:initialize\n\n // docs:start:get_note\n pub fn get_note(self) -> Note where Note: NoteInterface {\n let storage_slot = self.storage_slot;\n get_note(self.context, storage_slot)\n }\n // docs:end:get_note\n}\n\nimpl PrivateImmutable {\n // docs:start:is_initialized\n unconstrained pub fn is_initialized(self) -> bool {\n let nullifier = self.compute_initialization_nullifier();\n check_nullifier_exists(nullifier)\n }\n // docs:end:is_initialized\n\n // view_note does not actually use the context, but it calls oracles that are only available in private\n // docs:start:view_note\n unconstrained pub fn view_note(self) -> Note where Note: NoteInterface {\n let mut options = NoteViewerOptions::new();\n view_notes(self.storage_slot, options.set_limit(1)).get(0)\n }\n // docs:end:view_note\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"187":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier_leaf_preimage.nr","source":"global NULLIFIER_LEAF_PREIMAGE_LENGTH: u32 = 3;\n\nuse crate::{\n abis::{read_request::ScopedReadRequest, side_effect::Readable}, hash::compute_siloed_nullifier,\n merkle_tree::leaf_preimage::{LeafPreimage, IndexedTreeLeafPreimage}, traits::{Empty, Hash}\n};\n\nstruct NullifierLeafPreimage {\n nullifier : Field,\n next_nullifier :Field,\n next_index : u32,\n}\n\nimpl Empty for NullifierLeafPreimage {\n fn empty() -> Self {\n Self {\n nullifier : 0,\n next_nullifier : 0,\n next_index : 0,\n }\n }\n}\n\nimpl Hash for NullifierLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash(self.serialize())\n }\n }\n}\n\nimpl LeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl IndexedTreeLeafPreimage for NullifierLeafPreimage {\n fn get_key(self) -> Field {\n self.nullifier\n }\n\n fn get_next_key(self) -> Field {\n self.next_nullifier\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl Readable for NullifierLeafPreimage {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n let siloed_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.nullifier, siloed_value, \"Value of the nullifier leaf does not match read request\");\n }\n}\n\nimpl NullifierLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.nullifier == 0) & (self.next_nullifier == 0) & (self.next_index == 0)\n }\n\n pub fn serialize(self) -> [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH] {\n [self.nullifier, self.next_nullifier, self.next_index as Field]\n }\n\n pub fn deserialize(fields: [Field; NULLIFIER_LEAF_PREIMAGE_LENGTH]) -> Self {\n Self { nullifier: fields[0], next_nullifier: fields[1], next_index: fields[2] as u32 }\n }\n}\n\nimpl Eq for NullifierLeafPreimage {\n fn eq(self, other: Self) -> bool {\n (self.nullifier == other.nullifier) &\n (self.next_nullifier == other.next_nullifier) &\n (self.next_index == other.next_index)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NullifierLeafPreimage::empty();\n let serialized = item.serialize();\n let deserialized = NullifierLeafPreimage::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"20":{"path":"std/embedded_curve_ops.nr","source":"use crate::ops::arith::{Add, Sub, Neg};\nuse crate::cmp::Eq;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct EmbeddedCurvePoint {\n x: Field,\n y: Field,\n is_infinite: bool\n}\n\nimpl EmbeddedCurvePoint {\n fn double(self) -> EmbeddedCurvePoint {\n embedded_curve_add(self, self)\n }\n\n fn point_at_infinity() -> EmbeddedCurvePoint {\n EmbeddedCurvePoint { x: 0, y: 0, is_infinite: true }\n }\n}\n\nimpl Add for EmbeddedCurvePoint {\n fn add(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n embedded_curve_add(self, other)\n }\n}\n\nimpl Sub for EmbeddedCurvePoint {\n fn sub(self, other: EmbeddedCurvePoint) -> EmbeddedCurvePoint { \n self + other.neg()\n }\n}\n\nimpl Neg for EmbeddedCurvePoint {\n fn neg(self) -> EmbeddedCurvePoint { \n EmbeddedCurvePoint {\n x: self.x,\n y: -self.y,\n is_infinite: self.is_infinite\n }\n }\n}\n\nimpl Eq for EmbeddedCurvePoint {\n fn eq(self: Self, b: EmbeddedCurvePoint) -> bool {\n (self.is_infinite & b.is_infinite) | ((self.is_infinite == b.is_infinite) & (self.x == b.x) & (self.y == b.y))\n }\n}\n\n// Scalar represented as low and high limbs\nstruct EmbeddedCurveScalar {\n lo: Field,\n hi: Field,\n}\n\n// Computes a multi scalar multiplication over the embedded curve.\n// For bn254, We have Grumpkin and Baby JubJub.\n// For bls12-381, we have JubJub and Bandersnatch.\n//\n// The embedded curve being used is decided by the \n// underlying proof system.\n#[foreign(multi_scalar_mul)]\n// docs:start:multi_scalar_mul\npub fn multi_scalar_mul(\n points: [EmbeddedCurvePoint; N],\n scalars: [EmbeddedCurveScalar; N]\n) -> [Field; 3]\n// docs:end:multi_scalar_mul\n{}\n\n// docs:start:fixed_base_scalar_mul\npub fn fixed_base_scalar_mul(\n scalar_low: Field,\n scalar_high: Field\n) -> [Field; 3]\n// docs:end:fixed_base_scalar_mul\n{\n let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false };\n let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high };\n multi_scalar_mul([g1], [scalar])\n}\n\n// This is a hack as returning an `EmbeddedCurvePoint` from a foreign function in brillig returns a [BrilligVariable::SingleAddr; 2] rather than BrilligVariable::BrilligArray\n// as is defined in the brillig bytecode format. This is a workaround which allows us to fix this without modifying the serialization format.\n// docs:start:embedded_curve_add\nfn embedded_curve_add(\n point1: EmbeddedCurvePoint,\n point2: EmbeddedCurvePoint\n) -> EmbeddedCurvePoint\n// docs:end:embedded_curve_add\n{\n let point_array = embedded_curve_add_array_return(point1, point2);\n let x = point_array[0];\n let y = point_array[1];\n EmbeddedCurvePoint { x, y, is_infinite: point_array[2] == 1 }\n}\n\n#[foreign(embedded_curve_add)]\nfn embedded_curve_add_array_return(_point1: EmbeddedCurvePoint, _point2: EmbeddedCurvePoint) -> [Field; 3] {}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"220":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_point.nr","source":"use crate::{traits::{Serialize, Deserialize, Hash}, hash::poseidon2_hash};\nuse dep::std::cmp::Eq;\n\nglobal GRUMPKIN_POINT_SERIALIZED_LEN: Field = 2;\n\n// TODO(https://github.com/noir-lang/noir/issues/4931)\nstruct GrumpkinPoint {\n x: Field,\n y: Field,\n}\n\nimpl Serialize for GrumpkinPoint {\n fn serialize(self) -> [Field; GRUMPKIN_POINT_SERIALIZED_LEN] {\n [self.x, self.y]\n }\n}\n\nimpl Deserialize for GrumpkinPoint {\n fn deserialize(serialized: [Field; GRUMPKIN_POINT_SERIALIZED_LEN]) -> Self {\n Self {\n x: serialized[0],\n y: serialized[1],\n }\n }\n}\n\nimpl Eq for GrumpkinPoint {\n fn eq(self, point: GrumpkinPoint) -> bool {\n (point.x == self.x) & (point.y == self.y)\n }\n}\n\nimpl Hash for GrumpkinPoint {\n fn hash(self) -> Field {\n poseidon2_hash(self.serialize())\n }\n}\n\nimpl GrumpkinPoint {\n pub fn new(x: Field, y: Field) -> Self {\n Self { x, y }\n }\n\n pub fn zero() -> Self {\n Self { x: 0, y: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.x == 0) & (self.y == 0)\n }\n\n // TODO(David): Would be quite careful here as (0,0) is not a point\n // on the curve. A boolean flag may be the better approach here,\n // would also cost less constraints. It seems like we don't need to \n // group arithmetic either. \n fn assert_is_zero(self) {\n assert(self.x == 0);\n assert(self.y == 0);\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 64] {\n let mut result = [0 as u8; 64];\n let x_bytes = self.x.to_be_bytes(32);\n let y_bytes = self.y.to_be_bytes(32);\n for i in 0..32 {\n result[i] = x_bytes[i];\n result[i + 32] = y_bytes[i];\n }\n result\n }\n}\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"225":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/grumpkin_private_key.nr","source":"use dep::std::{cmp::Eq, embedded_curve_ops::fixed_base_scalar_mul};\nuse crate::{grumpkin_point::GrumpkinPoint, traits::Empty};\n\nglobal GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN: Field = 2;\n\nstruct GrumpkinPrivateKey {\n high: Field,\n low: Field,\n}\n\nimpl Eq for GrumpkinPrivateKey {\n fn eq(self, key: GrumpkinPrivateKey) -> bool {\n (key.high == self.high) & (key.low == self.low)\n }\n}\n\nimpl Empty for GrumpkinPrivateKey {\n fn empty() -> Self {\n Self { high: 0, low: 0 }\n }\n}\n\nimpl GrumpkinPrivateKey {\n pub fn new(high: Field, low: Field) -> Self {\n GrumpkinPrivateKey { high, low }\n }\n\n pub fn zero() -> Self {\n Self { high: 0, low: 0 }\n }\n\n pub fn is_zero(self) -> bool {\n (self.high == 0) & (self.low == 0)\n }\n\n pub fn serialize(self) -> [Field; GRUMPKIN_PRIVATE_KEY_SERIALIZED_LEN] {\n [self.high, self.low]\n }\n\n pub fn derive_public_key(self) -> GrumpkinPoint {\n let public_key = fixed_base_scalar_mul(self.low, self.high);\n GrumpkinPoint { x: public_key[0], y: public_key[1] }\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"35":{"path":"std/option.nr","source":"use crate::hash::{Hash, Hasher};\nuse crate::cmp::{Ordering, Ord, Eq};\nuse crate::default::Default;\n\nstruct Option {\n _is_some: bool,\n _value: T,\n}\n\nimpl Option {\n /// Constructs a None value\n pub fn none() -> Self {\n Self { _is_some: false, _value: crate::unsafe::zeroed() }\n }\n\n /// Constructs a Some wrapper around the given value\n pub fn some(_value: T) -> Self {\n Self { _is_some: true, _value }\n }\n\n /// True if this Option is None\n pub fn is_none(self) -> bool {\n !self._is_some\n }\n\n /// True if this Option is Some\n pub fn is_some(self) -> bool {\n self._is_some\n }\n\n /// Asserts `self.is_some()` and returns the wrapped value.\n pub fn unwrap(self) -> T {\n assert(self._is_some);\n self._value\n }\n\n /// Returns the inner value without asserting `self.is_some()`\n /// Note that if `self` is `None`, there is no guarantee what value will be returned,\n /// only that it will be of type `T`.\n pub fn unwrap_unchecked(self) -> T {\n self._value\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value.\n pub fn unwrap_or(self, default: T) -> T {\n if self._is_some { self._value } else { default }\n }\n\n /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return\n /// a default value.\n pub fn unwrap_or_else(self, default: fn[Env]() -> T) -> T {\n if self._is_some {\n self._value\n } else {\n default()\n }\n }\n\n /// Asserts `self.is_some()` with a provided custom message and returns the contained `Some` value\n fn expect(self, message: fmtstr) -> T {\n assert(self.is_some(), message);\n self._value\n }\n\n /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`.\n pub fn map(self, f: fn[Env](T) -> U) -> Option {\n if self._is_some {\n Option::some(f(self._value))\n } else {\n Option::none()\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value.\n pub fn map_or(self, default: U, f: fn[Env](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default\n }\n }\n\n /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`.\n pub fn map_or_else(self, default: fn[Env1]() -> U, f: fn[Env2](T) -> U) -> U {\n if self._is_some {\n f(self._value)\n } else {\n default()\n }\n }\n\n /// Returns None if self is None. Otherwise, this returns `other`.\n pub fn and(self, other: Self) -> Self {\n if self.is_none() {\n Option::none()\n } else {\n other\n }\n }\n\n /// If self is None, this returns None. Otherwise, this calls the given function\n /// with the Some value contained within self, and returns the result of that call.\n ///\n /// In some languages this function is called `flat_map` or `bind`.\n pub fn and_then(self, f: fn[Env](T) -> Option) -> Option {\n if self._is_some {\n f(self._value)\n } else {\n Option::none()\n }\n }\n\n /// If self is Some, return self. Otherwise, return `other`.\n pub fn or(self, other: Self) -> Self {\n if self._is_some { self } else { other }\n }\n\n /// If self is Some, return self. Otherwise, return `default()`.\n pub fn or_else(self, default: fn[Env]() -> Self) -> Self {\n if self._is_some { self } else { default() }\n }\n\n // If only one of the two Options is Some, return that option.\n // Otherwise, if both options are Some or both are None, None is returned.\n pub fn xor(self, other: Self) -> Self {\n if self._is_some {\n if other._is_some { Option::none() } else { self }\n } else if other._is_some {\n other\n } else {\n Option::none()\n }\n }\n\n /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true.\n /// Otherwise, this returns `None`\n pub fn filter(self, predicate: fn[Env](T) -> bool) -> Self {\n if self._is_some {\n if predicate(self._value) {\n self\n } else {\n Option::none()\n }\n } else {\n Option::none()\n }\n }\n\n /// Flattens an Option> into a Option.\n /// This returns None if the outer Option is None. Otherwise, this returns the inner Option.\n pub fn flatten(option: Option>) -> Option {\n if option._is_some {\n option._value\n } else {\n Option::none()\n }\n }\n}\n\nimpl Default for Option {\n fn default() -> Self {\n Option::none()\n }\n}\n\nimpl Eq for Option where T: Eq {\n fn eq(self, other: Self) -> bool {\n if self._is_some == other._is_some {\n if self._is_some {\n self._value == other._value\n } else {\n true\n }\n } else {\n false\n }\n }\n}\n\nimpl Hash for Option where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher {\n self._is_some.hash(state);\n if self._is_some {\n self._value.hash(state);\n }\n }\n}\n\n// For this impl we're declaring Option::none < Option::some\nimpl Ord for Option where T: Ord {\n fn cmp(self, other: Self) -> Ordering {\n if self._is_some {\n if other._is_some {\n self._value.cmp(other._value)\n } else {\n Ordering::greater()\n }\n } else {\n if other._is_some {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n"},"365":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/main.nr","source":"mod public_key_note;\n\n// Account contract that uses Schnorr signatures for authentication.\n// The signing key is stored in an immutable private note and should be different from the encryption/nullifying key.\ncontract SchnorrAccount {\n use dep::std;\n\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, NoteHeader, PrivateContext, PrivateImmutable};\n use dep::aztec::encrypted_logs::encrypted_note_emission::encode_and_encrypt_note;\n use dep::authwit::{\n entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions,\n auth_witness::get_auth_witness, auth::{compute_authwit_nullifier, compute_outer_authwit_hash}\n };\n use dep::aztec::hash::compute_siloed_nullifier;\n use dep::aztec::oracle::get_nullifier_membership_witness::get_low_nullifier_membership_witness;\n\n use crate::public_key_note::{PublicKeyNote, PUBLIC_KEY_NOTE_LEN};\n\n #[aztec(storage)]\n struct Storage {\n // docs:start:storage\n signing_public_key: PrivateImmutable,\n // docs:end:storage\n }\n\n // Constructs the contract\n #[aztec(private)]\n #[aztec(initializer)]\n fn constructor(signing_pub_key_x: Field, signing_pub_key_y: Field) {\n let this = context.this_address();\n let header = context.get_header();\n let this_npk_m_hash = header.get_npk_m_hash(&mut context, this);\n // Not emitting outgoing for msg_sender here to not have to register keys for the contract through which we\n // deploy this (typically MultiCallEntrypoint). I think it's ok here as I feel the outgoing here is not that\n // important.\n\n // docs:start:initialize\n let mut pub_key_note = PublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this_npk_m_hash);\n storage.signing_public_key.initialize(&mut pub_key_note).emit(encode_and_encrypt_note(&mut context, this, this));\n // docs:end:initialize\n }\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts file\n #[aztec(private)]\n #[aztec(noinitcheck)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(noinitcheck)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n // docs:start:entrypoint\n // Load public key from storage\n let storage = Storage::init(context);\n // docs:start:get_note\n let public_key = storage.signing_public_key.get_note();\n // docs:end:get_note\n // Load auth witness\n let witness: [Field; 64] = get_auth_witness(outer_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n\n // Verify signature of the payload bytes\n let verification = std::schnorr::verify_signature_slice(\n public_key.x,\n public_key.y,\n signature,\n outer_hash.to_be_bytes(32)\n );\n assert(verification == true);\n // docs:end:entrypoint\n true\n }\n\n /**\n * @notice Helper function to check validity of private authwitnesses\n * @param consumer The address of the consumer of the message\n * @param message_hash The message hash of the message to check the validity\n * @return True if the message_hash can be consumed, false otherwise\n */\n unconstrained fn lookup_validity(consumer: AztecAddress, inner_hash: Field) -> pub bool {\n let public_key = storage.signing_public_key.view_note();\n\n let message_hash = compute_outer_authwit_hash(consumer, context.chain_id(), context.version(), inner_hash);\n\n let witness: [Field; 64] = get_auth_witness(message_hash);\n let mut signature: [u8; 64] = [0; 64];\n for i in 0..64 {\n signature[i] = witness[i] as u8;\n }\n let valid_in_private = std::schnorr::verify_signature_slice(\n public_key.x,\n public_key.y,\n signature,\n message_hash.to_be_bytes(32)\n );\n\n // Compute the nullifier and check if it is spent\n // This will BLINDLY TRUST the oracle, but the oracle is us, and\n // it is not as part of execution of the contract, so we are good.\n let nullifier = compute_authwit_nullifier(context.this_address(), inner_hash);\n let siloed_nullifier = compute_siloed_nullifier(consumer, nullifier);\n let lower_wit = get_low_nullifier_membership_witness(context.block_number(), siloed_nullifier);\n let is_spent = lower_wit.leaf_preimage.nullifier == siloed_nullifier;\n\n !is_spent & valid_in_private\n }\n}\n"},"366":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_account_contract/src/public_key_note.nr","source":"use dep::aztec::prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext};\nuse dep::aztec::{\n note::utils::compute_note_hash_for_consumption, keys::getters::get_nsk_app,\n protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, grumpkin_point::GrumpkinPoint, hash::poseidon2_hash}\n};\n\nglobal PUBLIC_KEY_NOTE_LEN: Field = 3;\n// PUBLIC_KEY_NOTE_LEN * 32 + 32(storage_slot as bytes) + 32(note_type_id as bytes)\nglobal PUBLIC_KEY_NOTE_BYTES_LEN: Field = 3 * 32 + 64;\n\n// Stores a public key composed of two fields\n// TODO: Do we need to include a nonce, in case we want to read/nullify/recreate with the same pubkey value?\n#[aztec(note)]\nstruct PublicKeyNote {\n x: Field,\n y: Field,\n // We store the npk_m_hash only to get the secret key to compute the nullifier\n npk_m_hash: Field,\n}\n\nimpl NoteInterface for PublicKeyNote {\n fn compute_note_hash_and_nullifier(self, context: &mut PrivateContext) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = context.request_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n\n fn compute_note_hash_and_nullifier_without_context(self) -> (Field, Field) {\n let note_hash_for_nullify = compute_note_hash_for_consumption(self);\n let secret = get_nsk_app(self.npk_m_hash);\n let nullifier = poseidon2_hash([\n note_hash_for_nullify,\n secret,\n GENERATOR_INDEX__NOTE_NULLIFIER as Field,\n ]);\n (note_hash_for_nullify, nullifier)\n }\n}\n\nimpl PublicKeyNote {\n pub fn new(x: Field, y: Field, npk_m_hash: Field) -> Self {\n PublicKeyNote { x, y, npk_m_hash, header: NoteHeader::empty() }\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"62":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__SYMMETRIC_KEY, grumpkin_private_key::GrumpkinPrivateKey,\n grumpkin_point::GrumpkinPoint, utils::arr_copy_slice\n};\nuse dep::std::{hash::sha256, embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul}};\n\n// TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since\n// point is not the only input of the function. Unify naming with TS once we have a better name.\npub fn point_to_symmetric_key(secret: GrumpkinPrivateKey, point: GrumpkinPoint) -> [u8; 32] {\n let shared_secret_fields = multi_scalar_mul(\n [EmbeddedCurvePoint { x: point.x, y: point.y, is_infinite: false }],\n [EmbeddedCurveScalar { lo: secret.low, hi: secret.high }]\n );\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly\n let shared_secret = GrumpkinPoint::new(shared_secret_fields[0], shared_secret_fields[1]);\n let mut shared_secret_bytes_with_separator = [0 as u8; 65];\n shared_secret_bytes_with_separator = arr_copy_slice(shared_secret.to_be_bytes(), shared_secret_bytes_with_separator, 0);\n shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY;\n sha256(shared_secret_bytes_with_separator)\n}\n\n#[test]\nfn check_point_to_symmetric_key() {\n // Value taken from \"derive shared secret\" test in encrypt_buffer.test.ts\n let secret = GrumpkinPrivateKey::new(\n 0x0000000000000000000000000000000023b3127c127b1f29a7adff5cccf8fb06,\n 0x00000000000000000000000000000000649e7ca01d9de27b21624098b897babd\n );\n let point = GrumpkinPoint::new(\n 0x2688431c705a5ff3e6c6f2573c9e3ba1c1026d2251d0dbbf2d810aa53fd1d186,\n 0x1e96887b117afca01c00468264f4f80b5bb16d94c1808a448595f115556e5c8e\n );\n\n let key = point_to_symmetric_key(secret, point);\n // The following value gets updated when running encrypt_buffer.test.ts with AZTEC_GENERATE_TEST_DATA=1\n let expected_key = [\n 49, 167, 146, 222, 151, 129, 138, 184, 87, 210, 245, 249, 99, 100, 1, 59, 223, 180, 5, 99, 14, 7, 177, 236, 159, 203, 231, 72, 220, 180, 241, 23\n ];\n assert_eq(key, expected_key);\n}\n"},"63":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/getters.nr","source":"use dep::protocol_types::{\n header::Header, abis::validation_requests::KeyValidationRequest, address::AztecAddress,\n constants::CANONICAL_KEY_REGISTRY_ADDRESS, grumpkin_point::GrumpkinPoint,\n storage::map::derive_storage_slot_in_map\n};\nuse crate::{\n context::PrivateContext,\n oracle::{keys::get_public_keys_and_partial_address, key_validation_request::get_key_validation_request},\n keys::{public_keys::PublicKeys, constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}},\n state_vars::{shared_mutable::shared_mutable_private_getter::SharedMutablePrivateGetter}\n};\n\nglobal DELAY = 5;\n\n// docs:start:key-getters\ntrait KeyGetters {\n fn get_npk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ivpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_ovpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_tpk_m(header: Header, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint;\n fn get_npk_m_hash(header: Header, context: &mut PrivateContext, address: AztecAddress) -> Field;\n}\n\nimpl KeyGetters for Header {\n fn get_npk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, NULLIFIER_INDEX, self)\n }\n\n fn get_ivpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, INCOMING_INDEX, self)\n }\n\n fn get_ovpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, OUTGOING_INDEX, self)\n }\n\n fn get_tpk_m(self, context: &mut PrivateContext, address: AztecAddress) -> GrumpkinPoint {\n get_master_key(context, address, TAGGING_INDEX, self)\n }\n\n fn get_npk_m_hash(self, context: &mut PrivateContext, address: AztecAddress) -> Field {\n get_master_key(context, address, NULLIFIER_INDEX, self).hash()\n }\n}\n// docs:end:key-getters\n\nfn get_master_key(\n context: &mut PrivateContext,\n address: AztecAddress,\n key_index: Field,\n header: Header\n) -> GrumpkinPoint {\n let key = fetch_key_from_registry(context, key_index, address, header);\n if key.is_zero() {\n // Keys were not registered in registry yet --> fetch key from PXE\n let keys = fetch_and_constrain_keys(address);\n // Return the corresponding to index\n keys.get_key_by_index(key_index)\n } else {\n // Keys were registered --> return the key\n key\n }\n}\n\nfn fetch_key_from_registry(\n context: &mut PrivateContext,\n key_index: Field,\n address: AztecAddress,\n header: Header\n) -> GrumpkinPoint {\n let x_coordinate_map_slot = key_index * 2 + 1;\n let y_coordinate_map_slot = x_coordinate_map_slot + 1;\n let x_coordinate_derived_slot = derive_storage_slot_in_map(x_coordinate_map_slot, address);\n let y_coordinate_derived_slot = derive_storage_slot_in_map(y_coordinate_map_slot, address);\n\n let x_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n x_coordinate_derived_slot\n );\n let y_coordinate_registry: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(\n context,\n AztecAddress::from_field(CANONICAL_KEY_REGISTRY_ADDRESS),\n y_coordinate_derived_slot\n );\n let x_coordinate = x_coordinate_registry.get_value_in_private(header);\n let y_coordinate = y_coordinate_registry.get_value_in_private(header);\n\n GrumpkinPoint::new(x_coordinate, y_coordinate)\n}\n\n// Passes only when keys were not rotated - is expected to be called only when keys were not registered yet\nfn fetch_and_constrain_keys(address: AztecAddress) -> PublicKeys {\n let (public_keys, partial_address) = get_public_keys_and_partial_address(address);\n\n let computed_address = AztecAddress::compute(public_keys.hash(), partial_address);\n\n assert(computed_address.eq(address));\n\n public_keys\n}\n\n// A helper function since requesting nsk_app is very common\n// TODO(#6543)\npub fn get_nsk_app(npk_m_hash: Field) -> Field {\n get_key_validation_request(npk_m_hash, NULLIFIER_INDEX).sk_app\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"86":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr","source":"use dep::protocol_types::address::AztecAddress;\n\nstruct UnconstrainedContext {\n block_number: u32,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UnconstrainedContext {\n fn new() -> Self {\n // We could call these oracles on the getters instead of at creation, which makes sense given that they might\n // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user\n // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not\n // available.\n let block_number = block_number_oracle();\n let contract_address = contract_address_oracle();\n let chain_id = chain_id_oracle();\n let version = version_oracle();\n Self { block_number, contract_address, version, chain_id }\n }\n\n fn block_number(self) -> u32 {\n self.block_number\n }\n\n fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n fn version(self) -> Field {\n self.version\n }\n\n fn chain_id(self) -> Field {\n self.chain_id\n }\n}\n\n#[oracle(getContractAddress)]\nunconstrained fn contract_address_oracle() -> AztecAddress {}\n\n#[oracle(getBlockNumber)]\nunconstrained fn block_number_oracle() -> u32 {}\n\n#[oracle(getChainId)]\nunconstrained fn chain_id_oracle() -> Field {}\n\n#[oracle(getVersion)]\nunconstrained fn version_oracle() -> Field {}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"98":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/payload.nr","source":"use dep::protocol_types::{\n address::AztecAddress, grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint,\n constants::{GENERATOR_INDEX__IVSK_M, GENERATOR_INDEX__OVSK_M}, hash::poseidon2_hash\n};\n\nuse dep::std::{embedded_curve_ops::{embedded_curve_add, EmbeddedCurvePoint}, field::bytes32_to_field};\n\nuse crate::oracle::unsafe_rand::unsafe_rand;\n\nuse crate::event::event_interface::EventInterface;\nuse crate::note::note_interface::NoteInterface;\n\nuse crate::encrypted_logs::{\n header::EncryptedLogHeader, incoming_body::EncryptedLogIncomingBody,\n outgoing_body::EncryptedLogOutgoingBody\n};\n\npub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n event: Event\n) -> [u8; OB] where Event: EventInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_event(event, randomness).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; OB] = [0; OB];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = OB - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\npub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n ovsk_app: Field,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint,\n note: Note\n) -> [u8; M] where Note: NoteInterface {\n // @todo Need to draw randomness from the full domain of Fq not only Fr\n let eph_sk: GrumpkinPrivateKey = fr_to_private_key(unsafe_rand());\n let eph_pk = eph_sk.derive_public_key();\n\n // TODO: (#7177) This value needs to be populated!\n let recipient = AztecAddress::from_field(0);\n\n let ivpk_app = compute_ivpk_app(ivpk, contract_address);\n\n let header = EncryptedLogHeader::new(contract_address);\n\n let incoming_header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ivpk);\n let outgoing_Header_ciphertext: [u8; 48] = header.compute_ciphertext(eph_sk, ovpk);\n let incoming_body_ciphertext = EncryptedLogIncomingBody::from_note(note, storage_slot).compute_ciphertext(eph_sk, ivpk_app);\n let outgoing_body_ciphertext: [u8; 176] = EncryptedLogOutgoingBody::new(eph_sk, recipient, ivpk_app).compute_ciphertext(fr_to_private_key(ovsk_app), eph_pk);\n\n let mut encrypted_bytes: [u8; M] = [0; M];\n // @todo We ignore the tags for now \n\n let eph_pk_bytes = eph_pk.to_be_bytes();\n for i in 0..64 {\n encrypted_bytes[64 + i] = eph_pk_bytes[i];\n }\n for i in 0..48 {\n encrypted_bytes[128 + i] = incoming_header_ciphertext[i];\n encrypted_bytes[176 + i] = outgoing_Header_ciphertext[i];\n }\n for i in 0..176 {\n encrypted_bytes[224 + i] = outgoing_body_ciphertext[i];\n }\n // Then we fill in the rest as the incoming body ciphertext\n let size = M - 400;\n assert_eq(size, incoming_body_ciphertext.len(), \"ciphertext length mismatch\");\n for i in 0..size {\n encrypted_bytes[400 + i] = incoming_body_ciphertext[i];\n }\n\n // Current unoptimized size of the encrypted log\n // incoming_tag (32 bytes)\n // outgoing_tag (32 bytes)\n // eph_pk (64 bytes)\n // incoming_header (48 bytes)\n // outgoing_header (48 bytes)\n // outgoing_body (176 bytes)\n // incoming_body_fixed (64 bytes)\n // incoming_body_variable (N * 32 bytes + 16 bytes padding)\n encrypted_bytes\n}\n\nfn fr_to_private_key(r: Field) -> GrumpkinPrivateKey {\n let r_bytes = r.to_be_bytes(32);\n\n let mut high_bytes = [0; 32];\n let mut low_bytes = [0; 32];\n\n for i in 0..16 {\n high_bytes[16 + i] = r_bytes[i];\n low_bytes[16 + i] = r_bytes[i + 16];\n }\n\n let low = bytes32_to_field(low_bytes);\n let high = bytes32_to_field(high_bytes);\n\n GrumpkinPrivateKey::new(high, low)\n}\n\nfn compute_ivpk_app(ivpk: GrumpkinPoint, contract_address: AztecAddress) -> GrumpkinPoint {\n // It is useless to compute this, it brings no value to derive fully.\n // Issue(#6955)\n ivpk\n /*\n // @todo Just setting infinite to false, but it should be checked.\n // for example user could define ivpk = infinity using the registry\n assert((ivpk.x != 0) & (ivpk.y != 0), \"ivpk is infinite\");\n\n let i = fr_to_private_key(poseidon2_hash([contract_address.to_field(), ivpk.x, ivpk.y, GENERATOR_INDEX__IVSK_M]));\n let I = i.derive_public_key();\n\n let embed_I = EmbeddedCurvePoint { x: I.x, y: I.y, is_infinite: false };\n let embed_ivpk = EmbeddedCurvePoint { x: ivpk.x, y: ivpk.y, is_infinite: false };\n\n let embed_result = embedded_curve_add(embed_I, embed_ivpk);\n\n GrumpkinPoint::new(embed_result.x, embed_result.y)*/\n}\n"},"99":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/encrypted_logs/encrypted_note_emission.nr","source":"use crate::{\n context::PrivateContext, note::{note_emission::NoteEmission, note_interface::NoteInterface},\n encrypted_logs::payload::compute_encrypted_note_log, oracle::logs_traits::LensForEncryptedLog\n};\nuse dep::protocol_types::{\n address::AztecAddress, grumpkin_point::GrumpkinPoint, abis::note_hash::NoteHash,\n constants::MAX_NEW_NOTE_HASHES_PER_CALL, utils::arrays::find_index\n};\n\nfn emit_with_keys(\n context: &mut PrivateContext,\n note: Note,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n let note_header = note.get_header();\n let note_hash_counter = note_header.note_hash_counter;\n let storage_slot = note_header.storage_slot;\n\n let note_exists_index = find_index(\n context.new_note_hashes.storage,\n |n: NoteHash| n.counter == note_hash_counter\n );\n assert(\n note_exists_index as u32 != MAX_NEW_NOTE_HASHES_PER_CALL, \"Can only emit a note log for an existing note.\"\n );\n\n let contract_address: AztecAddress = context.this_address();\n let ovsk_app: Field = context.request_ovsk_app(ovpk.hash());\n\n let encrypted_log: [u8; M] = compute_encrypted_note_log(contract_address, storage_slot, ovsk_app, ovpk, ivpk, note);\n\n context.emit_raw_note_log(note_hash_counter, encrypted_log);\n}\n\npub fn encode_and_encrypt_note(\n context: &mut PrivateContext,\n ov: AztecAddress,\n iv: AztecAddress\n) -> fn[(&mut PrivateContext, AztecAddress, AztecAddress)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n let header = context.get_header();\n let ovpk = header.get_ovpk_m(context, ov);\n let ivpk = header.get_ivpk_m(context, iv);\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n\npub fn encode_and_encrypt_note_with_keys(\n context: &mut PrivateContext,\n ovpk: GrumpkinPoint,\n ivpk: GrumpkinPoint\n) -> fn[(&mut PrivateContext, GrumpkinPoint, GrumpkinPoint)](NoteEmission) -> () where Note: NoteInterface, [Field; N]: LensForEncryptedLog {\n | e: NoteEmission | {\n emit_with_keys(context, e.note, ovpk, ivpk);\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json b/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json deleted file mode 100644 index b5b8d9f58ead..000000000000 --- a/yarn-project/accounts/src/artifacts/SchnorrSingleKeyAccount.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"SchnorrSingleKeyAccount","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/f0owmWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLrX/ent52x9uL03n3fp7ut73upv3x6fbUP++m58PL/vrcxue3u9towGi7kVFkVDLaymiW0SKjJqMuIyliK0XMUsQsRcxSxCxFzFLELEXMUsQsRcxSxCxFLFLEIkUsUsQiRSxSxCJFLFLEIkUsUsQiRTQpokkRTYpoUkSTIpoU0aSIJkU0KaJJEV2K6FJElyK6FNGliC5FdCmiSxFdiuhSxCpFrFLEKkWsUsQqRaxSxCpFrFLEKkWsUsSQIoYUMaSIIUUMKWJIEUOKGFLEkCKGFJHNhlahVdFqS6uZVgutGq06rVZaURuhNkJthNoItRFqI9RGqI1QG6E2Qm0UtVHURlEbRW0UtVHURlEbRW0QaIZEM0SaIdMMoWZINUOsGXLNEGyGZDNEmyHbDOFmSDdDvBnyzRBwhoQzRJwh4wwhZ0g5Q8wZcs4QdIakM0SdIesMYWdIO0PcGfLOEHiGxDNEniHzDKFnSD1D7BlyzxB8huQzRJ8h+wzhZ0g/Q/wZ8s8QgIYENESgIQMNIWhIQUMMGnLQEISGJDREoSELDWFoSENDHBry0BCIhkQ0RKIhEw2haEhFQywactEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRIhctctEiFy1y0SIXLXLRsoue5KJFLlrkokUuWuSiRS5a5KL13y56Pf3cvR92Dy/7293e28eP4+O/q77X4/nX298v139/Aw=="},{"name":"verify_private_authwit","is_unconstrained":false,"custom_attributes":["aztec(private)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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M27pBbf0ilt6wy29w5Zecbtpxe2mFbebVtxueumtU8ql43bTittNK243rbjdtOJ204bbTRtuN2243bThdtNLb7xRLh23mzbcbtpwu2nD7aYNt5t23G7acbtpx+2mHbebXkr6Vy4dt5t23G7acbtpx+2mHbabpgW2m6YFtpumBbabpgW2m6YFtpumBbabpgW2m6YFtpumBbabpgW3mwbcbhpwu2nA7aYBt5teSlJVLh23mwbcbhpwu2nA7aYBt5tG3G4acbtpxO2mEbebXkr+Uy4dt5tG3G4acbtpxO2mEbebJtxumnC7acLtpgm3m17KiFMuHbebJtxumnC7acLtpgm3mwpuNxXcbiq43VRwu+mlNDHl0nG7qeB2U8HtpoLbTQW3m2bcbppxu2nG7aYZt5teyp1SLh23m2bcbppxu2nG7aYZt5vispASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LKeGykBIuCynhspASLgsp4bKQEi4LSXBZSILLQhJcFpLgspBkge2mgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSS4LCTBZSEJLgtJcFlIgstCElwWkuCykASXhSSWWUi911vpfXlRuuFuule64W66V7rhbrpXuuFuule64W66V7rhbrpTumUW0l7pdrtpX3rZSg+1PZVut5vulm63m+6Wbreb7pZut5v2+PA1TVGeSrfbTXdLt9tNe++3d47Lkp43R7vddLd0u910r3S7LKS13HwvPSzpqXSz3XS/dLPddL90s910v3Sz3XS/dLPddL90s910v3Sz3XQtN8Z76eW5dLPddL90s910t3S7LKS4xNq30pPUp9INd9O0HZfGZf0h4Kl0w910r3TD3XSvdLvdNCySbq8O4eHlt9LtdtPd0u120xDytsOE+OM1f5Rut5vulm63m+6WbrebhnrvpqGm37rpi5enVrf3/vHpv14cf+S256JzDFvV7e5KTP2fttjlLI215coUEFooW4dpdccWWX8p3YT2+HSScSnDSbn0hFu64JaecUsvuKVX3NIbbukdtvRLGU7KpeN209cMp+XXf7LslC0p3WqRVOPTm6cz31zOfHPcJ25xSUWCSyqShtszGm7P6Lg9o+P2jI47gXXcCcwuqWjoScZrlJBSDHgN+9F6c9w/0sDF8eTFcMvoNdx3gBY/f41qv/07DOvv29trQ6k/dV7aX2q8LVGoeUdnKGFboZLu6xnbrxWKsJUn2MrF7rciSby3i9KfvtCGj/dyv3+hS+qfv9BJ0q3m9Xf7h290qi+//rcm2pb7G4fWfppi+OBwnCmGjyTHmWJ4cB1niuGReJgpwXByGmeK4TF+nCmGDwjGmWL46GGcKeKmPJsyTaLN9TZ1pBL6nil1MyXci45leVXI0raqw8MzizEsX7d7mqyMYfc0KRzD7mnyPYbd00wOEHbHaWYSDLunmXYw7J5mjsKwe5oJDcNucbuvtNunyl2715/JNrsffn/9Yfc/LfRJ8dsW+vT3bQt9ovu2hT6lfdfC5JPXty30aerbFvqE9G0Lfer5toXiFn7XQp9Odi1cR8BbHfHhIevNQp9Ovm2hTyffttCnk29b6NPJdy0Un06+baFPJ9+20KeTb1vo08m3LRS38LsW+nSyb2HZ/kovtvZsoU8n37bQp5NvW+jTybct9OnkuxZmn06+baFPJ9+20KeTb1vo08m3LRS38LsWGp5OimzUYmll+WxhLLXcoBar5uVPZErOhocIZaWGs76yUsORXFmp4eT8RaUtPih9ZnIUwwFXWanhHKqs1HBcVFZqONUpKxUapfNkpD2l82Sk1rb8XfoLpfNkpD2l82SkPaUTZaTPSutEGWlH6UQZaUfpRBlpR+k8GanfcbR1ie1JqdAonScj7SmdJiPVkLd75GqM4UnpNBmpxrS9vKanS1yz5VtblJVOk5H2lFq+E0ZZ6TQZqfZw33t7lyel02SkXaXTZKS2pK3LtPB0R2xu02SkXaXTZKRdpbB3z+UGe/dctnyP0JeuJ2j99mt4f7iz4cftBC/qiGmj08f++AO3vBL4+UaQbPk+oy9Z2NO9jL5jYVvyrY4WkjxYGP/CQsv3KmlekmH5Eqa+XR7zQ2f6rDNvq7+ezGwvlZ8iDQcuPZGGs5aeSGEQaThh6Yk0HK6+JLIstxGoPETIXyINxzA9kZYDm5pIy5FKSWQxfTOYmshZEs9HkbMkno8iZ0k8H0UKg8hZEs9HkQSJp1i+YUxPJEHiKZZvAFMTaflGLz2RDInH8o1beiIZEo/lG7H0RDIkHsv3SumJZEg8lu9Q0hPJkHgs3xekJ5Ih8Vi+G0dPJEPisXwPjJ5IhsRj+X4UPZEMicfyHSN6IhkSj+V7OvREMiQey3dd6IlkSDyW74vQE8mQeCzfuaAnkiHxWL63QE/klYknBrk/6v7wDPhLkaHVsj0D3nr788H4cinRX7n0gFt6xC094ZYuuKVn3NILbukVt/SGWzpuN8243TTjdtOM200zbje9lDCsXDpuN8243TTjdtOM200zbjctuN204HbTgttNC243vRQZq1w6bjctuN204HbTgttNC243rbjdtOJ204rbTStuN70ULqpcOm43rbjdtOJ204rbTStuN2243bThdtOG200bbje9FEOpXDpuN2243bThdtOG200bbjftuN2043bTjttNO243vZQ2qFw6bjftuN2043bTjttNO2w3rQtsN60LbDetC2w3rQtsN60LbDetC2w3rQtsN60LbDetC2w3rQtuNw243TTgdtOA200Dbje9lJKmXDpuNw243TTgdtOA200DbjeNuN004nbTiNtNI243vZTApVw6bjeNuN004nbTiNtNI243TbjdNOF204TbTRNuN72U7qRcOm43TbjdNOF204TbTXFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSBWXhVRxWUgVl4VUcVlIFZeFVHFZSA2XhdRwWUgNl4XUcFlIbYHtpg2XhdRwWUgNl4XUcFlIDZeF1HBZSA2XhdQss5B6r7fS+/KidMPddK90w910r3TD3XSvdMPddK90w910r3TD3XSvdMPddKd0wyykvvSylR5qeyrdbjfdLd1uN90t3W433S3dbjft8eFrmqI8lW63m+6Wbreb9t5v7xyXJT1vjna76W7pdrvpbulmu+labr6XHpb0Z+l2WUj7pZvtpvulm+2m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AbrXBuheG6F7bYTutRG610boXnsx0Vi7euheG6F7bYTutRG610boXpuge22C7rUJutcm6F57MftWu3roXpuge22C7rUJutcm6F4r0L1WoHutQPdage61F1NStauH7rUC3WsFutcKdK8V6F6boXtthu61GbrXZuheezF+U7t66F6boXtthu61GbrXZuheW6B7bYHutQW61xboXnsxRVG7euheW6B7bYHutQW61xboXluhe22F7rUVutdW6F57MaFPu3roXluhe22F7rUVutdW6F7boHttg+61DbrXNuheezH9Tbt66F7boHttg+61DbrXNuhe26F7bYfutR2613boXnsxWUy7euhe26F7bYfutR2613bkXpsX5F6bF+RemxfkXpsX5F6bF+RemxfkXpsX5F6boblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblRGZoblaG5URmaG5WhuVEZmhuVoblR2TY3qvd6e+u+vKredK/drd50r92t3nSv3a3edK/drd50r92t3nSv3a3edK/drd5yr+1LL1v1obbn6i332t3qTXOj9qu33Gv3q7fca3t8+Nau/+Vz9ZZ77X71lntt73179bKk5x3TNDdqv3rLvXa/esO9dq0436sPS3qu3nCvPVC94V67W32xzI06UL3hXnugesO99kD1hnvtgeoN99q14hjv1ZcX1RvutQeqN9xrD1RvutfG2rfqk9Tn6k332rSdwsZFYn+u3nSv3aveMjfqQPWWe21YJN1eHUJcnqu33Gv3q7fca8OagbfqY87P1VvutfvVW+61+9Vb7rWh3nttqOm3Xvvqvdvt/CTKj0//9eK4vHrznuOt7L7+DnB/deq/nLHcx8c6YzkjhJKXzZkWdpzJ+Xbcmev9pfJLp+U0oajTMkNLVafphKKo03SWUdRpOvV8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dPXQvbZB99oO3Ws7dK/t0L22Q/fai1HD2tVD99oO3Ws7dK/t0L22I/fauCD32rgg99q4IPfauCD32rgg99q4IPfauCD32rgg99q4IPfauED32gDdawN0rw3QvTZA99qLuaXa1UP32gDdawN0rw3QvTZA99oI3WsjdK+N0L02Qvfai5mY2tVD99oI3WsjdK+N0L02QvfaBN1rE3SvTdC9NkH32ot5i9rVQ/faBN1rE3SvTdC9NkH3WoHutQLdawW61wp0r72Y5addPXSvFeheK9C9VqB7rUD32gzdazN0r83QvTZD99qLOXHa1UP32gzdazN0r83QvTZD99oC3WsLdK8t0L22QPfaixlk2tVD99oC3WsLdK8t0L22QPfaCt1rK3SvrdC9tkL32ov5VtrVQ/faCt1rK3SvheZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSE5kZFaG5UhOZGRWhuVITmRkVoblSC5kYlaG5UguZGJWhuVFqQe22C5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVILmRiVoblSC5kYlaG5UguZGJWhuVLLNjeq93t66L6+qN91rd6s33Wt3qzfda3erN91rd6s33Wt3qzfda3erN91rd6u33Gv70stWfajtqXrT3Kj96i332v3qLffa/eot99oeH76163/5XL3lXrtfveVe23vfXr0s6XnHNM2N2q/ecq/dr95wr10rzvfqw5Keqzfca/ert8yNOlC94V57oHrDvfZA9YZ77YHqDffaA9Ub7rVrxTHeqy8vqjfcaw9Ub7jXHqjedK+NtW/Vr4f1z9Wb7rVpO4WNi8T+VL1lbtSB6k332t3qLffasEi6vTqEuDxXb7nX7ldvudeGkLc9J8Scn6u33Gv3q7fca/ert9xrQ7332lDTb7321Xu32/lJlB+f/uvFcXn15j3HW9k9t7sxMfVfzlju42OdsZwRQsnL5kwLO87kfDvuzPX+Uvmp0zIZS1Wn5dyhqdN0QlHUaTrL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raiTJA/ZBm8r6iTJQ7Zx24o6SfKQbci2ok6SPHQxWjumeKMtxdzLZ52h1bJBq1pvTzCvfjErW7n6i+HX2tUH6OojdPUJunqBrj5DV1+gq6/Q1UP32grdaxt0r23QvbZB99oG3WsvRg1rVw/daxt0r23QvbZB99oG3Ws7dK/t0L22Q/faDt1rL2bLalcP3Ws7dK/t0L22Q/faDtxr07IA99q1euBeu1YP3GvX6oF77Vo9cK9dqwfutWv1wL12rR64167VA/fatXroXhuge22A7rUButcG6F57MRNTu3roXhuge22A7rUButcG6F4boXtthO61EbrXRuheezFvUbt66F4boXtthO61EbrXRuhem6B7bYLutQm61yboXnsxy0+7euhem6B7bYLutQm61yboXivQvVage61A91qB7rUXc+K0q4futQLdawW61wp0rxXoXpuhe22G7rUZutdm6F57MYNMu3roXpuhe22G7rUZutdm6F5boHttge61BbrXFuheezHfSrt66F5boHttge61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrh+61yNyotXroXovMjVqrR+61AZobFaC5UQGaGxWguVFhQe61AZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRAZobFaC5UQGaGxWguVEBmhsVoLlRwTY3qvd6e+u+vKredK/drd50r92t3nSv3a3edK/drd50r92t3nSv3a3edK/drd5yr+1LL1v1oban6k1zo/art9xr96u33Gv3q7fca3t8+Nau/+Vz9ZZ77X71lntt73179bKk5x3TNDdqv3rLvXa/esO9dq0436sPS3qu3nCv3a/eMjfqQPWGe+2B6g332gPVG+61B6o33GsPVG+4164Vx3ivvryo3nCvPVC94V57oHrTvTbWvlWfpD5Xb7rXpu0UNi4S+1P1lrlRB6o33Wt3q7fca8Mi6fbqEOLyXL3lXrtfveVeG9YAv1Ufc36u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+2pg/eD9V8D7r4D3XwHvvwLefzN4/83g/TeD998M3n912FcD6wfvvxm8/2bw/pvB+28G778FvP8W8P5bwPtvAe+/OvyqgfWD998C3n8LeP8t4P23gPffCt5/K3j/reD9t4L3Xx2m1MD6wftvBe+/Fbz/VvD+W8H7Lzj/SsD5VwLOvxJw/pWA868EnH8l4PwrAedfCTj/SsD5VwLOvxJw/pWA868EnH8l4PwrAedfCTj/SsD5VwLOvxJw/lUG519lcP5VBudfZXD+VV6w+28G519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnX2Vw/lUG519lcP5VBudfZXD+VQbnXxVw/lUB518VcP5VAedflQW7/xZw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQHnXxVw/lUB518VcP5VAedfFXD+VQXnX1Vw/lUF519VcP5VXbD7bwXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfVXD+VQXnX1Vw/lUF519VcP5VBedfNXD+VQPnXzVw/lUD51+1Bbv/NnD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VA+dfNXD+VQPnXzVw/lUD5181cP5VB+dfdXD+VQfnX3Vw/lVfsPtvB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+dfdXD+VQfnX3Vw/lUH5191cP5VB+df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W4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjS9AZW4LO2BJ0xpagM7YEnbEl6IwtQWdsCTpjK6MztjI6YyujM7YyOmMrL+CdOKMztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2MjpjK6MztjI6YyujM7YyOmMrozO2Cjpjq6Aztgo6Y6ugM7bKAt6JCzpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOroDO2Cjpjq6Aztgo6Y6ugM7YKOmOrojO2Kjpjq6Iztio6Y6su4J24ojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YqOmOrojO2Kjpjq6Iztio6Y6uiM7YaOmOroTO2Gjpjq6EzttoC3okbOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6uhM7YaOmOroTO2Gjpjq6Eztho6Y6ujM7Y6OmOrozO2Ojpjqy/gnbijM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6ujM7Y6OmOrozO2Ojpjq6Mztjo6Y6uj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cQqzulyuVGWcwKwulytVGacvq8vlSlXGycvqcrlSlXHqsrpcrlRlnLisLpcrVRmnLavL5UpVxknL6nK5UpVxyrK6XK5UZZywrC6XK1UZpyury+VKVcbJyupyuVKVcaqyulyuVGWcqKwulytVGacpq8vlSlXGScrqcrlSVeZKVcYp2dpyjVOy1eVyparClaqMM9DV5QqXXK5UZZyBri6XK1UZZ6Cry+VKVcYZ6OpyuVKVcQa6ulyuVGWcga4ulytVGeelq8vlSlVcbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWj1xs9cjFVo9cbPXIxVaPXGz1yMVWT1xs9cTFVk9cbPXExVZPi3DJpUpViYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OrCxVYXLra6cLHVhYutLotwyaVKVcLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6sLFVhcutrpwsdWFi60uXGx14WKrCxdbXbjY6jITjrrXeHtxTW/kTtSIDsidCVjcW7u9uNc3cifaqo7InWirOiJXuORONAAekTvRAHhE7kx994DcmfruAbkTDYAH5M4ELD4ilytVzQQsPiIXNlXdJQi+BNvpp8Z+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4ZNMl74SH+s+8bHuEx/rPvGx7hMf6z7xse4TH+s+8bHuEx/rPvGx7hMf6z7xse4TH+s+8bHuEx/rPlli3d+LMpSP7kUZSjD3osRiUYZSwL0oQ336XpShTnovylCvuxdlqBttRVmic9+LsrijWyJc34uyuKNbokTfi7K4o1siLd+LsrijW6IV34uyuKNbIv7ei7K4o1ui5t6LsrijWyLP3ouyuKNborfei7K4o1sioN6LsrijW6KI3ouyuKNbInHei7K4o1uiWd6LOnlHv39QueqD6lUf1K76oH7RB51N77t/ULjqg+JVH5Su+iC56oOu2hnKVTtDuWpnKFftDOWqnaFetTPUq3aGetXOUK/aGepVO0O9ameoV+0M9aqdoV61M9SrdoZ21c7QrtoZ2lU7Q7tqZ2hX7Qztqp2hXbUztKt2hnbVztCu2hn6VTtDv2pn6FftDP2qnaFftTP0q3aGftXO0K/aGfpVO0O/aGcQlb8WjVW2D2r9tw/6u6faROUvOk8oK9osK9ksS2yWlW2WVWyWVW2W1WyW1U2WFWzu8sHmLh9s7vLB5i4fbO7yweYuH2zu8sHmLh9s7vLB5i4fbe7y0eYuH23u8tHmLh9t7vLR5i4fbe7y0eYuH23u8tHmLp9s7vLJ5i6fbO7yyeYun2zu8snmLp9s7vLJ5i6fbO7yyeYuLzZ3ebG5y4vNXV5s7vJic5cXm7u82NzlxeYuLzZ3ebG5y2ebu3y2uctnm7t8trnLZ5u7fLa5y2ebu3y2uctnm7t8trnLF5u7fLG5yxebu3yxucsXm7t8sbnLF5u7fLG5yxebu3yxuctXm7t8tbnLV5u7fLW5y1ebu3y1uctXm7t8tbnLV5u7fLW5yzebu3yzucs3m7t8s7nLN5u7fLO5yzebu3yzucs3m7t8s7nLd5u7fLe5y3ebu3y3uct3m7t8t7nLd5u7fLe5y3ebu3w3uctnm3/7mm3+7Wu2+bev2ebfvubF5C6fbf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/uabf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/uabf7ta7b5t6/Z5t++Zpt/+5pt/u1rtvm3r9nm375mm3/7mm3+7Wu2+bev2ebfvmabf/ua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f1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/quD9VxW8/6qC919V8P6resM+fyt4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/1cD7rxp4/1UD779q4P1X7YZ9/jbw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4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2q+QzOe+one2XyGZz31F722/QjKf+4re836FZD73Fb5D/gLJfO4rfI/8BZL53Ff4LvkLJPO5r/B98hdI5nNf4TvlL5DM577C98pfIJnPfYXvlr9AMp/7Ct8vf4FkPvcVvo/+Asl87ouv6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o/+LruD76u+4Ov6/7g67o3vq574+u6N76ue+Prureb8Ummc1/G13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd94Wv677wdd0Xvq77wtd1X27GJ5nOfRW+rvvC13Vf+LruC1/XfeHrui98XfeFr+u+8HXdF76u+8LXdV/4uu4LX9d94eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33JVcL+mj7r0+P9vvPfglOdSrPCE71th69PwSPdiI41bt6RnCqN/WM4FTv6RnBqTLyjOBUCXlCcK4+7BnBuc7hCcGpsvGM4FTJeEawsQlmc1rIHdgvEcDu6SUiuCNqx+35IN0+/af3n+LaXx//T3Hcn6N69J7qCyRH76m+QnJwX3SF5ODO6ArJwb3RFZKNT3Jwf3SF5OAO6QrJwf3UFZL5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F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh62+vZP3tlay/vZL1t1ey/vb6yGR6ufxVJetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/ew3V7/1824+vLz/GD9/8N2/kOM7+JbHn7/fRx//6nR/l9Z6Pxyhv8PKfvnMfX9/5+OE7l3z8+7UlnxfTj+RGNP1fTj9U97um/9vpR3Kqmv5vpx/Jt2v6v51+pBSj6f92+lnTJ55+pISr6f92+pF+n6Lp/3b6kX67pOn/dvra9TFPX7u+sNPvr29c3r/v+/RD3UOk6f92+tr1MU9fuz7m6WvXF3b67Xv69WL6WdMnnr52fczT166Pefra9TFPX7s+5ulr1xd2+uX1lku9+ExvqDsxNf3fTl+7Pubpa9fHPH3t+pinnzV94ulr18c8fe36mKevXR/z9LXrY56+dn3E0w91P7um/9vpa9fHPH3t+pinr10f8/Szpk88fe36mKevXR/z9LXrY56+dn3M09euj3j6Q7s+5ulr18c8fe36mKevXR/z9LOmTzx97fqYp69dH/P0tetjnr52fczT166Pd/rtoV0f8/S162OevnZ9zNPXro95+lnTJ56+dn3M09euj3n62vURTz8p7++dfnrO4Gv6qVpO/8e7OVpS3meevvI+8/SV95mnnzV94ukr7zNPX3mfefrK+8zT12d7mKevz/YQT//Qro95+tr1hZ3+j7cxtkO7Pubpa9fHPP2s6RNPX7u+sNP/8Ua2dmjXxzx97fqYp69dH/P0tesjnv6pXR/z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l/M7J1YopvNczu+HWKGYznM5v8thhWI6z+X83oUViuk8l/M7ElYopvNczu8zWKGYznM5v3tghWI6z+X8noAViuk8l/NO/xWK6TyX8/79FYrpPJfzrvwViuk8l/Ne+xWK6TyX8w76FYrpPBddD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa90PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhb3Q99I2uh77R9dA3uh769sh0itk8V6ProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6XroO10Pfafroe90PfT9kekUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30PVJH+WjH64vbf7/zm95Ap/GU3kDP6dH764tHu9Ib6Ck9pTfQM3pKb6An9JTeQJl4Rm+kxuopvZHO3xm9kc7fGb2BsvCU3kyml8xfRWqpntIL66/eNMB6pjcNvn3Q2b7+KeXxMEnmznukVyj27YVWKPbthlYo9u2HVijOdIp9e6IVin27ohWKffuiFYp9u6gViuk8l/Me6RWK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QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77S9dBXuh76StdDX+l66Osj0ylm81yVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvoaqaP8+dWvL27//c5vegOdxjN6I3VXj95fXzzald5AT+kpvYGe0VN6Az2hp/QGysRTegMl4im9kc7fGb2Rzt8ZvYGy8IzeSE3VU3rJ/FWkluopvbD+6k1DDqDBtw/qpX39Uyr1p2Sej69kns/y/dVtvCv27YRWKPbthVYo9u2GVij27YcWKHbeI71CsW9PtEKxb1e0QrFvX7RCcaZTTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1BM57mc90ivUEznuZz3SK9QTOe5nPdIr1DM5rma8x7pFYrZPFdz3iO9QjGb52qPTKeYzXM15z3SKxSzea7mvEd6hWI6z+W8R3qFYjrP5bxHeoViOs/lvEd6hWI6z+W8R3qFYjrP5bxHeoViOs/lvEd6hWI6z+W8R3qFYjrP5bxHeoViOs910Hku513hKxTTea6DznOddJ7LeSf8CsV0nst5L/wKxZlOMZ3nct4Ov0Ixnedy3hC/QjGd53LeEr9CMZ3nct4Uv0Ixnedy3iy/QjGd56LroW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/peug7XQ99p+uh73Q99P2R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uJdoJvRh3lu+l2gm9GHeG8SXaCb0Yd7byZdoJvRh3pvPl2gm9GHeW9WXaCb0Yd4b25doJvRh3tvgl2gm9GHem+aXaCb0Yd5b7JdoJvRh3hvyl2gm9GGEffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+QdinfxD26R+EffoHYZ/+SdinfxL26Z+EffonYZ/++ciEmvl82EnYp38S9umfhH36J2Gf/knYp38S9umfhH36J2Gf/knYp38S9umfhH36J2Gf/knYp38S9umfhH36p6c+/bd35cgpvb0rR17m7V1ll+/KkR94e1eOTuy3d+XoTH17V45Ovbd35ehc+n5XnhrA396Vy2e7pxbtt3fl8tnuqYn67V25fLZ7anN+e1cun+2eGpHf3pXLZ7unVuG3d+Xy2e6pmfftXbl8tntqt317Vy6f7Z4aYt/elctnu6eW1bd35fLZ7qmp9O1duXy2e2r7fHtXLp/tnhoz397V4mf72yvV216p3fZK/bZXGne90uqGwLdXSre90nHbK523vVK+7ZVue0bU254R9bZnRL3tGVFve0a0254R7bZnRLvtGdFue0a0254R7bZnRLvtGdFue0a0254R7bZnRL/tGdFve0b0254R/bZnRL/tGdFve0b0254R/bZnRL/tGdFve0aM254R47ZnxLjtGTFue0aM254R47ZnxLjtGTFue0aM254R465nRDb5i9Sj5a9X6uM/r/SXn5LLJn81uuJ9HU7f1+n0fWWn76s4fV/V6ftqTt9Xd/q+hs/3lZw+75PT531y+rxPTp/3yenzPjl93ienz/vk9HmfnD7vk9Pn/eH0eX84fd4fTp/3h9Pn/eH0eX84fd4fTp/3h9Pn/eH0eX84fd6fTp/3p9Pn/en0eX86fd6fTp/3p9Pn/en0eX86fd6fTp/3p9PnfXb6vM9On/fZ6fM+O33eZ6fP++z0eZ+dPu+z0+d9dvq8z06f98Xp8744fd4Xp8/74vR5X5w+74vT531x+rwvTp/3xenzvjh93lenz/vq9HlfnT7vq9PnfXX6vK9On/fV6fO+On3eV6fP++r0ed+cPu+b0+d9c/q8b06f983p8745fd43p8/75vR535w+75vT5313+rzvTp/33enzvjt93nenz/vu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vtF7PLq9PvVTwe+vbn/8i47tSlcoNjrFsR3kCsWxfeEKxbHd3grFsT3cCsWxndkCxcHvt6xQHNtxrVBM57mCX3FZodjoFNN5ruC3XFYopvNcwe+5rFDM5rlq8JsuKxSzea4a/K7LCsVsnqs+jE4xm+eqwe/GrFDM5rlq8BsvKxTTea7g91hWKKbzXMFvp6xQTOe5gt85WaGYznMFv0myQjGd5wp+P2SFYjrPFfzWxwrFdJ4r+F2OFYrpPFfwGxorFNN5ruD3LlYopvNcwW9TrFBM57mC35FYoZjOcwW/+bBCMZ3nCn6fYYViOs910Xmu4Jc1Viim81wXnecyOs8V/NLJCsV0niv4VZIVio1OMZ3nCn4XZIViOs8V/IbHCsV0niv4vY0Viuk8V/DbGCsU03mu4HcsViim81zBb06sUEznuYLfh1ihmM5zBb/lsEIxnecKfndhhWI6zxX8RsIKxXSeK/g9gxWK6TxX8NsDKxTTea7gdwJWKKbzXME7/VcopvNcwfv3Vyim81zBu/JXKKbzXMF77VcopvNcwTvoVyim81x0PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtH10De6HvpG10Pf6Hro28PoFLN5rkbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0/XQd7oe+k7XQ9/peuj7w+gUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf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81fBe9b99ZL5q+A96/56yfxV8J51f71k/ip4z7q/XjJ/Fbxn3V8vmb8K3snur5fMX5H1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0nWX/7SdbffpL1t59k/e0XWX/7RdbffpH1t19k/e3Xw8j0cvmri6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrb7/I+tsvsv72i6y//SLrbzey/nYj6283sv52I+tvt4eR6eXyV0bW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97UbW325k/e1G1t9uZP3tRtbfbmT97Zap73q08/XF7fqkN9H7aEZvpj7k0fvri0f7pDfR82pKb6Ln1ZReI9ObKA9O6U2UB6f0Znr/zujN9P6d0ZsoD87ozdSHPKWXzF9l6kOe0gvrr940WAINsX1QO8dLQz/bd7n8MerrUx/H26eu5V1xbCe0QnFsL7RCcWw3tEJxbD+0QHHwBuMVimN7ohWKY7uiFYpj+6IVio1OMZ3nCt5mvEIxnecK3mi8QjGd5wrearxCMZ3nCt5svEIxnecK3m68QjGd5wrecLxCMZ3nCt5yvEIxm+cqwZuOVyhm81wleNvxCsVsnqs8jE4xm+cqwVuPVyhm81wlePPxCsV0nit4+/EKxXSeK3gD8grFdJ4reAvyCsV0nit4E/IKxXSeK3gb8grFdJ4reCPyCsV0nit4K/IKxXSeK3gz8grFdJ4reDvyCsV0nit4Q/IKxXSeK3hL8grFdJ4reFPyCsV0nit4W/IKxXSeK3hj8grFdJ4reGvyCsV0nit4c/IKxXSeK3h78grFdJ4reIPyCsV0nit4i/IKxXSeK3iT8grFdJ4reJvyCsV0nit4o/IKxXSeqxidYjrPVeg8V/Cu8BWK6TxXofNclc5zBe+EX6GYznMF74VfodjoFNN5ruDt8CsU03mu4A3xKxTTea7gLfErFNN5ruBN8SsU03mu4M3yKxTTeS66HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Fe6HvpK10Nf6XroK10PfX0YnWI2z1XpeugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10PfaXroa+ZOsqfX/364vbnd37Tm+htPKM3U3f16P31xaN90pvoKT2lN9Ezekpvoif0lN5EmXhKb6JEPKU30/t3Rm+m9++M3kRZeEZvpqbqKb1k/ipTS/WUXlh/9abBEmiI7YN6aV//lEr9Lpnb+ZXM7Sq/v7qNd8WxndAKxbG90ArFsd3QCsWx/dACxcF7pFcoju2JViiO7YpWKI7ti1YoNjrFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsVsnqsF75FeoZjNc7XgPdIrFLN5rvYwOsVsnqsF75FeoZjNc7XgPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea6TznMF7wpfoZjOc510nuui81zBO+FXKKbzXMF74VcoNjrFdJ4reDv8CsV0nit4Q/wKxXSeK3hL/ArFdJ4reFP8CsV0nit4s/wKxXSei66HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10Pfafroe90PfSdroe+0/XQ94fRKWbzXJ2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66HumjvLRztcXtz+/85veRG/jKb2JntOj968vbp/0JnpKT+lN9Iye0pvoCT2lN1EmntGbqbF6Sm+m9++M3kzv3xm9ibLwlF4j00vmrzK1VE/phfVXbxpgPdObhtg+aHx95+NxnMd30bx8fXWxD//wgtdILxAc2wktEBzbCi0QHNsLLRBsbIJju6EFgmPboQWCY/uhBYJjm6cFgtmcVvDy6AWC2ZxW8OroBYLZnFbw4ugFgtmcVvDa6AWC2ZxW8NLoBYLJnNYIXhm9QDCZ0xrBC6MXCCZzWuNhbILJnNYIXha9QDCZ0xrBq6IXCGZzWsGLohcIZnNawWuiFwhmc1rBS6IXCGZzWsErohcIZnNawQuiFwhmc1rB66EXCGZzWsHLoRcIZnNawauhFwhmc1rBi6EXCGZzWsFroRcIZnNawUuhFwhmc1rBK6EXCGZzWsELoRcIZnNaweugFwhmc1rBy6AXCGZzWsGroBcIZnNawYugFwhmc1rBa6AXCGZzWsFLoBcIZnNawSug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3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wfd4XfA9Xhd8j9cF3+N1PdDfyRd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4GXyPl8H3eBl8j5fB93jZA/2dbPA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9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vtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uh73Q99J2uh77T9dB3uh76/jA6xWyeq9P10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfc/UUT7a+fri9vfv/KY30dt4Sm+i5/To/fXFo33Sm+gpPaU30TN6Sm+iJ/SU3kSZeEZvpsbqKb2Z3r8zejO9f2f0JsrCU3qNTC+Zv8rUUj2lF9ZfvWmA9UxvGmL7oKt9/VOy8XBJ5sF7pFcoju2FViiO7YZWKI7th1YoNjrFsT3RCsWxXdEKxbF90QrFsV3UCsV0nit4j/QKxXSeK3iP9ArFdJ4reI/0CsV0nit4j/QKxXSeK3iP9ArFbJ5rBO+RXqGYzXON4D3SKxSzea7xMDrFbJ5rBO+RXqGYzXON4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5ruA90isU03mu4D3SKxTTea7gPdIrFNN5rkrnuYJ3ha9QTOe5Kp3nqkanmM5zBW+FX6GYznMFb4ZfoZjOcwVvh1+hmM5zBW+IX6GYznMFb4lfoZjOcwVvil+hmM5zBW+WX6GYznPR9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/YeuivB1sP/VMxmed6KibzXE/FZJ7rqdjoFJN5rqdiMs/1VEzmuZ6KyTzXUzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiOs/F1kP/VEznudh66J+K6TwXWw/9UzGd52LroX8qpvNcbD30T8V0nouth/6pmM5zsfXQPxXTeS62HvqnYjrPxdZD/1RM57nYeuifiuk8F1sP/VMxnedi66F/KqbzXGw99E/FdJ6LrYf+qZjOc7H10D8V03kuth76p2I6z8XWQ/9UTOe52Hron4rpPBdbD/1TMZ3nYuuhfyqm81xsPfRPxXSei62H/qmYznOx9dA/FdN5LrYe+qdiNs910PXQH3Q99AddD/1B10P/1EOnmM1zHXQ99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/0PXQH3Q99AddD/1B10N/ZOooH+18fXH7+3f+1pupoXxKb6Ln9OhfXzzaJ72JntJTehM9o6f0JnpCT+lNlImn9CZKxFN6M71/J/Rmaque0psoC0/pTZSEp/SS+atMLdVTemH91ZsGWM/0piG2Dyr2ytqjjv5TMi+vj/FcKn36dxfbB/nrje2D3PUGb5D21xvbB/nrje2D/PXG9kH+eo1Mb2wf5K83tmfy10vmr4I3RvvrJfNXwdui/fWS+avgTdH+esn8VfCWaH+9ZP4qeEO0v14yfxW8HdpfL5e/OoM3Q/vr5fJXZ/BWaH+9XP7qfBiZXi5/dQZvg/bXy+WvzuBN0P56yfxV8BZof71k/ip4A7S/XjJ/Fbz92V8vmb8K3vzsr5fMXwVvffbXS+avgjc+++sl81fB25799ZL5q+BNz/56yfxV8JZnf71k/ip4w7O/XjJ/Fbzd2V8vmb8K3uzsr5fMXwVvdfbXS+avgjc6++sl81fB25z99ZL5q+BNzv56yfxV8BZnf71k/ip4g7O/XjJ/Fby92V8vmb8K3tzsr5fMXwVvbfbXS+avgjc2++sl81fB25r99ZL5q+BNzf56yfxVIfNXwXu43fUG7+H210vmryqZvwres+6v18j0kvmr4D3r/nrJ/FXwnnV/vWT+KnjPur9eMn8VvGfdXy+Zvwres+6vl8xfBe9k99dL5q/I+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72k6y//STrbz/J+ttPsv72i6y//SLrb7/I+tsvsv7262Fkern81UXW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bdfZP3tF1l/+0XW336R9bcbWX+7kfW3G1l/u5H1t9vDyPRy+Ssj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tv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pvNcwfv3Vyim81zBu/JXKKbzXMF77VcopvNcwTvoVyim81x0PfSVroe+0vXQV7oe+krXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtH10De6HvpG10Pf6Hro28PoFLN5rkbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0/XQd7oe+k7XQ9/peuj7w+gUs3muTtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30PVNH+Wjn64vbn9/5TW+i13hKb6Kf06P31xeP9klvop/SU3oT/Yye0pvoJ/SU3kSZeEZvpsbqKb2Z3t8ZvZne3xm9ibLwlF4j00vmrzK1VE/phfVXbxpgPdObhtg+6Gpff5RsPFySefAe6RWKY3uhFYpju6EVimP7oRWKjU5xbE+0QnFsV7RCcWxftEJxbBe1QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxm+cawXukVyhm81wjeI/0CsVsnms8jE4xm+cawXukVyhm81wjeI/0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WX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX/7RdbffpH1t19k/e0XWX+7kfW3G1l/u5H1txtZf7s9jEwvl78ysv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj62+3TH3Xo52vL27XJ72J3qMZvZn6kEfvry8e7ZPeRD+vpvQm+nk1pdfI9CbKg1N6E+XBKb2Z3t8ZvZne3xm9ifLgjN5MfchTesn8VaY+5Cm9sP7qTYMl0BDbB7VzvDT0s/2Uyx+jvj71cbx96lreFcd2QisUx/ZCKxTHdkMrFMf2QwsUB28wXqE4tidaoTi2K1qhOLYvWqHY6BTTea7gbcYrFNN5ruCNxisU03mu4K3GKxTTea7gzcYrFNN5ruDtxisU03mu4A3HKxTTea7gLccrFLN5rhK86XiFYjbPVYK3Ha9QzOa5ysPoFLN5rhK89XiFYjbPVYI3H69QTOe5grcfr1BM57mCNyCvUEznuYK3IK9QTOe5gjchr1BM57mCtyGvUEznuYI3Iq9QTOe5grcir1BM57mCNyOvUEznuYK3I69QTOe5gjckr1BM57mCtySvUEznuYI3Ja9QTOe5grclr1BM57mCNyavUEznuYK3Jq9QTOe5gjcnr1BM57mCtyevUEznuYI3KK9QTOe5grcor1BM57mCNymvUEznuYK3Ka9QTOe5gjcqr1BM57mK0Smm81yFznMF7wpfoZjOcxU6z1XpPFfwTvgViuk8V/Be+BWKjU4xnecK3g6/QjGd5wreEL9CMZ3nCt4Sv0IxnecK3hS/QjGd5wreLL9CMZ3nouuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtD10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLX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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}},{"name":"fee_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":2,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}},{"name":"is_fee_payer","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::fee::FeePayload"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::entrypoint_parameters"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::entrypoint_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::verify_private_authwit_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"SchnorrSingleKeyAccount::verify_private_authwit_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"368":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/auth_oracle.nr","source":"use dep::authwit::auth_witness;\nuse dep::aztec::{protocol_types::{address::PartialAddress, grumpkin_point::GrumpkinPoint}, keys::PublicKeys};\n\nstruct AuthWitness {\n keys: PublicKeys,\n signature: [u8; 64],\n partial_address: PartialAddress,\n}\n\nimpl AuthWitness {\n fn deserialize(values: [Field; 73]) -> Self {\n let mut signature = [0; 64];\n for i in 0..64 {\n signature[i] = values[i + 8] as u8;\n }\n Self {\n keys: PublicKeys {\n npk_m: GrumpkinPoint::new(values[0], values[1]),\n ivpk_m: GrumpkinPoint::new(values[2], values[3]),\n ovpk_m: GrumpkinPoint::new(values[4], values[5]),\n tpk_m: GrumpkinPoint::new(values[6], values[7])\n },\n signature,\n partial_address: PartialAddress::from_field(values[72])\n }\n }\n}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> AuthWitness {\n let witness: [Field; 73] = auth_witness::get_auth_witness(message_hash);\n AuthWitness::deserialize(witness)\n}\n"},"369":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/main.nr","source":"mod util;\nmod auth_oracle;\n\ncontract SchnorrSingleKeyAccount {\n use dep::aztec::prelude::{AztecAddress, FunctionSelector, PrivateContext};\n\n use dep::authwit::{entrypoint::{app::AppPayload, fee::FeePayload}, account::AccountActions};\n\n use crate::{util::recover_address, auth_oracle::get_auth_witness};\n\n // Note: If you globally change the entrypoint signature don't forget to update default_entrypoint.ts\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload, fee_payload: FeePayload) {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.entrypoint(app_payload, fee_payload);\n }\n\n #[aztec(private)]\n #[aztec(view)]\n fn verify_private_authwit(inner_hash: Field) -> Field {\n let actions = AccountActions::init(&mut context, is_valid_impl);\n actions.verify_private_authwit(inner_hash)\n }\n\n #[contract_library_method]\n fn is_valid_impl(context: &mut PrivateContext, outer_hash: Field) -> bool {\n let witness = get_auth_witness(outer_hash);\n assert(recover_address(outer_hash, witness).eq(context.this_address()));\n true\n }\n}\n"},"370":{"path":"/usr/src/noir-projects/noir-contracts/contracts/schnorr_single_key_account_contract/src/util.nr","source":"use dep::std::{schnorr::verify_signature_slice};\nuse dep::aztec::prelude::AztecAddress;\nuse crate::auth_oracle::AuthWitness;\n\npub fn recover_address(message_hash: Field, witness: AuthWitness) -> AztecAddress {\n let message_bytes = message_hash.to_be_bytes(32);\n // In a single key account contract we re-used ivpk_m as signing key\n let verification = verify_signature_slice(\n witness.keys.ivpk_m.x,\n witness.keys.ivpk_m.y,\n witness.signature,\n message_bytes\n );\n assert(verification == true);\n\n AztecAddress::compute(witness.keys.hash(), witness.partial_address)\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"50":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth_witness.nr","source":"#[oracle(getAuthWitness)]\nunconstrained fn get_auth_witness_oracle(_message_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn get_auth_witness(message_hash: Field) -> [Field; N] {\n get_auth_witness_oracle(message_hash)\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"52":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/account.nr","source":"use dep::aztec::context::{PrivateContext, PublicContext};\nuse dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, hash::pedersen_hash};\n\nuse crate::entrypoint::{app::AppPayload, fee::FeePayload};\nuse crate::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash};\n\nstruct AccountActions {\n context: Context,\n is_valid_impl: fn(&mut PrivateContext, Field) -> bool,\n}\n\nimpl AccountActions {\n pub fn init(context: Context, is_valid_impl: fn(&mut PrivateContext, Field) -> bool) -> Self {\n AccountActions { context, is_valid_impl }\n }\n}\n\nimpl AccountActions<&mut PrivateContext> {\n // docs:start:entrypoint\n pub fn entrypoint(self, app_payload: AppPayload, fee_payload: FeePayload) {\n let valid_fn = self.is_valid_impl;\n\n let fee_hash = fee_payload.hash();\n assert(valid_fn(self.context, fee_hash));\n fee_payload.execute_calls(self.context);\n self.context.end_setup();\n\n let app_hash = app_payload.hash();\n assert(valid_fn(self.context, app_hash));\n app_payload.execute_calls(self.context);\n }\n // docs:end:entrypoint\n\n // docs:start:verify_private_authwit\n pub fn verify_private_authwit(self, inner_hash: Field) -> Field {\n // The `inner_hash` is \"siloed\" with the `msg_sender` to ensure that only it can \n // consume the message.\n // This ensures that contracts cannot consume messages that are not intended for them.\n let message_hash = compute_outer_authwit_hash(\n self.context.msg_sender(),\n self.context.chain_id(),\n self.context.version(),\n inner_hash\n );\n let valid_fn = self.is_valid_impl;\n assert(valid_fn(self.context, message_hash) == true, \"Message not authorized by account\");\n IS_VALID_SELECTOR\n }\n // docs:end:verify_private_authwit\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"55":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/fee.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__FEE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\nuse crate::entrypoint::function_call::FunctionCall;\n\n// 2 * 5 (FUNCTION_CALL_SIZE) + 2\nglobal FEE_PAYLOAD_SIZE: Field = 12;\n\n// 2 * 98 (FUNCTION_CALL_SIZE_IN_BYTES) + 32\nglobal FEE_PAYLOAD_SIZE_IN_BYTES: Field = 228;\n\nglobal MAX_FEE_FUNCTION_CALLS = 2;\n\n// docs:start:fee-payload-struct\nstruct FeePayload {\n function_calls: [FunctionCall; MAX_FEE_FUNCTION_CALLS],\n nonce: Field,\n is_fee_payer: bool,\n}\n// docs:end:fee-payload-struct\n\nimpl Serialize for FeePayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; FEE_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n fields.extend_from_array(self.function_calls[i].serialize());\n }\n fields.push(self.nonce);\n fields.push(self.is_fee_payer as Field);\n fields.storage\n }\n}\n\nimpl Hash for FeePayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__FEE_PAYLOAD\n )\n }\n}\n\nimpl FeePayload {\n fn to_be_bytes(self) -> [u8; FEE_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..MAX_FEE_FUNCTION_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n bytes.push(self.is_fee_payer as u8);\n\n bytes.storage\n }\n\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n if self.is_fee_payer {\n context.set_as_fee_payer();\n }\n }\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/cli/Earthfile b/yarn-project/cli/Earthfile deleted file mode 100644 index ad9f9c3c9876..000000000000 --- a/yarn-project/cli/Earthfile +++ /dev/null @@ -1,22 +0,0 @@ -VERSION 0.8 - - -export-aztec-cli: - FROM ../+build - ARG DIST_TAG="latest" - RUN yarn workspaces focus @aztec/cli --production && yarn cache clean - - RUN mkdir /cache && chmod 777 /cache - ENV XDG_CACHE_HOME /cache - VOLUME "/cache" - ENTRYPOINT ["node", "--no-warnings", "/usr/src/yarn-project/cli/dest/bin/index.js"] - SAVE IMAGE aztecprotocol/cli:${DIST_TAG} - -deploy-l1-contracts: - FROM +aztec-cli - ARG PRIVATE_KEY - ARG RPC_URL - ENV PRIVATE_KEY=$PRIVATE_KEY - ENV ETHEREUM_HOST=$RPC_URL - RUN echo "Deploying L1 contracts with PRIVATE_KEY=$PRIVATE_KEY and RPC_URL=$RPC_URL" - RUN --entrypoint deploy-l1-contracts diff --git a/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json b/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json deleted file mode 100644 index 4334baf5a574..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/AuthRegistry.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"AuthRegistry","functions":[{"name":"_set_authorized","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(internal)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/+2ZW0/jRhTHJ4Fw2wKJcUhMLiQQEyD3bGJKU/q4Up/71peql223Ui9SL6raj9hP1TlnZvyPcerVWVELVWvJsX38/825zDjxgZ7aUmpvR+mtpeymr/bUER+KtH+i3Jk+ob1wpArOZHQl2llXMvu6jk0h3aTRi3ym7WortAOrbT7TkSij26YoQjuc2r3QH+WlcoFW6GPvmD73S+SeB97X+0GP0lGR3g9Dl84LxUbaDunDaCiAD3q401OFV/p4ZMQvrPg4LBqjOgZ2bDSH5pTR32F2aJlREpSBloGWLfoTzA6tMEqCCtAK0IpFv4bZoR6jJPCAekA9i/4Gs0NPGCXBCdAToCcW/R5mh/qMksAH6gP1LfozzA6tMkqCKtAq0Ko5ppFyNqK9dWB26CmjJDgFegr01KJfwOzQGqMkqAGtAa1Z9FeYHVpnlAR1oHWgdYu+htmhAaMkCIAGQIN0eYJ4HoXIaTaiA/wSZoeeMUqCM6BnQM/S3s7iJ0OIeNmIDvANzA5tMEqCBtAG0EbaWyNekxmI9vYLzA5tMkqCJtAm0GbaWzN+eDIQ7e0vmB3aYpQELaAtoK20t1a8oDIQ7e0bmB3aZpQEbaBtoO20t3b8vAmRihwJ5Eg5l1z8Jw9Mz88PMDv0nFESnAM9B3pu0T9hdmiHURJ0gHaAdtKBduJyZCDa21cwO7TLKAm6QLtAu2lv3XjZCpGqHKnIkUCOtHNB3qFirVyKfCJHynLEy6VijVxyebZr7DwboY9CE2/ndwwqvJK7d3ASqtC9p+sRtxW2C3Z1kXR1aeCuOXV36PX/Eq/24Q6fhlZ0pb+TiO0XeIg+mWjnMANz5XIkph86WQ/ezI2iMao+Iuqr2BkhYYe6oLWwHgUcFWy2d0ZDIx7EtdlHbQ6Sncse0tNVLankxpXixowLdmGG2bfDdDdV0k7agQ3uYBNSykYSIblkDlfba5p985vwOF7aLk28VJVL09S5IpV67E6FJT6WbHl7xsnHer+OK3aFil0nK9ZHeNd6wM/08caIr6z4lpO8oTNgt0ZzbU7pmEY8OeLLkYYcCbIRXYbvYHbogFESDIAOgA7S3gbxF6cQqcqRmhxpyxFfjnhPnr6enynMDh0ySoIh0CHQYdrbMPYmRMpyxJcjXi65BHKknQvylorpVfAHzA4dMUqCEdAR0FHa2yh+SoVIKxvRAY5hduiYURKMgY6BjtPexvHUCpEbOeLJEV+ONORIIEdu5Ug9l3mpyZF2LvPi5ZLLWyqmn5sfYXbohFESTIBOgE7S3ibx39OESE2OeHKk+lwDC+RI4zlUTC+cb2F26JRREkyBToFO096mcU5CxJcjYzlSzUZ0GWYwO3TGKAlmQGdAZ2lvs/inKgOhbqT4KfqOBwYVmg3XXcy4V3EdyCzZxc7Z1Tzp6qWBZ+bU3aHG5iWalqXpYpdWFNku9s50sdRTU38ZcZivzJXLkZi70MkW8GZuFI3RtaBW55wRsuzoQVdrYT0KmLtYyvYBjd88rk0JtZkne7Jeb/3OltGa6nBU3Y1TMreuNyI72Qjim8WN6dwOMjNt59y2nd2S63J5NneQ/mLTtC+Sqa3N3AIriUTL+JVlCfnSaBa26BsRT474cqQhRwI5citH6nKkKkdqcqSdy7x4uaQ/yMVL+X9UsSCXBZPPGhvm8lS25Mgol6l8/538/jv5v579Wi4VG8uR41xy8Z7rgvFyecQaz7Vik1xy8XNZye+Q/vTJf5Kobdh6g77hgUGVbAmUVZt2cWFGXG8XI3YVJV09bs7QmNyh6bg37eK9FX1k28WVaRdXZKKdw3xtrlyOxKxCJ/sQ3syNojGqFSJaqdgZIfcdff35WliPAuZ2kbJ9MP/z21WJ/ytGcZl2UaYo2V7t9NbvbNlBonh2uhtnJ7JRRLiDXi76115ueV2wDug4vySk/jft/wAulotePisAAA==","debug_symbols":"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"},{"name":"is_reject_all","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/83Z6W7bRhAH8JUsKq5ikaIuU6dFS7R123HkokCafMwL9AGK3mjRA+iBoq/Yp+rO7PGXzILGFAURArRWw/nt7C6lmOss1JlS54HSx0TZo6YjKlR1/VKl851yLd2gsxKqigtldJGUaem4OsssUDVu6QoquNY/LjJlejivPdKFGvW1UBVCLwLqk2qrF/qsL2hg6qDPRuYGpuuc2WaDfpgcYh8tcEV3+F6/vjTJ5zb5IquaoLoAuzA5DdNk+gfCjjaZUkITtAnatPRnhB0NmVJCCBqChpZ+hbCjEVNKiEAj0MjS3xF2tMWUElqgLdCWpd8j7GjMlBJi0Bg0tvQXhB1tM6WENmgbtG1e86RZTHS1GcKOdphSQge0A9rJV+v4uRUQXe03hB3tMqWELmgXtGvp5wg72mNKCT3QHmjP0l8RdrTPlBL6oH3QvqXfIOzoJVNKuAS9BL209AeEHU2YUkICmoAm+ZVNfDUhCeUkkpNuMdHL8AXCjg6YUsIAdAA6sPRHhB0dMqWEIegQdJgf6H8mbTkJ5SSRk2Ypc4lLGdgz90V/Cv5C2NERU0oYgY5AR/lqI78MBURX+xJhR8dMKWEMOgYd56uN/bdWSNpyEspJIieDUsgzK6bvz9cIOzphSgkT0AnoJF9t4hdbSDpyEslJUkqVlpyEpcxlUAoZFpPUPI375+VHhgoPye6pmB/uM/fkrHusKRxTLjU9LXVl8MQ03RV6IL/Cw3Za52Zqk67tw/y8wl3MKUQnD/OleefmSLF55tJmqGYuVE1QzTGiufLFiKQzCh8N68mAP67Y2T6aHJ5jdrTJcZOYnu4l6pjedKECdXrwXeDNEVeyN6Rmu2nwuCfmnwHXob0NUzuc6b+RoJicDMlN5upN7SinZu7M0/HSMTPjpeWcBdxs2LfBgsupa7P7CuwNS02RT+kz41dsjhXLTldsgeFlusPP9OuNSZ7b5Fue5A21wG5NTmaa9JonkZzEctKTk6SY6GX4DmFHl0wpYQm6BF3mqy39rxwhactJR04GchLLSfS/T1/fn3uEHV0xpYQV6Ap0la+28tWEpCknsZxEpcwlkZNBKeSZFdOfgj8RdnTNlBLWoGvQdb7a2n9LhWRcTPQA9wg7umFKCRvQDegmX23jb62Q3MhJJCexnPTkJJGTWznpl3JfOnIyKOW+RKXM5ZkV09+bnxB2dMuUEragW9BtvtrW/+1XSDpyEslJ+0MdWCInvQ9hxfQH51uEHd0xpYQd6A50l6+283MSklhONnLSLiZ6GV4h7OieKSXsQfeg+3y1vf9VVUBoR1d9g33HW4YKmw23u9j7zUdmejzexd5xqbvTUvcG703TXaGNzT02LQ9mF/tgk17bXezB7GJpb/maTh7mJ+admyOZQ+bSXqGauVA1QXXAiA7KFyPyMNOd7o6G9WTAvIul2b5FF3d+bQKszd3pniy9rdp9Hm/sclvL1F5Nj7qt+00nryLP970fhD3OTFlO22f2dqpG6PeVwTs7Mj7x/4UmZPKomZomD4RJw55HhEP+zxYpt3hYc2omf9P5D3fVp4nDHAAA","debug_symbols":"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"},{"name":"set_authorized_private","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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N7AgwLYbWBBg2w1c/42NSlPPVgG239oLAgy9iV+PZOjd+noklbflPE7Z5ZovHunjgGKq8vaRprlHUmm/+dYjqf42iUr7zcbHz74fv/h+fPH9+NX34zffj999P/7w/fjT9eNP32/d6futO32/dafvt65K783Gx/f91p2+37rT91t3+n7rTtdvXXm4fuvKw/VbVx6u37rycP3WlYfrt648XL915eH6rSsP129debh+68rD91s3+X7rJt9v3eT7rZt8v3V1unn2Pb7vt27y/dZNvt+6yfdbN/l+62bfb93s+62bfb91s++3rk43z77H9/3Wzb7futn3Wzf7futm32/d4vutW3y/dYvvt27x/dbVaUba9/i+37rF91u3+H7rFt9v3eL7rSu+37ri+60rvt+64vutq9NLte/xfb91xfdbV3y/dcX3W1d8v3Wr77du9f3Wrb7futX3W1enl2rf4/t+61bfb93q+61bfb91q++3bvP91m2+37rN91u3+X7r6nRL7Xt832/d5vut23y/dZvvt27z/dbtvt+63fdbt/t+63bfb12dvqd9j+/7rdt9v3W777du9/3W7b7fur67qcR3N5X47qYS391U4rubSnx3U4nvbirx3U0lvrupxHc3lfjuphLf3VTiu5tKfHdTie9uKvHdTSW+u6nEdzeV+O6mEt/dVNV3N1X13U1VfXdTVd/dVPXh+q1bfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1X13U1VfXdTVd/dVNV3N1Xz3U3VfHdTNd/dVM13N1V7uH7rNt/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfHdTNd/dVM13N1Xz3U3VfXdTdd/dVN13N1X33U3VH67fut13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTdd/dVN13N1X33U3VfXdTDd/dVMN3N9Xw3U01fHdTjYfrt+7w3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVMN3N9Xw3U01fHdTDd/dVNN3N9X03U01fXdTTd/dVPPh+q07fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9X03U01fXdTTd/dVNN3N9XzOV2/dv/+nM6f3/WL9/mcrt+8z+d0/ep9Pqfrd+/zOV2/fJ/P6frt+3xO16/f53M6f//6rql6Pr/z96/voqrn8zt///quqno+v/P3r++yqufzO3//+q6rej6/8/ev78Kq5/M7f//6rqx6Pr/z96/v0qrn8zt///qurXo+v/P3r+/iqufzO3//+q6uej6/8/ev7/Kq5/M7f//6rq96Pr/z96/vAqvn8zt///qusHo+v/P3r+8Sq+fDOX//+q6xej6c8/ev7yKr58M5f//6rrJ6Ppzz96/vMqvnwzl///qus3o+v/P3r+9Cq+fzO3//+q60ej6/8/ev71Kr5/M7f//6rrV6Pr/z96/vYqvn8zt///qutno+v/P3r+9yq+fzO3//+q63ej6/8/ev74Kr5/M7f//6rrh6Pr/z96/vkqvn8zt///quuXo+v/P3r++iq+fzO3//+q66ej6/8/ev77Kr5/M7f//6rrt6Pr/z96/vwqvn8zt///quvHo+v/P3r+/Sq+fzO3//+q69ej6/8/ev7+Kr5/M7f//6rr56Pr/z96/v8qvn8zt///quv3o+v+/3b3Lef5Wc918l5/1XyXn/1fPpnD+/7/dvct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3XyXn/VfJef9Vct5/lZz3X2Xn/VfZef9Vdt5/lZ33X+WH7/dvdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfZef9Vdt5/lZ33X2Xn/VfFef9Vcd5/VZz3XxXn/Vfl4fv9W5z3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef9Vcd5/VZz3XxXn/VfFef+VOO+/Euf9V+K8/0qc91/Jw/f7V5z3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X4rz/Spz3X4nz/itx3n8lzvuvxHn/lTjvvxLn/VfivP9KnPdfifP+K3HefyXO+6/Eef+VOO+/Euf9V+K8/0qc91+J8/4rcd5/Jc77r8R5/5U4778S5/1X1Xn/VXXef1Wd919V5/1X9eH7/Vud919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXXef1Wd919V5/1X1Xn/VXPef9Wc91815/1XzXn/VXv4fv825/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wc91815/1XzXn/VXPef9Wd91915/1X3Xn/VXfef9Ufvt+/3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd91915/1X3Xn/VXfef9Wd918N5/1Xw3n/1XDefzWc91+Nh+/373DefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1Xw3n/1XDefzWc918N5/1X03n/1XTefzWd919N5/1X8+H7/Tud919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03n/1XTefzWd919N5/1X03f/VX747r96Pr/r9+/z+V2/f5/P7/r9+3x+1+/f5/O7fv8+n9/1+/f5/K7fv8/nd/3+fT6/8/ev7/6r5/M7f//67r96Pr/z96/v/qvn8zt///ruv3o+v/P3r+/+q+fzO3//+u6/ej6/8/ev7/6r5/M7f//67r96Pr/z96/v/qvn8zt///ruv3o+v/P3r+/+q+e/4Pz967v/6vkvOH//+u6/ev4Lzt+/vvuvnv+C8/ev7/6r57/g/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v/P3ru//q+fzO37+++6+ez+/8/eu7/+r5/M7fv777r57P7/z967v/6vn8zt+/vvuvns/v+/2bnPdfJef9V8l5/1Vy3n/1fDrnz+/7/Zuc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1XyXn/VXLef5Wc918l5/1X2Xn/VXbef5Wd919l5/1X+eH7/Zud919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Wd919l5/1X2Xn/VXbef5Vt9y9Vyb++tsrJ85v+/F94ftOfP7WO1/O3/v75TX/+LDy/6c+fhec3/fmz8Pym/f/189vu/1l4ftOf/y21X1/bSn7//KY//xee37T/X3h+cf78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eSnjrcfaaqG8lPHGY221UF7KeNuxtlooL2W86VhbLZSXqlBeyniHtbJa4x3W2mqhvFSD8lLG+8m11QqUWigvZbyfXFstlJcy3k+urRbKSxnvJ9dWC+WljPeTa6uF8lLG+8m11UJ5KeNd5tpqobwUVO95huo9z1C95xmq9zxD9Z5nqN7zDNV7nqF6zzNU73mG6j3PUL3nGar3PEP1nmeo3vMM1XueoXrPM1TveYbqPc9QvecZqvc8Q/WeZ6je8wLVe16ges8LVO95geo9Lw+BUovkpQpU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN7zAtV7XqB6zwtU73mB6j0vUL3nBar3vED1nheo3vMC1XteoHrPC1TveYHqPS9QvecFqve8QPWeF6je8wLVe16ges8LVO95geo9L1C95wWq97xA9Z4XqN5zgeo9F6jec4HqPReo3nN5CJRaJC8lUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsuUL3nAtV7LlC95wLVey5QvecC1XsukdqiZ8+vL+7lvdpAb6BrtZEahecYry+e/b3aQJ9SC2oDfUotqBUotYES34LaQIlvQW2k9+212kjv22u1gRLftdpIjcILaqG8VKRG4QW1br3UoUDcK7DteXqeLwUj96vU/Zjt9dQpfXrqVj/02nY9+npt+x59vbadj75e295HXa/xDmB9vbb9j75e2w5IX69tD6SvV8D0gvkr433A+nrB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"},{"name":"is_consumable","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/+2aWW/iVhTHLwSYmVKMYwiENRBw2CEsyUSaZh771Lc+VOpL1V2VukhdVPUr9lP1nnOXP2Dk0R1Nr6LRWHK4Pv7/7lmuMT5yhuJMiOcFIbeO0FteWkQgpPF5lvbXwozkgPZMIDLGFNNJotRI2sVZrAGR49EZzcmjnPxTuJZ/SrFQcz3P39GJPM06FJmMOqCPnJ742ZBCFDu5F2MT4gvBRtqK9EdpCPtoiDNywk/l58dK/EKLS3FWGUUJWElpimrI6F8wGzRglAQB0ABooNFfYTZomVESlIGWgZY1+i3MBg0ZJUEINAQaavRPmA16zigJzoGeAz3X6E8wGzRilAQR0AhopNHfYDZohVESVIBWgFbUZxIJ0hHprQezQauMkqAKtAq0mvRWtbmlINLbHzAb9IJRElwAvQB6odGvYDZojVES1IDWgNaSgdbs0jsikTsSuCNVd6SUjsjK/QKzQeuMkqAOtA60rtGvYTboJaMkuAR6CfRSo9/AbNAGoyRoAG0AbWj0Z5gN2mSUBE2gTaBNjX4Ps0FbjJKgBbQFtJWsbMt+AxyRsjtSd0cCL7lEXgJrpCNySf+B2aBtRknQBtoG2k56a9syOCKX7kjTS2Bld6TujjS8IG+omLwKvoPZoB1GSdAB2gHaSXrr2GI7IlV3JHRH6l68nLsjZS+5NLwgrXSkr57H7XPyHYMCD8fmaZgf72PzxCxnzAlsXXbVPXR1peCOGpoz9CB+hYfsfoGHfS261g/xgwxPMSAT7RxmUR2ZHMk2iI2sB2/qRFYZxQARDYR1Rki/R+a9sI4Cvs/obO+UhnO0tcmhNt3DHuIZ0usOqR062GiWDrdH7EkvSE5PU+S4O+o2YCbUy9DV4XRPIfl05CAkk8zVq9yeJqdW5jhe2noqXipnL8/Doj7MD9mduFZdV14vWF85+YSuGVuxASoWH1ZsiPBiOeHn8vNGiQdaPOIkb2gEbKQ0sRrSZxIJ3ZEoHZEB/g6zQceMkmAMdAx0nPQ2tneOFER6+xFmg04YJcEE6AToJOltYn96HJGKO1J1RxruSOSOhO88fbk+tzAbdMooCaZAp0CnSW9T680RCdyRyB0JveRSd0caXpA3VExeBX/DbNAZoySYAZ0BnSW9zey31BFppyMywCXMBp0zSoI50DnQedLb3C6tI3LjjoTuSOSOjNyRujsydkeaXtal6o40vKxL6CWXt6hYzR0pecklfKoXTOjlKzZ6ChWTN9ofYDboglESLIAugC6S3hY2J0ckckdq7kglHZFlWMNs0CWjJFgCXQJdJr0t7U9UCkIdXfYV+o5HBgWaDdNdLG3zEasZ97vYFbtaHbq6VfBSDc0Zamxu0bRsVBe70aKt7mJ3qoul3nJLO4f5oI5MjsTsYiNbw5s6kVVGsUNEO2GdEbLpyUkXe2EdBcxdLGX7iMZvZWuTR21Whz1Zf7h/5kxpVXU4quLJJVlp1yeRQjqC+Ja2MV3pSZaq7VzptrOg2s2CbjeLSH99atnXh6ntrdwaVxKJNvZRZQP5RmnWuugnkdAdidyRkTtSd0fG7kjTHam4I1V3pOFlXUIv6U+8eAneo4rVvVwwfq6xqZdvZdsdmXlZyg/35A/35P979ateKlZzR0pecgmf6gUTevmKjZ5qxeZecom8XMlvkf7inf8kUR929iX6hkcGxWFLILRatYtrNeN+u7hlV9tDV8fNGRqTHZqOe9Uu3mvRS90uPqh2kRrEl7RzmF+oI5MjMQ+xkd3BmzqRVUbxgIgehHVGyH1PHn+2F9ZRwNwurlW7ePwqkFsu9SqQ970Kn3plzNWDZjsy7XVGHLyr1L3iVp/d7k1bsG8xsXD0OmzNYerNvNDucvtn4l8FtmMsvtaR8Y5/QVWmwL7Q3KohB8LISu97CJtic3LLIwKyAxpe/kv7f2Q7N08WKwAA","debug_symbols":"1d3RapVXEMXxd8m1lD2zZ/bM9lVKKWlrS0BiqbFQxHfvseaYigdyVonN+V8V9TtmcF0sXfn49f3VL69+evfbjze3v755e/Xy+/dXr9/8fH138+b28KP3V+M7m//87Nvfr28//sTbu+s/7q5ejhdXr25/Ofz3w4urX29ev7p6OS0//PDi4wdC/UCqH1jqB0r9QKsf2OIHfKgfMPUDrn5ATdrVpF1N2tWkXU3a1aRdTXqqSU816akmPdWkp5r0VJOeatJTTXqqSU816VCTDjXpUJMONelQkw416VCTDjXpUJMONelUk0416VSTTjXpVJNONelUk0416VSTTjXppSa91KSXmvRSk15q0ktNeqlJLzXppSa91KRLTbrUpEtNutSkS0261KRLTbrUpEtNutSkW0261aRbTbrVpFtNutWkW0261aRbTbrVpLea9FaT3mrSW016q0lvNemtJr3VpLea9FaTtjHkT5j8CZc/Ia8nQ55PhryfDHlAGfKCMuQJZciZm5y5yZmbnLm+mOmTmb6Z6aOZvprps5m8m5k8nJm8nJk8nZm8nZk8npm8npk8n5m8n5k8oJm8oJk8oZm8oZk8opm8opk8o5m8o5k8pJm8pJk8pZm8pZk8ppm8ppk8p1no3w2RM5cXNZMnNZM3NZNHNZNXNZNnNZN3NZOHNZOXNZOnNZO3NZPHNZPXNZPnNZP3NZMHNpMXNpMnNpM3NpNHNlv69z3lzOWdzeShzeSlzeSpzeStzeSxzeS1zeS5zeS9zUr/ZrecuTy5mby5mTy6mby6mTy7mby7mTy8mby8mTy9WetvOMiZy+ubyfObyfubyQOcyQucyROcyRucySOcySucbf21Fv29FvnFFnmHc3mHc3mHc3mHc3mHc3mHc3mHc3mHc3mHc9NfZpIzl3c4l3c4l3c4l3c4l3c4l3c4l3c4199f019g+w9vsMmZ6++w6S+x6W+x6a+x6e+x6S+yyTucyzucyzucT/21RTlzeYdzeYdzeYdzeYdzeYdzeYdzeYdzeYdzeYfz0N9VlTOXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdziXdzhf+lvpcubyDufyDufyDuend7iosPsPRbV/8bkXXz29Z98/vLs/P3v41sqJZw8D//2zh3+Kfn728Je2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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fGs0oWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+Flf31O+/x2dxutMNpuZBQZlYy2Mppl1GS0yKjLSIrYShGzFDFLEbMUMUsRsxQxSxGzFDFLEbMUMUsRTYpoUkSTIpoU0aSIJkU0KaJJEU2KaFLEIkUsUsQiRSxSxCJFLFLEIkUsUsQiRSxSRJciuhTRpYguRXQpoksRXYroUkSXIroUMaSIIUUMKWJIEUOKGFLEkCKGFDGkiCFFrFLEKkWsUsQqRaxSxCpFrFLEKkWsUsQqRWSzoVVoVbTa0mqmVaPVQqtOq0EraiPURqiNUBuhNkJthNoItRFqI9RGqI2iNoraKGqjqI2iNoraKGqjqA0CzZBohkgzZJoh1AypZog1Q64Zgs2QbIZoM2SbIdwM6WaIN0O+GQLOkHCGiDNknCHkDClniDlDzhmCzpB0hqgzZJ0h7AxpZ4g7Q94ZAs+QeIbIM2SeIfQMqWeIPUPuGYLPkHyG6DNknyH8DOlniD9D/hkC0JCAhgg0ZKAhBA0paIhBQw4agtCQhIYoNGShIQwNaWiIQ0MeGgLRkIiGSDRkoiEUDaloiEVDLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5adtGTXLTIRYtctMhFi1y0yEWLXLT+20Wvp5+798Pu4WV/u9t7+/hxfPx31fd6PP96+/vl+u9v"},{"name":"unconstrained_is_consumable","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"boolean"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2d21PbRhTGJQOJioOBEF9lgzA3B9NgcGP60g60T33pQx761pkS7KRMUjxjzEz7zzPNynvw8cmGWaVHW58Zacbjlbw6328/7UWStSPfmyy5Tx9fp5fQNrpAnnP93flvywljrE6anD4jp484se8PCyf0IhKi5uA0BsG/f0A7VvX3xWh0+U90fdMf/B0N78bR8F30dnh307992HOs9wpQpIirZN93uk9QcFpN83hbMN22AKXT257qz8M+JN462gblWv70Kej0+8H4p4/Dqw+/3v31djDCnoHnPik9XVS059NoPw9vxqPLq/FFvz8a3N7ivZcMEe+/EHEZRfzz8vrmlz7e68nXRfptMLq9Ht7gvZ5aRgpQpMhjq92neW+2flEW0MMlAp5v+HlOUipnR8XNI3+5/FNePSNeBcSrAsqTR/49S8E/H+lCbFgHvaTMuTlgTrNerPDHPV3VvODrCvEXlwv6QsZ62cHHbQnpFZDumk5zD8urOtaijg0ca0h7g93z7pVqW+ve7PJYX7aBeJ6z80z6Mv5yTursC8TOE/d1V3lVJF6tE68KKA9mKKbgn490ITasFw3afF6cfae0SxZelAw8JcdelAzafF703intsoUXZQNP2bEXZYM2Y72Ix/uKhRcVA0/FsRcVgzZjvYi1qxZeVA08VcdeVA3ajF6cKe2ahRc1A0/NsRc1gzajF6+VdmjhRWjgCR17ERq0+bw4jc+H6hZe1A08dcde1A3ajH1nfH7RsPCiYeBpOPaiYdBmbCNXSnvTwotNA8+mYy9ALylzSSBzUSBzOAfMAUnzaHfj/nPLwostA8+WYy9ALylzOAfMAUnzaPcGvjd7zf0lLyIDT+TYC9BLylwSyFwUyBwKZK4IZG5kzE6Y56HfCEiaR/ssvh7etvBi28Cz7dgL0EvKXJsD5oCkebR78f3PpoUXTQNP07EXTYM24zV8fA6zY+HFjoFnx7EXoJeUORTI/EIgc1Egc0kgc1kgc0Ugc1Ugc00gs8T+uS6QuSGQWWL/LHEclFif56HfCEiaR7sXP5G5a+HFroFn17EXuwZtxuvt+D/XPQsv9gw8e469AL2kzHWBzEWBzKFA5qxuuGGuCGQuC2TO+o2vYw5Imke711Pa+xZe7Bt49h17AXpJmcsCmUsCmXcEModzwByQNI92N9Y+sPDiwMBz4NgL0EvK3JwDZjUfBOaGXPhp8nT7ecIDnnmE0SOMeZTeQJ61dPrc45vHgY9PC2m9ZPejY6zjsP4yVe3ulYrb5i9T/GzYkY61pGO3DWX6Vqd9Zj+PUFwf6cD2RZT+0Z/mhXzgB7RbYFdzxQ51GrPT/Q7IfgWU59BQ/oi5/G3C0ybM6ph0UTtPo27Z1Gs17wza8g/IlxY7z2Q+bc6bXR7rd3C7X+XnOUmpnB2T7zlSJty/4fmOaY0/LcID64+NmY8xL8wBc0raD/NTc0RvmfiBfVgiPoGncGxhvifkx/M9D9nLMJnvmWSMx31iGmNsOuWctDXa126QMhVQHvxcRArjblxvDwkPrLfRcUjCXBTIXBLIXBbIXBHIXBXIXBPIHApkrgtkbghkltg/SxwHJbbBTYHMEn3eEsic9RtumCXWZ4nnohLH7ux8ww1zJJBZ4nXKtkDmpkBmiWNKdr/ODXN2v84Nc3a/zg1zdr/ODXN2v84Nc3bd7YZZYn2W2G/sCGTeFcgssT5n9+vcMGd1ww2zxHN+iddWWb/hhnlPILPE+izxnF/ieZ3ENrgvkHke7pmr53Dhmdw/cmnyTObZYB7wzCOMHmHMo/Qh8gzmS5x7vPNsQOsIaf1f8yLS0Z7MsznmL1P8/DG8FxDm2RwbynSi0z6znx0U10c6sH0RpX/PTfNCPvAD2i2wq3k2r3Qas9P92mS/AsrzylD+iLn8x4TnmDCrY/IGtfM06pZNvVbP+0NbxvNsYD4A4/utTtLqX1W/hN+Nphab/gz3XZw8y970nXG34+Ho8v3gzeDy4WWEvjf7Wjf6jdHv0XoObW+h9ILh93v0ndJ0opnpdBD7iPC5GFKhe1vW63hIhTwftTlr3ueLaXiG4wMxV1CZIG8O5WuhWDnkA/x+r7dDPjwNMe997lvemx5P+E29uvFfP4YqlrZ2AAA=","debug_symbols":"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"},{"name":"set_reject_all","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"reject","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/83X2Y7TMBQGYKcb7XSmM9MmTZtuaZqllArBBUgIhiskHoAnQGK5YZFYxDvyVPgc++RvCWTkm2oipXGPz+djO1ONnKqmUt2W0tdC2Ut/66qB6uhHg+6XSlq6Qbc3UJ6ETB4N0uS8prkP8ziUUSeN3uCWjisTo8RWZqlqJ/pj8ETJpK7po5MqGbKXySzvKQ7S1aMPk0PjdlP0pKqtji/KOONZqzNzN81oPEw/a9iOPgbsm5yeadKzSjr15GhKspjz562DHBrvvDpfui7MfC/obptS9qveGiqnLtv8pK5L2kFT5IW+h+WOXWHHhsc7do3pDfWAb/RzZJKvbLLPixxRC8w3OUPTZPoDYaEBU0oIQAPQwNKvCAsdM6WEMegYdGzpN4SFhkwpIQQNQUNL3yIsdMKUEiagE9CJpR8RFjplSglT0Cno1NL3CAuNmFJCBBqBRpbGCAudMaWEGegMdGbpd4SFzplSwhx0Djq39BPCQhdMKWEBugBdmGeVBO7EdydRPdFreoSw0CVTSliCLkGX1WrLsloN0dW+ICx0xZQSVqAr0FW12qrcQUfiu5PInYTuZH4ScsuO6ffzC2GhMVNKiEFj0LhaLS5/xTVEV3uHsNA1U0pYg65B15Y+RFhowpQSEtAENKlONClfsSMZuRPfnQTuZOxOQncycSfTk7yXmTuZn+S9+CdZyy07pn83nxEWumFKCRvQDejG0p8IC02ZUkIKmoKm1Ymm5docie9Oors6sdCdjO/Cjum/gg8IC82YUkIGmoFm1WpZuSZHEriTxJ1E9URvw2OEheZMKSEHzUHzarW8/JdVQ6jbe43zzA1DhUOMnFoom+sbm6qWwlVwqeK41Nbg3DSlhw5MWxyGdh1u7mzSA716snuPh9hTiG6e5ivzTdZIZp9J2n1UMx0NE1R7zGivymJEdrEOPzuY1l8TfurZ1d6Yw2FblQdljxcty29jm4rjY98gPexp2kGK8u10/vl2CjuLAj04Yxb/PWPmW88W4PPxhsjkN91/AGbVK/CEEAAA","debug_symbols":"1dzLSlthGIXhe8lYyr/W9x+9lVJK6qEEJIrGQhHvvbHNTioG4kDa/c6MfkkWGeTFyfO0uLz69vj962p9ffuwOP/8tLi5vVhuVrfr7aOnRfqk/Pu3D3fL9csvHjbL+83iXM75bHG1vnz5sebns8X16uZqcR4qz2dvrot67K6LhvbXI44c15zq7rhmvzr+cvYyqBwfZB8GlRODRvTd8eh9f6vsI7cqaXrhcbi1j20fxZpeuPTDCsfYja/k8Y08vpPHD/B4J/J4k8cHeXwmjydHyuRImRwpkyNlcqSCHKkQeTy5sPEBhVWq039HktOJ+dP4dOJVW5mWt/r3R5J3wwt1eKUOb9ThnTp8QIfnRB0u6nBTh1MDlDN1OLWcmVrOTC1nppYzU8tZqOUs1HIWajkLtZyFWs5CLWehlrNQy1mo5SzUclZqOSu1nJVazkotZ6WWs1LLWanlrNRyVmo5K7WcjVrORi1no5azUcvZqOVs1HI2ajkbtZyNWs5GLWenlrNTy9mp5ezUcnZqOTu1nJ1azk4tZ6eWs1PLOajlHNRyDmo5B7Wcg1rOQS3noJZzUMs5qOUc1HIqUdOpRG2nEjWeStR6KlHzqUTt5/ZNscupBVWiJlQJ21BhGypsQ4VtqLANFbahwjZU2IYK21BhGypsQ41tqLENNbahxjb0Ixyf/7Qc21BjG2psQ41tqLENDWxDA9vQwDYUi/UosA3FOkPCQkPCSkPCUkPCWkPCYkPCakPCckPCekPCgkPCikPCkkPCmkPCokPCqkPCskPCukPCwkPCykPC0kPC2kPC4kPC6kPC8kPC+kPCAkTCCkTCEkTCGkTCIkTCKkTCMkTCOkTCQkTCSkTCUkTCWkTCYkTCakTCckTCekTCgkTCikTCkkTCmkTCokTCqkTCskTCukTCwkTCykTC0kTC2kTC4kTC6kTC8kTC+kTCAkXCCkXCEkXCGkXCIkXCKkXCMkXCOkXGOkXGOkXGOkXGOkVO1IYa6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQZ6xQF1ikKrFMUWKcosE5RJGpDA+sUBdYpCqxTFFinKLBOUWCdosA6RYF1igLrFAXWKQqsUxRYpyiwTlFgnaLAOkWBdYoC6xQF1ikKrFMUWKcosE5RYJ2ieIdT1Map5Tnl6To7Xr3L2+sY06Lt0/a3jjQt6h+xKPafZW6nFtUyza+jHm49pkVjbove4QX960Wa3SLPblHMblGe3aIyu0V1dova7BbN7js7ZvednWf3nZ3n9J29ffRjeb9afru5etg+4+WPj+uLzep2vXu4+Xn35y/b218="},{"name":"set_authorized","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"authorize","type":{"kind":"boolean"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/+2Zy27aQBSGBwikTQhJSmwM5mLABgImCYt20ZbuKnXfVZeV0mbTi9SL+o59qs45M+PfjinRVK2FqiANHp/5vzmXMSFHhKIixIOqkK+e0C9590A0RE1eyjReCDOTExqlhigZk9Lt0WDdnhppHZsiWqTdyzyTdlGJ9MZCrVbId6Q3EbWRfDt+LEx4p/S2H1K8vPlBZOKV21b09IDelIY8PAyxEoqqyL5ol0OOXxyqUdFB0jb1qKwX6tiwrjQHakrXPLK/HcmEZJI5eraX0tB+R/l46dVQ8TZoVHla17eyNOROnFT5SlGcUAWVk+dyNJOKnaJizWzFHiG8ptzwtbyeKfGpFjuc5BnNgDlK01RTRr/BbFCXURK4QF2grkY/w2zQFqMkaAFtAW1p9AvMBvUYJYEH1APqafQtzAZtM0qCNtA20LZGb2A2aIdREnSAdoB2NPoOZoP6jJLAB+oD9TUawGzQLqMk6ALtAu1q9CvMBu0xSoIe0B7QnkY/wGzQPqMk6APtA+2rax5x7RHHHvG3IzKnK5gNOmCUBAOgA6CDvLdB4m0LIr19gtmgAaMkCIAGQIO8tyCpoCXi2CO+PeLZI71CkDsqJs/nB8wGHTJKgiHQIdBh3tsw+RRvQaS3a5gNOmKUBCOgI6AjjV7AbNAxoyQYAx0DHecDHSdHbImc2SOOPeLaIy17xLNH2vZIp5Bz6dojvULOxSkklzsqJj83H2E2aMgoCUKgIdBQo99hNmjEKAkioBHQKB9olORmiTj2iL+rgXn2SGsXKiafgvcwG3TCKAkmQCdAJ3lvkyQnS8S1R8b2iL8dkWVYwWzQKaMkmAKdAp3mvU2Tr6wtCH0Zll6hn1kzKNDEmK6F1HwMig3FnsBrxq5mWVfnCp6qqVmhhukczdCixtOFFsUye2KXJd5iSSYaHOZLdWdyJGYZGdkc3tRCWRnFEhEtReKMkEUgzU9TYd0K+ElJZ7tGQzlLarOP2syyvd5xmF6pKK2qDkdV33gkM+16I1LdjiC+adLwzvQmU9XO0i21s1XVxtKG1MbWkf5807HPs6mlTm6OJ4lEi+RflwXkC6WZ66JvRBx7xLVHWvaIZ4+07ZGOPeLbI117pFfIuTiFpN8vxMvgP6qYV8gDU8wzFhTyqRzaI6NCjvL+b/L93+R/ffrdQio2tkfCQnJxdvWBcQr5iLV2tWJRIbm4hTzJf5D+5K9/JdGXXPkGfcOaQZFtCYRWq3ZxrnZMt4sxu4qzrm43Z2hMlmg6LlW7eKlFV7pdXKl2kfpm+snhisO8VncmR2JWkZFdwJtaKCujWCGilUicEXIZyE3fpMK6FTC3i5TtWv2WSKOK3eKkTDWUKc62V/UwvVLRm8TJ6VQ3nk6so4ixgl4u/m0vt5iVtAO6zsaEeD9p/AKfECQnvR4AAA==","debug_symbols":"1dzRahxXFobRd9G1GWrvs/epOn6VYRiUxBkERg6xMhBM3j1yorZiIugLkaTWnVp9uvqnBfWpb9anm+/effPT//57d//9h483b//96eb9h29vH+4+3D8++nSz/Sv6t99+/OH2/vMvPj7c/vhw8/ao483Nu/vvHn+axy9vbr6/e//u5u2I/uXNn852HOPpcMeKL6fXeOHwrG0+HZ6VXx3+z5vPc+aLc3L7MmddmbPGZfo6nqdH5Qtnoy/XjfV8NvOl5aszLhfuo59Pj/U0fXenH+70xU7PzZ0e7vThTi93ervT3SSlm6R0k5RukoabpOEmaaQ73a3peHVNY5uXbz4RuV0Zf7nudu371LrsntvXH8jvs6c5ezdnH+bsRc6uzZwd5uw0Zw9ztpmbanO2WckyK1lmJcusZJuVbLOSbVayzUq2Wck2K9lmJdusZJuVbLOS06zkNCs5zUpOs5LTrOQ0KznNSk6zktOs5DQruZuV3M1K7mYld7OSu1nJ3azkblZyNyu5m5XczUoeZiUPs5KHWcnDrORhVvIwK3mYlTzMSh5mJQ+zksus5DIrucxKLrOSy6zkMiu5zEous5LLrOQyKxmbmcnYzE7GZoYyNrOUsZmpjM1s5eOborvNWsZm5jI2tJeB9jLQXgbay0B7GWgvA+1loL0MtJeB9jLQXibay0R7mWgvE+3l6xWcf2g32stEe5loLxPtZaK9HGgvB9rLgfZyoL1EnZsYaC9RoCdQoSdQoidQoydQpCdQpSdQpidQpydQqCdQqSdQqidQqydQrCdQrSdQridQrydQsCdQsSdQsidQsydQtCdQtSdQtidQtydQuCdQuSdQuidQuydQvCdQvSdQvidQvydQwCdQwSdQwidQwydQxCdQxSdQxidQxydQyCdQySdQyidQyydQzCdQzSdQzidQzydQ0CdQ0SdQ0idQ0ydQ1CdQ1SdQ1idQ1ydQ2CdQ2SdQ2idQ2ydQ3CdQ3SdQ3idQ3ydR3ydR3ydR3ydR3yc3s5eJ+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j6J+j4D9X0G6vsM1PcZqO8zNrOXA/V9Bur7DNT3GajvM1DfZ6C+z0B9n4H6PgP1fQbq+wzU9xmo7zNQ32egvs9AfZ+B+j4D9X0G6vsM1PcZqO8zUN9noL7PQH2fcdX3OeaVd1jjeDq7juPK6ujLdWM9n80cL1238zJ99dHPp8e6bF/u9qvOz5m3B7w94e0D3l7w9oa3T3j7Dm+Huzrgrhbc1YK7WnBX69Vd/Wv+d9/7Mnyff/xE6rK70N2N7p7o7h3dfaC7l7m7N3R3oLsT3Y328qoNdNbdaC8b7WWjvWy0l432cqK9nGgvJ9rLifbyqg101t1oLyfay4n2cqK9nGgvd7SXO9rLHe3ljvbyqg101t1oL3e0lzvayx3t5Y728kB7eaC9PNBeHmgvr9pAZ92N9vJAe3mgvTzQXh5oLxfay4X2cqG9XGgvr9pAZ92N9nKhvVxoLxfay2X2sjazl7WZvazN7GVtZi9rM3tZm9nL2sxe1mb2sjazl7WhvQy0l4H2MtBeBtrLqzbQWXejvQy0l4H2MtBeBtrLRHuZaC8T7WWivbxqA511N9rLRHuZaC8T7WWivRxoLwfay4H2cqC9fL0B9A/tRns50F4OtJcD7eVAe1loLwvtZaG9RH2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fQn2fRn2fRn2fRn2fRn2f3sxeNur7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7NOr7TNT3majvM1HfZ6K+z9zMXk7U95mo7zNR32eivs9EfZ+J+j4T9X0m6vtM1PeZqO8zr/k+axvXdtdWl92V46v3+PPpsS57Hl/25WyO7bJnvn7P+PI51n5tz+zL+Lme/0KR67JnP9me42R71rn2XHNx/vY9cbI9ebI942R76mR7+mR7TnZ/zpPdn/Nk9+c8z/358dH/b3+8u/3m/buPj6/4/ORP998+3H24f3r48PMPvz/zePZX"},{"name":"consume","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"inner_hash","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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cq6F5FwLybkWknMtJOdaSM61kJxrITnXQnKuheRcC8m5FpJzLSTnWkjOtZCCayEF10IKroUUXAspFramwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k4FpIwbWQgmshBddCCq6FFFwLKbgWUnAtpOBaSMG1kIJrIQXXQgquhRRcCym4FlJwLaTgWkjBtZCCayEF10IKroUUXAspuBZScC2k5FpIybWQkmshJddCyoWtaXItpORaSMm1kJJrISXXQsonLKTcj6Zve5m+0159mT8+Hb4vDx//2np7Vvtlkpxvkp5vkp1v0j7fJD/fpDjfpDzfpDrfpD7dJD3fp7ee79Nbz/fprWf69D7+6j9/+PvHH/7004+/HG/8/l/+49OfP3/8+dPlLz//19/+9785nv1v"}],"outputs":{"globals":{"storage":[{"fields":[{"name":"reject_all","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"approved_actions","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_authorized_parameters"}}],"kind":"struct","path":"AuthRegistry::set_authorized_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"reject","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_reject_all_parameters"}}],"kind":"struct","path":"AuthRegistry::set_reject_all_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::set_authorized_private_parameters"}}],"kind":"struct","path":"AuthRegistry::set_authorized_private_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"approver","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}},{"name":"authorize","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::_set_authorized_parameters"}}],"kind":"struct","path":"AuthRegistry::_set_authorized_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"inner_hash","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::consume_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::consume_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"AuthRegistry::is_reject_all_parameters"}},{"name":"return_type","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::is_reject_all_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"on_behalf_of","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"message_hash","type":{"kind":"field"}}],"kind":"struct","path":"AuthRegistry::is_consumable_parameters"}},{"name":"return_type","type":{"kind":"boolean"}}],"kind":"struct","path":"AuthRegistry::is_consumable_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"122":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr","source":"#[oracle(packArgumentsArray)]\nunconstrained fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {}\n\n#[oracle(packArguments)]\nunconstrained fn pack_arguments_oracle(_args: [Field]) -> Field {}\n\n/// - Pack arguments (array version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments_array(args: [Field; N]) -> Field {\n pack_arguments_array_oracle(args)\n}\n\n/// - Pack arguments (slice version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments(args: [Field]) -> Field {\n pack_arguments_oracle(args)\n}\n\n"},"124":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/returns.nr","source":"#[oracle(packReturns)]\nunconstrained fn pack_returns_oracle(_returns: [Field]) -> Field {}\n\nunconstrained pub fn pack_returns(returns: [Field]) {\n let _unused = pack_returns_oracle(returns);\n}\n\n#[oracle(unpackReturns)]\nunconstrained fn unpack_returns_oracle(_return_hash: Field) -> [Field; N] {}\n\nunconstrained pub fn unpack_returns(return_hash: Field) -> [Field; N] {\n unpack_returns_oracle(return_hash)\n}\n"},"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"144":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr","source":"use crate::context::{PublicContext, UnconstrainedContext};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:public_mutable_struct\nstruct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl Storage for PublicMutable {}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicMutable { context, storage_slot }\n }\n // docs:end:public_mutable_struct_new\n}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) where T: Serialize {\n let fields = T::serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n pub fn read(self) -> T where T: Deserialize {\n // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the\n // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns\n // historical data.\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"315":{"path":"/usr/src/noir-projects/noir-contracts/contracts/auth_registry_contract/src/main.nr","source":"contract AuthRegistry {\n use dep::aztec::{state_vars::{PublicMutable, Map}, protocol_types::address::AztecAddress};\n use dep::authwit::auth::{IS_VALID_SELECTOR, compute_outer_authwit_hash, assert_current_call_valid_authwit};\n\n #[aztec(storage)]\n struct Storage {\n reject_all: Map>,\n // on_behalf_of => authwit hash => authorized\n approved_actions: Map>>,\n }\n\n /**\n * Updates the `authorized` value for `msg_sender` for `message_hash`.\n *\n * @param message_hash The message hash being authorized\n * @param authorize True if the caller is authorized to perform the message hash, false otherwise\n */\n #[aztec(public)]\n fn set_authorized(message_hash: Field, authorize: bool) {\n storage.approved_actions.at(context.msg_sender()).at(message_hash).write(authorize);\n }\n\n /**\n * Updates the `reject_all` value for `msg_sender`.\n * \n * When `reject_all` is `true` any `consume` on `msg_sender` will revert.\n * \n * @param reject True if all actions should be rejected, false otherwise\n */\n #[aztec(public)]\n fn set_reject_all(reject: bool) {\n storage.reject_all.at(context.msg_sender()).write(reject);\n }\n\n /**\n * Consumes an `inner_hash` on behalf of `on_behalf_of` if the caller is authorized to do so.\n * \n * Will revert even if the caller is authorized if `reject_all` is set to true for `on_behalf_of`.\n * This is to support \"mass-revoke\".\n *\n * @param on_behalf_of The address on whose behalf the action is being consumed\n * @param inner_hash The inner_hash of the authwit\n * @return `IS_VALID_SELECTOR` if the action was consumed, revert otherwise\n */\n #[aztec(public)]\n fn consume(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n assert_eq(false, storage.reject_all.at(on_behalf_of).read(), \"rejecting all\");\n\n let message_hash = compute_outer_authwit_hash(\n context.msg_sender(),\n context.chain_id(),\n context.version(),\n inner_hash\n );\n\n let authorized = storage.approved_actions.at(on_behalf_of).at(message_hash).read();\n\n assert_eq(true, authorized, \"unauthorized\");\n storage.approved_actions.at(on_behalf_of).at(message_hash).write(false);\n\n IS_VALID_SELECTOR\n }\n\n /**\n * Updates a public authwit using a private authwit\n * \n * Useful for the case where you want someone else to insert a public authwit for you.\n * For example, if Alice wants Bob to insert an authwit in public, such that they can execute\n * a trade, Alice can create a private authwit, and Bob can call this function with it.\n *\n * @param approver The address of the approver (Alice in the example)\n * @param message_hash The message hash to authorize\n * @param authorize True if the message hash should be authorized, false otherwise\n */\n #[aztec(private)]\n fn set_authorized_private(approver: AztecAddress, message_hash: Field, authorize: bool) {\n assert_current_call_valid_authwit(&mut context, approver);\n AuthRegistry::at(context.this_address())._set_authorized(approver, message_hash, authorize).enqueue(&mut context);\n }\n\n /**\n * Internal function to update the `authorized` value for `approver` for `messageHash`.\n * Used along with `set_authorized_private` to update the public authwit.\n * \n * @param approver The address of the approver\n * @param message_hash The message hash being authorized\n * @param authorize True if the caller is authorized to perform the message hash, false otherwise\n */\n #[aztec(public)]\n #[aztec(internal)]\n fn _set_authorized(approver: AztecAddress, message_hash: Field, authorize: bool) {\n storage.approved_actions.at(approver).at(message_hash).write(authorize);\n }\n\n /**\n * Fetches the `reject_all` value for `on_behalf_of`.\n * \n * @param on_behalf_of The address to check\n * @return True if all actions are rejected, false otherwise\n */\n #[aztec(public)]\n #[aztec(view)]\n fn is_reject_all(on_behalf_of: AztecAddress) -> bool {\n storage.reject_all.at(on_behalf_of).read()\n }\n\n /**\n * Fetches the `authorized` value for `on_behalf_of` for `message_hash`.\n * \n * @param on_behalf_of The address on whose behalf the action is being consumed\n * @param message_hash The message hash to check\n * @return True if the caller is authorized to perform the action, false otherwise\n */\n #[aztec(public)]\n #[aztec(view)]\n fn is_consumable(on_behalf_of: AztecAddress, message_hash: Field) -> bool {\n storage.approved_actions.at(on_behalf_of).at(message_hash).read()\n }\n\n unconstrained fn unconstrained_is_consumable(on_behalf_of: AztecAddress, message_hash: Field) -> pub bool {\n storage.approved_actions.at(on_behalf_of).at(message_hash).read()\n }\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"86":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/unconstrained_context.nr","source":"use dep::protocol_types::address::AztecAddress;\n\nstruct UnconstrainedContext {\n block_number: u32,\n contract_address: AztecAddress,\n version: Field,\n chain_id: Field,\n}\n\nimpl UnconstrainedContext {\n fn new() -> Self {\n // We could call these oracles on the getters instead of at creation, which makes sense given that they might\n // not even be accessed. However any performance gains are minimal, and we'd rather fail early if a user\n // incorrectly attempts to create an UnconstrainedContext in an environment in which these oracles are not\n // available.\n let block_number = block_number_oracle();\n let contract_address = contract_address_oracle();\n let chain_id = chain_id_oracle();\n let version = version_oracle();\n Self { block_number, contract_address, version, chain_id }\n }\n\n fn block_number(self) -> u32 {\n self.block_number\n }\n\n fn this_address(self) -> AztecAddress {\n self.contract_address\n }\n\n fn version(self) -> Field {\n self.version\n }\n\n fn chain_id(self) -> Field {\n self.chain_id\n }\n}\n\n#[oracle(getContractAddress)]\nunconstrained fn contract_address_oracle() -> AztecAddress {}\n\n#[oracle(getBlockNumber)]\nunconstrained fn block_number_oracle() -> u32 {}\n\n#[oracle(getChainId)]\nunconstrained fn chain_id_oracle() -> Field {}\n\n#[oracle(getVersion)]\nunconstrained fn version_oracle() -> Field {}\n"},"87":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr","source":"use crate::{hash::hash_args_array, oracle::returns::unpack_returns};\nuse dep::protocol_types::traits::Deserialize;\n\nstruct PackedReturns {\n packed_returns: Field,\n}\n\nimpl PackedReturns {\n pub fn new(packed_returns: Field) -> Self {\n PackedReturns { packed_returns }\n }\n\n pub fn assert_empty(self) {\n assert_eq(self.packed_returns, 0);\n }\n\n pub fn raw(self) -> Field {\n self.packed_returns\n }\n\n pub fn unpack(self) -> [Field; N] {\n let unpacked: [Field; N] = unpack_returns(self.packed_returns);\n assert_eq(self.packed_returns, hash_args_array(unpacked));\n unpacked\n }\n\n pub fn unpack_into(self) -> T where T: Deserialize {\n let unpacked: [Field; N] = self.unpack();\n Deserialize::deserialize(unpacked)\n }\n}\n"},"90":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress, traits::Deserialize\n};\n\nuse crate::context::{\n private_context::PrivateContext, public_context::PublicContext, gas::GasOpts,\n public_context::FunctionReturns, inputs::{PrivateContextInputs, PublicContextInputs}\n};\n\nuse crate::oracle::arguments;\n\ntrait CallInterface {\n fn get_args(self) -> [Field];\n fn get_original(self) -> fn[Env](T) -> P;\n fn get_selector(self) -> FunctionSelector;\n fn get_name(self) -> str;\n fn get_contract_address(self) -> AztecAddress;\n fn get_is_static(self) -> bool;\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateCallInterface {\n pub fn call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n );\n let unpacked: T = returns.unpack_into();\n unpacked\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateVoidCallInterface {\n pub fn call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n ).assert_empty();\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty();\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticCallInterface {\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticVoidCallInterface {\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.deserialize_into()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.assert_empty()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicStaticCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n let unpacked: T = returns.deserialize_into();\n unpacked\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n\nimpl CallInterface for PublicStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicStaticVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json b/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json deleted file mode 100644 index a44a57e1f459..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/ContractClassRegisterer.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"ContractClassRegisterer","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpBattQGIXRvWhsiu9vSU/PWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq82/Cyf/r48f1wej1fhu3X23A8P++uh/PpfroN6y+1/Hl7edudHi8u1937ddhuWq2G/enl8dQ+V8Pr4bgfttU3n99Wj1GH0WYto8ioZLSR0SijSUazjJqMpIiNFDFKEaMUMUoRoxQxShGjFDFKEaMUMUoRoxQxSRGTFDFJEZMUMUkRkxQxSRGTFDFJEZMUMUsRsxQxSxGzFDFLEbMUMUsRsxQxSxGzFNGkiCZFNCmiSRFNimhSRJMimhTRpIgmRSxSxCJFLFLEIkUsUsQiRSxSxCJFLFLEIkV0KaJLEV2K6FJElyK6FNGliC5FdCmiSxFZr2kVWhWtNrQaaTXRaqZVo9VCK2oj1EaojVAboTZCbYTaCLURaiPURqiNojaK2ihqo6iNojaK2ihqo6gNAs2QaIZIM2SaIdQMqWaINUOuGYLNkGyGaDNkmyHcDOlmiDdDvhkCzpBwhogzZJwh5AwpZ4g5Q84Zgs6QdIaoM2SdIewMaWeIO0PeGQLPkHiGyDNkniH0DKlniD1D7hmCz5B8hugzZJ8h/AzpZ4g/Q/4ZAtCQgIYINGSgIQQNKWiIQUMOGoLQkISGKDRkoSEMDWloiENDHhoC0ZCIhkg0ZKIhFA2paIhFQy5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWuSiRS5a5KJFLlrkokUuWnbRk1y0yEWLXLTIRYtctMhFi1y0/ttF76efu/fD7um4f9ztfXz8OD3/u+p7P15/vf39cv/3Nw=="},{"name":"broadcast_private_function","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"artifact_metadata_hash","type":{"kind":"field"},"visibility":"private"},{"name":"unconstrained_functions_artifact_tree_root","type":{"kind":"field"},"visibility":"private"},{"name":"private_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"private_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"vk_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::private_function_broadcasted::PrivateFunction"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZrdattAFITfRdcmaM/vrl+llKIkTjEYOcROoRi/e+VUkptmwfS4CZkre62Z1Zgd6ZOEDs396vb5+7d1/7DdNcsvh2azvev2620/jA5Nspffdo9dfxru9t3Tvlm2i2bV3w+fx0XzsN6smiUVPi7e6MiVRym566xOySpqzq6jmovQBXVRSqO6aD7PTVyOXxdNctTgGTV4AQ1OLWrwhBqcUIMzanBBDa6owVHJSajkJFRyEio5GZWcjEpORiUno5KTUcnJqORkVHIyKjkZlZyMSk5BJaegklNQySmo5BRUcgoqOQWVnIJKTkElp6CSU1HJqajkVFRyKio5FZWcikpORSWnopJTUcmpqOQ0VHIaKjkNlZz2geQUSj6qhbJcGVxQg38gOYVbmYKzXRv8KnIKs81R/Nzakl7m9necu8ofpkTTUWRterWHk6l67mdLaTY5X4iVZAg2yofv+ipYZWkzaZ7WNlP2v/6Ht58vUvovkdznSOr+Zvlu6g8NPE978WJ/lJUmVw65SsRVv1e96EohF4VcHHJJyKUhl4VcoW5oqBsa6oaFumGhblioGxbqhoW6YaFuWKgbFuqGhbphoW54qBse6obXu6FldnnNxf/s8nSTqi7mdr5ylfZM9UTDmX4Y/eie1t3tZnV6Ifm08bm/m95PHob7n4+/twzaXw=="},{"name":"broadcast_unconstrained_function","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"artifact_metadata_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_artifact_tree_root","type":{"kind":"field"},"visibility":"private"},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"private"},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"},"visibility":"private"},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::unconstrained_function_broadcasted::UnconstrainedFunction"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZrdTuMwFITfxdcVis+Pj91XWa1WAcqqUpUiWpBQ1XcnhSTlx1LFKSDmqnUz407iST5fZBeuF5f3//8tu5v1Jsz/7MJqfdVul+uuH+1CTM+/bW7b7jDcbNu7bZg3s7DorvvP/SzcLFeLMKfC+9kHHZnyICUzndQxpoqas+mg5iJ0Ql2U4qAumo9zE5f931mIhho8owYvoMGpQQ0eUYMTanBGDS6owRU1OCo5CZWchEpOQiUno5KTUcnJqORkVHIyKjkZlZyMSk5GJSejkpNRySmo5BRUcgoqOQWVnIJKTkElp6CSU1DJKajkFFRyKio5FZWcikpORSWnopJTUcmpqORUVHIqKjkVlZwJlZwJlZwJlZzpB8kpFG1QC2U5M7igBv9Bcgo3MgbndG7ws8gpzGmKYsfWlvg8t33j3FX+iDTjyYqpvvmHg6n67BdL460nmexErCh9sEHef9c3wSpLm0nzuLaZsr07D2t+X6T4JZHMpkhq9mH5Lurbe8vjAlpJr8pKo0tcLnW5kstlLld2uYrHVd9JnHRFl4tcLlc3kqsbydWN5OpGcnUjubqRXN0wVzfM1Q1zdcNc3TBXN8zVDXN1w1zdsHo3tEwuq7nKp10WL2L1yjM3085VmiPVI/VP+n700N4t28vV4vBC8uHgfXc1vp/cD7ePty9Heu0T"},{"name":"register","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"artifact_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_root","type":{"kind":"field"},"visibility":"private"},{"name":"public_bytecode_commitment","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"1ZfdbuIwEIXfxdcIef5tXmW1WqUtXSGhUBW60grx7mvYOKXFUtShrdorcHI+z5n4xEn24W558/T716q/32zD4sc+rDe33W616ctoH0BOx7YPXX8cbnfd4y4s4iws+7vye5iF+9V6GRaY6TC70KEJDVI0k1ENoA01I9igZkw8oc6CMKizpOe5kfLh5yyAflfj9onGKXI1Tnqt8XSNcSbS0YrhqM5wmjt/3NwYW3MDal1TwPSywhGCJkQ5VUhIJmxlxioGtWcx66kCNiukWNcXkuJEBWWWQa18tr6l8UZ0Ekp1X/4ne32d6KsZ4qahTDWliPFy4ZobGiLEEbKpLoBLomrTpSO8sg/9epbsXSzZeAux2EWNOG9vGcS1E1I6K8KVyh6qfZtPUuCi8O0Uz6nZl6UaZ8t6tufiQHF0UeCi0EWRi2IXJS5KXZS5qOSiXNkQVzbElQ1xZUNc2RBXNsSVDXFlQ1zZEFc2xJUNdWVDXdlQVzbUlQ1tZ0PySFmLkrdTNoemQ6JYX3KIz95AAMtzr4z+dI+r7ma9PH5gHU8+9bf1e6sMd38f/p8p2n8="}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"artifact_hash","type":{"kind":"field"}},{"name":"private_functions_root","type":{"kind":"field"}},{"name":"public_bytecode_commitment","type":{"kind":"field"}}],"kind":"struct","path":"ContractClassRegisterer::register_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::register_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"artifact_metadata_hash","type":{"kind":"field"}},{"name":"unconstrained_functions_artifact_tree_root","type":{"kind":"field"}},{"name":"private_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"private_function_tree_leaf_index","type":{"kind":"field"}},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"}},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"vk_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::private_function_broadcasted::PrivateFunction"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_private_function_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_private_function_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"artifact_metadata_hash","type":{"kind":"field"}},{"name":"private_functions_artifact_tree_root","type":{"kind":"field"}},{"name":"artifact_function_tree_sibling_path","type":{"kind":"array","length":5,"type":{"kind":"field"}}},{"name":"artifact_function_tree_leaf_index","type":{"kind":"field"}},{"name":"function_data","type":{"fields":[{"name":"selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"metadata_hash","type":{"kind":"field"}},{"name":"bytecode","type":{"kind":"array","length":3000,"type":{"kind":"field"}}}],"kind":"struct","path":"events::unconstrained_function_broadcasted::UnconstrainedFunction"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_unconstrained_function_parameters"}}],"kind":"struct","path":"ContractClassRegisterer::broadcast_unconstrained_function_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"246":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr","source":"use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF;\nuse crate::traits::{ToField, FromField, Hash, Serialize, Deserialize};\n\nstruct ContractClassId {\n inner: Field\n}\n\nimpl Eq for ContractClassId {\n fn eq(self, other: ContractClassId) -> bool {\n other.inner == self.inner\n }\n}\n\nimpl ToField for ContractClassId {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for ContractClassId {\n fn from_field(value: Field) -> Self {\n Self { inner: value }\n }\n}\n\nimpl Serialize<1> for ContractClassId {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n}\n\nimpl Deserialize<1> for ContractClassId {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self { inner: fields[0] }\n }\n}\n\nimpl ContractClassId {\n pub fn compute(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field\n ) -> Self {\n let hash = dep::std::hash::pedersen_hash_with_separator(\n [\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ],\n GENERATOR_INDEX__CONTRACT_LEAF\n ); // TODO(@spalladino): Update generator index\n\n ContractClassId::from_field(hash)\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"293":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr","source":"mod events;\nmod capsule;\n\ncontract ContractClassRegisterer {\n use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector};\n use dep::aztec::protocol_types::{\n contract_class_id::ContractClassId,\n constants::{\n ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT,\n MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE\n },\n traits::Serialize\n };\n\n use crate::events::{\n class_registered::ContractClassRegistered,\n private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction},\n unconstrained_function_broadcasted::{ClassUnconstrainedFunctionBroadcasted, UnconstrainedFunction}\n };\n\n // docs:start:import_pop_capsule\n use crate::capsule::pop_capsule;\n // docs:end:import_pop_capsule\n\n #[aztec(private)]\n fn register(artifact_hash: Field, private_functions_root: Field, public_bytecode_commitment: Field) {\n // TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode\n // TODO: Validate packed_public_bytecode is legit public bytecode\n\n // docs:start:pop_capsule\n let packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] = pop_capsule();\n // docs:end:pop_capsule\n\n // Compute contract class id from preimage\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n\n // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered\n let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode };\n context.push_new_nullifier(contract_class_id.to_field(), 0);\n\n // Broadcast class info including public bytecode\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ContractClassRegistered: {}\",\n [\n contract_class_id.to_field(),\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_private_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n unconstrained_functions_artifact_tree_root: Field,\n private_function_tree_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n private_function_tree_leaf_index: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: PrivateFunction\n ) {\n let event = ClassPrivateFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n private_function_tree_sibling_path,\n private_function_tree_leaf_index,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassPrivateFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.vk_hash,\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_unconstrained_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n private_functions_artifact_tree_root: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: UnconstrainedFunction\n ) {\n let event = ClassUnconstrainedFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassUnconstrainedFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n}\n"},"294":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/capsule.nr","source":"// We should extract this to a shared lib in aztec-nr once we settle on a design for capsules\n\n// docs:start:pop_capsule\n#[oracle(popCapsule)]\nunconstrained fn pop_capsule_oracle() -> [Field; N] {}\n\n// A capsule is a \"blob\" of data that is passed to the contract through an oracle.\nunconstrained pub fn pop_capsule() -> [Field; N] {\n pop_capsule_oracle()\n}\n// docs:end:pop_capsule"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json b/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json deleted file mode 100644 index 9fa3c02fa69d..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/ContractInstanceDeployer.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"ContractInstanceDeployer","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpBattQGIXRvWhsiu9vSe/JWymlOIlTDMYOsVMoJnuv3dIF9Mz0JN3ZNzq82/Cyf/r48f1wej1fhu3X23A8P++uh/PpfroN6y/V/7y9vO1OjxeX6+79Omw3rVbD/vTyeGqfq+H1cNwP2+r989vqMVpgtFnLKDIqGW1kNMpoktEsoyYjKWIjRYxSxChFjFLEKEWMUsQoRYxSxChFjFLEKEVMUsQkRUxSxCRFTFLEJEVMUsQkRUxSxCRFzFLELEXMUsQsRcxSxCxFzFLELEXMUsQsRTQpokkRTYpoUkSTIpoU0aSIJkU0KaJJEV2K6FJElyK6FNGliC5FdCmiSxFdiuhSxCJFLFLEIkUsUsQiRSxSxCJFLFLEIkUsUkTWa1qFVkWrDa1GWk20mmnVaNVpRW2E2gi1EWoj1EaojVAboTZCbYTaCLVR1EZRG0VtFLVR1EZRG0VtFLVBoBkSzRBphkwzhJoh1QyxZsg1Q7AZks0QbYZsM4SbId0M8WbIN0PAGRLOEHGGjDOEnCHlDDFnyDlD0BmSzhB1hqwzhJ0h7QxxZ8g7Q+AZEs8QeYbMM4SeIfUMsWfIPUPwGZLPEH2G7DOEnyH9DPFnyD9DABoS0BCBhgw0hKAhBQ0xaMhBQxAaktAQhYYsNIShIQ0NcWjIQ0MgGhLREImGTDSEoiEVDbFoyEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFyy56kosWuWiRixa5aJGLFrlokYvWf7vo/fRz937YPR33j7u9j48fp+d/V33vx+uvt79f7v/+Bg=="},{"name":"deploy","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"salt","type":{"kind":"field"},"visibility":"private"},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"},"visibility":"private"},{"name":"initialization_hash","type":{"kind":"field"},"visibility":"private"},{"name":"public_keys_hash","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::public_keys_hash::PublicKeysHash"},"visibility":"private"},{"name":"universal_deploy","type":{"kind":"boolean"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"salt","type":{"kind":"field"}},{"name":"contract_class_id","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::contract_class_id::ContractClassId"}},{"name":"initialization_hash","type":{"kind":"field"}},{"name":"public_keys_hash","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"aztec::protocol_types::address::public_keys_hash::PublicKeysHash"}},{"name":"universal_deploy","type":{"kind":"boolean"}}],"kind":"struct","path":"ContractInstanceDeployer::deploy_parameters"}}],"kind":"struct","path":"ContractInstanceDeployer::deploy_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"121":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs.nr","source":"use dep::protocol_types::{address::AztecAddress, grumpkin_point::GrumpkinPoint};\n\n// = 480 + 32 * N bytes\n#[oracle(emitEncryptedNoteLog)]\nunconstrained fn emit_encrypted_note_log_oracle(_note_hash_counter: u32, _encrypted_note: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_note_log(\n note_hash_counter: u32,\n encrypted_note: [u8; M],\n counter: u32\n) {\n emit_encrypted_note_log_oracle(note_hash_counter, encrypted_note, counter)\n}\n\n#[oracle(emitEncryptedEventLog)]\nunconstrained fn emit_encrypted_event_log_oracle(_contract_address: AztecAddress, _randomness: Field, _encrypted_event: [u8; M], _counter: u32) {}\n\nunconstrained pub fn emit_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n encrypted_event: [u8; M],\n counter: u32\n) {\n emit_encrypted_event_log_oracle(contract_address, randomness, encrypted_event, counter)\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedNoteLog)]\nunconstrained fn compute_encrypted_note_log_oracle(\n _contract_address: AztecAddress,\n _storage_slot: Field,\n _note_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_note_log(\n contract_address: AztecAddress,\n storage_slot: Field,\n note_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_note_log_oracle(\n contract_address,\n storage_slot,\n note_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n// = 480 + 32 * N bytes\n#[oracle(computeEncryptedEventLog)]\nunconstrained fn compute_encrypted_event_log_oracle(\n _contract_address: AztecAddress,\n _randomness: Field,\n _event_type_id: Field,\n _ovsk_app: Field,\n _ovpk_m: GrumpkinPoint,\n _ivpk_m: GrumpkinPoint,\n _preimage: [Field; N]\n) -> [u8; M] {}\n\nunconstrained pub fn compute_encrypted_event_log(\n contract_address: AztecAddress,\n randomness: Field,\n event_type_id: Field,\n ovsk_app: Field,\n ovpk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n preimage: [Field; N]\n) -> [u8; M] {\n compute_encrypted_event_log_oracle(\n contract_address,\n randomness,\n event_type_id,\n ovsk_app,\n ovpk_m,\n ivpk_m,\n preimage\n )\n}\n\n#[oracle(emitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_oracle_private(_contract_address: AztecAddress, _event_selector: Field, _message: T, _counter: u32) -> Field {}\n\nunconstrained pub fn emit_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: T,\n counter: u32\n) -> Field {\n emit_unencrypted_log_oracle_private(contract_address, event_selector, message, counter)\n}\n\n#[oracle(emitContractClassUnencryptedLog)]\nunconstrained fn emit_contract_class_unencrypted_log_private(contract_address: AztecAddress, event_selector: Field, message: [Field; N], counter: u32) -> Field {}\n\nunconstrained pub fn emit_contract_class_unencrypted_log_private_internal(\n contract_address: AztecAddress,\n event_selector: Field,\n message: [Field; N],\n counter: u32\n) -> Field {\n emit_contract_class_unencrypted_log_private(contract_address, event_selector, message, counter)\n}\n"},"127":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/logs_traits.nr","source":"use dep::protocol_types::address::AztecAddress;\n\n// TODO: this is awful but since we can't have a fn that maps [Field; N] -> [u8; 480 + N * 32]\n// (where N is the note pre-image size and 480 + N * 32 is the encryption output size)\n// The fns for LensForEncryptedLog are never used, it's just to tell the compiler what the lens are\n\n// The to_bytes fn for ToBytesForUnencryptedLog is used to allow us to hash some generic T\n\n// I could have omitted N from the trait, but wanted to keep it strictly for field arrs\n// TODO(1139): Once we enc inside the circuit, we will no longer need the oracle to return\n// anything, so we can remove this trait\ntrait LensForEncryptedLog {\n // N = note preimage input in fields\n // M = encryption output len in bytes (= 480 + N * 32)\n fn output_fields(self: [Field; N]) -> [Field; N];\n fn output_bytes(self: [Field; N]) -> [u8; M];\n}\n\nimpl LensForEncryptedLog<1, 512> for [Field; 1] {\n fn output_fields(self) -> [Field; 1] {[self[0]; 1]}\n fn output_bytes(self) -> [u8; 512] {[self[0] as u8; 512]}\n}\nimpl LensForEncryptedLog<2, 544> for [Field; 2] {\n fn output_fields(self) -> [Field; 2] {[self[0]; 2]}\n fn output_bytes(self) -> [u8; 544] {[self[0] as u8; 544]}\n}\nimpl LensForEncryptedLog<3, 576> for [Field; 3] {\n fn output_fields(self) -> [Field; 3] {[self[0]; 3]}\n fn output_bytes(self) -> [u8; 576] {[self[0] as u8; 576]}\n}\nimpl LensForEncryptedLog<4, 608> for [Field; 4] {\n fn output_fields(self) -> [Field; 4] {[self[0]; 4]}\n fn output_bytes(self) -> [u8; 608] {[self[0] as u8; 608]}\n}\nimpl LensForEncryptedLog<5, 640> for [Field; 5] {\n fn output_fields(self) -> [Field; 5] {[self[0]; 5]}\n fn output_bytes(self) -> [u8; 640] {[self[0] as u8; 640]}\n}\nimpl LensForEncryptedLog<6, 672> for [Field; 6] {\n fn output_fields(self) -> [Field; 6] {[self[0]; 6]}\n fn output_bytes(self) -> [u8; 672] {[self[0] as u8; 672]}\n}\n\ntrait LensForEncryptedEvent {\n // N = event preimage input in bytes\n // M = encryption output len in bytes (= 480 + M)\n fn output(self: [u8; N]) -> [u8; M];\n}\n\nimpl LensForEncryptedEvent<96, 512> for [u8; 96] {\n fn output(self) -> [u8; 512] {[self[0] as u8; 512]}\n}\nimpl LensForEncryptedEvent<128, 544> for [u8; 128] {\n fn output(self) -> [u8; 544] {[self[0] as u8; 544]}\n}\nimpl LensForEncryptedEvent<160, 576> for [u8; 160] {\n fn output(self) -> [u8; 576] {[self[0] as u8; 576]}\n}\nimpl LensForEncryptedEvent<192, 608> for [u8; 192] {\n fn output(self) -> [u8; 608] {[self[0] as u8; 608]}\n}\nimpl LensForEncryptedEvent<224, 640> for [u8; 224] {\n fn output(self) -> [u8; 640] {[self[0] as u8; 640]}\n}\nimpl LensForEncryptedEvent<256, 672> for [u8; 256] {\n fn output(self) -> [u8; 672] {[self[0] as u8; 672]}\n}\n\n// This trait defines the length of the inputs in bytes to\n// the unencrypted log hash fn, where the log can be any type T\n// as long as the ACVM can convert to fields.\ntrait ToBytesForUnencryptedLog {\n // N = preimage input in bytes (32 * num fields or chars)\n // M = full log input in bytes ( = N + 40 = N + 32 for addr, + 4 for selector, + 4 for len)\n fn to_be_bytes_arr(self) -> [u8; N];\n fn output_bytes(self) -> [u8; M];\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for Field {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n self.to_be_bytes(32).as_array()\n }\n fn output_bytes(self) -> [u8; 72] {[self as u8; 72]}\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for AztecAddress {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n self.to_field().to_be_bytes(32).as_array()\n }\n fn output_bytes(self) -> [u8; 72] {[self.to_field() as u8; 72]}\n}\n\nfn arr_to_be_bytes_arr(fields: [Field; L]) -> [u8; N] {\n let mut bytes: [u8] = &[];\n for i in 0..L {\n // Note that bytes.append() results in bound error\n let to_add = fields[i].to_be_bytes(32);\n for j in 0..32 {\n bytes = bytes.push_back(to_add[j]);\n }\n }\n bytes.as_array()\n}\n\n// each character of a string is converted into a byte\n// then an ACVM field via the oracle => we recreate here\nfn str_to_be_bytes_arr(string: str) -> [u8; N] {\n let chars_bytes = string.as_bytes();\n let mut bytes: [u8] = &[];\n for i in 0..L {\n let to_add = (chars_bytes[i] as Field).to_be_bytes(32);\n for j in 0..32 {\n bytes = bytes.push_back(to_add[j]);\n }\n }\n bytes.as_array()\n}\n\nimpl ToBytesForUnencryptedLog<32, 72> for [Field; 1] {\n fn to_be_bytes_arr(self) -> [u8; 32] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 72] {\n [self[0] as u8; 72]\n }\n}\n\nimpl ToBytesForUnencryptedLog<64, 104> for [Field; 2] {\n fn to_be_bytes_arr(self) -> [u8; 64] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 104] {\n [self[0] as u8; 104]\n }\n}\n\nimpl ToBytesForUnencryptedLog<96, 136> for [Field; 3] {\n fn to_be_bytes_arr(self) -> [u8; 96] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 136] {\n [self[0] as u8; 136]\n }\n}\n\nimpl ToBytesForUnencryptedLog<128, 168> for [Field; 4] {\n fn to_be_bytes_arr(self) -> [u8; 128] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 168] {\n [self[0] as u8; 168]\n }\n}\n\nimpl ToBytesForUnencryptedLog<160, 200> for [Field; 5] {\n fn to_be_bytes_arr(self) -> [u8; 160] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 200] {\n [self[0] as u8; 200]\n }\n}\n\nimpl ToBytesForUnencryptedLog<192, 232> for [Field; 6] {\n fn to_be_bytes_arr(self) -> [u8; 192] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 232] {\n [self[0] as u8; 232]\n }\n}\n\nimpl ToBytesForUnencryptedLog<224, 264> for [Field; 7] {\n fn to_be_bytes_arr(self) -> [u8; 224] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 264] {\n [self[0] as u8; 264]\n }\n}\n\nimpl ToBytesForUnencryptedLog<256, 296> for [Field; 8] {\n fn to_be_bytes_arr(self) -> [u8; 256] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 296] {\n [self[0] as u8; 296]\n }\n}\n\nimpl ToBytesForUnencryptedLog<288, 328> for [Field; 9] {\n fn to_be_bytes_arr(self) -> [u8; 288] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 328] {\n [self[0] as u8; 328]\n }\n}\n\nimpl ToBytesForUnencryptedLog<320, 360> for [Field; 10] {\n fn to_be_bytes_arr(self) -> [u8; 320] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 360] {\n [self[0] as u8; 360]\n }\n}\n\nimpl ToBytesForUnencryptedLog<352, 392> for [Field; 11] {\n fn to_be_bytes_arr(self) -> [u8; 352] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 392] {\n [self[0] as u8; 392]\n }\n}\n\nimpl ToBytesForUnencryptedLog<384, 424> for [Field; 12] {\n fn to_be_bytes_arr(self) -> [u8; 384] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 424] {\n [self[0] as u8; 424]\n }\n}\n\nimpl ToBytesForUnencryptedLog<416, 456> for [Field; 13] {\n fn to_be_bytes_arr(self) -> [u8; 416] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 456] {\n [self[0] as u8; 456]\n }\n}\n\nimpl ToBytesForUnencryptedLog<448, 488> for [Field; 14] {\n fn to_be_bytes_arr(self) -> [u8; 448] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 488] {\n [self[0] as u8; 488]\n }\n}\n\nimpl ToBytesForUnencryptedLog<480, 520> for [Field; 15] {\n fn to_be_bytes_arr(self) -> [u8; 480] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 520] {\n [self[0] as u8; 520]\n }\n}\n\nimpl ToBytesForUnencryptedLog<512, 552> for [Field; 16] {\n fn to_be_bytes_arr(self) -> [u8; 512] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 552] {\n [self[0] as u8; 552]\n }\n}\n\nimpl ToBytesForUnencryptedLog<544, 584> for [Field; 17] {\n fn to_be_bytes_arr(self) -> [u8; 544] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 584] {\n [self[0] as u8; 584]\n }\n}\n\nimpl ToBytesForUnencryptedLog<576, 616> for [Field; 18] {\n fn to_be_bytes_arr(self) -> [u8; 576] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 616] {\n [self[0] as u8; 616]\n }\n}\n\nimpl ToBytesForUnencryptedLog<608, 648> for [Field; 19] {\n fn to_be_bytes_arr(self) -> [u8; 608] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 648] {\n [self[0] as u8; 648]\n }\n}\n\nimpl ToBytesForUnencryptedLog<640, 680> for [Field; 20] {\n fn to_be_bytes_arr(self) -> [u8; 640] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 680] {\n [self[0] as u8; 680]\n }\n}\n\nimpl ToBytesForUnencryptedLog<672, 712> for [Field; 21] {\n fn to_be_bytes_arr(self) -> [u8; 672] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 712] {\n [self[0] as u8; 712]\n }\n}\n\nimpl ToBytesForUnencryptedLog<704, 744> for [Field; 22] {\n fn to_be_bytes_arr(self) -> [u8; 704] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 744] {\n [self[0] as u8; 744]\n }\n}\n\nimpl ToBytesForUnencryptedLog<736, 776> for [Field; 23] {\n fn to_be_bytes_arr(self) -> [u8; 736] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 776] {\n [self[0] as u8; 776]\n }\n}\n\nimpl ToBytesForUnencryptedLog<768, 808> for [Field; 24] {\n fn to_be_bytes_arr(self) -> [u8; 768] {\n arr_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; 808] {\n [self[0] as u8; 808]\n }\n}\n\nimpl ToBytesForUnencryptedLog for str where [Field; L]: ToBytesForUnencryptedLog {\n fn to_be_bytes_arr(self) -> [u8; N] {\n str_to_be_bytes_arr(self)\n }\n fn output_bytes(self) -> [u8; M] {\n [0; M]\n }\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"288":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr","source":"mod events;\n\ncontract ContractInstanceDeployer {\n use dep::aztec::protocol_types::{\n address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress},\n contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE,\n traits::Serialize\n };\n\n use crate::events::{instance_deployed::ContractInstanceDeployed};\n\n #[aztec(private)]\n fn deploy(\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys_hash: PublicKeysHash,\n universal_deploy: bool\n ) {\n // TODO(@spalladino): assert nullifier_exists silo(contract_class_id, ContractClassRegisterer)\n\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.msg_sender()\n };\n\n let partial_address = PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n let address = AztecAddress::compute(public_keys_hash, partial_address);\n\n // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed\n context.push_new_nullifier(address.to_field(), 0);\n\n // Broadcast the event\n let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 };\n let event_payload = event.serialize();\n dep::aztec::oracle::debug_log::debug_log_format(\"ContractInstanceDeployed: {}\", event_payload);\n context.emit_unencrypted_log(event_payload);\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/GasToken.json b/yarn-project/protocol-contracts/src/artifacts/GasToken.json deleted file mode 100644 index df953de52daa..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/GasToken.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"GasToken","functions":[{"name":"_increase_public_balance","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(internal)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"deploy","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"artifact_hash","type":{"kind":"field"},"visibility":"private"},{"name":"private_functions_root","type":{"kind":"field"},"visibility":"private"},{"name":"public_bytecode_commitment","type":{"kind":"field"},"visibility":"private"},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+1dB3gcxfXfk09ykSU3MM3gk3v33anbxg0wHUzvRZJlejOdAKGGXgIhgSQQSgolQEhCSaEESAESSP+nkJ5AEhIgkEBozn9Ges/66Xl277S3c7qBue9739uZm9n3e29nZ97UTQW9v5qaIPjzkN7rlCJ9WaUoA+EhdM3htAhXi/RDRbhOhEeJ8BgRHifCGylaCuGJ4v+MCDeI8CQRnkZh/KWILyXemG1paupuzXfnGnMd2Xx7Z1tztqm5s6Ut15ZrbmtelW9rbOxua2prbe9sb82255oau3Orm9sbV2d7f/9O9d0rW+JPYxsO2KYrWqtoBvGZxGcR17I9f//yOYr+k+ots1gu/uPt84EvF2+kgn6/KuJLiWdL++WmBcnVkW+mksOl1dZ1u75nJuhtk/RPmKNfXJKyE7pXNgUYWYf/qsBbit5W9I6id1MGvZJUZjgZk4XrwvUO8beIb6boPaiEuKC9Tf+/B+nWpqIfQKkF6X/JFaTVNnFqI8XE2SgjNDbtGKXpfu+SvdcS/x9xLXMtpEupcJWiIYrSVX3x/KtKWOcEX45cqip5p4rLeZhTNVpRdZVdG72dYEVYnaCNqukdEOr3+yUkK2+SU8kVdcJ2aOpoy7V2tfU1APpXU2Wxoq8mg9cE6/9cMnwSOPMdqxqbm9ubbNqgpsqODZLGmaBXZhVnOqjsMsU/9OiG0/VQVRaGKRquaISiWkUjFdUpqlc0yvaLPyww1+pJP6RhVRX9kHJ8gbYYTYExVZbd7CEk7LdCxhCLDyGmq5InVyU3uio5t2eMpcKRdJ83SZ3HGu7Vme1a1ZzrbFnVmuvuaG7r6mpvzOXyHS0dLZ35ttXdnc25tuY2dc+ujnybEpfv6Mp1ZztauvWLrGuUcvRxx1YlXyPq3zibL5ktQyDopO67QYKFzJbeG1Ql/oyMWJOoWDTWpCoCvm+Sz2jDhF8o3WjoezYEvQNH5Wrhax1s4cdTYKNytPDjqYXnsBaaETKTbvFrE2zxxydY6DdypMVPUueNHW3xN7bU4m/iWouvDbGJhRZ/0wpv8bXemzrS4m9EWJNu8ZN8RptZaPE3G4QWf2Rlt/j8y6MtJlBg83K0+FrYe0JG0i38yAQKZvfq3t+EBAv55o608EnqvAXcK9fWmM+3Nup0bauyuaZVXfm2fH5VZ1O2K9vRle9ub8q1r27KNzV2rerqVPfsyK3Oru7oal/d1ournC38FpZa+ImutfDaEBMttPCZCm/htd4ZR1r4zQlr0vdtsNAqN5AnUs5Wuc7BVnkSBSaXo1WeRK0yh01Ck26l6xJspSclWJlMdqSVTlLnKY620lMstdJTXWultSGmWmilp1V4K631nuZIKz2ZsCZ93+kWWunpg9BK11d2K20cLZ9BgZnlaKW1MBwt10IzQmbSrXR96RXAutHyGQlWJjMdaaWT1HlWlZuj5bMstdKzXWultSFmW2il51R4K631nuNIKz2TsCZVEfB9k3xGcy20+PqeDUH/X9KVYSrB5zTUUgOQdNkfk8Bz72rOd3V0tKyKejaVtOHIlca5JsF3cpQj5bFckxCl2jPBJcy5yY7onOR+oBEfQJ2HO1LvYF1bqv3mVSXbPmtfYF6V/UMA5ieAm7emyH2W+t64+XeEllHVt81geVWfTmuBbyTypSn+TQrXVPnN1J577rnnnnvuueeee+6555577rnnLvPZinIwTsSLKXRY/5+l8Z8c8bGK9KLN6qDvcFBOv3Fg/i0lni3p19xo574tzXbu29rk1n1b2i3dt9vSfVvt3DeftXPf1k479220hXeVW/ZtyVmyg6V6x5odWizdt9mt+1p7j10rv7bqdVvtZs/Zfylx71SiMuwcQZeyY5C+Q1j5fmGHU3qn9oPB9cnOjeC0L6Vy0egnaz/w5aKJOmd6Ip87Z6bfUuLZ0n6NugwOEfdOJSsjNz2wV1knhXGGAxhnJogxBc+7ucryqnT+Jb0qqSnB1ZDNCa7E0i+wJtNhvNK+jdn8qo72zhaVraO1paU919iU68w3Z5tbmrs6mrtaWlvzjfmW3OqO9vaO1Qp18+rV3c251raurs58rinXGnXvbMxfe1tnV4uyDd4z6cLc5Mjq03mO4HTlAN0t4Z4tVCG0Em8j3k58AfGFxBcR35L4YuJLiC8lvow4r5rbivjWVNEtJfnbqPAKRdsq2k7R9op2ULSjop0U7axoF0W7KlqpaDdFuyvaQ9GeivZStLeifRTtq2g/RfsrOkDRgYoOUnSwokMUHaqoQ1Gnoi5FqxR1K1qt6DBFhys6QtGRio5SdLSiYxQdq+g4RccrOkHRGkUnKjpJ0cmKTlF0qqLTFJ2u6AxFH1J0pqKzFJ2t6MOKzlF0rqLzFJ2v6AJhiwtV+COKLlJ0saJLFF2q6DJFlyu6QtGViq5SdLWijyq6RtG1ij6m6DpFH1f0CUXXK7pB0ScVfUrRpxXdqOgmRZ9RdLOiWxTdqug2RZ9V9DlFn1f0BUW3K7pD0Z2K7lL0RUV3K7pH0b2KvqToPkVfVvQVRV9VdL+iBxQ9qOghRV9T9HVF31D0TUUPK3pE0aOKHlP0LUWPK3pC0ZPCFt9W4e8o+q6i7yl6StHTip5R9H1FP1D0rKLnFP1Q0Y8U/VjRTxT9VNHPFP1c0f8p+oWiXyr6laJfK3pe0W8U/VbR7xT9XtEfFP1R0Z8U/VnRXxS9oOhFRX9V9DdFf1f0kqJ/KPqnopcVvaLoVUX/UvSaotcV/VvRfxS9oehNRf9V9JaitxW9o+hdRe8pWqvof4q095dSVKVoiKL0kF5bZMgW1Spco2ioomGKhisaoahW0UhFdYrqFY1SNFrRGEVjFY1TtIGiDRWNV7SRoo0VbaJoU0WbKZqgaHNFWyiaqCijqEHRJEWTFU0hLFwhTVXhaYqmK5qhaKaiWYpmK5qjaK6ieYrmK8oqyinKK2pU1KSoWVGLolZFbYraFS1QtFDRIkVbKlqsaImipYqWKVquaCtFWyvaRtEKRdsq2k7R9op2ULSjop0U7axoF0W7KlqpaDdFuyvaQ9GeQ/rPsuylwnsr2kfRvor2U7S/ogMUHajoIEUHKzpE0aGKOhR1KupStEpRt6LVig5TdLiiIxQdqegoRUeTrNEk6xgVPlbRcYqOV3SCojWKTlR0kqKTFZ2i6FRFpyk6XdEZij6k6EzqHZxF92Sf5mwV/rCicxSdq+g8RedT2guIXzik/3v1ERW+SNHFii5RdKmiyxRdrugKRVcqukrR1Yo+qugaRdcq+pii6xR9XNEnFF2v6AZFn1T0KUWfVnSjopsUfUbRzYpuUXSrotsUfVbR5xR9XtEXFN2u6A5Fdyq6S9EXFd2t6B5F9yr6kqL7FH1Z0VcUfVXR/YoeUPSgoocUfU3R1xV9Q9E3FT2s6BFFjyp6TNG3FD2u6AlFTyr6tngm31Hh7yr6nqKnFD2t6BlF31f0A0XPKnpO0Q8V/UjRjxX9RNFPFf2M7jWS7vVzFf4/Rb9Q9EtFv1L0a0XPK/qNot8q+p2i3yv6Az2bPxL/E3H+bOBfiL9A/EXifyX+N+J/J/4S8X8Q/yfxl4m/QvxV4v8i/hrx14n/m/h/iL9B/E3i/yX+FvG3ib9D/F3i7xFfS/x/xPnTOKl0Gfa9t1X1/6aidmAyEN5S/L9Y/L9MhJeL9FuJ8NYi/QoR3k6EdxDhnUR4FxFeKcK7i/CeIry3CO8rwvuL8IEifLAIHyrCnSK8SoRXi/DhInykCB8twseK8PEivEaETxLhU0T4NBE+Q4TPFOGzRfgcET5PhC8Q4Y+I8MUifKkIXy7CV4rw1SJ8jQh/TIQ/LsLXi/AnRfjTInyTCN8swreK8GdF+PMifLsI3ynCXxThe0T4SyL8ZRH+qgg/IMIPifDXRfibIvyICD8mwo+L8JMirB02DA8T4REiPFKE60V4tAiPFeENRHi8CG8swpuK8AQR3kKEMyI8SYSniPA0EZ4pwnNEeL4I50W4WYTbRHihCC8W4WUivLUIbyvCO4jwziK8UoT3EGHtUKYgvJ/4f38RPlikP0T8f6gIrxLpu8X/q0X4SJH+KPH/0SJ8jgifL8IXiPCFInyRCF8iwpeJ8BUifJUIf1SErxXh60T4EyJ8gwh/SoRvFOHPiPAtInybCH9OhL8gwneI8F0ifLcI3yvC94nwV0T4fhF+UIS/JsLfEOGHRfhREf6WCD8hwt8W4e+K8DMi/JwI/0SE/0+EfyXCvxHh34vwn0T4byL8kgj/U4RfEWHtJC+F8Dvi/3dF+D0RXkth/FURX0q8krb1Lq6yM5hZyTpfMMSNreAXDknOflXp5Pte+p6ZoP8vlfBzb6myM4GTSvhZtVaVrnNza1Nje0f/ZaBJl6kkJ/KWWKo7kn42ixyp45I81mRLR57Ngn44G1s6mjq7unP51nx7V7ajOdvd3tjSku/MN3Xm21s6c7lsVz6vT57tbl3dtKq7sbuxQ1cBjeq6s7vD5rNJJahze5meTak6D0mXp+4t+b1JoG3jiXiNTa8U+z6B1DbQK4bSxPV441rSYS38v7Cq/wojPh5kHsU3EV9KfBnx5cS3Ir418W2IryC+LfHtiG9PfAfiOxLfifjOxHchvivxlcR3I7478T2I70l8L+J7E9+H+L7E9yO+P/EDiB9I/CDiBxM/hPihxDuIdxLvIr6KeDfx1cQPI3448SOIH0n8KOJHEz+G+LHEjyN+PPETiK8hfiLxk4ifTPwU4qcSP4346cTPIP4h4mcSP4v42cQ/TPwc4ucSP4/4+cQvIH4h8Y8Qv4j4xcQvIX4p8cuIX078CuJXEr+K+NXEP0r8GuLXEv8Y8euIf5z4J4hfT/wG4p8k/ininyZ+I/GbiH+G+M3EbyF+K/HbiH+W+OeIf574F4jfTvwO4ncSv4v4F4nfTfwe4vcS/xLx+4h/mfhXiH+V+P3EHyD+IPGHiH+N+NeJf4P4N4k/TPwR4o8Sf4z4t4g/TvwJ4k8S/zbx7xD/LvHvEX+K+NPEnyH+feI/IP4s8eeI/5D4j4j/mPhPiP+U+M+I/5z4/xH/BfFfEv8V8V8Tf574b4j/lvjviP+e+B+I/5H4n4j/mfhfiL9A/EXifyX+N+J/J/4S8X8Q/yfxl4m/QvxV4v8i/hrx14n/m/h/iL9B/E3i/yX+FvG3ib9D/F3i7xFfS/x/xHXHSfMU8SriQ4iniVcTryE+lPgw4sOJjyBeS3wk8Tri9cRHER9NfAzxscTHEd+A+IbExxPfiPjGxDchvinxzYhPIL458S2ITySeId5AfBLxycSnEJ9KfBrx6cRnEJ9JfBbx2cTnEJ9LfB7x+cSzxHPE88QbiTcRbybeQryVeBvxduILiC8kvoj4lsQXE19CfCnxZcSXE9+K+NbEtyG+gvi2xLcjvj3xHYjvSHwn4jsT34X4rsRXEt+N+O7E9yC+J/G9iO9NfB/i+xLfj/j+xA8gfiDxg4gfTPwQ4ocS7yDeSbyL+Cri3cRXEz+M+OHEjyB+JPGjiB9N/BjixxI/jvjxxE8gvob4icRPIn4y8VOIn0r8NOKnEz+D+IeIn0n8LOJnE/8w8XOIn0v8POLnc3nl9p/CHyF+EfGLiV9C/FLilxG/nPgVxK8kfhXxq4l/lPg1xK8l/jHi1xH/OPFPEL+e+A3EP0n8U8Q/TfxG4jcR/wzxm4nfQvxW4rcR/yzxzxH/PPEvEL+d+B3E7yR+F/EvEr+b+D3E7yX+JeL3Ef8y8a8Q/yrx+4k/QPxB4g8R/xrxrxP/BvFvEn+Y+CPEHyX+GPFvEX+c+BPEnyT+beLfIf5d4t8j/hTxp4k/Q/z7xH9A/FnizxH/IfEfEf8x8Z8Q/ynxnxH/OfH/I/4L4r8k/ivivyb+PPHfEP8t8d8R/z3xPxD/I/E/Ef8z8b8Qf4H4i8T/SvxvxP9O/CXi/yD+T+IvE3+F+KvE/0X8NeKvE/838f8Qf4P4m8T/S/wt4m8Tf4f4u8TfI76W+P+IB9RfTBHXxwRU04IZ/iU9xqL7nAndy+p4Q03CY9S44+u/1C9/m/g7xN8lXkPPw++Qen9yveNrKC1Iw3Ix1D/3D3y5GJbu20RUFYT/lhLPlvZr1mWwWtw7layMnK7vErqXtV12bzuA8R0HML6bstO+J4kxBfccbnNhMN6zKuF7D0sn5+wMT87ZGdAuSDWZ1pjryjW2trQpWJ25zo5mFVzd1pJvbe5sau1ubFu1uqMr19LduKp1db4p39XZ3Nq2qj3f0dSdX9Xe2BR172zMX2t356rGlnarE43D0uVxgrOl/XJVjuB0cRfkCOpo1RIfSbyOeD3xUcRHEx9DfCzxccQ3IL4h8fHENyK+MVV0S0n+Jiq8qaLNFE1QtLmiLRRN1AtpFDUomqRosqIpiqYqmqZouqIZimYqmqVotqI5iuYqmqdoviK9ekA/lLyiRkVNipoVtShqVdSmqF3RAkULFS1StKWixYqW6DKnaJmi5Yq2UrS1om0UrVC0raLtFG2vaAdFOyraSdHOinZRtKuilYp2U7S7oj0U7aloL0V7K9pH0b7CFvup8P6KDlB0oKKDFB2s6BBFhyrqUNSpqEvRKkXdilYrOkzR4YqOUHSkoqMUHa3oGEXHKjpO0fGKTlC0RtGJik5SdLKiUxSdqug0RacrOkPRhxSdqegsRWcr+rCicxSdq+g8RecrukDRhYo+ougiRRcrukTRpYouU3S5oisUXanoKkVXK/qoomsUXavoY4quU/RxRZ9QdL2wxQ0q/ElFn1L0aUU3KrpJ0WcU3azoFkW3KrpN0WcVfU7R5xV9QdHtiu5QdKeiuxR9UdHdiu5RdK+iLym6T9GXFX1F0VcV3a/oAUUPKnpI0dcUfV3RNxR9U9HDih5R9KiixxR9S9Hjip5Q9KSibyv6jqLvKvqeoqcUPa3oGUXfV/QDRc8qek7RDxX9SNGPFf1E0U8V/UzRzxX9n6JfkC0yZItfqvCvFP1a0fOKfqPot4p+p+j3iv6g6I+K/qToz4r+ougFRS8q+quivyn6u6KXFP1D0T8VvazoFUWvKvqXotcUva7o34r+o+gNRW8q+i9h4QrpLRV+W9E7it5V9J6itYr+p0g3uClFVYqGKEorqlZUo2ioomGKhisaoahW0UhFdYrqFY1SNFrRGEVjFY1TtIGiDRWNV7SRoo0VbaJoU0WbKZqgaHNFWyiaqCijqEHRJEWTFU1RNFXRNEXTFc2o7tWFd0HOVOFZimYrmqNorqJ5iuYr0g6E/jZzXlGjoiZFzYpaFLUqalPUrmiBooWKFinaUtFiRUsULSVZvONumQovV7SVoq0VbaNohaJtFW2naHtFOyjaUdFOinZWtIuiXRWtpJ7RbnRP9ml2V+E9FO2paC9Feyvah9LuS3y/6v7v1f4qfICiAxUdpOhgRYcoOlRRh6JORV2KVinSX71cregwRYcrOkLRkYqOUnS0omMUHavoOEXHKzpB0RpFJyo6SdHJik5RdKqi0xSdrugMRR9SdKaisxSdrejDis5RdK6i8xSdr+gCRRcq+oiiixRdrOgSRZcqukzR5YquUHSloqsUXa3oo4quUXStoo8puk7RxxV9QtH1im4Qz+STKvwpRZ9WdKOimxR9RtHNim5RdKui2xR9VtHnFH1e0RcU3a7oDroX74K8U4XvUvRFRXcrukfRvYq+pOg+RV9W9BVFX1V0Pz2bB4g/SPwh4l8j/nXi3yD+TeIPE3+E+KPEHyP+LeKPE3+C+JPEv038O8S/S/x7xJ8i/jTxZ4h/n/gPiD9L/DniPyT+I+I/Jv4T4j8l/rNqi50dfWM1sNzjyOhrDmsHJgPhMeL/seL/DUV4vEi/kQhvLNJvKsITRHgLEc6I8CQRniLC00R4hgjPEuE5IjxPhLMinBfhJhFuEeE2EV4gwotEeLEILxXh5SK8tQivEOHtRHgHEd5JhHcR4ZUivLsI7ynCe4vwviK8vwgfKMIHi/ChItwpwqtEeLUIHy7CR4rw0SJ8rAgfL8JrRPgkET5FhE8T4TNE+EwRPluEzxHh80T4AhH+iAhfLMKXivDlInylCF8twteI8MdE+OMifL0I/0qEnxfh34rw70X4jyL8ZxF+QYT/KsJ/F+F/iPDLIvyqCL8mwv8W4TdE+L8i/LYIvyfC2lnE8BARrhHh4SI8UoRHifBYEd5QhDcW4c1EeAsRbhDhKSI8XYTnVPdvH+aK/+eJcF6kbxT/N4lwm0jfLv5fIMKLRfol4v+lIrynCO8jwvuK8H4ifIAIHyTCh4hwhwh3iXC3CB8mwkeI8FEifIwIHyfCJ4jwiSJ8sgifKsKni/CHRPgsEf6wCJ8rwueL8IUifJEIXyLCl4nwFSJ8lQh/VISvFeHrRPgTInyDCH9KhD8jwreJ8BdE+C4RvkeE7xPhr4rwgyL8sAg/KsLfEuEnRFg7yUsh/Jz4/4ci/CMR/jGF8ScH4ytpR9vYtJ3BzErWed9qN3ZB7lednP1+Xp183+vnhrKeSvi5j0jbmcBJJfysatOl69yaU5jbW52ZyBtnqe5I+tmMdqSOSyeo8xhHnk094mxuyjXmm1e3dHR0tLe0tq5etbq7rbFTGSnb2dG4qrt7dXNTY1djrr25O9farSzd1tbR0pbNNXXmVuVbulbZfDapBHWuK9OzKVXn/6suT91bKs5fJNC28US8xoa7ILUN9GqpXxDX441rSYe18P+odP/VVWn6v4rihxHfgPiGxMcT34j4xsQ3Ib4p8c2ITyC+OfEtiE8kniHeQHwS8cnEpxCfSnwa8enEZxCfSXwW8dnE5xCfS3we8fnEs8RzxPPEG4k3EW8m3kK8lXgb8XbiC4gvJL6I+JbEFxNfQnwp8WXElxPfivjWxLchvoL4tsS3I7498R2I70h8J+I7E9+F+K7EVxLfjfjuxPcgvifxvYjvTXwf4vsS34/4/sQPIH4g8YOIH0z8EOKHEu8g3km8i/gq4t3EVxM/jPjhxI8gfiTxo4gfTfwY4scSP4748cRPIL6G+InETyJ+MvFTiJ9K/DTipxM/g/iHiJ9J/CziZxP/MPFziJ9L/Dzi5xO/gPiFxD9C/CLiFxO/hPilxC8jfjnxK4hfSfwq4lcT/yjxa4hfS/xjxK8j/nHinyB+PfEbiH+S+KeIf5r4jcRvIv4Z4jcTv4X4rcRvI/5Z4p8j/nniXyB+O/E7iN9J/C7iXyR+N/F7iN9L/EvE7yP+ZeJfIf5V4vcTf4D4g8QfIv414l8n/g3i3yT+MPFHiD9K/DHi3yL+OPEniD9J/NvEv0P8u8S/R/wp4k8Tf4b494n/gPizxJ8j/kPiPyL+Y+I/If5T4j8j/nPi/0f8F8R/SfxXxH9N/HnivyH+W+K/I/574n8g/kfifyL+Z+J/If4C8ReJ/5X434j/nfhLxP9B/J/EXyb+CvFXif+L+GvEXyf+b+L/If4G8TeJ/5f4W8TfJv4O8XeJv0d8LfH/EQ+oPU4RryI+hHiaeDXxGuJDiQ8jPpz4COK13P4TryNez+0/8dHExxAfS3wc8Q2Ib0h8PPGNiG9MfBPimxLfjPgE4psT34L4ROIZ4g3EJxGfTHwK8anEpxGfTnwG8ZnEZxGfTXwO8bnE5xGfTzxLPEc8T7yReBPxZuItxFuJtxFvJ76A+ELii4hvSXwx8SXElxJfRnw58a2Ib018G+IriG9LfDvi2xPfgfiOxHcivjPxXYjvSnwl8d2I7058D+J7Et+L+N7E9+HySuV4PwrvT/wA4gcSP4j4wcQPIX4o8Q7incS7iK8i3k18NfHDiB9O/AjiRxI/ivjRxI8hfizx44gfT/wE4muIn0j8JOInEz+F+KnETyN+OvEziH+I+JnEzyJ+NvEPEz+H+LnEzyN+PvELiF9I/CPELyJ+MfFLiF9K/DLilxO/gviVxK8ifjXxjxK/hvi1xD9G/DriHyf+CeLXE7+B+CeJf4r4p4nfSPwm4p8hfjPxW4jfSvw24p8l/jninyf+BeK3E7+D+J3E7yL+ReJ3E7+H+L3Ev0T8PuJfJv4V4l8lfj/xB4g/SPwh4l8j/nXi3yD+TeIPE3+E+KPEHyP+LeKPE3+C+JPEv038O8S/S/x7xJ8i/jTxZ4h/n/gPiD9L/DniPyT+I+I/Jv4T4j8l/jPiehfkL9U1/pIeY9F9zoTu1bPgfmhQlt1CuRTYwpZtZiV3r37fu/pV9frYEwNdTQ/AtOshaQMlOPBlZbV7Wy6/urUpa/WIQ/0wbdggaZw/dwRnOqjsMsW/FOg/nK5/rWz8vKLfKPqtot8p+r2iPyj6o6I/2X7xhwXm2jfph/R8dUU/pBxfoC3+TC3pX2w+BJ7+1MJ+K2QMsfgQYg6T52mYPPfn6uSG3P9iqXAkPd2ZpM4vGO7Vme1a1ZzrbFnVmuvuaG7r6mpvzOXyHS0dLZ35ttXdnc25tuY2dc+ujnybEpdXUyTd2Y4W3fvqqVHWK6RB8i/yC9XJ14j696LNl8yWIRB0Uvf9a4KFzJbef61O/BkZsSZRsWisSVUEfN8kn9HfEn6hdKOh79kQ9G5mLlcL/zsHW/i/Uzl+qRwt/N+pheewFpoRMpNu8X+XYIv/9wQL/UuOtPhJ6vwPR1v8f1hq8f/pWouvDfFPCy3+yxXe4mu9X3akxX+JsCbd4if5jF6x0OK/Mggt/u8ru8XnXx5t8SqV43+Vo8XXwt4TMpJu4X+fQMHsXt37ezXBQv4vR1r4JHV+De6Va2vM51sbdTr9oY2mVV35tnx+VWdTtivb0ZXvbm/Kta9uyjc1dq3q6lT37Mitzq7u6Gpf3daLq5wt/GuWWvjXXWvhtSFet9DC/7vCW3it978daeH/RViTvu9/LLTK/yFPpJyt8h8cbJXfoLL3Zjla5TeoVeawSWjSrfQfEmyl30iwMnnTkVY6SZ3/62gr/V9LrfRbrrXS2hBvWWil367wVlrr/bYjrfSbhDXp+75joZV+ZxBa6T86OFr+LpW998rRSr8rRsvfK8No+R8THC1/N8HK5D1HWukkdV7r6Gj5Wkut9P9ca6W1If5noZXW6xSTKmS29Ma1lAnd10or/R5hTXq0PMlnlKpJvsXX92wI+v+SrgxTCT6nXzuyFPMvCTQALd2rsm2dqzuink0lnV/iSuP8qwQb5z85Uh7LNQlRSWd1vOmIzkmegfHbD6DOv3Gk3vl5gvVOVU2y7bP2BfQ9M0H/X9J+1pAEcPPWFN4+wM9J31vv/eKzQkYoStf0bTNYXtWn01rgeqUE5ktT/M8p/lfif88999xzzz333HPPPffcc88999xzz93isxVVwzgRL6bQYf1/msaVqonrs4VqxBkxSY+P4r2ypf1ys4MP3pjwHEd0rkpQ57mO6DwkQZ3nOaJzkvNa8x3RuTpBnbNl0jlb2i+XS9B+b6TcmFvOO/JsGhN8NvOq3Hg2TQnqbBNnc+CGPVscwdnqCM42R3C2O4JzgSM4FzqCc5EjOLd0BOdiR3AucQTnUkdwLnME53JHcG7lCM6tHcG5jSM4VziCc1tHcG7nCM7tHcG5gyM4d3QE506O4NzZEZy7OIJzV0dwrnQE526O4NzdEZx7OIJzT0dw7uUIzr0dwbmPIzj3dQTnfo7g3N8RnAc4gvNAR3Ae5AjOgx3BeYgjOA91BGeHIzg7HcHZ5QjOVY7g7HYE52pHcB7mCM7DHcF5hCM4j3QE51GO4DzaEZzHOILzWEdwHucIzuMdwXmCIzjXOILzREdwnuQIzpMdwXmKIzhPdQTnaY7gPN0RnGc4gvNDjuA80xGcZzmC82xHcH7YEZznOILzXEdwnucIzvMdwXmBIzgvdATnRxzBeZEjOC92BOcljuC81BGclzmC83JHcF7hCM4rHcF5lSM4r3YE50cdwXmNIzivdQTnxxzBeZ0jOD/uCM5POILzekdw3uAIzk86gvNTjuD8tCM4b3QE502O4PyMIzhvdgTnLY7gvNURnLc5gvOzjuD8nCM4P+8Izi84gvN2R3De4QjOOx3BeZcjOL/oCM67HcF5jyM473UE55ccwXmfIzi/7AjOrziC86uO4LzfEZwPOILzQUdwPuQIzq85gvPrjuD8hiM4v+kIzocdwfmIIzgfdQTnY47g/JYjOB93BOcTjuB80hGc33YE53ccwfldR3B+zxGcTzmC82lHcD7jCM7vO4LzB47gfNYRnM85gvOHjuD8kSM4f+wIzp84gvOnjuD8mSM4f+4Izv9zBOcvHMH5S0dw/soRnL92BOfzjuD8jSM4f+sIzt85gvP3juD8gyM4/+gIzj85gvPPjuD8iyM4X3AE54uO4PyrIzj/5gjOvzuC8yVHcP7DEZz/dATny47gfMURnK86gvNfjuB8zRGcrzuC89+O4PyPIzjfcATnm47g/K8jON9yBOfbjuB8xxGc7zqC8z1HcK51BOf/HMGpb+gCzpQjOKscwTnEEZxpR3BWO4KzxhGcQx3BOcwRnMMdwTnCEZy1juAc6QjOOkdw1juCc5QjOEc7gnOMIzjHOoJznCM4N3AE54aO4BzvCM6NHMG5sSM4N3EE56aO4NzMEZwTHMG5uSM4t3AE50RHcGYcwdngCM5JjuCc7AjOKY7gnOoIzmmO4JzuCM4ZjuCc6QjOWY7gnO0IzjmO4JzrCM55juCc7wjOrCM4c47gzDuCs9ERnE2O4Gx2BGeLIzhbHcHZ5gjOdkdwLnAE50JHcC5yBOeWjuBc7AjOJY7gXOoIzmWO4FzuCM6tHMG5tSM4t3EE5wpLOKsSxrkt4GzMtjQ1dbfmu3ONuY5svr2zrTnb1NzZ0pZryzW3Na/KtzU2drc1tbW2d7a3ZttzTY3dudXN7Y2r6WbVaTeezXaOlKHty1SGSn3u6QR13sERnRsT1HlHR+qKnRKsKy4c4obOOyeo8y+r3ah3dnGkftz1A1g/rnSkrtgtwfemKu2GzrsnqPN+jtQVezhSV+zpCM69HMG5tyM493EE576O4NzPEZz7O4LzAEdwHugIzoMcwXmwI37cIQn6NPkqN3Q+NEGda2rcKI8djrw3nY7g7HIE5ypHcHY7gnO1IzgPcwTn4Y7gPMIRnEc6gvMoR3Ae7QjOYxzBeawjOI9zBOfxjuA8wRGcaxzBeaIjOE9yBOfJjsw1TUtQ51McGaM4Ncm5Jkf666c58t6c7gjOMxzB+SFHcJ7pCM6zHMF5tiM4P+wIznMcwXmuIzjPcwTn+Y7gvMARnBc6gvMjjuC8yBGcFzuC8xJHcF7qCM7LHMF5uSM4r3AE55WO4LzKEZxXO4Lzo47gvMYRnNc6gvNjjuC8zhGcH3cE5yccwXm9IzhvcATnJx3B+SlHcH7aEZw3OoLzJkdwfsYRnDc7gvMWR3De6gjO2xzB+VlHcH7OEZyfdwTnFxzBebsjOO9wBOedjuC8yxGcX3QE592O4LzHEZz3OoLzS47gvM8RnF92BOdXHMH5VUdw3u8IzgccwfmgIzgfcgTn1xzB+XVHcH7DEZzfdATnw47gfMQRnI86gvMxR3B+yxGcjzuC8wlHcD7pCM5vO4LzO47g/K4jOL/nCM6nHMH5tCM4n3EE5/cdwfkDR3A+6wjO5xzB+UNHcP7IEZw/dgTnTyzhrBI4Sz63LEGdf+qIzkMT1Plnjug8LEGdf+6IzsMT1Pn/HNF5RII6/8IRnWsT1PmXjug8MkGdf+WIznUJ6vxrR3SuT1Dn5x3ReVSCOv/GEZ1HJ6jzbx3ReUyCOv/OEZ3HJqjz7x3ReVyCOv/BEZ03SFDnPzqi84YJ6vwnR3Qen6DOf3ZE540S1Pkvjui8cYI6v+CIzpskqPOLjui8aYI6/9URnTdLUOe/OaLzhAR1/rsjOm+eoM4vOaLzFgnq/A9HdJ6YoM7/dETnTII6v+yIzg0J6vyKIzpPSlDnVx3ReXKCOv/LEZ2nJKjza47oPDVBnV9PUGc9N56me80G/VNkgyH0f7UiPZ+s51f1fKOef9PzUXp+Rs9X6PF7PZ6tx3f1eKce/9PjYXp8SI+X6PED3Z/W/Uvd39L9D+2Pa/9U+2vaf9HtuW7fMop0/afrA/1+6PKi7afPRZ+uaIaimYpmAd6nUn06zFE0V9E8RfO1jRTlFOX1c1TUpKhZUYuiVkVtitoVLVC0UNEiRVsqWqxoCT23ZYqWK9pK0daKtlG0QtG2irZTtL2iHRTtqGgnRTsr2kXRropWKtpN0e6K9lC0p6K9FO2taB9F+yraT9H+ig5QdKCigxQdrOgQRYcq6lDUqahL0SpF3YpWKzpM0eGKjlB0pKKjFB2t6BhFxyo6TtHxik5QtEbRiYpOUnSyolMUnaroNEWnKzpD0YcUnanoLEVnK/qwonMUnavoPEXnK7pA0YWKPqLoIkUXK7pE0aWKLlN0uaIrFF2p6CpFVyv6qKJrFF2r6GOKrlP0cUWfUHS9ohsUfVLRpxR9WtGNim5S9BlFNyu6RdGtim5T9FlFn1P0eUVfUHS7ojsU3anoLkVfVHS3onsU3avoS4ruU/RlRV9R9FVF9yt6QNGDih5S9DVFX1f0DUXfVPSwokcUParoMUXfUvS4oicUPano24q+o+i7ir6n6ClFTyt6RtH3Ff1A0bOKnlP0Q0U/UvRjRT9R9FNFP1P0c0X/p+gXin6p6FeKfq3oeUW/UfRbRb9T9HtFf1D0R0V/UvRnRX9R9IKiFxX9VdHfFP1d0UuK/qHon4peVvSKolcV/UvRa4peV/RvRf9R9IaiNxX9V9Fbit5W9I6idxW9p2itov8p0pVBSlGVoiGK0oqqFdUoGqpomKLhikYoqlU0UlGdonpFoxSNVjRG0VhF4xRtoGhDReMVbaRoY0WbKNpU0WaKJijaXNEWiiYqyihqUDRJ0WRFUxRNVTRN0XRFMxTNVDRL0WxFcxTNVTRP0XxFupLLKcoralTUpKhZUYuiVkVtitoVLVC0UNEiRVsqWqxoia5rFS1TtFzRVoq2VrSNohWKtlW0naLtFe2gaEdFOynS35zX32DX3zfX3/vW39LW35bW31rW3zHW3wjW39/V37bV343V32TV3zvV3xLV3+nU38DU35fU3248VJH+tp/+bp7+Jp3+3pv+lpr+Tpn+Bpj+vpb+dpX+LpT+5pL+npH+VpD+Do/+xo3+foz+Nov+7on+poj+Xof+Fob+NoT+7oL+DoE+41+fn6/Pptfnvusz1fV55fos8HMU6TOs9fnQ+uxlfa6xPjNYn8erz7rV58jqM1r1+af6bFF9bqc+E1OfN6nPctTnJOozCPX5fvrsPH0unT7zTZ+nps8q0+eA6TO29PlV+mwofe6SPtNInxekz+K5WZE+Q0afz6LPPtHniugzO/R5GPqsCX2Ogz4jQZ8/oPf2633zek+63u+t91Lrfcp6D7DeX6v3rup9oXrPpd7PqPcK6n14eo+b3j+m92bpfU96T5Her6P3wuh9JnoPh94fofce6HX9es28Xo+u13rrddS6/dHrf/XaWr1uVa8J1est9VpGvU5Qr8HT69v02jG9lkqvLdJrbfTaE70WQ69N0HP1eu5az+XquU0916fnvvRckJ4b0XMFeuxcjyXrsVU91qjH3vRYlB6b0WMVuu+u+7K6b6f7Otr3176w9g21r6R9h8+ycxP0ts/8m0C846STuo85/qTMScdlOlatypx6xEmHZ447pXvN6qOPOxXT6R87Tdsfe0rH0UesynQdd+xJazq6Tsp0Hd1x4omZnphjjj/5pO5VmdXHrckc1nGiuu1R3bpp6mn3Bipb1yUDzfNcjDzjqwaWR4vopHSbpuLnnQ55NyG+bM2ajtMzRxy7qvu0zHEnn5Q5bnWm87iTj111ImY8oAShh8cVuiZuxm8Pi482Mzx+3gXDYwLeJm7GlXEzHhw349FxM54RN+NVcTNeV8KjvDGu0NtKEHpXXKH3lSD0m3GFPl6C0DdLyJseERNwfdyMG4+Oj3b66JhC55Ug9Iy4Qs8rQegVcYVeW4LQkePi5922hLxnlJD34RLy9gx3xMxbDXkH9IBGxs04Lm7GCXEzToqbcWbcjNm4GQ8p4VHeEFfozXEz3hE3471xM34tbsbH4mZ8Om7GH8XN+Ne4GV+Lm/HduBlrNoyZcVzcjJMg42bEuzqOPrrn7TjxxO41Jx1yTMdph3QecdIhJx5xRjdmnRFX5sGQcaAv5VFxha6Jm/HZEtC+HFfoW3EzbjU+PtorS8j7qfExAX8ubsbnS0D7t7hCX4+bcdZG8dG2bBRT6JZxM24bN+POJag5f9P4eRs3jQm4PW7GfUpAe0wJeU+IC/jUuBmvKwHtXSXkvTcu4PvjZvxJCWj/VkLef8YF/HrcjGM2i492egl5Z28WE3AubsZdS0DbXULeI+ICPi5uxitKQHtjCXlviQv4C3EzfrsEtD+LK/TXcTO+VQLa4RPi562bEBPwuLgZcyWgXVZC3m3iAt4xbsYjSkB7egl5z4oL+Py4GW8pAe19cYU+GDfjz0pA+1IJeV+JC/g/sV/SzeOj3a+EvKs3jwn4mLgZT42b8WLI2LC+msecfPRJRxx/9Onhul4eV/IdJRj47rhCny5B6LNxhb5agtDUFvHzVm8RE3Bt3IwzS0B7Ygl5z4kL+KK4GT8aN+P1cTPeARljval3x5X8dAlP5tm4Ql8qQegrcYWOnBhf6OiJMYXmSxC6VQl5t40LeOe4GY8qAe39JeR9PC7gp+Jm/EncjL+Km/FlyBirengtruRRmb6MA30y4zIxhWZLENoUV+huJQjdK67QU0sQenEJeS+PC/iauBm/VALaN0rIO6QhJuDRkHGAE4MbxpU5IW7GLGSMVUE0xZW8G2Qc8GsTV+iaEoSeElfo9SUIvaOEvHfHBfyVuBl/VALaF0vI+1JcwP+Km3HUpPhoO0rIe+6kmIC/UYLQqsnx846aHBPwkhKE7hhX6D5xMx5UAtoNp8QUOmFKfKGz4wrNlSD0j5A3VmvzQlzUQ6bGRz10akyhU0oQOiOu0G1KELp9XKGrSxB6ZFyhF5Ug9LK4Qu8uQegjJeR9PC7g78XN+EIJaN8tIW/PXuc4gGviZpwyLT7aBSXkXRwX8NZxM3aWgPa0EvKeGRfweXEz3lwC2hdKyPt6XMBvx82Ynh4z44aQMVZrvElcyS3T4xt4QVyh+5Qg9IC4Qs8qQeiVJeS9Ji7g6+NmfKAEtP8tIW/1jJiAR8bNmIGMsd6bKXElL5sR307bxBV6WAlCTysh75lxAZ8XN+PNJaD9ewl522fGz7vNzJjK7hQ34x5xMx4UN2NXCfbZFE7KifWybjErJuqFs+KjXhJX6IElCD00rtCzShB6blyht5Ug9Ksl5H0oLuBH4mZ8vgS0r5WQ9424gN+Nm3HT2fHRHlhC3iNmxwR8fNyMF0DGWNXSxXElf64EO90RV+gzJQh9voS8v48L+IW4GdNz4qNdUULePebEBLx/3IzHQsZYRXhNXMlXlWCna+MKvb8Eod8pIe/TcQH/MG7Gl0tAm54bP++wuTEB18fNOKcEtMtLyLsiLuCd4mY8sgS055SQ94K4gC+Nm/H2EtA+UkLex+MC/l7cjC+UgPbdEvL2HC4aB3BN3IxT5g0crT41Uf/inEjGeQd8IhlnPKAEoYfHFbombsY4J5Jx3jgnknHeAZ9Ixhm3iZtxZdyMB8fNeHTcjGfEzXhV3IzXlfAob4wr9LYShN4VV+h9JQj9Zlyhj5cg9M0S8g74RDLOWB83Y5wTydZVuQM9p4szzitB6BlxhZ5XgtAr4gq9tgShcU4k47zblpD3jBLyPlxC3jgnknHeAZ9Its7IcTOOi5txQtyMk+JmnBk3YzZuxkNKeJQ3xBV6c9yMd8TNeG/cjF+Lm/GxuBmfjpvxR3Ez/jVuxtfiZnw3bsYBn0i2rhKImzHGiWScdUZcmXFOJOO8R8UVuiZuxmdLQPtyXKFvxc0Y50QyzntlCXkHfCIZZ/xc3IzPl4D2b3GFvh43Y5wTyTjvgE8k44xbxs24bdyMO5egZpwTyTjvgE8k44ztcTPuUwLaY0rIe0JcwKfGzXhdCWjvKiHvvXEB3x83409KQPu3EvL+My7g1+NmjHMi2bredgl5B3wiGWfMxc24awlou0vIe0RcwMfFzXhFCWhvLCHvLXEBfyFuxm+XgPZncYX+Om7Gt0pAG+dEMs474BPJ1nUm4mbMlYB2WQl5t4kLeMe4GY8oAe3pJeQ9Ky7g8+NmvKUEtPfFFfpg3Iw/KwHtSyXkfSUu4P/EfkljHAXFefcrIe+ATyRb5/TGzXhq3IyxTyTjG1weV/IdJRj47rhCny5B6LNxhb5agtA4J5KtG2cf6MFMnLE2bsaZJaA9sYS858QFfFHcjB+Nm/H6uBljn0i27qWJK/npEp7Ms3GFvlSC0FfiCo1zIhnnHfCJZJwxX4LQrUrIu21cwDvHzXhUCWjvLyHv43EBPxU340/iZvxV3IyxTyRbN5MTV3KcE8nWeWiZmELjnEjGeQd8IhlnjHMiGecd8Ilk61y7EoReXELeAZ9IxhmviZsxzolknPeNEvIO+ESydVU+ZBzgxOCGcWVOiJsx9olk616buJLjnEi27rWJK3RNCUJPiSv0+hKE3lFC3rvjAv5K3Iw/KgHtiyXkfSku4H/FzRjnRDLO21FC3gGfSMYZv1GC0Dgnkq0z1EDP+OKMS0oQumNcofvEzXhQCWgHfCLZulo/xuFg6+aT4grNlSA09olkfIMX4qKOcyIZ5x3wiWSccUoJQmfEFbpNCUK3jyt0dQlCj4wr9KIShF4WV+jdJQh9pIS8j8cF/L24GV8oAe27JeQd8IlknLEmbsY4J5Jx3gUl5F0cF/DWcTN2loD2tBLynhkX8HlxM95cAtoXSsj7elzAb8fNOOATydb5HXFPJOMbbBJXcpwTyda9cHGF7lOC0APiCj2rBKFXlpD3mriAr4+b8YES0P63hLwDPpFs3bB+3IyxTyRb197ElRznRLJ1fmFcoYeVIPS0EvKeGRfweXEz3lwC2r+XkDfOiWTrHutAj/nijDvFzbhH3IwHxc3YVYJ9Yp9IxjcY8IlknDHOiWTrBj/iCj2wBKGHxhV6VglCz40r9LYShH61hLwPxQX8SNyMz5eA9rUS8r4RF/C7cTPGOZFsXckvIe+ATyTjjMfHzRj7RLJ1k3hxJX+uBDvdEVfoMyUIfb6EvL+PC/iFuBnjnEjGeVeUkHfAJ5Jxxv3jZox9Itm6ybi4kq8qwU7XxhV6fwlCv1NC3qfjAv5h3Iwvl4A2zolknHfAJ5Jxxvq4GeeUgHZ5CXlXxAW8U9yMR5aA9pwS8l4QF/ClcTPeXgLaR0rI+3hcwN+Lm/GFEtC+W0LeAZ9Itm6APm7GAZ9Ixmfp8BprOHIryChaStfZUn5t2ZYauHkq6P+rVVQV9AcwVNE4iEonjymn71ud9H2z2eZhhD/h+2ZTfebpwZ0BOdVgKz6UKZWc7BzKThENB5kBPSO+Hgtp4ZCoHsz8rBl7naIauh4ekS8t8tVDmhqD/pmE9R8q8AwVmKshbozWYVhfPGOzUd70+zMk6P+T71gGrhFP4u+VspWuU/jdPaz7pK2OO/akNR1dJ21/7IkndRzb1Z0CiEMEJPwPVVhrSKN/VYY4nbYW0rMMHcfFJA1xVQIDmhOL5Ri6tlRFNmEVKR9nFQoe1ifbVHUOg/wJ4stZKi55S69FDp83lgH5bG3ppauCOpQ7DJ5l0FuehogmcQTkOb6j66hlaw47+ZjuY086EQs4A5eFvgrCVcBZ4bT4jxWuCqJfoBpQQr4s+sXg+VhLL8ZqfDFqgv6/HuxsxGH9dWLjDhHxaQqnwfg6vprra4g3vWBYiFIQt86+ELeuEoK4dZUQxK1rx8H/mQBiLfg/LZZevHbv//StZ/+g+T98BqSu3GqG9f9fB0ckj61dvz9Y9+hflP/DGGzZSt+fe23dx55wcvfJ3StP7jz6iK4VJx/bddIRxx27VcfRR6Onw+CHC/AmL0g+cP3DCh09hzRcV8M15h1qiFsLRjGFER9WcqwHVnLDIa5YT2upuB/L5vhsKb+2XDs2KJsE/X8mT2tYYG5oOJ4r/CoRLxsgjpcNEMfLBojj+UWqEfFDubEQ8cM4LOKH8wsp4kdQeISIr+UGSsSPpPBIEV9H4ToRX0/hehE/isKjRPxoCo8W8WMoPEbEj6XwWBE/jsLjRPwGFN5AxG9I4Q1F/HgKjxfxG1F4I4jn//QvEyTWWGetePVZS159W66tHF492xnrFnRWTb29tEin6z9eK68brU1ES2Kp0eqxe62F++o6eSTonQn617ccz2l4xYhOMxvSDYW0/P8Cw//8K7bBrU9e5x7HcBTgzIAclD0asCYkO4eyub1mOaPAhnzdDmlHC3uxrRl7XdDXGxwdkW+oyFcPaeoM+mcS1r9e4KkXmPUzmQfXWI74dbPtlGF9gLJs1FEjQK9V3Z0nH7bTcYcF4reuAxn01V0bw/+Mq6edB7wyL753w8Q9MoG5c1+G0axm9LHQD2Wd3qejWY3laPcGYTSrUY5mse+Ko1k4oKJ/To5mzaGaysqL0b4q/0EdzfpVAHlE4enJw/pB3DBRgeg47rygUzNC2FPH1YJsjsMOC8dxZwU7qtxRGQFxo0A/5txBGQlx3DnBl4U7JvUQx52SURDHHRJuOHVwB7rOBIk55z0zlDsmfd9sU08nZefE79vr4O1C92IHj+XsCLbala6TdvB2gfumQA7Hp+F6FqTldGwPbnQZuy4jO9H1rhH5dhD56iHNTgb9Mwnrv7PAs7PArJ/JRMCRfJlt9mW2+N+Ay2wbpJVlj2dy349ldi7gSL7MtvsyW/xvwGV2BaSVZY8/bfF+LLMLAUfyZXaVpTKb92VW/faEtLLs8Wct3o9ldnvAkXyZXW2pzDb6Mhv0fezWVPZ48uz9WGb3ARyJl9n2vKUy2zvx8kEvs8dDWln2eGXG+7HMdgOO5Mts4ypLZdbXs+p3NqSVZY9X578fy+yJdK3Hv3amQTirYwntTd12ynHviroPejm+AtLK8pih6/djOT6PrnU53pPK8SSI24viJgPe5Mt2c4sfcyj6N+CyfSOklWWUF5G8H8v2NYAj+TLb3uL9iuKVGmiZvQvSyrLHK/ffj2X2ZsCRfJntsFRms12+zAbB1yCtLHsz6Pr9WGbvoWvtL3yZ/IVZEPcVipsNcV+luDkQdz/FzYW4ByhuHsQ9SHHzIe4histC3NcoLgdxX6e4PMR9g+IaIe6bFNcEcQ9TXDPEPUJxLRD3KMW1QtxjFNcGcd+iuHaIe5zicLHZExS3EOKepLhFEPdtitsS4r5DcYsh7rsUtwTivkdxSyHuKYpbBnFPU9xyiHuG4raCuO9T3NYQ9wOK2wbinqW4FRD3HMVtC3E/pLjtIO5HFMfjtLh74/upXm5lwWquq6tnTUfQ/5cS4QxcMwZbC3Nx96r+GsXKNUec0nFSN+/dSAFEhs0mwv9QhbWQplL2bdhap6bvPQIwZSBseSO0l11AtoX9A3lcFsa/qNd3COCpsWALXM5WDJ4au3iy9UHZ1mhGloM0yLawOTOPSwaLsTuuaU68WaFyMJA9CtisJL5/x95+j54uLi8/XBsk212oE7YaKmxVD2lGgv3qLNgvBXL53hyuAzxyk2xt0H/fSyVg5LgqwGNrL1BYfYDPEJc/S5tVV5jNED95qOvqVY11JLirNupzfXvcG5Ux4EhDmpfn9mEbnerTCzFLfUyb2TNBsjZnWYHQgeXVBevvO6kL1t+DYssNR/9aYmR5WHZqQvRIQ5rNyP64f4p/2E6jDfA+QRBen4y0ZIOwd2MkYMTl7IzHln/BZSIV9G8T0Ba227mkdeJ6pjrExmlIMyOiDJnaTKxTA/o/Dddss2GWdAt7XsPKKDuIkG2hfstjXRqA/oHAwz88oMJCGcsPdIjDti9lSc+ed7Se7pW0LzpK2Gq4sFU9pKkH+42yYL8UyOV7cxj3AruGuT5Yv/2sDfqXx0rAiG0f47HVNoTVYfgMTVsL+f/qCrMZ9otw+x1j3dmu/5xHm3J7WyXsh/7zl8B/3q2A/zxcxJXTN+Uwy6sDvUz+JPrPFvylvKnvJ30RLDs1IXrgWREHFuk/ow1wrz3LNtUntvqWYe9GHXBZL9v0ibhMsD+GYwDMbbXNFmzcU8647aoOsXEa0hxRwH+WZ0lw+TH1dzhtVdC/LeC8VUH/szT0j7eWy3tkArv+loW6v8f2eMZGBvDj2SOc5sQCtpfniuB7zFye7VEF6erhXjpe1iVse06H553ZHOsIe+fQ77ctO4iQbaGNGnCfA+vpxMtqrqvnkL4RA8AzCvDYOLfG0jvZU8/yNu+k+0Bjha1GCFvVQxo832WsBfuZ+jccxsO/PWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj7kQZo1nOF0z1lpIN7xCMHLcaMAzyhKeKoGHw/gMq+m6xmCz6gqzWRVgHErXIwHrg8P68I5MGm+uq13jrQN5GQOONKRZM7cv7TcIW53AzPqMEHHD4N6ZIFmbsyy+N4dZXh1hCuC/OrgeAhhrksZIdh4agpHlYfmuCdEjDWm+Q/YfHaz/qwed0AZ8zXVHLdwP65PBen/xmVQBnuGW8HCZSNG9a4UtsD4ZCTbj/7FsV1nCyLL43sOFfbCdqAU8tZbwhL1rXraFOjqbzdeCDP6lRDgD1yMBj433phZkFINnuF082XrAg7JsvY9h5QDrKwv1Zx7r6mLsPgrwjEkeTwv6VcXgQZ96dPJ4cpb0zKKvuDbB+2pbjRO2GiVsVQ9pxoL9xlmwXwrk8r05zPI8Zo/ZYx5czBqP9JtrIV1VhWDkOBwXsFA/R7bJ+AzZhxpqsFlthdkMfUvue2OfY+zwPrwWfKoWtCmPC0gcaUjTBOMC4ylBXbC+j4zjHGjzxPvcZHPZ5+Ywy6sDfUz9ZPSlLfh0PXauCcHI8nSa0YDbpEca0jSQQqZxAdQNx55MdYet8bGw92AsYGTs6DPa7l/zGMBwgy1syR4tbDHay14n20JbMeA+lO15AHz3isEz1jKeqGdj2ffp6WdtkPx9e+rYDele3JYxfpaXhjQLI+pPvBfj5PqU71kHttoQbLZh8rr1e15cf40eBNlBhGwLz7Snrz8++fv2lJWN6F5cVhg/y0tDmhUFyspGwj5cVviedWCrjcBmG1mwWVRZKafsIEK2hWea1/fdOPn79pSVTeheXFYYP8tLQ5rdCpSVTYR9uKzwPevAVpuAzTZJXrfIssLyqkBPLDNVkIb/X0vxEn+mTDoEITpYKhuN+r6bJn/fnjK3Gd2LyxzjZ3lpSHNIgTK3mbAPlzm+Zx3YajOw2WbJ6xZZ5lheFei5CaStgjT8P5c5iT9VJh2CEB0slY0mfd8Jyd+3p8xtTvfiMsf4WV4a0hxToMxtLuzDZY7vWQe22hxstnnyukWWOZZXBXpiGaqCNPw/lzmJP1UmHYIQHSyVjWZ93y2Sv29PmZtI9+Iyx/hZXhrSfKhAmZso7MNlju9ZB7bitDgeZ3kuLbIc4hgm911NY5jYd55oCWPY2I3JZtinZ7xY/qsgDf/P78/m4h6ZwN68YdQYEI5d25YdRMhOfN0UrUniMsPvWI14Hrje6OoC71iV0EOub8JxvaqIfJx+A0iD452YpgpwcpqPR+C0OdYcVoZqyig7iJBtqwzx+85lSNZRaUhzU4EyJOsXubaiDnQaE5GP00eVoSpxHyxDny1Qht6PY9GF1pnZLEOyredngmWI03xxgG29nAusA50mRuTj9FFlSLZ/WIa+XKAM2fIjwsoQ+glyDihD19Lu3B7LdyVTJh2CEB1slkX2L7ksThQ2SUOahwuUxS2EHlwW+Z51oNMWEfk4fVRZnCjug2XxiQicuH6O81ry6yPLJ8pmXRJcb5VDGfrZynf3fVeeab5rIPNLQwFPgyU8QweApwHwZJLHk7OkZ89c1iS6V9JrBicLWw0VtqqHNJPAfpMt2C8FcvneHGZ5LmLGfiz2tTndmArBiGWX8Vgoz5F1GD5DuccGbVZbYTbDPRO8tonncHX78DdYY2VhvDav8U4AeRnAgWP5nOaNOX1p/wlrrDYFPZiPF3G25mFTIIvvzWGc4+T5BJzL4mtcY2VhXUGPnTcIwYjrQHmMryZEjzSk+W+R/hTagK9xzaFcazos6CsDmSDZ5xS2L7EOOOtcjvFOLhPsB25ssIWFNXdZSzbuKWdyzaS0Ma6ZrKaLsL6DXNPK5QfvKdeLVoEsHB+pCvrve9Q/7tvJe+j0tsqhpfWqeewPRa1XXbe2soDt5bpRfI+Zy72ZVZBuBOTV8bIuYdtzOlz3YGkdROQ7x/IstRN5bJMCwIC/DFxvAHiSLy9N2dqgf5tQCA/uK7Oxh9nW3jhLfelsStgnA/bEvbOcBvvYGQv2i/JPWd5AMY9yELO3s7dzGGZvZ2/nMMzezt7OYZi9nb2dwzB7O3s7h2H2dvZ2DsPs7eztHIbZ29nbOQyzt7O3cxhmb2dv5zDM3s7ezmGYvZ29ncMwezt7O4dh9nb2dg7D7O3s7RyG2dvZ2zkMs7ezt3MYZm9nb+cwzN7O3s5hmL2dvZ3DMHs7x8Os8cg1/fhdIFxPn4G8S+k6W9qvaIwch/t6h1vCs7HAw2F8hrwfbVODzWorzGYbAy7eg4ffkZtb24c3+TME8z1r7DcFeRnAgedLcpqRsD8wR9hwfyDuCZRnmlrae9djc7n3jsN4Xi7rg/ts5B7GWsiDZcXWt8rkdyE4jPuvpC7lsGMqxI42ZYe92+PsPoc8PvMA9A8EHv5h25B8Pde7b2gg3zwaDngc2k+XxX1OSe8bkufsyO+Z1gfrn7mC+5gS1DOyTZhoV7ZxD5XJFhkDnkyZbcHyBop5qIOYvZ29ncMwezt7O4dh9nb2dg7D7O3s7RyG2dvZ2zkMs7ezt3MYZm9nb+cwzN7O3s5hmL2dvZ3DMHs7ezuHYfZ29nYOw+zt7O0chtnb2ds5DLO3s7dzGGZvZ2/nMMzezt7OYZi9nb2dwzB7O3s7h2H2dvZ2DsPs7eztHIa5Euys8cj9Cbi3ZlyFYOS4OsAz3BKesH0n+Ax5H8l4g80qbT8S7jPjfUD43dx9RvbhTf4bLr37kcaDvAzgwG9kcZpJs/vSHkDYcF8P7uUZJeJs7ZdIBf33b2QC83ewTN9aknuP8LtxWFZslec6gVt+36jOoEs57JgKsaNN2WHvtuV6JY/PPAD9A4GHf8MBT/J7SHr3Iw0fAB5sq2x9x8jGXhmsg5Pej9QgbDVc2Ko+KO93NuX+KA6zPI/ZY/aYPWaP2WP2mD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9lj9pg95qUes8fsMXvMHrPHHHjM2dJ+HrPH7DF7zB6zx+wxe8wes8fsMXvMTmLWeOQ+glpIV1chGDmuHN+DCNsfgs+Q93uMM9istsJsht9EsfCNlmzY95HOrbMpN9ezdn8cyMsYcKQhze0z+tJeSNhwXw/u5THtU7OxXyIVhO8BGwoY5P7DumD9vUe1kAfLoK33ZKjAzWGsO6Qu5bBjKsSONmWH1RmW66s8PvMA9A8EHv5NBDzJ1035LNaDxeBpADyZxPH07keyUAf37EeaRPdKej/SZGErU93OaSaB/SZbsJ/Jp+HwZLuye2wxpQhbTDHgmVJmW7C8gWKe5CBmb2dv5zDM3s7ezmGYvZ29ncMwezt7O4dh9nb2dg7D7O3s7RyG2dvZ2zkMs7ezt3MYZm9nb+cwzN7O8TBrPHJ+qBbSDa0QjA3wP+NpsIQnbN4PnyHP49UZbFZbYTbD9QM8D8tlT8+5zq7vw5v82Xy988F1IC8DOFheGtI8Mr0v7fz6Pjvz/ziXalp/kElch+i5fZaH86o41yrnfmshTznWJGQEbg43AEapSznsmAqxo03Zhc51tfQc8vjMA9A/EHj41wB4kp/Da8xifVUMHmyrJiWOp3c+2MZcJdbBSc8HTxW2ahC2qoc0U8B+Uy3YLxWsPz/N4al2ZffYYloRtphmwDOtzLZgeQPFPMVjLgtmXzY85jDMvmx4zGGYfdnwmMMw+7LhMYdh9mXDYw7D7MuGxxyG2ZcNjzkMsy8bHnMYZl82POYwzL5seMxhmH3Z8JjDMPuy4TGHYfZlw2MOw+zLhscchtmXjXiY6yk+CPqvB5wMeSoBI8eV45yCsHVz+Ax5HdxQg81qK8xmuE6W1zHy+6LXLG44qg9v8uea9K6nnAjyMoCD5aUhze3T+tJuQtjqIE8G9GkQcbbWe6WC8DWsLA/XTjZAXAbwMp8k4myW50kCN4cnA0apSznsmAqxo03ZYWcNWa5X8vjMA9A/EHj4NxnwJL8GLteG9VUxeLB9tbFG3I6evespuU5Mej3ldGGrycJW9ZBmGthvugX7pYL113dymOV5zOXBPEzgT0h2T5mbUYQtZhjwzCizLWbYld1ji5lF2GKmAc/MMtuC5X0QME/zmD3mEMzTHcTs643yYPbvoMcchtnXGx5zGGb/DnrMYZh9vfHBwazxyHHNWkg3qUIwlnN/bYPAw2F8hrXwv7RZbYXZrAFw8VwBl71qRTfDPEYmebxNaFOex5BnAaQhzUaT+tJ+FuYxOC3OAZjmt2ydxRE2d8Ty8HwFnCOQcxa1kAfLiq3yLM+q4fBUwCh1KYcdUyF2tCk7bI7Scr2Sx2cegP6BwMM/nDdIfjw2l8X6qhg86BPYmJu1o2fvPAbXdUnPY8i2Xo5nl7utl+P9HI7yTzxmj9lj9pg9Zo/ZY/aYPWaPOVvaryjMeD4qjptwuikVgrGc62PCxhfwGfJ4wSSDzcox7jQQm+FaPAtrA/udbcj312NGI0b3yU1+PWSu3zfieDyrQTyXNKT5ZUNf2nrCFjYuZBpDtLUWOmwMkeXh+lYcK+LrkYDRxhhFKlh/X4BpnRvXZzUheqQhzSZk/9HB+j/UDcfnZoo4re+sxPXtfSayHufwLMDIuswEPLbPH+axugaDLWzJZj353jPKKLtByDbpnXgdm+tq17L5WXPdwuWY5aUhzYyI8oz3Ypxc5+A7zjrNsqkb2VXikbrpNLPpukakmQX6c5r5EfrrtmikQTdb727Yu4KyLdTlPWPLs4TuKRHOwDX6MnOSx9NSG/SvtwvhmQN4ZiePJ2dJz56x5bl0r6THlucJW00TtqqHNHPBfvMs2C8FcvneHGZ5LmK2JLvn+c0vwhbzDXjml9kWLG+gmOd6zGXBXAllQ+Ph9oWx1kK6WRWCkeNmAx4L9X6kf4jP0NRXnwPXlWSzBsDF/VYue9oP7YQ+tYXxjzz2fdjvleMfaUjzUKYv7WroU3PaWQZ9sJza2icZNoaDe135HcI1IoiXuWmva4Ml3JMEbg43AEbTWhvbdkyF2NGmbDnmMG0Q9A6C8PLD1zj+krjfTH1Rrh/4nWTZLC8NaT5UoC8q66NZBt1kPVo2fUPqTKmvTsN+RI1IMwdswmnOj7DJYL4/VYAR65QqSIN9m6pg/THOTDC47wL2vxKTTeUe2z597znCJmlIc2WBci/7RVzuTWU8qj8l/RtTWZR9HCyLHytyrMRy/yiyfLK8KtAFy1cVpOH/uXxKG2YCaz5gz5gLPh/WBX8ZuMYxjuT9vaYs+pbF4JkPeBJ/h2jMxYJf2zPmkqV7JT3mkhO2MvnLnCYL9stZsJ+pn8jhnF3ZPbbIF2GLvAFPvsy2YHkDxZx1ELO3s7dzGGZvZ2/nMMzezt7OYZi9nb2dwzB7O3s7h2H2dvZ2DsPs7eztHIbZ29nbOQyzt7O3cxhmb2dv5zDM3s7ezmGYvZ29ncMwezt7O4dh9nb2dg7D7O3s7RyG2dvZ2zkMs7ezt3MYZm9nb+cwzN7O3s5hmL2dvZ3DMFeCnXHPN+595HTzKgQjx5Vjj3DYvhZ8hrznb5bBZrUVZjM8N573Z3LZ0/tnvjymD2/yezF6zwmaC/IygMO0J+vEiX1pHyBsdcH6e2fwXA0sp+U6G4XDLE9j5L0/eB4Q4mU+U8Rp3La+kxp2ZpFpf+vMMtoxFWJHm7L5+fC9Zxtk2/pOKj4H1j8QePiHZ7NlE8fTe7745AHgwfbVRr1rR8/e/Uhc1yW9H0m29ZOFrcrd1mcFHg7n7crusUVjEbZoNOBpLLMtWN5AMec8Zo858OXZY/blOVvaz9vZYy4rZl+ePziYNR7Zv62FdDMrBCPHzQc8Fvo/keMW+Ax5HGKewWa1FWYzHHPjMSN+x/WY0YSxfXgt9OWb0KY8nsU4WB6eAZzbAtISNjyvC8eC5ok4m+OcLIvvzWGWVwd6zYM4OXYVNvZpqzyHjX1mAaPUpRx2TIXY0aZsfj5877kG2RaeQx6feQD6BwIP/yzPz3RhfVUMHvQJbJwPY2usBevgpMezmoSt5PhRPaRpBPs1WbCfaXyNw012ZffYorkIWzQb8DSX2RYsb6CYGz3msmD2ZcNjDsPsy4bHHIbZl414mHHdA/ZfOd38CsFYznnBsH4ePkPut8002Ky2wmxmWv/B74vuY58ytg+vhXUETWhT7v/LNQx4/uxmm/elPQP6/5wH+86mcSFb51eGjbmwPOzrY99a9vVrIU851j7Jc0A5nAeMUpdy2DEVYkebssPW9pRT7yBCbwtlII/lLQDbBwIP/7Cvn3x/MdeKdWUxeLBttzGeaqtfjPV/0mMPLcJWsq9fD2mawX4tFuxnGgvhMMvzmD1mj9lj9pg9Zo/ZY/aYPWaP2WP2mD1mj9keZo1HjvfVQrpchWAs5zqJsHE4fIY8LjvfYLPaCrMZrhWysScM19nx/fXY/FqYN0h+vVauNSXkZYL114qlIc1vJvSlrRrXex02/m6aq7G1VjNsrobl4fo7HJPn65GA0cZ4bCpYf92yrNd0Gq7PakL0SEOaOrL/6GD9Xz3ohDaQ66Jr4X7lqKfk3C2HWwCjnGezOV8Qtk4yB3Y01VOmuSVb85Bhc0s4D8lxuOfcxvrOgX7D0PJ60yyeFWF5Hn3AczxYflst4WkeAJ5WwGPj/bakZ88cTxvdK+k5nnZhq2Zhq3pI0wb2a7dgvxTI5XtzmOW5iBnrJ8ZaC+lyFYKR41oAo1z7oP2e1nF9eC34zz3ftUd5mWB9/zkNae4An2yhwSer5Lae9SlHWx/m7+PaElM7asE+eZN9csI+WG5rAnPbn4Y02xXwB+eJvDbbpYG0k9guWXj/m7CuKQZPO+BpSx5PzpKePe3kArpX0u3kQmErU/3JaRaA/RZasJ+pDeQwy/OYPeYwzOiPMNZaSJerEIxl8uGy6Ofw/bUvcST4ORbaiSYc65V+DstLQ5oTwM85Fvwc6dOE+ZY26vIo35Ll1YEO2NbZ8nPk+HmLsEWYn2PBPk0m++SEffB9kH4OlgNO86Ei/RzLfsWA/Rz0KyzUK21YhxWDZyHgWZA8npwlPXv8nEV0r6T9nC2FrUz1MqdZBPbb0oL9TG0rh1mex+wxe8we8wcBM/rtjLUW0uUqBGOZ+jr9/Ha+v/aN7wa/3YLf06bt0AbyMsH6/Yc0pGkHv/0+8Nuljx7WB7Phm0T1wVheHeoAeGz57W0CT5uwRZjfbsE+bSb75IR98H2QfjuWA07zSJF+u2U/ecB+O/rJFuqVNqzDisGzJeBZlDyenCU9e/z2xXSvpP32JcJWpnqZ0ywG+y2xYD9T28phlucxe8wes8f8QcCMfjtjrYV0uQrBWKa+Tj+/ne+vfeNXwW+3MT6o7bAA5GWC9fsPaUiTAr/93+C3Sx89rA9mwzeJ6oOxvDrQAX03W377AoFngbBFmN9uwT5tJvvkhH3wfZB+O5aDdWMFG/TyQn67XVv3rqHF9yUTrF/uEHdNBG5TndAo9MA1w+hz2z5DMcH75k02M60p5jR1A7SZ/MZTXbB+e2RJt5yld7rHZouFzeS66TSk2aCAzRaH2AzXZbOtOG0VpMM2SMfzuiX+fy3Fczpck2Zp3W2TyUbyPCu00eYDtBHP6WK5Yr3Qp7GlW07o1mjQjdNMLqBbLkQ3fP6sU86ubnlLPlaPzZYKmzH+JWAzTjOrgM2WhtgMz4FmWy0Fm1nQrVHfd5klmy0XNmP8y8BmnCZXwGbLQ2y2BGy2lK6Xg81s7FvQPmGLAWMgMPIP9zJwPjwjaXnyGAe8fh5ttpUlPMsHgGcrwGOhfOYs6dnj62xN90p6HHAbYavlwlb1kGZrsN82FuyXArl8bw6zPBcx4/majLUW0jVXCEaOWwYY5Vmhut7ddYM+vBb6ZHkcs5H9bpaXhjQ/2Kwv7R6ErQ7S4h4K0145W984CNtjiecwmr5vY2tfnNxP2ShsgWsDW+zaJ2+yT7Owj07D/ktNYPZzcV/HoQX63aZ20ta+tzhtuaV2qWWg7fYywGPrO6EW9Myi35N0Oynrz2ZhK6w/Lfs9Pe/yMoGHwyzPY/aYPebBxWw6d6UW0rVUCEaOw/3gNupnrbvsr2uf7VLwJy34Gi0psL8cN2B5eE7EdeBPXgn+JK8vwv2uJn/J1pnZYftDccyP14iV45yfsH0caAsL/lXWko17fFJ5tovJ3+Q0nywwviTP9JH9EdznYvnbWjlb46NYx0SNa3OaWwrYbFmIzUznwnPaKkiH9YeO5z4O7n+ognQ4z2KpP9tislGzwIU2unOANuJ6CcsV64W+vC3d5N77vEE3TvOlArrND9ENn79sr/D5Y7uFc0Ly+ct76PS2xjMsjce2oE/Etmf8LC8Nab5ewPbSv2oTtsMzEnAs1YJujTjmmeB9e2y2jbAZ498abMZpvlXAZtuE2Gw52EyOtVWBLPT7qoL1xy25vMp76PSWbNSk77si+fv22H5buhfbnvGzvDSkeaaA7beFcCbosz3fsw7sxWkt6das77udJZttL2zG+LcDm3GaHxew2fYhNlsBNmNbcdoqSLct5NXxcu8ul1dOh/ugLe2LjlxThHtaP6iyLexTzg/0jBDck7+9BVvUBv33gxTCs71lPFHPBmVbqDN61rTtQPeS/ibWGZzmbwXqjB2EHryeEf1N1mkH0G2H5HXrZ9eUsGs5ZQcRsm090x3pXtLPxmfKaV4v8Ex3FHrwM0U/m3XaEXTbMXndIp9pOWUHEbJtPdOd6F7Sf8dnymneK/BMdxJ68DNF/5112gl02yl53SKfaTllBxGybT3Tnelesn+Bz5TTDN2wl4c9052FHvxMsX/BOu0Muu2cvG6Rz5TlVYGejGspxe8s7MC+osS/tEw6BCE62Cwbu9C9ZP8Hywan2aBA2dhF6MFlA/s/rNMuoNsuyesWWTZYXhVcM661hGlXCC8tEdNq+un7roxx39UFfvq+u5WONycjArBDFVyzrGL+N6VdCXm2E+nWivDQoO8ZYZnk/ydHlElL703kO7sdyLZQrnveWdZd9r93MdhnZoF3djehB7+z2P+WzwjLWyY53Vr03F+bQdZg1Q/lkB1EyF6ZvOyefjLW06x/IPDwbyXg2d0SnpUDwLM74Nk1eTw5S3r2zBHuQfdKei3QnsJWK4Wt6iHNHmC/PS3YLwVy+d4cZnkuYtZ4+L1hrLWQbpcKwchxuwIeC+U5sg7DZyjPEkWbtVaYzRYARl6Pges0Vm7Yh9fCPEfP3PUKkJcBHDgXxGn2gXUhexK2OkjbatAHbW5rf6/c385h7PdzfxH3tvA1js1aOBunx86LQjCiTyDPtJR64JmWh0T4WejXoA04jusOfE5Yn9g6Uz/sObUDRsa7BPDY8om4TLA/ttxgCwv7w7KWbNzvjPjqEBvjOq+jC/jqcr0Vlx98h9hWuN7KRvmxueZpV2EzORachjQnFrDZriE2wzLOtsI201bdGFbGWR62mVyP18L/lufRcqa6kcNtgFGu68A6Hb8h1iribNo2bP0f1rlbG+xoay6UZfGzHgzZQYRsG2uLBjoPi2e1WOjPteO7UwwerANsfTvCgp791qAm3b9cKWy1SNiqHtLgXiYL4xc5U50uxxU9Zo/ZY/aYPebKxIw+LmOthXStFYKR43A8wsaYc5S/hs+QfejlBpvVVpjNsO/C41W4h/4xGEuzsF67HW0q58lwLTqn2QTG0p40jKVhn2aJiKvksTT8LrKFsbR2G2NpzxUYSxtpsIHsH+NZ5OXoM4edRY7fEJJjPzb7f2HjDPiNUS6/WMZN/fVK+KbncsBjob6IfNe8bDvzHQM9LwnPzrHx3tQG/dvhQnjKMY4T9mwsfxsra6mu7Gkv8OyeTLB+XZmGNK8UGN+VZ7ZwO4Dju2wr9H1t7YnGc54zEC6n7CBCtkNjWu3Yt+GywvhZXhrSvF2grIT1k7CNZlvhuhcb63B027a1QZat/kVYudy1jLKDCNkW1pPlsX8UgP6BwMM/XHO2R/J4WmuD/uvtCuHBdS821nBY0jOL6zmSHoveS9hqN2GrekizJ9hvLwv2S4FcvjeHWZ7H7DF7zB7zQDHjWBpjrYV0u1YIRo7DdbkW2pRIPwKfoVxPgTZbXmE2w3FEHpvE73c3j+/Da2F8sRVtKsdITeea/nrTvrTthA3HtXBceoGIszmOFLYO1bSODb8NyNc4rmChf9RqGh9k2fgNbe4H1ITogX2drcn+YWOkWxtswNc4Z7BSxFnyxXOoH9+bw7sBRta5HH0i/J5KJjDPm8mxdexTYNmuhDkXXEtjaz4i7F3zsq2sTc0PdP0SrtO18d7g/FcxeCyPL2TxW2koy9b7GFYOsL6yNZYxkH1Slscy8n4so7Sf70eVz9+Wfgb2CVZWCMZy9qPC6jB8hnIeBW22qMJshvu2uP+CewjOgX6Urf1Ecs/CCoEN9yzcCP2oC6AfJfteuIYBbT6YaxhMfSu+Rt/DRhuYCtb/xjrLZnk6Db9DNUH4/CKnuapAP2qJwQZ8bdoHivWJrfc3bE/jHoCRdcb6xLZPxP0ok09ke091gvftKWfcdlWH2DgNaT4dUYbwXoyTyw/fsw5sxWmrgvXbqAzFy33RfG6NvIdOb6scWqr7e2y/N92LbS/r/jSk+XwB2+8N4UzQZ3t8V9henLYK0qEtdbysS9j2nA7HuMox5iXfOVxbNljjbZbaqDy2hwHoHwg8/MN1uzbK6kDPeNwL8OydPB5b72RPPbsP3SvpPtC+wlZtwlb1kGYfsN++Fuxn6t9wmOW5iFnjkfVWLaRrrxCMHLc34LHVvwirw/AZss+9wmCzRRVmM+wDcT+D/Qvdjj4LfSAb5/hgn43bbYkjDWkOgT7Qj6EPtLuwL+qDNrdwZnbkeDueh8V9jV0hjq+xD2Srr7kiBCP6BPye14TokYY0vymyD4Q2kPOV2BZifWLr/ZX9QFkH4zNBP8CWT4T9zwyELftE2XL64dLG6If/fYB+OJcf7FezrdAPl21UhuL3FljYD5f30OltlUP0ixK8bx59DLY942d5aUjz7wK2l/7KCmG7OrAXp62CdGhLHS/rErY9p8N5Hpvzt2HvXDnWtMpzE02yLbRRA17TugLw2CirOOZaDB7b/rAlPXvq2f3oXkn3gfYXtlohbFUPafYD++1vwX4pkMv35jDLcxEzrpNAf57T7VohGDluX8BjoTxH1mH4DNnn3t1gs0UVZjPT/B77F7odnbBRH15bfaC9QF4mWH9eLw1pGqAPlCFsdcH6fUycX0Cb21qnFTa/gOu0pF7Yd8M+kI020FR2WTbLwz5+TYgeaUgzm+xv8qFQN1w7J/ci2XxXw/o7+wBGuabQpv/Dz599L9O6ZFv9nXL53NLG6HO3RpQXvBfj5PKD/R22le26Hn2XBO+bRz+Abcb49wObcZrFBWy2f4jNsIyzrfYHm1kYZ4ks4wvKKDuIkG2hDWs1PVOuL7EN4zTbDfCZcttmWvMb5V9K3wTbqRqRZn/Aue585gicOMaF5cqWTxNWrtCn4Xae7VUL/1tec5oz2Z/DSwAjx+FcqjwXEsfMl5fBtmFj5vsDRjmfXI51TPJZ4zyDac9KJdkM5xnwWTM23D9hYa1Bv7N80nTv5QKPHfvkuga6/hrrD1tjjhbKQRbrkmGJ3bfZ6KsvEraqhzSW15BF1m2m75skZ4uWZmyzomyxuwGPrTP8w2yxu0F2grbokb1fEbbYz4DHgi8baYv9DLITtEWTln1AEbY4wIDngDLbguUNFPNuFYB5mLhORnZrTx13YBG2ONCA58Ay2+JAg+zkbJHvGc8+qAhbHGTAc1CZbcHyBop5vwrAPExcJyO7pcfXOrgIWxxswHNwmW3B8gaKeT8HMR9YAZiHietkZLd0a9mHFGGLQwx4DimzLQ4xyE7QFqu17EOLsMWhBjyHltkWhxpkJ9iu9vhFHUXYosOAp6PMtmB5A8V8oIOYD3AQ824OYt7dQcz7OYjZxXewEsrGMHGdjOyWLi27swhbdBrwdJbZFizvg4D5QAcx7+cg5t0dxHyog5grwc74DYK1G9nEk1tVK/CwzQKBMRAYa+Ea5ze66HppkNw8BD6fLpC1KnF79D4fWV44vMqq7FyXvu/q5HXqGX87jO7F8/erDTodTtephO15GNw3BXI4Pg3X72zUl5bTsT34vWXser6xm64Ru8zXKfLVQ5pug/6ZhPVfLfCsFpj1M3kV3nMbZauYcq3XQfC7vDnxsG84dok4m/Vll8DN4U7AyPUl1g9dlvCEfcOR5YV9l6eSbFYPcThXX2sJz8YCz8YGW9iSvYGQvUEZZY8SskeVUfZwIXt4GWUPFbKHllH2RCF7YhllzxCyZ5RR9jQhe1oZZc8WsmeXUfZcIXtuGWXPFLJnCtl1cI3f3Ur82zm5rp55OpbBa6Lk95ws9SO6Bvrdnk7AY6OdttS2GvdmLRc64TpIXLtka61emF8XtXY2CvNuDmLe3UHM5dgD58tG/7kpVzAf6CBmF8vzQQ5idtHOLpbngx3EfIiDmA91ELOL5dnFdtD7ouXB7NuU8mB2sWx0eMxlwex9/vJgdvEdPNRBzJVgZz0OymOi921sE0/vWgrEwzYLBMZAYMQ1GJ1gM56XXRoku5aCZeHcf3fi9ohe69JtVXbvWorDktepZ/z3cLoXr6U4zKDTEXSdStieuM4hBXI4Pg3X92zcl5bTsT34vWXsep6C1yUgdplvf5GvHtKsNuifSVj/wwSewwRm/Uxug/fcRtkqplzrtRT8Lm8OdvHz635+PVvaz8+vw739/Lp92a7Mr1fDf6tEnE0fdJXAyOH9ASP7oHbXkPbiYVkpureUXS9sVYk2q4c4XDcx0hKesPazHLLD2s9yyA5rP8shO6z9LIfssPazHLLD2s9yyA5rP8shO6z9LIfssPazHLLD2s9yyA5rP32d6uvUpGX7OtXXqeWSXcl1Kvr7QwBP4n2kXFfPWBTL4DW/LBv7ZxbGu3vW/HJfgX8pEc7A9f6Ax0bfx1J/pWfMV84zVAudcI8irvnttKBn1PhjJzyHgWDezUHMlbonOgpzpe49f7+VjQMcxFypZym838rzQQ5idtHOLpbngx3EfIiDmA91ELOL5dnFdtD7ouXB7NuU8mB2sWx0eMxlwex9/vJgdvEdPNRBzJVyfhqPiV69iU08yZ+fxusHlwbJrvllWbhG1cJZY5Frsldbld275vfw5HXqGf/F9aUZkIM6HUnXqYTtietxUyCH49NwfcUmfWk5HduD31vGrucpeP0sYpf5OkW+ekhzmEH/TML6Hy7wHC4wa73Og/fcRtkqplybzk/T7zm/c2mI6wS7cRzWpxzH9x4LcWzzDSGObbIRxHGZ2ATi2GabQdxRBsxHg04cdwxd10DcsXRdBXHH0fUWEHc8XY+BuBPoegTEraHrTSHuRLrGNc0n0fV4iDuZrnH98Sl0PQ7iTqVrXCt8Gl3XQdzpdI3res+g6wkQ9yG6xjW4Z9J1BuLOomtcL3s2XU+FuA/T9QyIO4eup0DcuXQ9HeLOo2tcm3o+XTdA3AV0PQniLqTrORD3EbqeDXEX0fVkiLuYrnFt6CV0PQviLqVrXMd5GV0vhLjL6XpLiLuCrpsg7kq6XgxxV9F1DuKupuulEPdRum6BuGvoOgtx19J1I8R9jK6XQdx1dD0f4j5O11tB3CfoehuIu56ut4W4G+h6e4j7JF3vAHGfousdIe7TdL0TxN1I1ztD3E10vR3EfYaud4G4m+m6GeJuoet5EHcrXbdC3G10nYe4z9L1Soj7HF3vCXGfp+t2iPsCXe8NcbfTNX6L+Q663hfi7qTrBRDHdVc3xLH/iP4a19+4b4vb1NUQx/XjYRDHdcPhEMd1/xEQx3XNkRDH9eNREMdz+0dDHM/7HwNxXJ8dC3HcvhwHcVwXHg9xXPefAHFcf6+BOG6bToQ4rm9Pgjiul0+GOG7DToE4rtNPhThu106DOG4PToc4buvOgDhuSz4Ecdz+nQlxXKefBXHcJp4NcdyufRjiuE4/B+IydH0uxHEdfB7EcR18PsRx3XoBxHHdfyHEcbvxEYjjuv8iiOM24mKI4/blEojjevlSiOP6+zKIm03Xl0MctxtXQBy3B1dCHNcXV0Ec15lXQxzXwR+FOK7Tr4E4rleuhTiuqz8GcdxuXAdxXJ99HOK4PfgExHF9dj3E8Xe7b4A4rqc+CXFc13wK4rit+zTE8fnGN0Ict383QRy3dZ+BOF5zcjPELaXrWyCO26tbIW45Xd8GcdxefRbi+AzBz0Ect2Gfh7gVdP0FiON27XaI4zbnDojjto7raV0f6jqMv5uK9ftuIm4YyM4EyfZB5PdKOczyNEb5jc46uMbv+C4QcRp3myXcCwRuDuM351mHBRDH11yuUpBH3gu/Z8zf4q4JkZeGNFmqmE3f3x4WWPnufc+3zNkf4L48Y9sHMHKapgiMeC/GuZvQF225L+hm4XnnTbrtIfCgbgsK2H9fCxhtlnV8fvreuxt05zRLNu2z0zK6xrprL7DjSsP//Isa68PnvX/yOveMSx0AODMgB2UfCFgTkp1D2TwuJb9lmobrXTftSyu/i2r6HjvPMSB2mW+FyIffU93PoH8mKM84NMvTz2RrKGdcjjQmW9+x3i/ERnuAjTjNArCRrW/dy29by2/dYxtVI9Jw3jSk2TeiztK6sS/AemN7i36Chbotsr3dFzBy3G6AUeqsy8sE6vTUwf/YD95NxHn/p/jnkaT/syuk4XId5f9wmmMLtL8W3ske/4fHTaT/sxdg5DRrCvg/e0M4E0T7P3uDbhbqv7xJN342uxl0O62A/fe2gNFm3Y/PT997d4PunOYsaJc+DP4NP7c9wI5XGv7nX5T/g8/bQn2bxfaOn/e+Btn7A9aEZPdra9n/YTkcn4brK8D/kX4D25qx63eG/VTELvO1iXx4ttM+Bv0zCesv+z77Csw983JQzq4E/8dWO7VPiI12BRtxGvR/9rCER/o/jAP7zNL/4TQm/+fjBfwf9gVYb2xv0U+wULdFtrd7A0aOQx9N6qzLy7M0EFwH/+N8QbuIs+lHsCy+t7QztnPtEMfX6P9In2gY6J0JyuO37Q4YWQeT34b+z+4h91oBabhc14TIS0OaLxZofy28kz3+D88vcZvB2PYAjJzmSwX8nz0hnAn6njfal22wJ+jWnrxueZNu/GzaDbo9UMD+e1rAaEn3HJY99n8WGHTnNN+Adulh8G/4ue0Kdvy+4X/+Rfk/+Lwt1LdZbO/4ee9tkL0vYE1Idr+2lv0floPjcHz9DPg/0m9gWzN2HO9H7DLf7iJfPaTZy6B/JmH9Zd9nb4FZP5PHoJx9H/wfW+3UXiE2WgE24jS4z2KBJTyy/ZF9bZ2Gn3+NSIP9Fk7z0wL+D/sCrDf6FugnWKjbcqgL35vDewJGjkMfTeqsy8s54P9wO4zzX6ZxLVt1a5hfh74O+zOmcZTlgLtNxGncKy3hlmM2HF4JGE2+HF/jtz5XhtwL/R9+fjUh8tKQ5u8F2l8L4wTt6Mdxm8HY8H3jNC8X8H+kT7hA6Iu2xLXhFuqbVpNusr5B3f5dwP4WfPLWctS17P8sMujOad6Cdukd8G/4uS0BO47YbP3/+Rfl/+DztlDfZrG94+e9p0H23oA1Idn92lr2f1gOjsPx9fDN+tJKv4FtzdhxvB+xy3wrRb56SLOHQf9MwvrLvs+eArN+JmuhnHE5KkcfQNoI/R85J67xLLKER7Y/jIPl6TT8/KX/g3MGnGYs2bDQ/BeOk0jfweZ4w5Kgv74c3h0wchzOZUmddXlpBv+H2+FWg16toJet5ximF8vD76QvgbglgJf5AhFXyX4bniXbHnIv9H/4+dUE4X1wTjMjoixb6SPRN3J5vSC3GdL/S0OaOREY8V6MU5ZttGUedLPwvI26mcZ/OE2+gP3zFjDaLOv4/PS9lxt05zStm/XZqR38G34XtgY7bmf4n39R/g8+bwv9myz6fNKXR9m7A9aEZPfzN9n/Mc038vW24P/IPgPbGvsMcj7AlG+RyFcfrD9+Z7Otk/1BOfagn8kiKGfbgf+zxBKmXUNshP4Pp8H5r8S/R054lgs8jAP71XL+i9NwXpz/WlnA/2FfwLTeBP0EC3VbZHubB4xybUmtQeeesUPaHIFrVHBPznIRZ9P/kc+Rw+j/bC10QJ8I/TbT86hU/4fbiyj/B+fIeD9BlP/DaVYXaH+bk7dJW5T/0wwYOc2RA/R/ZJsb5v8sT163vEk3fjbLDbodX37/J29J9xyWPfZ/tjbozmlOhnbpVPBv+LmtADt+xPA//7z/U5z/c2GE/8O2Hqj/I9c/VKL/cwaUs4+A/2Orndo1xEZLwEYm/8fWeqStBR7GgX1m6f9wGs6L/s+VBfwf9gVwbIXzop9QCf4P+mhS55718uD/cL2Fe7Xnizit1zJLerEsvjeHWZ7GmKVr/s+Ub4mwRwruIZ8/501DmpsKtFkW2pYen4H3A1YL/bFt4TS3FvAZtoJwJujzA/medaDvVnZ1a8F3NMpn4DS3F7C/hX5Ui02fYRvQUd87a9Cd09wNdfm94BPwc2sGOz5i+J9/UT7D1mDLbZPXucdn2A5wZkAOyt4esCYkO4ey2WdgORyfhuuHwWfgdGwPtjVjxz4iYpf55ot89ZBmhUH/TML6byvwbCsw62fyZShnj4DPsJUlTCtCbIQ+A6dZBjbKWsKzTOBhHCzP1M9cIvChr/+dAj4Dt594bolsb22OETUH/fXl8NaAkePwHBWpsy4vl9IhEzj3gmeWNIo4m74Qy+J7c5jl4dhDo108beiLcL2XFXjSkObnBdpw6ddwG54F3Vin+aCbBf8sj+NTUjd8HzjN8+X3ofI2fdOtQEd970UG3TnNH6Bu/ZOhjcZ1H6/FbMNxXdc2yeucxTqbn/c2BtnbAtaEZPdrL7gNZzkcn4brf0EbLts+tjVjxzFUxC7zzRf56gOzD2PBf+rnM/K9txGY9TN5AcrZa9CG26prtw6xURZsxGmwrrU1DiHrfsYRte4jK/Dhuo+3C7Th3J5hGy7bP5v9iLD1EcsBo+z71hp01uVlV2jDeawgB3kWiTit15aW9Fok9OIwy9MYF9I1PluZj/VshzR8D/n8OW8a0oyY0MvD2qzFieufa8XnWi30XwwY1/nJERhNZaRR6FsH+i6xqluvP7RU6JY16MZpNihg/6UWMFrSvV8fg32GhQbdOc0mE/rstBld43u4AOw4y/A//6J8hqVBny0t9POypnGerQyytwGsCcnu1z6xz8BycIyXr2dO6Esr21q2NWPHOVbELvMtEvnqA7PPZMFf6+ej8r23Epj1M9kCyhmXI5trJZaH2Ah9Bk6zJdhooSU8Wwo8jIPl6TRyriAr8OFcQT6iztK6cftpWiuBbetSS/qGzRUsBYymtRJSZ11eXqUDJ3G/Qa6AXraeY5heLA/3nOA+KJmP9WyFNHwP+fxxjT+nWV6gzUre9+31GfC5ZIL153vQr1lRwGeQ70Sj0Bf9ry2t6tbrMywWupl8Nk6zU9l9tl6fwfYaaPYZ2g26c5rdoC7fA3wCua5G/99p+J9/UT7DYrClhbGVrGlcaZlB9laANSHZ/don9hlYDs7N8HUH+AyyrWVbM/Y6wInYZb4FIl99YPaZbI3LLxN4lgnM+pnsDeWsE3wGW/3BpYHZRugzcJqFYKNynUvBOHDdWlibgWvSOM2RRfoMuIeB82LbaqvfsjDor6/st9QH67cHtQaddXm5G3yGFqED7lNFvWyvXed7twm8GiP7AfhsZT7WsxnS8D3k88f18pzmjAJtVvJ7F3t9Bn5m8kwyk19zdgGfQZaRRqEv+l8LreqWbcKxIOkzoG6c5oKy+2zZJku69+vTsM/QatCd01wCdfll4BPwc2sBO37S8D//onwGPHPHQr8yaxpXWmKQvQywJiS7X/vEPgPL4Xgc07oBfAbZ1rKtcS8b17GIXeZrE/nqA7PPZMFfixyHZnk955BBOfsk+Ay2+oOLQ2yEPgOnwTO6WizhaRV4GAfLi2ozOC+2GbcW6TPgeRecF9tWW/2WsLO7FgFG2R7UGnTW5eVI8BnmCx1w3QTqZes5hq2bYHkaI3/zoNkqnt42HO2UCdYvV2lI8+UCbbgso9yG4/oC1gn3kdg6V709RDeTD/VQgTbcxtlfNvsY2FbrezcZdOc0D0Pd+ii00XKNZ8/5fob/+RfVhmMdaaHOyJrGsBYZZC8GrAnJ7uczcRvOctCX4usfQBsu2xm2Nc6vyf6SKZ/cQ4ft00KD/pmE9Q+bc8Wxt8ehnD0LbbitunZhiI2wDec0WNc2WcIj637GwfJ0Gn7+sg3HfULr1nsV2YbjPj7Z/tnsH4etv28HjByHewSkzrq8tEIbnhU64PeEUK9GS3rJ/XMcZnnoZ+C6QVxDwbxJxFnaQ9iDu0ngln4Grv9rgji+xnMlmkPuNQ/S8DOtCZGXhjT/KND+Jl5H0LkS0v+R/hj6P68O0P/JC33Rlnb3NZt9O342eYNubxSwf6sFjHZ07y3r+Pz0vecbdOc070C79B74N/zcsmDHkZuv/z//ovwfy/ums+jzyT3CKBvnpROS3c/fZP+H5aAfum78efO+tLKNlmO+ODeM2GW+ZpEP2/Y2g/6ZoDz9VRwj5Q8TYjmy2U61hdhoHtiI0zSBjeZbwiPbH8bB8nQafv41Ig3nTUOaDciGhfwf3EsgfQc7dVuvvtmgv75ybKI+WH8tZa1B554z2cb2Xuv3gb/3OB/y5ESczbqVZfG9OYy+jrRzXdDfX2PeKOJs+t9hezvQ15G+3GD6kZZskUe78y+q7cK6wUJfrRH94GLw4P4mG76yJT2zWNesDZJt+2Vd3yRshXW95bG3fv4X35vDUfOgHnPymDUeWc/h93IbKwQjx9kd846ud/EZcnuUM9istsJshuemWGjzs+iT4Fk9O4IPm0tebmMqWP9soHniueDZQK+Df70rXYeNu8wTcTb9DpYVBGafFn2jeRDH1yMBo4X2rjHKN8c1KXI8x+Sbc5r9C/jmIw024Gv0CU31lC1/PeydawWMrDP6ILb8Qy4TqaC/n422sO2nJHjfRmw/q0NsjOd9HhZRhoppi3E8E8cAbJQfS+M6jaZxHcaPawE5zbEFbLYgxGZYxuU6rqpg/fN2MxQvz8pbS/HyHjq9zXlUC+M6PbaX68DkuA6uAzutgO3lHFmTsB3uncR1R/OS1y2yfsHxIW4fsQ2tpLazPljfJ0DdqijfLAo327VrFn2WdGBuS9FnuQTGQvmZDwn6Pw9sg5vEvTnPLIhvEvcu47rELsRYLfRYZMB4RQGMFspVl811S1gv6Hub9ppwmmvAX/0YzCtweZkJdrzN8D//UiKcgWscu7Ew999T3uV+48UG2UsBa0Ky+60dTIl7474Xvr518/UxsD3Y1owd9zWbsHO+eSIf7iXY0qB/JmH95TqQxQKzfiafgHJ2G/TZbI0PbxlioxzYiNOwf2Yan5XrF3BMvSYw+8Q4P3BngbplZvL6G+s/xjYTMHKaewap/rOgu7H+yxt05zRfgXJ5P9Rv0g/R/z9p+J9/vv4rrv57IqL+k/VYsfVfTuSrxPrvIShnT0L9Z+ssuC1DbNQINuI0UWPLnB7rP36fakQa03dQnilQt1jwf431H2ObBxg5zXODVP/Z6lOF+X+oO6f5KZTLn0P9xs80B3b8i+F//vn6r7j6788R9Z+sx4qt/xpFvkqs/34J5ewvg+D/yToK678FEMdrF3D8V57PbGmuIXK9Bvqt8vxFrJM5H/fFsd5mnWpEGhwr4DT/iqgTaw159XM9BdaHyHUEOL+OY8eDuc6UbWoa/8d5GtOc22CO/5v26/A1ro9tDbkXro+V312LGguv2qKXl/u7a3IPjdzPjHtoaiIw4r0Yp2nsmW2AezYs+ACNJt1M81mcZmQB+9sY+7c5riq/u5Yz6M5pxmzRZ6dxdI37f7AemmT4n39Rfgo+bwtj+VkcX+XnvdAgG/fxJCS73/4Y9lNYDo4L8nXDFn1pZVvKtsZzibgNRewyX6vIZ2qDUf9MYMcv5nvL8x70MxkP5YzLkc12akGIjXD+g9PgfK8t/0O2P6Z5Ddn/k/PR2P+bFVFn4bog3B9kWoNoa39Q2DocXMMt91DUGnTGtSj6fZhM8TMhz3wRZ7P/z7L43hzGfbBy7TPuGUL/R66ZrbR1vYPpj1uyRX6gY4y4/spCe92E72UxeLDfbWNtiiU9s1jXJ70+VtateWGrcq9BDOsj4XkOHrPHbMKMe1twXQanK8c5FsVgNI052OrPhLUV+Ay5DZ1vsFlthdksC3gs+ClZHEfC/Y3d4Hdb2AfWlBLyMoCD5eEcbvPEvrRHEDb0Q9BXmiXibPpKLCsIzON56M/Ngji+xjW9FtropqhxSZxz5/IWNS7JaU4q0J8YabCB3JcfVk8N5lgk64x+ky2fFvc6ZgLzeQy2fasE79uE7Wd1iI1xXfi5BcYIC7XFOHZcjn1gFsaam3D8TZ47YBr7vbiAzdpCbIZlXO4fqQJZ2N7h2l3cq1ZluIdOb8lGeUvjDk047lPMeuprCthejiHlhe1M66ltjhdbGDs1nocZtQ76hgI2WxRis0LroGclr1tknczy0HdEv6OS/I36YH0/CnXjddBzKdxo165Z9PPSgdn/6LdWD8a85TpoOS+Mvo1cBz0X4vPi3mU8U7/fOnD5/d1FBoz3FMBo4YyYrB3dzetg5hl0X7cOEMb974f5Iy4vk8GOTxr+519KhDNwjWN05V4Hg7KXAtaEZA98HeAW62Nge7CtB7oOZpbIV5HrAKGcPQn93HKtA5T1M87BmfaucD5Oj/tA+H2qCcz9iDSkeaZA3TI5cf3N9R9jmwwYOc1zg1T/Ja979DpA1H3dOkAolz+H+k36IT3rtwz/88/Xf0WuA4yo/2Q9Vmz9N1/kq8h1gFDO/gL1n621sFuG2Mi0DyRqPN60Dy5sHwjOg3OafxSoW5L3f831H2PDvXqc5tVBqv9s9anC/D/UndP8B8rlm1C/yTOt9P81E9f/n3++/iuu/queuD4Gtoesx95P+0DehnLG5Wgw9oHgfE8x+0Dk3KPJ/5Njc+j/1ZGuYXVL8vM85vqPseE8D6cZUwCjrfrP1lmHYf4f6s5pxsMc18ZQv8nvG+n/pxv+55+v/4qr/6ZF1H9x94G0iHyVWP9tBuVsOtR/5fL/TGdYmfaB8Bo9XPvPecqxfi/su154brzc04Z1MufjscioM5TmivvgXFljRJ1Ya8irn+uEsb3X/pz0+LjLcU76LEgzkHPSty7QTlbCOenbRWDEezHOwTsnvXduS+pmWgPBaXYpYH8b88U255UGck76HtB+7AV+iOmc9FWG//kX5af4c9L7rrvAT/kgnZO+L5SzVeCnlPucdJz/NZ2TXq79A3KdHrZRct0W9i84zdERdVbYOemmNVq29l2Gtbd4TrrpbEipM65f1O/DHIqfZ8gzD/SyNQcQNmfP8jTG2XRtWiOI/o/cGzLY+1dYB9yXbasvPVngMcm2YIv8QOdYcM2uDV8F98MXgwf73TbWM1rSM4t1/dog2bZf1jVyP3+5162H9ZHwm2Aes8dswoxnZuC6NE43v0IwmsYcbPVnwtoKfIbchs4y2KwcZ5oOxGaTAY8FPyWL40i4zuoLE63KbUL/iPthEkca0pyR6Ut7F2GrgzzoK00WcTZ9pbDyhr6Sye/ja9wHYqGN7rffRmKM2lcu9cC5mgcK9CdGGmwg5z/C6qnBHIuUdYVNnxbH/zLB+n2ZcvhWCd63CdvP6hAbY5/0iQJjhIXaYhw7Lsd+53LtnWH8prHfpwvYrCXEZljG5Z7DKpCF7R3u98A92VWGe+j0lmyUr5Q9OD8tYHs5hiS/YWvag2NJt8ZK2Tvz6wI2WxBis0LfIpDfcc9QvGyz5LcI0I8px7iPrNtZHvqg6L9Ukt9SD3GoD1/zfhKej0Xf3oafmgr67+1AzLjmmdO8AmPnXHZ4P8kskQ99JL4358Fzi7Pi3mFzQAsS17+p334aOU+1wIDx9QIYky9XTVk7uvefN+DnM9ugO6f5L8wfvA3zUFxe5oAdh2fW/59/KRHOwDWO9VnYQ9PzvPFsrAzIQdmLAWtCsvut3UgRsRyOT8P1sExfWrkOhW3N2HWdznM9iF3mmyzy1UOahQb9MwnrL/coLhKYe74VDeWMy5HGNNcSpoUhNsJ5Kk5j2gPI+UznAPD7FDWfxGlGZ4gH6/+0/nMS199c/zG2OYBx3beBM9EYbdV/yeturv/mGnTnNJtk+uy0GV2H7aebZfiff77+K67+m5npS1uoHiu2/psl8lVi/bdFpu+ay5HGNNsSpoUhNsL9dJwGx/Xninym/cT8nOR+OvQ51/mbmV5evjPrzfXfXKFrv3NzMtEYbdV/tsbMw/w/01m9CzJ9dlpE12H76XY0/M8/X/8VV//tkOlLW6geK7b+k3vlK7H+W5Lpu+ZyVI49pdJGc8FGnCZqP508A8Lk/80V90H/b/dMLy/ffjpz/WfaT8dp9s5EY7RV/9naTyfrv8kG3TnNAZk+Ox1E1zjPh+uljjb8zz9f/xVX/x2V6UtbqB4rtv6bK/JVYv13aKbvmstROf0/WUeZ1rLi90FNY624DnCw1q/hWCvbDutkzsdjkVhvs041Ig3nxTHR0zK9PGw/icyrn+uXx/Re4zw2zuFW0vdZcA7XNPeMawRM6z0Gc+7ZdNY2X+N+ksaQe82FNHJtcNQ87CWZXl62vgztJ+F5MTnvif48p7kiE44R78U4TfOeco+JpbmVJpNu/GyyBt2uzYTrZmve2ea8Ej4/fW/TOhJOc32mz06fpGv8vhn20+4w/M+/KD8Fn7eFudYeP0XOI7caZLcD1oRk99u7wH6K/E47zmHfnulLK/dhyG9Wmb7FY8onvyFRD2laDPpnEtZf7iWT89H6mdyY6bvmcmSznWoJsRH20zgNrjWy1W+U7Y9cZ6fT8POX/T/cB8Zp7sv08rD1X6bvuJnWN9navxm276IZMMo54FqDzrgOUr8P0yke141OEnFarwZLerEsvjeHWZ7GOI2uJ0HcJMDLfLaIszl3If1YDs8BjKzDbMBjqx/RIPCYZFuwRR7tzr+otmsO4LGwR7+xFmQUgwf7SjbmOC3p2e+cj6T3k8g+idxzht+MtLxfqadsyzMIOIx7Bz1m+5g1HlnP4berZlcIRjk2YukdjKx38RlyezTJYLNyrIsbiM0aAI+FNj+LYzJ8f+2T/DVjVW4j+hrcp5E40pDmUw19af9B2OqC/t9fY94g4mz6HWHlDf0Okw/F17g3w0J712PnOSEYcTxHnvUl9cCzvt7M9PJCezPQBnyNPqGpnrI1Phr2zuG38WRdYdM/5DKRCvr72WgL235KgvdtxPazOsTGOHeWJmOHjbcVaotxXzunxXXb/N/aoH8/PAnfbDX9cP/MQO67usAvob3JORkRgB2q4BrHugr9b0qbhzyyX75WhIcGgfGcOv5/TES5sNUmWxqXb8RxEX4n5Lgx7nkbX+CdkGMs/E7gPIQ8W8eSbnlLY1uNOL4rx+1xDT6n2byAzZpCbGYat+e0VZAO98fpeNku8v4PToe+UjnGaWT7wfLQz0UfqZJ8o3qIQ334mvd/8Bgi9h9s+MKpoP9eDMSMa/TW7Udp6MPMZYf3f0wS+dAP43tzHtyLPEfcu3zr/7ItiLFa6NFkwNhcAKOFctVic/0f1i/63tMMunOaBdAfWUTX+H5NBzvuaPiffykRzsA1js1Z+F5kT3mX59K1GGTj/E9CsvvNq6SC/vsbcW8kX+8A75rcB8m2Zuy6Tudx+KgzjxtEPjyDq9mgfyZh/eUcjty72bP+D8oZlyONaaYlTM0hNpoENuI0UetIOD2Or/H7VBOY+zxpSLN7gbplevL6G+s/xjYdMHKavQep/rOgu7H+m2nQndMcAOXyIKjfpB/Ss27L8D//fP1XXP13VET9J+uxYuu/SSJfJdZ/h0I5Oxrqv2mWMDWH2Gg22IjT4P63mSKfHJtAf7hGpEGfk9OcWKBusTCGY6z/Zgpdsf47dZDqP1tjhGH+H+rOac6Ecnk21G/8THFs+wrD//zz9V9x9d/lEfWfrMeKrf9mi3yVWP+dC+XsCqj/Gixhag6x0UywEacxfRcUx/f5/cF1K5Ms4Z4mcMs1KvUQx7bDOpnzybWE6NvKc6s4L+5buSGiTqw15NXPtZMS41wR2lHOndhaG4H1P9+bwywP50lM8zs4D2eaUx3M+R35LYM6uMb1z/ND7jUT0nD5qAkKz3XcWaCdTHxMm9Y/4zddMsH65zhie3ZPBEa8F+OcI/RFW+I5LRZ8gEaTbvxs5hh0+2oB+9sYx7Y5rirPkWkw6M5pvgbtxzfAD+Hnhn7K04b/+ZcS4QxcW/7OR78zdcPmBHCtZ9J+Cu7zxjYSxwX5+inwU8L6ElF7Bkz55JyaqQ1G/TMJ6y/3g8jz4/QzeQTK2dPgp9hqp/IhNkI/hdPgfL4tv0m2P3Iti07Dz1/uo8Lv8nCaH0fUWbjuC/dJmdYQ2Fp/Pknoy2H87qacA6k16IxrjXBv1RTIM1XE2ez/syy+N4dZHvpoUyFuKuBlPl3EadwzLOGeLnBzeAZgZB2mQxxfo/8zI+ReWJb5OdaEyMN5sr8WaH8TH8sm/0ee/cvYcLyF0/yjgP8j1/tPFfqa1u4Pg3SZpHSj7x5K3fjZTDXo9loB+9v4Nq0d3XvLupyjnWTQndO8Ce3SW+Df8HPDc4qGTVr/f/5F+T/4vC34fP3OJeTnPccgG78Tl5DsHMpm/0eu58X9v0Mn9aWVbaI8Gw/XcEV9426GyIfrYy2vl4vsE2Mb9i6UMy5HNtup2SE2agAbybkrm+Mvsv1hHLiuQ55/1CDw4flHoyljmP/DvgDrjWMr6CfYOisjbL89npPHcdMAo9RZl5cRMP6ToXhcmz5FxNmsW1kW35vD6OtIO9cF/f015tNEnM25y7DxP/R1pC83mH6kJVvk0e78i2q7sG6wsKagBf3gYvDgt1dt+MqW9Ox3Lk/S+79kXT9d2ArrevQHbK1dl3Od8kwPj9lj9pgHFzPOd+E4BKebViEYOW4G4LG1ti2sTcZnyL7KFIPNaivMZlMBjwV/MIv+Kt9f+6t7QP9mSvJyW1JCXgZwsLw0pDlyWl/afQhbmE9aaWNysj9gGpOz5ZtFjfXhXKc8t8M01sdpOgv020YabMDX2F+YJeJsvnNhZ3nMBoymsT1bfQcuE6mgf9mfBnY01VOm/pat/m9Yfwv7v3K9hc35l7B3zcu2UkfnsW3gX0qEM3Bte+4Gx0mKwVOOMYCwZ4OyLbyfWUt1pXF9qKwrcX3oeRFtAd6LcXI7gN+pZlvhekQb6ypwTBFl2WpzpoMdMhCeXUbZQYRsC/P2Az6bCPf72dizXhsM7DxiPPPFxlyDJT2zuMYs6bEpuS5Mnv9cD2nwTGVb6xLCviuP3+HymO1jxvEQXP/B6cqxRqUYjBxXjjOaw+pdfIbsU80w2KyhwmyGfWnui+O6hLthnMBC/7UxFay/DkKO6WDfdA6ME9wH4wRyrRaOE6DNbc25hZULnHPj8mAaJ0Df2tZ626khGFmeTiPPCZd64DqBbxY5v2taY4Vr4+eKOJvrAOQ3fkzryVln9F1s+XFcJtiHnCFsgfUJjmHy/1i2ba3TlOPmsk3AdgLHgAdrTO6DLNtCHZ0f6FoqnP+18d7geH4xeCz3x7I4nl+O/T1h5cDy2Yz5gfa10B+zceYT7k8qBg/61Db8Q0t6ZtFXTLrvJ9fgm86x5DS4TyNvwX4pkMv35jDuU5Rtdi2km1shGMt5xmxYfYDPkOvvqQabzagwm2GfRI5Nar//39AnsVGf47gmr0+OGiN9eWoftv9Cn0T6RNgnQZsPZp+E9TL1SbAdt+WPh/VJcC0xv0NRfRJOM4QWNob1SWYabMDXpjEOrE9svb9h/XU8E1COM9j0L7hMcJ9klsEWtsc4k9ZpIPtoR0eUIbwX4+TyY9qnjG2mrXWzYc9rehllBxGyLdRv+YGuScV1NrZ80akDwGN7fNemLxrnvNxCP20ruUd1qrBVPaSxfDZqpM+Ce3hlW4R+1fQKwSi/f2ezng2rD0y+6GyDzWZUmM3wGz7yvATdluQm9+G1sQ4Ax9/YF5X7xvDski+BL9pM2PBsD/RFZ4k4m75oWLlAP2y20Av908HwRVl2lC8q9UBfdGmEH2HyvfUzMdUdg/mdTOkn2fQl+PmzHzPbYAvb4ytJ6xR2djieU8Zpdirgd8qxGlm3Yj8B20dbc6Fhz2t+GWUHFSrbQltgPIteztliedp3gOWJ2wisk+VZ9KZ8nB7rSbneeKq4D87pHlxknx3LtK39BWFlmuVVBev391IUL8cW+Fx5ea5JapB1QB8Mz/wy7eOwvf+f7y1tFzanMjt5PD3vFa6D1/fOG2RbOAeiC/1K/qVEOAPX2I+1UX4sPfN+eyuHJXbf5rxpPEbWY7iuCjHYavPD9ijlDLKTs0VLs6kPbbKF6dwtW32tMFs0GmQnaIt+Z35F2aLJgMfWtwnCbNFkkJ2gLfp9azzKFs0GPLbOIwuzRdQZalGYcxWAeZi4TkZ2a08d11KELVoMeCycORxpixaD7ORske933nGULVoNeCx81z3SFng28kAwN1UA5mHiOhnZLT1nerUVYYs2Ax5bZziH2SLq3OkozE0OYm6pAMzDxHUyslu6tez2ImzRbsDTXmZbtBtkJ2iL1Vr2giJsscCAZ0GZbbHAIDvBdrXHL1pYhC0WGvAsLLMtWN5AMbc4iLnZQcw5BzE3Ooi5yUHMLr6DlVA2honrZGS3dGnZi4qwxSIDnkVltgXL+yBgbnEQc5ODmBsdxLzAQcyVYGc9nzGDrmum2MSTW1UbDGwNHGOohWuc39iSrpcGye7VYVlbgqzFiduj9/nI8sLhxVZl57qwvUzuvr3rkZbRvarFvVGn5XSdStiey+C+KZDD8Wm4HjKlLy2nY3vwe7uUuJ7rXkLXiF3mWyTy1UOaJQb9Mwnrv1TgWSow9+xBgDVpNspWMeVaz+Xzu7w5cfxWSgNx/e5vKeJs1pdbCtwcXgQYub7E+mFLS3hYVoruPRiygwqUXQfXuDfewtx0z5lIXG65TmPZuK6P04wnQGHrahYL3fIG3eT7YtLXdC9Og2ttGGONSLMYsK97FyOwD2Y5x3U1+O5XBes/C15XI9vxTODf1cGSbeu95DaV30su0/hecpo5Bd7LJUIPfi9N7+CSiHycPuodXCzug+9gPgInnpuB/oSF8/8iyzTLqwJdsHxVQRr+n99LWY9lBlkHPEODn3kt/I9+h61+QNg3GRYDRvk9DNxrkyCefmfG8nq3JcI+tnzH2mBgZ05in8JG+bH0zLNYJ/C9G4RO9cH663ct1aU5ky8h69KBYs45iLnRQcxNDmJ2sWw0O4i5xUHMLpbnVgcxu2hnF8tzm4OY2x3EvMBBzC6WZxfbQe+Llgezb1PKg9nFsrHQYy4LZu/zlwezi++giz5SJdgZ18k8N8Umnt51MoiHbRYIjIHAiOtrcFx0KV0vTQxj7zqZqXBflrUscXtEr2NaZlV27zqZrZLXqWf8d2u6VzXdeyuDTtvQdSphe24N902BHI5Pw/X3YZ0Mp2N78HvL2PUcGa81Qewy31SRrx7SLDfon0lY/60Enq0EZv1MvgXvuY2yVUy51nOA/C7jOhmej6kFvlTE2awvlwrcHJ4KGLm+XAp4llrCEzbHxzLwe3pLKtRm9RCH+vB1FeWbSGGci1uaPOaeOgrnp/HeeE4Lp/kT1BNcZocE/Z8HnhMzVdyb80yE+Kni3mHrUizMRbYhxmqhh2ntzIsFMFrwFdrs6N5/LSU/n8kG3TnNP6b02ellusb3KwN2fM/wP/+K8XMGo01G2ZXQJr8b0SZn6HqgbfJSka8S2+R/QTl7D9rnJZYwLQ+x0QywEaeZBraV307l9LgmiN+nGpGG86YhTZoKYFjdkklcf3P9h9/RZIzr3o0CGG3Vf5nE72uu/7CMcTynqZvaZ6dRdK3rN+mH6P+3MPzPP1//FVf/bT61L22heqzY+m+GyFeJ9d9YKGdcjjSmyZYwLQ+xEX6nmtPMBdvK72hxeqz/+H2qEWk4L/qWUwvULUsT199c/zG2pYCR08wcpPoved2j/T/UndPMg3KZhfqNn+kMsOMSw//88/VfcfXf4oj6T9ZjxdZ/00S+Sqz/GqGcLYH6r1z+n6yjsP7D7z3Lb6vIbxKZ/L+54j7o/60oULfMSFx/c/0nv0+D9d8Og1T/Ja97tP+HunOaXaFc7gb1Gz/TaWDHQw3/88/Xf8XVf4dE1H+yHiu2/psr8lVi/bcnlLNDB8H/k3UU1n943rH8ZpHpu03S/5PfMEL/77ACdcu0xPU313+MDfvonOaoQar/ktc92v9D3TnN8VAu10D9Jr89qf8/1/A//3z9V1z9d05E/SfrsWLrv+kiXyXWfydDOTt3EPw/0/fcOQ2eAzJZ5JPfoMc+co1Is27MD9JcXKBusXBeh7H+myx0xfrv8kGq/2ydBRDm/6HunOajUC6vhfqNn+l0sOOthv/55+u/4uq/WyLqP1mPFVv/zRf5KrH++ziUs1uh/rP1rcflITaaDDbiNFtC3CS65vR4jscksKUtvzXsHA/EzXFR45Y8Fx31jaeJ4j74jad7IurEWkNe/VxvHtV7jd+8wm9ATRVxw4LyffNqqrAHfqdqKsTx9QzAPV/EadyD+c1U1gG/y2n6Fks25F5zIA3vL6gJkYffD320QDtp4bsTxm8DRX1r6okIjHgvxjlV6Gv6NpDNtTVSN3nuGur2VAH72/jGtU3d8fnpe5u+OcdpnoX244fgh/Bzmw12/J3hf/5F+Sn4vC18K6PHT2kGnBmQg7JbAGtCsnMom/0U+V2FNFz/FvwU+Y0GtjVj1+8Mr3VG7DJfVuTDbzs0GvTPJKy//G5Kk8Csn8lPoJz9DvwUW+1UY4iN5oCNOI3l77AZ2x/5TU6dhp9/jUiD41+c5sWIOgu/M8t61wbm7yPaqNtQF743h/OAkePmAcaob6bid0nx2+tyTMlm3SrnceT3fE0+Gn5nEf2feSJuWGDvG4TzBG6Tr2Py5fga/Z/5IffCsszlriZEXhrSvFeg/bXgEzZiOynHck0+WmpaOEa8F+OU40JoS9x7aut5S91mCTyo29AI3Sz5nzmbuuPz0/eebdCd04yc1menerrGPtUcsOPmhv/5F+X/WP5uWhbbYH7epm+2oZ+SkOx+7T/7P/K7YGm4njCtL23Y97oYO57/GfWdr6kiH37nK2/QPxPY9TUaBWb9TMZAOeNypDHZ+jZyWH9sFtiI08wDG82xhEf6A4wD+8yMQ34rG79nzmmmRtRZWjf2BVhvbG/RT7D1Tcew9jYHGDkOx3Kkzrq8/JsGyOoM/+OaUfz2qK1yxbL43jOEDhqj/C4s7v1pANxzRJzNccs5Arf0I9FHmwNxfD2FuGlMUI4tmMqylIdleWGB9tdCH6kF/ThuM+SaJBy3XFLA/5E+4QyhL9oS+1sW1uo0mnST44+o2zYF7G/BT2m0uU4Jn5++90yD7pxmB2iXdgL/hp/bLLDjAYb/+Rfl/+DztlDfZk3jfTmD7EbAmpDsfm0t+z8sB/fE8fX+4P9Iv4Ftzdj1O8N+KmKX+eaKfDi2kTXonwns9DX43jmBWT+TXaGcHVAG/ycbYqOpYCM5JmRz/Ed+v1z6Y9hG1Yg0nDcNaboK+D/sC+A4CedFP8FWHyysvcV1EhxnmstinXV5uRv8H/5/GuSZLuJs1q1h4z/o60wRetUJHZnPFHHlLH8cngUYWYeZEMfXI4mnII+8VwOkkWOZUh6OZZ5eoP2dnbRNcl3tWEblGAn2NzjNWQX8H1nepwt90ZZY31io/1pMuvGzmW7Q7fwC9rfQJ2yxWffj89P3nmLQndNcDO3SpeDfyDkz/f8Nhv/5F+X/4PO24MtnTf7uPIPsLGBNSHa/uQ32f1gOjrfx9fXg/8g22jT+zO0XYpf5Zol82LbPNeifCcrT12d5+plcAeXsBvB/bLVTc0Ns1AA24jQzwUa2ztyX7Q/jwH41P/8akQb9H05zSwH/h30B1ht9C/QTbI13ha2TwflH05oYqbMuL3uA/zMU7sl5Jok4m+uoWBbfm8Msrw50mARxkwAv8ykizua83RSBm8M4b8c6TAE8tt4HuR7YJNuCLfJod/5FtV24ztNCe9040LkUnLu2sc/Bkp5ZrOvXBsm2/WF9S9yTI8eAhkFcgnpG9pFwDtljto8ZvxGD8yCcbkqFYDT13231DcLqXXyG3B5NMtistsJsNhnwWGjzs7gmme+vfZJfgA87KXm5jSkhLwM4WB7uhz5nel/a5wkbtunod0wUcTb9DpYVCB3Q72B9JkIcX48EjBbau0aTr8qy8fwiLm81IXqkIc2LBXzzkQYb8DX6hKZ6ajDH9Vhn9EFs+YdcJlJBfz8bbWHbT0nwvo3YflaH2DgNaf5dYLytUFuM47DYv7VRfiyN2zbiWBbbjPGbxlHfKWCz2SE2wzLOtuK0VSAL27sqSMP/8/f85D10eks2ylvqwzfiGIocH2Z5uB+zmgpemO3leIyc/8F1ozhmNTF53SLrF5aHfhC2oZXUdtYH6/sEqFsV5ZtA4Wl27ZpFnyUdmNtS9FnGT+/DzM98SND/eWAbPFXcm/NMgPip4t5hY/rJr7Np7PcNw2qhx1wDxk0LYEy+XDVm7ejef86Tn0+DQXdOMxH81Qa6xvdrKNgxa/iffykRzsA1jt1YmOfted44xp0BOSh73RrqIFl745xACuTg+t91cxHwrsn1CmzrqLXapnwTRb56SDPPoH8mYf3D9jTi2u8pUM64HNkcH54XYqNJYCNOg2P/cnyW08+ANPw+1QRmnzgNaVoL1C1DE9ffXP8xtqGAkdMsHKT6L3ndzfXfZIPunGYplMvlUL9JP0T/v5vhf/75+q+4+m9lRP0n67Fi6z+5p78S679toJztBvVfgyVM80JsNAVsZNpTJfuznB7rP3k+oOzfom+5b4G6JXn/11z/MTbTGf4HDlL9Z6tPFeb/oe6cpgPKZRfUb/xMJ4Ed1xj+55+v/4qr/06IqP9kPVZs/TdF5KvE+m81lLM1g+D/yToK67/ZEJehaxz/xTqacVuYa8ihb8n35jD6rRzHtsM6mfNxXxzrbdapRqTBsQJOc3ZEnVhryKuf64ajeq9Naxhwfh3Hjm2dERi27oXl4XyHafwf52lMc26DOf7POpjW9eL62Bkh95oIafh9qAkKj4VfVaCdTHwektbH4t6PTLD++uA0pLm2wPinXDNsGnuWa2YtjS02mnQzzWdxmhsK2N/G2L/NcVV8fvrekwy6c5qboP24GfwQfm5YD91r+J9/UX4KPm8LY/k9foocy59jkI1neiUku99aTPZT5D5UnEe4B/wU2ZayrXF/ojxDw5RvhshnaoNR/0xgxy/me88RmPUzuQ3K2b3gp9hqp2aH2AjnP0znpdjyP2T7Y5rXkP0/OR+N/b8HI+osXBeEa09NaxBt7UcJW4eD+9Pl+cK1Bp1xLYp+H4ZT/FDIkxFxNvv/LIvvzWGWh+sIMhCXAbzM5ZrZSlvXO5j+uCVb5Ac6xojrr2yt1508ADzY77axNsWSnlms65NeHyvr1snCVuVegxjWR2J5LmLGM15xvQCnm1QhGE19YVt+dlgdhs+wFv6XNqutMJs1AB4L7WfPWtM6IUu3738HfzCTvNx8SsjLAA6Wh3OLR87oS/syYcP2EdvwOhFnsw1nWYHQAdvwDFwz52tca2qh7cib/D6WHbUPTOqBcwhvFfBzRxpswNfoX5nqqcEcI2OdsT235Wtl6F58nTHYwnabn+B989h+VofYGNcr19D7HDZ2VagtxjHNcuxPsjAGmsdxIbaZ/FYfjgvVFbDZzBCbYRmX+xqqgvX3Y2QoXtYBvNYUx2I5/TARXkrX2dJ+ke8Ky8M2HduDSmoH6oP12zfUTa6bRF/Jgl2z2P6mA3O7gO1vw4w+zFx2eN1kRuTDNkeeh4TrJieLe5dtrD2b77dutFroYZrbn1oAY/LlKp+1o3v/M+XkmlnUfd26d/C95tA1vl/DwY4LDf/zLyXCGbjGPn3iZ49ke8u7PJ9jtkE2jhsnJLvfeGwq6L/2GNcv8PUCeNfkGna2NWPH8wkRu8xXJ/LhWQSzDPpnEtZfjv3Kdff6mcyHcsblyOa44awQG2XARpzGtNad03J6XDfO71NNYPbv0pBmeYG6ZXji+pvrP8Y2HDCu+/bpINV/yeturv8aDLpzmh2hXO4M9VuG/q8DOx5o+J9/vv4rrv47IKL+k/VYsfVfRuSrxPpvJZSzA6H+s7V2blaIjXD9DafBsSlcy6x/uG4E53vKNW833YDbtP5D7m2Se5TQH5frhnA9Iac5PKJOrDXk1c91dn3vtWluB+cdcBxgsM5DwbEr01gOjrmZxk8HcyzHdNYMX+O6oWkh96qDNHIfdtS4xukF2snEx5Rp3RC3VXIcAeepOc1ZBcYRZkA4E5jHEeRaIltzgybdTGOTnOb8Ava3MY5jc1wBn18mWP99xLJ3MbQfl4Ifws+tAex4g+F//kX5Kfi8LaxTyGJbKfcAo2z0JxKS3a+dZj9Fnt+Ke7+vBz9FrrdhW0edRWnKJ89QwzNbZxr0zwR2fQK5/1o/kyugnN0Afkq5zrHDeohtxGlw7D5jCY9sf0zjevz85XwKrvfjNLdE1Fk4x4trcqTvYKlui5xTnQEYOQ7XQEudcV5R/0dLqPuN0w4VcTb9X5bF9+Ywngkj1zbheYDo/2REXKWtd7L5PoSdGZCxa4v8QPvYDYDHQnvdhO9lMXiw322jr2RJzyzW9UmvG5J1a4OwVbnXk4T1kViex+wxh2HGPVaMFfv4mQrBaBpzsNWfCWsr8BlyGzrUYLNynIEzEJtNBDw2zrfR+o4TsrQf9Tz43RbOFmhKCXkZwIFnC3CaP8/qS/t7wlYHedBXahBxNscKsT3OBOZzklkf9J/4Gtdn2fAZUsH680myXtNp5H5GqQfuZ3ypQH9ipMEGaH/9w33PGbCBrXduirCBafxO9jFs+rRcJtjflmPeWE9hGc/ANWO01S9mWXzvjLAPtj84Lm/rLJKwd83L7isjCcrOY3+ZfykRzsD1OMCTsWALbKuKwZOxiydbH/S3O8uy9T6GlQN/vrw/X34gP20rf1a7x2zC7M+XXx9PWL1rWrMwyWCzoRVmM+wfybHUnjUEM/vwWug3Dfgc+M9D328+YcN1AtiPN/lGmeR1iCwXLA/7Paa+H/pLFvr2jSYfnmXjuhW5N0fqgXtzFpD9TX0/Ux8K538tn3Pe80zkegvT+S5yfYVNnw3XdWYC85nvFnySrC3fS+sxkLUgKyLKC96LcXL5Ma21wfbRRvmxVD8bz6aR9TOeTbNzAZvNCrEZlvF1a+vBZhZ0y1taT9pjM7meVJ5Bj2s69yxgs7D1E/hdVLkWweZ4VFi9MLWMsoMI2Q3Jy24yPdMMhVkePtODB/hM5bwH1vVRa2I4Pe7Vb6Brub4e1xNzmlUROHGMAMuVhfGayHI1DvCwb4RzHnLs3abfhGM4mWD9MRS0meU5o37j47wGbo6wjx1b5LoGOr6WATw2yo+tcTKsT4Yldt/mnrWbct27aRyd0yAGC21W5Jj5bIPs5GzR0qxlzy3CFnMNeGztSciE2GKuQXaCtjCeWWqyxTwDHlvnpWVCbDHPIDtBW/TUb/OLsMV8Ax4L5wtH2gK/OT0QzLMrAPMwcZ2M7NaeOi5bhC2yBjy2vo2dCbFF1iA7OVv07inMFWGLnAGPrfOaMyG2iDpjOgpzOc6YzhTAPExcJyO7pWcfSb4IW+QNePJltgXLGyjmeQ5izlYA5mHiOhnZLd1admMRtmg04Gkssy0aDbITtMVqLbupCFs0GfA0ldkWTQbZCbarPX5RcxG2aDbgaS6zLVjeQDFnHcQ830HMsx3EPNdBzPMcxOziO1gJZWOYuE5GdkuXlt1ShC1aDHhaymwLlvdBwJx1EPM8BzHPdRBzk4OYK8HOej6D5zaGzrKJJ7dqoHslGUOtwMMYW+l6aZDsel2W1Qqy2hK3R+/zkeWFw21WZee69H0XJK9Tz/jbQroXz98uMOi0iK5TCdtzIdw3BXI4Po3Xs/rScjq2B7+3jF3PE7fTNWKX+VpEvnpI027QP5Ow/gsEngUCs34mb8HaPRtlq5hyPTroe5c3J65tzPOquFerVcTZrC9bBW4OtwBGri+xfmi1hCdsrp7l4R6gORVqs3qIQ334uoryyW/cWbJrv3Po0gIznmnDaTaDeiJDcUOC/s8D98m1iHtzHjx3tkXcO+ysoEzi+jdlEaM8dzFjwDixAMbky1VT1ubakjbQUd8bz3fkeE4zBdYVT6NrfL9GgR2bDf/zrxg/ZzDaZJRdCW1yU0SbzLYeaJvcKvJVYps8E8pZM/jhts5Yag+x0SSwEafBM7XlHllOj+vi+H2qEWnwTG9Os6hA3TIqcf3N9R9jGwUYOc3SQar/ktfdXP/NMejOabaBcrkt1G/SD9H/7234n3++/iuu/tsrov6T9Vix9d8kka8S678doJztDfWfrbOX20NshPvWOc2MoM+2M0Q+To/1H79PNSIN50Xf8qACdUvy/q+5/mNsrYCR03QMUv1nq08V5v+h7pxmNZTLw6F+42c6Cex4quF//vn6r7j675SI+k/WY8XWf1NEvkqs/46CcnbqIPh/so7C+m8W2FbuK+L0Uf6f3GeE/t/ZBeqW5PeWmus/+Y0FrP/OG6T6L3ndo/0/1J3TXATl8hKo3/iZTgE7Xm/4n3++/iuu/vtERP0n67Fi678ZIl8l1n+XQzm7fhD8P1lHYf2HZ67xmbCcvjbof74y4x6ss5HxewlsO6yTOR+PRWK9zTrJ7w6Yvkfy2Yg6sdaQVz/Xc8lAuC8f94A3iDibY4ANQX97NMA1Y+T6sAHi+BrPE5gq4izt1y76uwMZujZ9d4D3hKWC8O8O4L7/gXx34P4C7aSF/dhNWG6L2Wv+tQiMeC/G2SD0DfvuQEPyuhn30fOzaTDo9mgB+8+wgNGS7sbvDkwy6M5pnoT24zvgh/Bzw7NEfmb4n39Rfgo+7w/6dwd+Cn5K2B7r9+N3B56CcvYz8FMyljCFfXdgItjI9N0BW2fnThJ45Nm52EbViDTYv+A0v4mos/CcKfzugOl8ZQt1W2R7i/1kPIOBMUqd8cwk09n46P9kQC9bfUCWxfduEHgLnUmL6zNM5yIP5vei5Jw8+pv43aUpIfdCH0mWZSkPy/LrBdrfxM/qoO8u8bsh57LwOx+c5s0C/o/0CaVPjrbEs5Es+ABNJt342TQYdHuvgP0t+ORNNv0ffH763kMNunOaqtl9dkrTNY5D4zna4wz/8y8lwhm4xudtob7td+aknJdA2TgemZDsfm0t+z8sB89f4uuxs/vSSr+Bbc3Y8ZvnUWOppjFY+e1DS75nztT3kWMi+pkMhXLG5chmOzU9xEZ4Vg2nwXVjts5Zlu2PPBNHp5Hf3R0n8OGZ9ZuRDcP8nwxd4ziJ6ds2tsYbwr6VMA0wSl+n1qAzfi9Avw8bUDyeW14n4myO/7Esvrf8jrjp21B1Qf/vRDEfKuKGBZX1vSib74McVzTJtmCLAZ87jt/IsNBe5/G9LAZPA+DJJI8nZ0nPfvNSSZ83LetWOdZV7u/ENAg8HMa+rmuY8Ww3xhp2Ju5gYsSyy3hs+dlhdRg+Q67b6ww2q60wmw0HPBbaz57vAY0XsnT7vstsq3Lz2G5z/0DiSEOaZ8FX3Z2u6yAPtuHDRZzNNjysvGEbbvJH+Bq/B5RJHmPe5PfJNfJYJmtC9MDzLw8q4OeONNiArwud3T2YY2SyrrDpa+H3wDMQRlvYbvMTvG8e28/qEBvjGe9HRpQhvBfjlG0xjmmW47uXFsZA8zguJPfumMYkTyhgs6khNsMyLr89VxWsP+6foXhZB6yleE6H9Ug5+nfyXWF52KZje1BJ7UB90L/+Z334Wu6bywBmG+1+CmwVtXeK01wIY2RcdnjfnOl71RPFvTkP7pubKO5dtrF2Wjcov0do+qY2p7mkAMbky1XvusHkde//fTx+PqMMunOaK8H3uhrGm7m8bAB2/Izhf/6lRDgD19int7C2pOd5zwCcGZCDsnHcOCHZ/cZjU0H/7wThPgK+vgneNTlnzLbGs/95/C7qO0TDRT6ca55m0D+TsP6Fvlejn8m1UM4+A/2P8ZYwTQuxUR3YiNPgmLAct+P0kyANv081gdm/S0OazxeoWzZIXH9z/cfYNgCMnObOQar/ktfdXP+NN+jOae6Fcnkf1G/SD9H/P2b4n3++/iuu/ns0ov6T9Vix9V+dyFeJ9d9XoZw9BvWfrb2j00JsNBRsJNfc4bcacPxMrrco57zdZANujmPbYZ3M+dgXxXqbdZLrpnE/Laf5fkSdWGvIq5/rPjQ4guNCOCYix0lsrkcLmw9keTgmYhrLwTG3BhE32GM5GbrG8QK+xnVDk0LuNR7ScFmK+lY2p/lNgXYy8TFlWjeEe3cywfrrprA9+0OBcQS5lso0jsA2wHV7NuYGTbrxs5lo0O3FAva3MY5jc1wBn5++t2lcltP8A9qPl8EPwefG/79n+J9/UX6K7e/YYVsp9wCY1ogm7afgHhr0W3D9Ol+/C34Kp2N7sK2j9hqY8k0S+eohzVSD/pnArk8wTWDWz+RfUM7eAz8lYwnT1BAbjQcbcZoGsJGt8UjZ/sh5K5MfMV7gQz+imhalh82nmL41a5ovsLVON2x9DZ6vIMcAaw0647yiTr8xxeOY7TgRZ9P/DfsuGa4Vkmub6oL+65yYy7VElbbeaVjQ/xktTRCP9KtNsm3MIQ+0j41z6bbWMcUd87TRV7KkZ7/z3JJeNyTrVtM8SgP8z/ZrsGC/qD4Sy3MRM9bXOEeGfbxKwGjqC9vys8PqMHyGXLePM9istsJsNgrwWGg/e9YNbSpk6fa9bY5VuXlst7l/IHGkIc1Dc/rSLqLrOsiDbfgoEWezDQ8rb9iGm/wRvsZ1Qxbajh47Dw/BGLU+XuqBcwjbFvBzRxpsIOdkwuqpTPI2KHqMTNYVNn0t3M+WCdYfiy1Hm5/gffPYflaH2BjXnu0ZUYaKaYtx3BX7ipnkdcuVc60V4zeNSR5QwGaTQ2yWAZuxrTgtrg/C9k7HyzqA1w1xOmwXytG/k+8Ky8M2HduDSmoH6iEO9eFruW4IfSUb7X4KbCXXjuDcNqc5bk4fZi47vG7ItN9quLg358F1Q8PFvcs21k7z5jjfi3pMNmA8sQDG5MtV77y57TMD+PlsYNCd05wGvtcZdI3v18Zgx0sM//MvJcIZuMY+vYW1Uj3PW+5bnmqQjePGCcnuNx6bCvqf4YNn9vD1xfCuyflmtjWeI2Q671Tmk+vCcI/mFIP+mYT1DzuzAecIzoJydgn0Pza1hGlKiI1wHyvusWfbbiDyjYNrTsPPSe43xXUpnObqAnVL8j6ouf7bQOiK9d/HBqn+s+V/y/pvU4PunOYGKJefgvpN+iH6/zsN//PP13/F1X93RNR/sh4rtv4bJ/JVYv13E5SzO6H+29gSpikhNtoAbMRpGiCO53Rw/Iz/x/keW2v+GgTuBgNujmPbYZ3M+eQaffTH5bohzotjUg9E1Im1hrz6uc6lzgiOC+GYiBwnsbn+qtA+cRwTMY3l4Jibafw0Ywl3MWM5pj34fI3rhjIh99oU0nBZqgkKj2t8t0A72ZC0TWjdELdVchyhATBymmcKjCNMgnAmMI8jyLVENseVpG6bCjyo248K2N/GOI7Nso7PT98bxwI4ntP8HNqPX4Afwu8Cjre/aPiffykRzsA1Pm8L6xSy2FbKs7NQNvoTCcnu106zn8JycD8NX78Afopcb8O2jjqjy5RvqMhnWruL+mcCuz6BPOtPP5NfQzl7EfwUW2Nrk0NstCnYiNPg2P04S3jkWB/jwHE9OZ9imtviNK8UmE+JWl+MfoKtdbph7e0kwMhx6BtEzStq3OwfjYE8G4s4m/uGpD8o1zHh/OLGELcx4GW+gYizWf7k+INpbZPcB4NroND/GRdyLxzvkHugpDzcA1U9t5eX7dth5P+MYPmBeY4gDWmGR2DEezHOjYW+aMsRoJuFflrepBs/m40Nuo0qYP8RFjDa7KPi89P33tSgO6fZYG6fncbTNY7DTAA7TjX8z78o/weft4V+WeR+PpSdAawJye5X17P/w3JwnTpfT5nbl5bTsT3kPBb2GxG7zCfnkvC8veEG/TMJ6x92lhvL089kEyhnXI5stlPDQ2yE+1vlHm6NZ4IlPJsKPIyD5WEbJffN4pwjp5kbUWdp3dgXwPEmzot+goW6LbK9HQEYOQ7XQEuddXn5Gz2oOshfBXmGijitV40lvcLKOssznVuIYyuF1lyNtoQ7bK59NGBkHaLWXKWC/mUuE6y/5lmnGQN2MclLQ5qtCrS/Y5K2Cfk/Y+le3Gaw/DGAkdNsW8D/GQvhTND3vNG+bIOxoJuF9rDFpJtpDz6n2bmA/cdawGhzjBafn773cIPunGZ3aJf2BP+GbYF+ZJfhf/5F+T/4vC2M7/f4PxsCzgzIQdm4rzMh2TmUzf4Py+H4NFx3gv/D6dgebGvsT8k9MaZ8o0U+03yLTV8jrK1jeT17n6GcdYH/Y6udGhdiI/R/ZH+vnGu95Bp87LNJ/8fUHz2qgP/DvgD/Xxus7ztYqttyqAvfm8NjASPqyxilzrq8jAX/x7R3oVbE2fTrWBbfm8MsT+MbCdg4rhb04f9qRJzGXWUJd43AzeEqwCifB/pEQ4inII+8F67lk+M/Uh72wc8t//hPF/px3GYwNnzfOM2FBfwf6RPWCn3RlqNBt9rkdWs36Sb9b9TtsgL2T9wnVxit6B4y/jPSoDunuRrapWvAv8Hnxv/fYviff1H+Dz5vC/VtFts7ft5jDbI3AKwJyV5vrTX6AzjWy9c3g/8j/Qa2NWPXYfZTEbvMVyXyYd96jEH/TML6y77PWIFZP5ProJzdAv6PrXZqTIiNcIwM+6iMZ6QlPLL9YRzYr5b75uXYAu6bv6OA/8O+AI6TSN/B5nhDXdBfXw6PBowcNwIwSp11eXlwWO81jqMMgzzDRZzNchW2/gf9H8ZuWv+D/o/0iWyWvzC/bSRgxOfAcXyN/s/IkHtVQRpZlqU8LMuPFmh/E1/PSv5PPd2L2wy0BWPkNE8U8H/qIZwJ1j/jHG1ZD7pZeN55k25VAg/q9lQB+9dbwGizrOPz0/euMejOaZ6FdumH4N/wuzAU7Pg7w//8i/J/8HlbqG+z2N7JsUyUPRawJiS7X1vL/g/LwXE4vv4t+D9xxkxN+UaIfPWQZpRB/0zC+su+z2iBWT+Tn0A5+x34P+Uab5FjH7i3DucfbI3JSv9H+mPYRtWINOj/cJoXC/g/7Atgm4Z6MrdQt0W2t/XA5bhNrUFnXV52psoF/Z+0IU8a9LJVruTYR5XQAf0f7ENWgT6Me4SIs9knDhuPQ1/H5MvxNfo/tSH3GgZpuK2pCZGXhjTvFWh/E28nyf/Bvn0miPbRUvPCMeK9GCf2O4Kgvy1x/Z2t8T6pGz+bKoNuQyN0s+J/0v54W7rj89P3No09cpqR8/rsVE/XWFei/7O54X/+Rfk/+Lxt7cuW432mc7jQT0lIdr/2n/0floNz3Xw9YV5fWjlGwbZG7NxeIHaZr1bkw7GNeoP+mcCurzFKYNbPZAyUMy5HNtup+hAbDQO7cBrL69OM/g/jQP9Hzn8Ng7D+4fzX1Ig6qz7o7x8wHwH3YX1t1G1R7S3OP65bWwoYpc66vIykygXHMoOkcbdlW2vg5vi89K8KBQ/rk91vLHxYHxuSPL6eNiOd9H2z2eZhQZ8PluB9czjHx/aohWscd7Whl363cJ9gzTB4lkFveeI4br9GQJ7jO7qOWrbmsJOP6T72pBOxgWPgGLc26O8cVwFnhdPiP1a4ynAvDbhayMPCxv8ND6y/GI34YsiJn/fxi5F7n74YOfliVBlejKr3w4tRI9JJGTIuDXEpw3VV0H+UW/5viqs1yBljiJMzH/J++oe9hiRPH9X34GdRbcCWDsyFM5U8lhzqOyRY3wZjDPb5f5svqgtSxwoA","debug_symbols":"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1JWH76du8v3UTb6fusn3Uzf5furqZPPsO77vp27y/dRNvp+6yfdTN/l+6mbfT93s+6mbfT91s++nrk42z77j+37qZt9P3ez7qZt9P3Wz76du8f3ULb6fusX3U7f4furqJCPtO77vp27x/dQtvp+6xfdTt/h+6orvp674fuqK76eu+H7q6uRS7Tu+76eu+H7qiu+nrvh+6orvp271/dStvp+61fdTt/p+6urkUu07vu+nbvX91K2+n7rV91O3+n7qNt9P3eb7qdt8P3Wb76euTrbUvuP7fuo230/d5vup23w/dZvvp273/dTtvp+63fdTt/t+6urkPe07vu+nbvf91O2+n7rd91O3+37q+s6mEt/ZVOI7m0p8Z1OJ72wq8Z1NJb6zqcR3NpX4zqYS39lU4jubSnxnU4nvbCrxnU0lvrOpxHc2lfjOphLf2VTiO5tKfGdTVd/ZVNV3NlX1nU1VfWdT1Yfrp271nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVNV3NlX1nU1VfWdTVd/ZVM13NlXznU3VfGdTNd/ZVO3h+qnbfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlXznU3VfGdTNd/ZVM13NlX3nU3VfWdTdd/ZVN13NlV/uH7qdt/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU3VfWdTdd/ZVN13NlX3nU01fGdTDd/ZVMN3NtXwnU01Hq6fusN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTDd/ZVMN3NtXwnU01fGdTTd/ZVNN3NtX0nU01fWdTzYfrp+70nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVNN3NtX0nU01fWdTTd/ZVM9zun7s/v2czs/v+sH7PKfrJ+/znK4fvc9zun72Ps/p+uH7PKfrp+/znK4fv89zOn/++o6pep7f+fPXd1DV8/zOn7++o6qe53f+/PUdVvU8v/Pnr++4quf5nT9/fQdWPc/v/PnrO7LqeX7nz1/foVXP8zt//vqOrXqe3/nz13dw1fP8zp+/vqOrnud3/vz1HV71PL/z56/v+Krn+Z0/f30HWD3P7/z56zvC6nl+589f3yFWz8M5f/76jrF6Hs7589d3kNXzcM6fv76jrJ6Hc/789R1m9Tyc8+ev7zir5/mdP399B1o9z+/8+es70up5fufPX9+hVs/zO3/++o61ep7f+fPXd7DV8/zOn7++o62e53f+/PUdbvU8v/Pnr+94q+f5nT9/fQdcPc/v/PnrO+LqeX7nz1/fIVfP8zt//vqOuXqe3/nz13fQ1fP8zp+/vqOunud3/vz1HXb1PL/z56/vuKvn+Z0/f30HXj3P7/z56zvy6nl+589f36FXz/M7f/76jr16nt/589d38NXz/M6fv76jr57nd/789R1+9Ty/8+ev7/ir5/l9P3+T8/yr5Dz/KjnPv0rO86+ep3N+ft/P3+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z7/KzvOvsvP8q+w8/yo7z7/KD9/P3+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvivP8q+I8/6o4z78qzvOvysP387c4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8q+I8/6o4z78qzvOvivP8K3GefyXO86/Eef6VOM+/kofv5684z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr8R5/pU4z78S5/lX4jz/SpznX4nz/Ctxnn8lzvOvxHn+lTjPvxLn+VfiPP9KnOdfifP8K3GefyXO86/Eef6VOM+/Euf5V+I8/0qc51+J8/wrcZ5/Jc7zr6rz/KvqPP+qOs+/qs7zr+rD9/O3Os+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvqPP+qOs+/qs7zr6rz/KvmPP+qOc+/as7zr5rz/Kv28P38bc7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qOc+/as7zr5rz/KvmPP+qO8+/6s7zr7rz/KvuPP+qP3w/f7vz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/6s7zr7rz/KvuPP+qO8+/Gs7zr4bz/KvhPP9qOM+/Gg/fz9/hPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr4bz/KvhPP9qOM+/Gs7zr6bz/KvpPP9qOs+/ms7zr+bD9/N3Os+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bz/KvpPP9qOs+/ms7zr6bv/Kv88J1/9Ty/6+fv8/yun7/P87t+/j7P7/r5+zy/6+fv8/yun7/P87t+/j7P7/r5+zy/8+ev7/yr5/mdP3995189z+/8+es7/+p5fufPX9/5V8/zO3/++s6/ep7f+fPXd/7V8/zOn7++86+e53f+/PWdf/U8v/Pnr+/8q+f5nT9/fedfPc/v/PnrO//q+R2cP3995189v4Pz56/v/Kvnd3D+/PWdf/X8Ds6fv77zr57fwfnz13f+1fP8zp+/vvOvnud3/vz1nX/1PL/z56/v/Kvn+Z0/f33nXz3P7/z56zv/6nl+589f3/lXz/M7f/76zr96nt/589d3/tXz/M6fv77zr57nd/789Z1/9Ty/8+ev7/yr5/mdP3995189z+/8+es7/+p5fufPX9/5V8/zO3/++s6/ep7f+fPXd/7V8/zOn7++86+e53f+/PWdf/U8v/Pnr+/8q+f5nT9/fedfPc/v/PnrO//qeX7nz1/f+VfP8zt//vrOv3qe3/nz13f+1fP8zp+/vvOvnud3/vz1nX/1PL/z56/v/Kvn+Z0/f33nXz3P7/z56zv/6nl+38/f5Dz/KjnPv0rO86+S8/yr5+mcn9/38zc5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvkvP8q+Q8/yo5z79KzvOvsvP8q+w8/yo7z7/KzvOv8sP38zc7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yo7z7/KzvOvsvP8q+w8/yrbzl+qkv/4bJWT85u+/xfOb/r+qXW8zt/6+/Obvn8Wzm/6/lk4v+n7Z+H8pvX/9flt5/8snN/0/d9S++OzreT35zd9/y+c37T+Xzi/OD+/6efvwvlNP38Xzm/6+btwftPP34Xzm37+Xp/fdv7PwvmdP39t5/8snN/589d2/s/C+Z0/f23n/yyc3/nz13b+z8L5f/75ezoT/PNnR5+vc4yR5OMcbfzWtHFDWtDOahNUtRmq2uK12qMCcV9BdV9Bc19Bd1/BcF+BWw3xqqC71QVHBW6f9UcFbp/fRwW2n8mjP14fnpcK5GmMX8fo6a0C2ZB8tLNa28/6b1Wr+xcc3baG2EnGtjbZSca25tlJxraW2khm2NZoO8nY1n47ydjWlDvJBNKqymSEZE7IUAOfkaEGPiNDDXxGhhr4jAw18AmZSQ18RoYa+IwMNfAZGWrgMzJCMidkqIHPyFADn5GhBj4jQw18RoYa+D2Z8qAGPiNDDXxGhhr4jAw18BkZIZkTMtTAZ2Sogc/IUAOfkaEGPiNDDXxCJlEDn5GhBj4jQw18RoYa+IyMkMwJGWrgMzLUwGdkqIHPyFADn5GhBj4hk0H1zGWmY8mgemaBDOiz6TKHr2TQZ9MCGdBn0wIZ0GfTNZkCOp9ZIAM6n1kgA6pnLjOKSgHVMwtkhGROyIDOZxbIgGrgBTKgGniBDKgGXiADqoGvyQioBl4gA6qBF8hQA5+RoQY+IyOByHzjK6fR5FXh87t8fDq9+/RlwlGRSIp5J8dI+nonx0hqfCfHSNpdiePBJpJ6V2ZTI+l3bTaRFLw2m0gaXptNJBWvzUbI5pQNtfk5G1S9PdvrK6fZyy9s3lSY2zgqHOM9SVTFrU8SVXN/k+RRoNS33sX4dho3HI3vvfHDEVX3a3NE9QjaHFH9hDZHIUcVjqg+5XscL2e2xvcy+eEI6mieZ3v9ijU/Pp/5tx2N8S1VnkiCeprvkrx61hjf2eWHI6inUecI6mnUOYJ6GnWOQo4qHEE9jTpHUE/zTY6XnibUVrmdHFEdTUoHmpSHgqMJtbNuK8lQO+5uJHn1rAm1EW8nR1RPo80R1dNocxRyVOGI6mm0OaJ6Gm2OqJ7mexwvPU2onYI7OcL+jma0D47zgmOfx1d+fHw2Pb3Ni2OofYU7OcL+jkaZI6yfaeng2EVhUhFqd+JekkKSKySvNGSozYw7OcJ6GmWOsJ5GmSOsp1HmCPtbGlWOEmr/5E6OsL+j+RbHq1mFhNptuZMjHU1OI7/zKPIQsjllQ99xzgbVSzynVceZc718Vl5OCSTU/sy9JFH9xDdJXuo3VD+hzDHULs+dHFH9hDZHVD+hzRHVT2hzFHJU4YjqU77H8XJOEGq/6U6OdDTP/2jLW48Sah+qNhv6jlM2GdZLfPb96fJZeT0lyLBuQp0krJ/4Hskr/RZqq+9OjkKOKhxh/YQyR1g/ocwR1k8oc4T1HsocYX3KtzhezglC7dLeyZGORocj/YwOR/oZHY5Cjioc6Wd0ONLP6HCknzmdKYbaR67Nhr7jlE2oneSnX/moFkLxH9Xa1uXzSC8c89NX/u1qbatn7WolTrXXkyPjm7i1q7WtF7Wrta3qtKu1rdO0q7WtvJSrNb4f+nvVXrox4xuftasNpKUWqg2kpRaqFahqI2mp62qNa6nx4fhm+cuuwPi+Yu1qjWup71S7oC6Mayndao3v59Wu1riWUq7WuJZSrta4llKuVgJVe6kujG931a42kJZaqDaQllqoNpKWuq42kpa6rNb2XtD5kNdXno/a/rIrsL29U71a01rqe9VeqwvbmzDVqxWoak1rKfVqTWsp9WpNayn1ak1rqW9We60uTGsp7Wpt7yNUrzaQllqoNpKWuq42kpa6rlbcVNt+dXxHBX700VkFfjTPWQXGdcx8nWM+D/KXvaXt3Wnq1RrXMd+p9lqj2t5Dpl6tcR2jXK1xHaNcrXEdo1ytQFVrXPN8q9pLjWp7z5R6tYG01EK1gbTUQrWRtNRVtdX2/iP1aiNpqetqHWmp+c6zVttbfJYqENMVJPmo4NNbtu9/4kZ+RZaOT2fOKX1Ua1vzaFdrW/N8q9o+jj9dT/niK1/OI6rt/TZbydjWUjvJ2NZdG8nY3imzlYxtPbeTjG3tt5OMbU25k4yQzAmZQLpWmQw18BkZauAzMtTAZ2SogU/I2N6FspUMNfAZGWrgMzLUwGdkhGROyFADn5GhBj4jQw18RoYa+IwMNfAJGdu7M7aSoQY+I0MNfEaGGviMjJDMCRlQPVPl9bcQVU7IgOqZazK2c9tvJFNfAf619fdkQJ9NC2RAn00LZECfTQtkQOczC2RA5zMLZED1TEvtj8+2kt+TAdUzC2RA5zPXZGxn6G8lA6qBF8iAauAFMqAaeIGMkMwJGVANvEAGVAMvkKEGPiNDDXxGhhr4hIzt3QffJPONr9z7623c/su20o+3BW3vSdhKJpIG1iUTSQPrkhGSOSETSQPrkomkgXXJRNLAv0dmtvdkImlgXTKRNLAqGeM7K24j8ykxo9T3ZEA18AIZUA28QAZUAy+QEZI5IQOqgRfIgGrgBTKgGvg658r4TpCdZEA18DUZ47tGlMgc1ULo2qNa21o159eHZynzotr0GPI69bOCj0/3Tz/LthWofr0CVq9ttahfr20NqF+vbWWnX69tvaZfr20Vpl6v8f0n+vXaVlf69YLpK+NbUPTrFbB6wfSV8V0o+vWC6Svj+1D068XSV834ThT9erH0VTO+F0W/Xix91R4CVi+WvmrG967o14ulr5rxHSn69YLpK+P7TPTrBdNXxneP6NcLpq+M7wnRrxdMXxnf6aFfL5i+Mr5/Q79eMH1lfFeGfr1g+sr4Xgv9esH0lfEdFPr1gukr4/si9OsF01fGdzvo1wumr4zvYdCvF0xfGd+ZoF8vmL4yvt9Av14wfVXA9JXxrRT69YLpqwKmrwRMXxnfEKJfL5i+Mr7NQ79eAasXTF8Z36ehXy+YvjK++0K/XjB9ZXxPhX69YPrK+E4J/XrB9JXx/Q/69YLpK+O7GvTrBdNXxvcq6NcLpq+M70DQrxdMXxnfV6BfL5i+Mr5bQL9eMH1lfA+Afr1g+sp4Zr9+vWD6yni+vn69YPrKeBa+fr1g+sp4br1+vWD6ynjGvH69YPrKeB68fr1g+sp4drt+vWD6Ciy/vYHltzew/PYGlt/ewPLbG1h+ewPLb29g+e0NLL+9geW3N7D89gaW397A8tsbWH57A8tvb2D57Q0sv72B5bd3sPz2Dpbf3sHy2ztYfnt/CFi9WPqqg+W3d7D89g6W397B8ts7WH57B8tv72D57R0sv72D5bd3sPz2Dpbf3sHy2ztYfnsHy2/vYPntHSy/vYPlt3ew/PYOlt/ewfLbO1h+ewfLb+9g+e0dLL+9g+W3d7D89g6W397B8ts7WH57B8tv72D57R0sv72D5bd3sPz2Dpbf3sHy2ztYfnsHy2/vYPntHSy/vYPlt3ew/PYOlt/ewfLbO1h+ewfLb+9g+e0dLL+9g+W3d7D89g6W397B8ts7WH57B8tv72D57R0sv72D5bd3sPz2Dpbf3sHy2ztYfnsHy2/vYPntHSy/vYPlt3ew/PYOlt/ewfLbO1h+ewfLb+9g+e0dLL+9g+W3d7D89g6W397B8ts7WH57B8tv72D57R0sv72D5bd3sPz2Dpbf3sHy2ztYfnsHy2/vYPntHSy/vYPlt3ew/PYOlt/ewfLbO1h+ewfLbx9g+e0DLL99gOW3D7D89vEQsHqx9NUAy28fYPntAyy/fYDltw+w/PYBlt8+wPLbB1h++wDLbx9g+e0DLL99gOW3D7D89gGW3z7A8tsHWH77AMtvH2D57QMsv32A5bcPsPz2AZbfPsDy2wdYfvsAy28fYPntAyy/fYDltw+w/PYBlt8+wPLbB1h++wDLbx9g+e0DLL99gOW3D7D89gGW3z7A8tsHWH77AMtvH2D57QMsv32A5bcPsPz2AZbfPsDy2wdYfvsAy28fYPntAyy/fYDltw+w/PYRKd979vz6cP/1Kx/VBnr6LlQb6G6eY7w+PPv7agPdzAvVBrqXF6oNdCsvVBvI815XGynxeaHaSM/b62ojPW+vqw3kdReqFahqobRUpJTnhWrdaqmjArf66KjAtuYp/fghkvlQ8N3Gc5j167Wte/Trta189Ou1rX306xWwem3rH/16bSsg/XptayD9em0rJv16wfSV8Rxm/XrB9JXxHGb9esH0lfEcZv16wfSV8Rxm/XrB9JXxHGb9erH01TSew6xfL5a+msZzmPXrxdJX8yFg9WLpq2k8h1m/Xix9NY3nMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq+M5zDr1wumr4znMOvXC6avjOcw69cLpq8amL4ynrOtXy+Yvmpg+qoJWL1g+sp4mrp+vWD6yniiun69YPrKeKq6fr1g+sp4srp+vWD6yni6un69YPrKeMK6fr1g+sp4Irt+vWD6Ciy/fYLlt0+w/PYJlt8+wfLbJ1h++wTLb59g+e0TLL99guW3T7D89gmW3z7B8tsnWH77BMtvn2D57RMsv32C5bdPsPz2iZXfXh5Y+e3PeqH01bNeKH31rBdKXz3rFbB6ofTVs14offWsF0pfPeuF0lfPesH0FVZ++7NeMH2Fld/+rBdMX2Hltz/rBdNXWPntz3rB9BVWfvuzXjB9hZXf/qwXTF9h5bc/6wXTV1j57c96wfQVVn77s14wfYWV3/6sF0xfYeW3P+sF01dY+e3PesH0FVZ++7NeMH2Fld/+rBdMX2Hltz/rBdNXWPntz3rB9BVWfvuzXjB9hZXf/qwXTF9h5bc/6wXTV1j57c96wfQVVn77s14wfYWV3/6sF0xfYeW3P+sF01dY+e3PesH0FVZ++7NeMH2Fld/+rBdMX2Hltz/rBdNXWPntz3rB9BVWfvuzXjB9hZXf/qwXTF9h5bc/6wXTV1j57c96wfQVVn77s14wfYWV3/6sF0xfYeW3P+sF01dY+e3PesH0FVZ++7NeMH2Fld/+rBdMX2Hltz/rBdNXWPntz3rB9BVWfvuzXjB9hZXf/qwXTF9h5bc/6wXTV1j57c96wfQVVn77s14sfZXA8tsTWH57AstvT2D57c9qwOrF0lcJLL89geW3J7D89gSW357A8tsTWH57AstvT2D57Qksvz2B5bcnsPz2BJbfnsDy2xNYfnsCy29PYPntCSy/PYHltyew/PYElt+ewPLbE1h+ewLLb09g+e0JLL89geW3J7D89gSW357A8tsTWH57AstvT2D57Qksvz2B5bcnsPz2BJbfnsDy2xNYfnsCy29PYPntCSy/PYHltyew/PYElt+ewPLbE1h+ewLLb09g+e0JLL89geW3J7D89hQp33v2/Ppw//Urv6qNlO69UG2gu3mO48Ozv6820M28UG2ge3mh2kC38kK1gTzvQrWBHO9CtZGet5fVRkp7Xqg2kNddqDaQ012oFkpLRUp5XqjWrZY6KnCrj44KbGueKi8nPdscV767vo7xHBe9/4mzrXm0q7WteZSrNZ7ArF2tbc2jXa1tzaNdrW3No12tQFVrW/NoV2tbH2lXC6WljCcua1cLpaWMpy1rVwulpYwnLWtXC6WljKcsa1cLpaWMJyxrVwulpYynK2tXi6SlsvFkZe1qkbRUNp6qrF0tkpbKD4GqFklLZeNpytrVImmpbDxJWbtaKC1lPEVZu1ooLWU8QVm7WigtZTw9WbtaKC1lPDlZu1ooLWU8NVm7WigtZTwxWbtaKC1lPC1Zu1ooLWU8KVm7WigtZTwlWbtaKC1lPCFZu1ooLWU8HVm7WigtZTwZWbtaKC1lPBVZu1ooLWU8EVm7WigtZTwNWbtaKC1lPAlZu1ooLWU8BVm7WigtZTwBWbtaKC1lPP1Yu1ooLWU8+Vi7WigtZTz1WLtaKC1lPPFYu1ooLWU87Vi7WigtZTzpWLtaKC1VobSU8Qxr5WqNZ1hrVwulpRqUljKeT65drUBVC6WljOeTa1cLpaWM55NrVwulpYznk2tXC6WljOeTa1cLpaWM55NrVwulpYxnmWtXC6WloHLPM1TueYbKPc9QuecZKvc8Q+WeZ6jc8wyVe56hcs8zVO55hso9z1C55xkq9zxD5Z5nqNzzDJV7nqFyzzNU7nmGyj3PULnnGSr3PEPlnheo3PMClXteoHLPC1TueXkIVLVIWqpA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9L1C55wUq97xA5Z4XqNzzApV7XqByzwtU7nmByj0vULnnBSr3vEDlnheo3PMClXteoHLPC1TueYHKPS9QuecFKve8QOWeF6jc8wKVe16gcs8LVO55gco9F6jcc4HKPReo3HOByj2Xh0BVi6SlBCr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPBSr3XKByzwUq91ygcs8FKvdcoHLPJVJa9Oz59eFe3lcb6Al0XW2kROE5xuvDs7+vNtAttVBtoFtqoVqBqjaQ41uoNpDjW6g20vP2utpIz9vragM5vutqIyUKL1QLpaUiJQovVOtWSx0ViPsKbGuenuergpH7let+zPY6dUqfTt3qR722VY9+vbZ1j369tpWPfr22tY96vcYzgPXrta1/9Ou1rYD067WtgfTrFbB6wfSV8Txg/XrB9JXxTGD9esH0lfFcYP16wfSV8Wxg/XrB9JXxfGD9esH0lfGMYP16wfSV8Zxg/Xqx9FU1nhWsXy+WvqrG84L168XSV/UhYPVi6atqPDdYv14sfVWNZwfr1wumr4znB+vXC6avjGcI69cLpq+M5wjr1wumr4xnCevXC6avjOcJ69cLpq+MZwrr1wumr4znCuvXC6avjGcL69cLpq+M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778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcD7rwp4/1UB778q4P1XBbz/qoD3XxXw/qsC3n9VwPuvCnj/VQHvvyrg/VcFvP+qgPdfFfD+qwLef1XA+68KeP9VAe+/KuD9VwW8/6qA918V8P6rAt5/VcH7ryp4/1UF77+q4P1X9Yb9/q3g/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQPvv2rg/VcNvP+qgfdftRv2+7eB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vx28/6qD9191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3td+hWQ+9xW9s/0KyXzuK3pv+xWS+dxX9J73KyTzua/wHfIXSOZzX+F75C+QzOe+wnfJXyCZz32F75O/QDKf+wrfKX+BZD73Fb5X/gLJfO4rfLf8BZL53Ff4fvkLJPO5r/B99BdI5nNffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/X/cHXdX/wdd0ffF33B1/XvfF13Rtf173xdd0bX9e93YxPMp37Mr6ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67o3vq574+u6N76ue+Pruje+rnvj67ovfF33ha/rvvB13Re+rvtyMz7JdO6r8HXdF76u+8LXdV/4uu4LX9d94eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33ha/rvvB13Re+rvvC13Vf+LruC1/XfeHrui+5WtBH23999Wi/f++X4FRv5RnBqT6tR+8PwaOdCE71WT0jONUn9YzgVJ/TM4JTZeQZwakS8oTgXH3YM4JzvYcnBKfKxjOCUyXjGcHGJpjNaSF3YL9EALunl4jgjqgdt+eDdPv0n95/imt/ffl/iuP+HNWj91RfIDl6T/UVkoP7oiskB3dGV0gO7o2ukGx8koP7oyskB3dIV0gO7qeu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rL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bcXsv72QtbfXsj62wtZf3sh628vZP3thay/vZD1txey/vZC1t9eyPrbC1l/eyHrby9k/e2FrL+9kPW3F7L+9kLW317I+tsLWX97IetvL2T97YWsv72Q9bdXsv72StbfXsn62ytZf3u9GZleLn9VyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXsn62ytZf3sl62+vZP3tlay/vZL1t1ey/vZK1t9eyfrbK1l/eyXrb69k/e2VrL+9kvW3V7L+9krW317J+tsrWX97Jetvr2T97ZWsv72S9bdXsv72StbfXlP1e98f+/b88n18+ObfPMi+H/0psdvrOfr4t9/5Vh7PvN9G+QHP/vSd+3h+5/3Ddy62//raYsfJ9DO5EU3/y+mn6n7X9L+dfianqul/O/1Mvl3T/3b6mVKMpv/t9E3TJ55+poSr6X87/Uw/T9H0v51+pp8uafrfTl+7Pubpa9eXdvr98Y3Lz+/7c/qp7hBp+t9OX7s+5ulr18c8fe360k6/vaZfT6Zvmj7x9LXrY56+dn3M09euj3n62vUxT1+7vrTTL49HLvXkd3pT3cTU9L+dvnZ9zNPXro95+tr1MU/fNH3i6WvXxzx97fqYp69dH/P0tetjnr52fcTTT3WfXdP/dvra9TFPX7s+5ulr18c8fdP0iaevXR/z9LXrY56+dn3M09euj3n62vURT39o18c8fe36mKevXR/z9LXrY56+afrE09euj3n62vUxT1+7Pubpa9fHPH3t+nin327a9TFPX7s+5ulr18c8fe36mKdvmj7x9LXrY56+dn3M09euj3j6m/L+2ulv9xk8p79Vz+l/vM3RNuV95ukr7zNPX3mfefqm6RNPX3mfefrK+8zTV95nnr5+t4d5+vrdHuLp79r1MU9fu7600/94jbHt2vUxT1+7Pubpm6ZPPH3t+tJO/+NFtrZr18c8fe36mKevXR/z9LXrI57+oV0f8/S160s7/c+/03to18c8fe36mKdvmj7x9LXrY56+dn3M09euj3n62vUxT1+7PuLpm3Z9zNPXro95+tr1MU9fuz7m6ZumTzx97fqYp69dH/P0tetjnr52fczT166PePpFuz7m6WvXxzx9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"},{"name":"claim","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"},{"name":"secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"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"},{"name":"claim_public","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"},{"name":"secret","type":{"kind":"field"},"visibility":"private"},{"name":"leaf_index","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"5X1tjyTpjdx/2c+CkSSfF1J/xTAM3Z3OECCsDiedAUO4/+4cu7O6BpOzOaOrioqo55NmtVnN4E4HyaqOiP77L//yx3/6j//1P//067/+5a+//P6///2XP//ln//wtz/95df9n/7+y/bfrP2///ev//aHX7/8H3/92x/+/W+//H773S9//PVf9v/9z9/98q9/+vMff/m9Z//P//G7Ly/oP/uC8bMvmD/7gvzZF9RPvsC3n32B/ewL/GdfED/7gp/9m/af/Zv207/p1sw/XtNam1+97HffPB09Px6OXnfPjo8S8/kl8vkl6uklYnt+CXt+CX9+iXh+ifb8Ev35JZ7P7ng+u+P57I7ns7s9n93t+exuz2d3ez672/PZ3Z7P7vZ8drfns7s9n93t+ezuz2d3fz67+/PZ3Z/P7v58dvfns7s/n939+ezuz2d3fz67x/PZPZ7P7vF8do/ns3s8n93j+ewez2f3eD67x/PZPZ7P7vl8ds/ns3s+n93z+eyez2f3fD675/PZPZ/P7vl8ds/nszufz+58Prvz+ezO57M7n8/ufD678/nszuezO5/P7nw+u+v57K7ns7uez+56Prvr+eyu57O7ns/uej676/nsruez27YNUMMANRxQIwA1GqBGB9QYgBoTUCMBNQA8NwDPDcBzA/DcADw3AM8NwHMD8NwAPDcAzw3Acwfw3AE8dwDPHcBzB/DcATwHyNgMoGMzgJDNAEo2A0jZDKBlM4CYzQBqNgPI2QygZzOAoM0AijYDSNoMoGkzgKjNAKo2A8jaDKBrM4CwzQDKNgNI2wygbTOAuM0A6jYDyNsMoG8zgMDNAAo3A0jcDKBxM4DIzQAqNwPI3AygczOA0M0ASjcDSN0MoHUzgNjNAGo3A8jdDKB3M4DgzQCKNwNI3gygeTOA6M0AqjcDyN4MoHszgPDNAMo3A0jfDKB9M4D4zQDqNwPI3wygfzOAAM4ACjgDSOAMoIEzgAjOACo4A8jgDKCDM4AQzgBKOANI4QyghTOAGM4AajgDyOEMoIdzgB7OAXo4B+jhHKCH860BanRADUAMDEAP5wA9nAP0cA7QwzlAD+cAPZwD9HAO0MM5QA/nAD2cA/RwDtDDOUAP5wA9nAP0cA7QwzlAD+cAPZwD9HCOiHVD5Lohgt0AejgH6OEcoIdzgB7OAXo4B+jhHKCHc4AezgF6OAfo4Rygh3OAHs4BejgH6OEcoIdzgB7OAXo4B+jhHKCHc4AezgF6OAfo4Rygh3OAHs4BejgH6OEcoIdzgB7OAXo4B+jhHKCHc4AezgF6OAfo4Rygh3OAHs4BejgH6OEcoIdzgB7OAXo4B+jhHKCHc4AezgF6OAfo4Rygh/OJ+PUKAJ4D9HAO0MM5QA/nAD2cA/RwDtDDOUAP5wA9nAP0cJ6I36MC4DlAD+cAPZwD9HAO0MM5QA/nAD2cA/RwDtDDOUAP54X4hUmI35gE+JVJAD1cAPRwAdDDxdYANQC/NwmghwuAHi4AergA6OHCEL8aDcDzh+jh6vawt69qfPtspX08a5vF58N+8qxFjePhFl89/AE+lME3ZfBdGfxQBj+Vwacy+BIG/xBd58vAmzJ45Q3ryhv2IdrZl4FX3rCuvGFdecO68oZ15Q0byhs2lDdsKG/YUN6wD1Gtvwy88oYN5Q0byhs2lDdsKG/Yprxhm/KGbcobtilv2If4RV4GXnnDNuUN25Q3bFPesE15w3blDduVN2xX3rD9qRv2o0YD1HjAvmqtjoenQf8ShjL4qQw+lcGXMPhHuOFeB96Uwbsy+FAG35TBK2/Yobxhh/KGHcobdihv2Km8Yafyhp3KG3Yqb9hHeH1fB155w07lDTuVN+xU3rBTecOm8oZN5Q2byhs2lTfsI1z2rwOvvGFTecOm8oZN5Q2byhu2lDdsKW/YUt6wpbxhH5Fv8Trwyhu2nrphP2rMp9doj0iZaLUdD5ef1XBAjQd8M/V+fIP0UWc1BqDGBNRIQI16fo1HpDOMefBjnH5fPSKd4bKGA2oEoEYD1OiAGgNQYwJqJKBGPb+GA3juAJ47gOcO4LkDeO4AnjuA5w7guQN47gCeB4DnAeB5AHgeAJ4HgOcB4HkAeB4AngeA5wHgeQPw/BFGvLn1j4en5VkNB9QIQI0GqNEBNQagxgTUSECNen6NR/iMLmsAeN4BPO8AnncAzzuA5x3A8w7geQfwvAN4PgA8HwCeDwDPB4DnA8DzAeD5APB8AHg+ADwfAJ5PAM8ngOeP0FzPOH42MVs7qxGAGg1QowNqDECNCaiRgBr1/BqP0Kpe1jBADQDPE8DzBPA8ATxPAM8TwPME8DwBPC8AzwvA8wLwvAA8LwDPC8DzAvC8ADwvAM/r+Tzv2waoYYAaDqjxCJ73edSY21mNBqjRATUGoMYE1EhAjXp+jUfo4S5rGKCGA2oAeG4AnhuA5wbguQF4bgCeG4DnDuC5A3juAJ47gOcO4LkDeO4AnjuA5w7guQN4HgCeB4DnAeB5AHgeAJ4HgOcB4HkAeB4Anj9CD5dbfDyc8XWNb5+1zQ5AtsXdT6+iPhA9Qj33YERGh8jpEAUdokaHqNMhGnSIJhrRuBlh9z9/hejbp3vdVLnb3Vce80Cf0uhLGX3fpNG7NPpgRj/8+Ex8hJ2hb9LouzT6IY2eet5foqee9+Pmjh/jDP2gnveX6E0aPfW2ukTPPTHzSAIZ6WfouSfmFXrqmZPjuHPq/tkb+kk9c6ofX7lGO0NPPXMu0VPPnEv01BfyJfomjZ563l+ip573l+ipP8+5Qz/jDD31fX+JnnrXVvcb+jxBn9y7to3fRs+9a6/Qc+/aK/Tcu/YKPfeureO9VVWdoefetdl/G/13du3MA323doHeNz8Q+dY/e7UvfX/zdOTxcPO7Z/0Mvd8CPuPO9/fl2Q/0qYz+e24NEfQmjd6l0Yc0+iaNvj8X/UeVAakyH1FlzFuVrIu/iXn7m5jV777ydiBKOkRFhmhsGx0io0PkdIiCDlGDIxpxQzS+QnRyucbtk+mvsqLPnp09b1/3DrEfjfZVGp2rNFqLNGq2SqO+SqOxSqOrrBdbZb3YWKXRVfbodwyUPW4fXvY+Lhq1rX/+Gp4xTg7N79gbH13FvlPFvlfl43X+D74u/sHXtX/wdedjZp+zx+tGXf1X9PDje8fjrkrFycNtHJ8d9/tPQmyc/2zr9jF5z7t3G4fOfXzHiygDf2rDT234JQ3/O75PGfimDd+14Yc2/KYNX3vrhvbWjUds3Xa7l7319tvwe2zH1b4fZPO3Hx6f1/WYs98//AH/EVu35fHWwPvmF/D3Rw743usCvvfj72o/b+wE/iO2brfbD6H6nbjhO//1R7v9179TeJ3DT/9UXsf4Fn57yNa9CSi858X3vvU8vh+s333k/uW7/wOS8UFyPkjBB6nxQep8kAYfpMkHKfkgFR2kzje9O9/07nzTu/NN7843vTvf9O5807vzTe/ON7073/QefNN78E3vwTe9B9/0HnzTe/BN78E3vQff9B5803vwTe/JN70n3/SefNN78k3vyTe9J9/0nnzTe/JN78k3vSff9E6+6Z180zv5pnfyTe/km97JN72Tb3on3/ROvumdfNO7+KZ38U3v4pvexTe9i296F9/0Lr7pXXzTu/imd9FN77nRTe+50U3vudFN77nRTe+50U3vudFN77nRTe+50U3vudFN77nxTW/jm97GN72Nb3ob3/Q2vultfNPb+Ka38U1v45vexje9nW96O9/0dr7p7XzT2/mmt/NNb+eb3s43vZ1vejvf9A6+6R180zv4pnfwTe/gm97BN72Db3oH3/QOvukdfNObz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJaTz2s5+byWk89rOfm8lpPPazn5vJbJ57VMPq9l8nktk89rmRvd9E4+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsnntUw+r2XyeS2Tz2uZfF7L5PNaJp/XMvm8lsXntSw+r2XxeS2Lz2tZG930Lj6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1LD6vZfF5LYvPa1l8Xsvi81oWn9ey+LyWxee1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"},{"name":"mint_public","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"amount","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"check_balance","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"fee_limit","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"5ZztjpTHFYTvZX+jqM/pqv7gVqIowjaOkNBiGRwpQr73LMl8LNqRlzqZrKfEL3uhe/r0VjHF1rw8n+9+evvDb//4+7v7nz98vHv918937z/8+ObTuw/3D199vmt/ifjPr3785c39l1/4+OnNr5/uXrdXd2/vf3r47++v7n5+9/7t3etc/P1vr75sSHVDVzdA3UB1w1A3THXDUjdscUM2dYOqdKpKp6p0qkqnqnSqSqeqdKpKp6p0V5XuqtJdVbqrSndV6a4q3VWlu6p0V5XuqtJQlYaqNFSloSoNVWmoSkNVGqrSUJWGqjRVpakqTVVpqkpTVZqq0lSVpqo0VaWpKj1UpYeq9FCVHqrSQ1V6qEoPVemhKj1UpYeq9FSVnqrSU1V6qkpPVempKj1Vpaeq9FSVnqrSS1V6qUovVemlKr1UpZeq9FKVXqrSS1V6qUpvVemtKr1Vpbeq9FaV3qrSW1V6q0pvVemtKh2tyTvk7qTJ5UmT25Mm1ydN7k+aXKA0uUFpcoXSZM1D1lzvy/TCTG/M9MpM78z00kxvzfTaTO7NQi7OIvWOVNZc7s5CLs9Cbs9Crs9C7s9CLtBCbtBCrtBC7tCi68W4rLlco4Xco4VcpIXcpIVcpYXcpYVcpoXcpoVcpwX0T0NkzeVGLeRKLeROLeRSLeRWLeRaLeReLeRiLeRmLeRqLeRuLeRyLeR2LeR6LeR+LeSCLeSGLeSKLeSOLeSSLYb+uaesudyzhVy0hdy0hVy1hdy1hVy2hdy2hVy3hdy3xdQ/7JY1lyu3kDu3kEu3kFu3kGu3kHu3kIu3kJu3kKu3WPoTDrLmcvsWcv0Wcv8WcgEXcgMXcgUXcgcXcgkXcgsXW3+sRX+uRX6wRe7hUu7hUu7hUu7hUu7hUu7hUu7hUu7hUu7hMvSHmWTN5R4u5R4u5R4u5R4u5R4u5R4u5R4u9efX9AfYCk+wyZrrz7DpD7HpT7Hpj7Hpz7HpD7LJPVzKPVzKPVx2/bFFWXO5h0u5h0u5h0u5h0u5h0u5h0u5h0u5h0u5h0voz6rKmss9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XMo9XA79qXRZc7mHS7mHS7mHS7mHS7mHS7mHS7mHS7mHS7mHy6n/UwRZc7mHS7mHS7mHy8s9HPs+biJif7Xv1ZPVyNUPq9HbeTVwYfHkOqydG+cXzuM8eWPz4Mbm4Y3NM25snnmFeXqu0zx9PJ7ncMh6iUP2NQ4ZPB0y4+khl0tc+RCcDlntwiH5EodcDBaC43TIHM8cwjgZkQ9t9Wn17hcWD7TjSw/kV4sPE11+63i4yXmi+cxEux9Nstc6rQ3khbUPn7Af1j50wY/+ZFwafjPj+ML8cvJxdd/H6Wk9/bCeflpPv6yn38bT98sft9hMn9bTd+vpndOqN+e06s05rXpzTqvenNOqN+u0uvzRss301lkbV8jaaOP481JEtmfmv1xDXfoJ/zj6HI+/JzhODtvJaTv5sJ182k6+bCffrpNns508bCe3TaLstpPbZmjaZmjaZmjaZmjaZmjaZmi3zdBum6HdNkO7bYZ22wztthnabTO022Zot83QbpuhsM1Q2GYobDMUthkK2wyFbYbCNkNhm6GwzVDYZihtM5S2GUrbDKVthtI2Q2mbobTNUNpmKG0zlLYZOmwzdNhm6LDN0GGbocM2Q4dthg7bDB22GTpsM3TYZui0zdBpm6HTNkOnbYZO2wydthk6bTN02mbotM3QaZuhyzZDl22GLtsMXbYZumwzdNlm6LLN0GWbocs2Q5dthm7bDN22GbptM3TbZug1uDt/0uS2GbptM3TbZui2zdDtmqForhmK5pqhaK4ZiuaaoWiuGYrmmqForhmK5pqhaK4ZimaboWGboWGboba0H4RthtpyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKYItpwi2nCLYcopgyymCLacItpwi2HKKYMspgi2nCLacIthyimDLKaItp4i2nCLacopoyylic81Q2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4i2nCLacopoyymiLaeItpwi2nKKaMspoi2niLacItpyimjLKaItp4jfwClaeG7y6OfJB7465enqvo4vjTx/TyL3hbW5jtP3WF+tPUw/radf1tNv4+nHN3CLbnn6+P9OfzglX+SUfo1TJk6n7PGMEjHm8e3z4X/3+bV7O86EG5yJNzjTuMGZ5g3OtG5wpv3yM53+MhJjta9meroauY7vHOjtfIOLLz25jn/N2Y+GzsNdo31Hd83v6K79O7orvqO78sbv2nOd7trH47seLjDcLzBv/QKDpwvMuHCBdfMXwOkCj1afL/B8Pu/nOoWx8njIWH09PeQbsDlXOCRe4pC8xiHg6ZBxQZNv4MZc4RC8xCG8iib9fEj+8Tt+j9FOP9PO8+J+HGi99ECZeRwoO54MhKt8h/bxLWHsxqcyfMM/6Xv+kB15OuRRtXA+ZF7lJu18yP7ftGZ76YGe0Xpc4zu0edZ69T8eKPvJqdnZng60b2ygKRv1sG8V9+3avtWK+6K4L4v7enEfivtY3FfUfc3ivqJfVtEvu+iXXfTLLvplF/2yi37ZRb/sol920S+76Jdd88tsrbgvivuyuK8X96G4j8V9o7hvFvet4r6iX6Lolyj6JYp+iaJfouiXKPolin6Jol+i6Jco+iWLfsmiX7Lolyz6JYt+yaJfsuiXLPoli37Jol960S+96Jde9Esv+qUX/dKLfulFv/SiX3rRL73oFxT9gqJfUPQLin5B0S8o+gVFv6DoFxT9gqJfWPQLi35h0S8s+oVFv7DoFxb9wqJfWPQLi34ZRb+Mol9G0S+j6JdR9Mso+mUU/TKKfhlFv4yiX2bRL7Pol1n0yyz6ZRb9Mot+Kfa0cxb9Uux3Z7HfnYV+9+Grf7759d2bH96//fiw58tv/nb/46d3H+4PX3761y///Z2Htf8G"},{"name":"set_portal","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"},"visibility":"private"}],"return_type":null},"bytecode":"H4sIAAAAAAAC/72WzY7TMBDH3XbbbbtJyva7Tb+Sxg0SFy7sBcGdM08AAgkk4IDgAI/CO/Ai+xC8AXckDotn7PE/aXYrRUIbye14/P/NjD2R4ky1lOqeKfOslXvMrKsi1TF/TRrPlVjGoNGIVENcmhaJspbxq5Z2gDpjy2RQ7dT8XDxRkixTbVV+SN/hrHZUFRT73CrOaWRUO3v7WjSmlJYz+zaPaHp504WmWbcAW6TnkF7mI1xAFHTYvCDTjDCh9ZisqwYqbLnDIFmoaSGkqLZmF7y0qxvzkMoqSBwaxc3RQ0mtgnIHiFFIrSKriGg0fTiahkdT5adBmeues9lzu4h4k4/IwiarbaGnF3my18ZuKRAHeUzWnUGe/rhuls+pXzj523oblHsbcW/71d4GFolkr1gJ0VA6iQGX+Yysuxo64IYOKFTbN6OHqHtu+i3FhuViB3jBTLMbL83/A2Qi8aVuWqe6BHZpNaE1GX0Ht6BDRkkwBDoEOnToK7gFHTFKghHQEdCRQz/DLeiYURKMgY6Bjh36Fm5BJ4ySYAJ0AnTi0DdwCzpllARToFOgU4e+gFvQGaMkmAGdAZ059CPcgs4ZJcEc6Bzo3P7XRky2r3ALumCUBAugC6ALh36BW9AloyRYAl0CXVYLXfpX4ARisr2GW9CYURLEQGOgsUM/wC3oilESrICugK6qha78W3MCMdl2cAu6ZpQEa6BroOtqtrU/lppIXB8Z1UfG97KXyWnEHPY3uAXdMEqCDdAN0E0128b35wRisr2HW9AtoyTYAt0C3Tr0E9yC7hglwQ7oDuiuWujOZ6uJLO4ly7A+Ev/3wsxhf4db0IRREiRAE6BJNVvi3/SayOQ0wp/9v/iIZwwqfLnlU81CLZ9zE/GscIFJOVVaTrW3cGJNWSFzjxuAttcQ7VYO5sCIzRscIicXDc7+x85kj8TkWmQZstmFpttNjopy5ZMRoqkDvwtlHRV8JRfYDCFSfzYBziY9uo1he2nluvjrJ4W2N70EDQlcmJDrTuy74+9qVpO6ctLCGftyUpSzL5cTPnQ3QXvbx4L28B6wLsNZVlyRkyLRgStt26aJ/IATpr7pwtn7ZBrJ8nKyw0P33vCsw5ubX9P4B9hf6AanDQAA","debug_symbols":"5Z3rShtRGEXfJb+lzN7n7quUUlIvRZAoXgpFfPeaxkTFlIAdF2eYf07yzex9GNYZlIXzsDg9+3H/8/vF6vzqdnH89WFxeXWyvLu4Wj0dPSyGL9LfT2+vl6v1B7d3y5u7xXFQGI4WZ6vT9Y85Px4tzi8uzxbHrunx6N20B+fnaQ+p7KYVy57pULfD0a9m3fZduWpXo76Z/Xa0Lh+mXD5NuXyecvky5fJ1yuXbhMt7+NzymxARIR4jJJddSG0HbkPZ3YbS0qsrD8+FQm+FYm+FUm+Fcm+FSm+Fam+FGl4oh12h/KbQ+9kW2vNsy+3AbEl1d934MuvNOsMwk3V6JuuMM1lnnsk6y0zWWWeyzpk8V+JMnitRM1nnTJ6f8fBvV+XtOjenpY+dlj92WvnYaf/YY+v2rgSHQ/dQyX6eVkqJ+4tCGqZcXlMu7ymXD1MuH6dcPn1u+U1IJkLKGCHlJaTmPSGVCGlASB6IEBEhJkLCyCFNe0IiEZKIkEyEFCKkEiENCCkDESIixEQIQXwhiC8E8YUgvhDEF4L4QhBfCeIrQXwliK8E8ZUgvhLEV4L4ShBfCeIrQXwjiG8E8Y0gvhHEN4L4RhDfCOIbQXwjiG8E8RoGJEVIipGUgKREJCUhKRlJKUhKRVIQ9oWwL4R9IewLYV8I+0LYF8K+EPaFsC+EfSPsG2HfCPtG2DfCvhH2jbBvhH0j7BthPyDsB4T9gLAfEPYDwn5A2A8I+wFhPyDsB4T9iLAfEfYjwn5E2I8I+xFhPyLsR4T9iLAfEfYTwn5C2E8I+wlhPyHsJ4T9hLCfEPYTwn5C2M8I+xlhPyPsI86eEGlPiLUnRNsT4u0JEfeEmHtC1D0h7p4QeU+IvSdE3xPi7wkR+IQYfEIUPiEOnxCJT4jFJ0TjE+LxCRH5hJh8QlQ+IS6fEJlPiM0nROcT4vMJEfqEGH1ClD4hTp8QqU+I1SdE6xPi9Rnx+ox4fUa8PiNen4eIpCQkJSMpBUmpSArCPuL1GfH6jHh9Rrw+I16fEa/PiNdnxOsz4vUZ8fqMeH1GvD4jXp8Rr8+I12fE6zPi9Rnx+ox4fUa8PiNenxGvz4jXZ8TrM+L1GfH6jHh9Rrw+I16fEa/PiNdnxOsz4vUZ8fqMeH1GvD4jXp8Rr8+I12fE6zPi9XkUr6+kuE0prb5JeT+dd8P51X8HfXn/xCgO4LiNQneNYneNUneNcneNaneNWm+NRjEax23U3Q6Zu9shc3c7ZO5uh8zd7ZC5ux1yFAu0pu202hD+t1HtrlHrrdEoJuq4jdRdI3fXKHTXKHbXKHXXKHfXqLs9u3S3Z5fu9uza0579dPRreXOx/HF5tn5h7/rL+9XJ9v29T4d3v6833zzN/gE="},{"name":"balance_of_public","is_unconstrained":true,"custom_attributes":["aztec(public)","aztec(view)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"owner","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"}},"bytecode":"H4sIAAAAAAAC/83YW2/rRBAH8E0apyU0ztVp7o2buLm7PSUgjqA8IiQekXgEcRcSN3ER4ivypWBndmf/SX3kaqUj60Ry44zntzO7TtpsF+pMqYtA6cdE2UdFR1SoqvqpTMdHSs70CR2lUJUklNBFUuZMx9VZYoGq8JmuoIIb/eMyUWaEi8q7dKFCYy1UidB5QGNSbXWuj+qCGlPv66OWSGO6zpk9rdEPk0PsrQWu6AE/1s9vm+QLm3yZlE1QXYJdmpyaOWX6F8JC60wpoQ5aB61b+gvCQkOmlBCChqChpd8gLLTBlBIaoA3QhqV/Iiy0yZQSmqBN0KalPyIstMWUElqgLdCWpb8iLLTNlBLaoG3QtnnOkno+0dVmCAvtMKWEDmgHtGPp1wgL7TKlhC5oF7Rr6VcIC42YUkIEGoFGlv6EsNAeU0rogfZAe9nl6blqnqTuT8J8ouf0HcJCr5hSwhXoFeiVpV8iLLTPlBL6oH3QfrbRvnuD5RBd7XuEhQ6YUsIAdAA6yFYbuAZziK72G8JCh0wpYQg6BB1mqw3d7xhP0vEnkT9p+pPQn7QLqdL1J/VC5tIqpLFn7r5+R/+DsNARU0oYgY5AR9lqI7cMnqTjT3qFNBb6k64/iQohz6yYfhd8i7DQMVNKGIOOQcfZamO32DlEV/sDYaETppQwAZ2ATrLVJu6LjyfpFlKl6U/CQuYSFUKG+SSm+BTf/V8yVPjCL9/weaOSyC5Aj1hReEy51PS01LXBE3MqV2hzcY2NQ1zl09gm3diNybzEQ8wpRAe3OTKvZI4UmyeSNkM1c6FsgmqOjubKFSMS68ul5lFbTxp+r2Rn+9Lk8ByTow2bTGJ6ui+qYnrThQrU6YPvAm/0uJK9IRU7TI37npgPqAxob8PUtjN9FQnyyUlLMpnrDypHORVzZ572S4+Z6ZeWcxbwac2+DBZcTt2YnWRgb1hsinxI7xm3YnOsWHK6Ygu0l+gBP9PPtyZ5bpOXPMlbOgNbmpzEnNJzljT8SSuf6AZ/R1joiiklrEBXoKtstZX7zZFDdLUfEBa6ZkoJa9A16Dpbbe3+BHmStj8Z+5PIn7T8SeO1T1/fn3uEhW6YUsIGdAO6yVbbuGqepO5PWv6kUchcuv4kKoQ8s2L6XfA3wkK3TClhC7oF3Warbd2n1JOM8oluMEVY6I4pJexAd6C7bLWdu7We5NafNPxJy58s/UnXn6z8Sa+Q+zL2J1Eh96VRyFyeWTH9ufkZYaF7ppSwB92D7rPV9u5/TZ5k7E8a/qT9pjbW9SfLN3XF+oXMpeVPdq99+vpz8wJhoSlTSkhBU9A0Wy11f6JyCO3oyp9i3/HIUGGzIbuL1G0+EjPi8S72jkvdnZa6Nzg1p3KFNjb32LQ8mF3sg016x+5iD2YXe6AQHdzmJ+aVzJHMIZG0F6hmLpRNUB3Q0UG5YkQeZnrQx6O2njTMu1ia7SOGuHNrE2Bt7k73ZPGybPd5vLHLbC1jezU+GrbqNp28ijzfz10T9nFmynJamtjbqWqh21fqEYP/njzImAyiwTmfxvalKfTFaaGQ7y2PFyK75KoEtpJNP2pQpQZQWym/QWJpsux4asLSEa+G+/dInIgqz+m0/y8d/wMOUhUC9x0AAA==","debug_symbols":"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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fGs0oWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+FlP93XaJ/f7m6jFUbbjYwio5LRVkazjJqMFhl1GUkRWyliliJmKWKWImYpYpYiZililiJmKWKWImYpokkRTYpoUkSTIpoU0aSIJkU0KaJJEU2KWKSIRYpYpIhFilikiEWKWKSIRYpYpIhFiuhSRJciuhTRpYguRXQpoksRXYroUkSXIoYUMaSIIUUMKWJIEUOKGFLEkCKGFDGkiFWKWKWIVYpYpYhVililiFWKWKWIVYpYpYhsNrQKrYpWW1rNtGq0WmjVaTVoRW2E2gi1EWoj1EaojVAboTZCbYTaCLVR1EZRG0VtFLVR1EZRG0VtFLVBoBkSzRBphkwzhJoh1QyxZsg1Q7AZks0QbYZsM4SbId0M8WbIN0PAGRLOEHGGjDOEnCHlDDFnyDlD0BmSzhB1hqwzhJ0h7QxxZ8g7Q+AZEs8QeYbMM4SeIfUMsWfIPUPwGZLPEH2G7DOEnyH9DPFnyD9DABoS0BCBhgw0hKAhBQ0xaMhBQxAaktAQhYYsNIShIQ0NcWjIQ0MgGhLREImGTDSEoiEVDbFoyEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFyy56kosWuWiRixa5aJGLFrlokYvWf7vo9fRz937YPbzsb3d7bx8/jo//rvpej+dfb3+/XP/9DQ=="}],"outputs":{"globals":{"storage":[{"fields":[{"name":"balances","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"portal_address","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"artifact_hash","type":{"kind":"field"}},{"name":"private_functions_root","type":{"kind":"field"}},{"name":"public_bytecode_commitment","type":{"kind":"field"}},{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}}],"kind":"struct","path":"GasToken::deploy_parameters"}}],"kind":"struct","path":"GasToken::deploy_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"portal_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}}],"kind":"struct","path":"GasToken::set_portal_parameters"}}],"kind":"struct","path":"GasToken::set_portal_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::_increase_public_balance_parameters"}}],"kind":"struct","path":"GasToken::_increase_public_balance_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}},{"name":"secret","type":{"kind":"field"}},{"name":"leaf_index","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::claim_public_parameters"}}],"kind":"struct","path":"GasToken::claim_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"owner","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}}],"kind":"struct","path":"GasToken::balance_of_public_parameters"}},{"name":"return_type","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::balance_of_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::mint_public_parameters"}}],"kind":"struct","path":"GasToken::mint_public_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"to","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"amount","type":{"kind":"field"}},{"name":"secret","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::claim_parameters"}}],"kind":"struct","path":"GasToken::claim_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"fee_limit","type":{"kind":"field"}}],"kind":"struct","path":"GasToken::check_balance_parameters"}}],"kind":"struct","path":"GasToken::check_balance_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"122":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr","source":"#[oracle(packArgumentsArray)]\nunconstrained fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {}\n\n#[oracle(packArguments)]\nunconstrained fn pack_arguments_oracle(_args: [Field]) -> Field {}\n\n/// - Pack arguments (array version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments_array(args: [Field; N]) -> Field {\n pack_arguments_array_oracle(args)\n}\n\n/// - Pack arguments (slice version) will notify the simulator that these arguments will be used later at\n/// some point in the call. \n/// - When the external call is made later, the simulator will know what the values unpack to.\n/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments \n/// itself.\nunconstrained pub fn pack_arguments(args: [Field]) -> Field {\n pack_arguments_oracle(args)\n}\n\n"},"125":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_public_data_witness.nr","source":"use dep::protocol_types::{\n constants::PUBLIC_DATA_TREE_HEIGHT, hash::pedersen_hash,\n public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::{Hash, Serialize},\n utils::arr_copy_slice\n};\n\nglobal LEAF_PREIMAGE_LENGTH: u32 = 4;\nglobal PUBLIC_DATA_WITNESS: Field = 45;\n\nstruct PublicDataWitness {\n index: Field,\n leaf_preimage: PublicDataTreeLeafPreimage,\n path: [Field; PUBLIC_DATA_TREE_HEIGHT],\n}\n\n#[oracle(getPublicDataTreeWitness)]\nunconstrained fn get_public_data_witness_oracle(\n _block_number: u32,\n _leaf_slot: Field\n) -> [Field; PUBLIC_DATA_WITNESS] {}\n\nunconstrained pub fn get_public_data_witness(block_number: u32, leaf_slot: Field) -> PublicDataWitness {\n let fields = get_public_data_witness_oracle(block_number, leaf_slot);\n PublicDataWitness {\n index: fields[0],\n leaf_preimage: PublicDataTreeLeafPreimage { slot: fields[1], value: fields[2], next_index: fields[3] as u32, next_slot: fields[4] },\n path: arr_copy_slice(fields, [0; PUBLIC_DATA_TREE_HEIGHT], 1 + LEAF_PREIMAGE_LENGTH)\n }\n}\n"},"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"136":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr","source":"use dep::protocol_types::{\n address::AztecAddress, contract_instance::ContractInstance, utils::arr_copy_slice,\n constants::CONTRACT_INSTANCE_LENGTH, utils::reader::Reader\n};\n\n#[oracle(getContractInstance)]\nunconstrained fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}\n\n// Returns a ContractInstance plus a boolean indicating whether the instance was found.\n#[oracle(avmOpcodeGetContractInstance)]\nunconstrained fn get_contract_instance_oracle_avm(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {}\n\nunconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n get_contract_instance_oracle(address)\n}\n\nunconstrained fn get_contract_instance_internal_avm(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH + 1] {\n get_contract_instance_oracle_avm(address)\n}\n\npub fn get_contract_instance(address: AztecAddress) -> ContractInstance {\n let instance = ContractInstance::deserialize(get_contract_instance_internal(address));\n assert(instance.to_address().eq(address));\n instance\n}\n\npub fn get_contract_instance_avm(address: AztecAddress) -> Option {\n let mut reader = Reader::new(get_contract_instance_internal_avm(address));\n let found = reader.read();\n if found == 0 {\n Option::none()\n } else {\n Option::some(reader.read_struct(ContractInstance::deserialize))\n }\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"139":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/get_l1_to_l2_membership_witness.nr","source":"use dep::protocol_types::{address::AztecAddress};\n\nglobal L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH: u64 = 17;\n\n// Obtains membership witness (index and sibling path) for a message in the L1 to L2 message tree.\n#[oracle(getL1ToL2MembershipWitness)]\nunconstrained fn get_l1_to_l2_membership_witness_oracle(\n _contract_address: AztecAddress,\n _message_hash: Field,\n _secret: Field\n) -> [Field; L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH] {}\n\nunconstrained pub fn get_l1_to_l2_membership_witness(\n contract_address: AztecAddress,\n message_hash: Field,\n secret: Field\n) -> [Field; L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH] {\n get_l1_to_l2_membership_witness_oracle(contract_address, message_hash, secret)\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"144":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/public_mutable.nr","source":"use crate::context::{PublicContext, UnconstrainedContext};\nuse crate::oracle::storage::storage_read;\nuse crate::oracle::storage::storage_write;\nuse dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:public_mutable_struct\nstruct PublicMutable {\n context: Context,\n storage_slot: Field,\n}\n// docs:end:public_mutable_struct\n\nimpl Storage for PublicMutable {}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_new\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n PublicMutable { context, storage_slot }\n }\n // docs:end:public_mutable_struct_new\n}\n\nimpl PublicMutable {\n // docs:start:public_mutable_struct_read\n pub fn read(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n // docs:end:public_mutable_struct_read\n\n // docs:start:public_mutable_struct_write\n pub fn write(self, value: T) where T: Serialize {\n let fields = T::serialize(value);\n storage_write(self.storage_slot, fields);\n }\n // docs:end:public_mutable_struct_write\n}\n\nimpl PublicMutable {\n pub fn read(self) -> T where T: Deserialize {\n // This looks the same as the &mut PublicContext impl, but is actually very different. In public execution the\n // storage read oracle gets transpiled to SLOAD opcodes, whereas in unconstrained execution the PXE returns\n // historical data.\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n"},"147":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_immutable.nr","source":"use crate::{\n context::{PrivateContext, PublicContext, UnconstrainedContext},\n oracle::{storage::{storage_read, storage_write}}, state_vars::storage::Storage\n};\nuse dep::protocol_types::{constants::INITIALIZATION_SLOT_SEPARATOR, traits::{Deserialize, Serialize}};\n\n// Just like PublicImmutable but with the ability to read from private functions.\nstruct SharedImmutable{\n context: Context,\n storage_slot: Field,\n}\n\nimpl Storage for SharedImmutable {}\n\nimpl SharedImmutable {\n pub fn new(\n // Note: Passing the contexts to new(...) just to have an interface compatible with a Map.\n context: Context,\n storage_slot: Field\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n}\n\nimpl SharedImmutable {\n // Intended to be only called once. \n pub fn initialize(self, value: T) where T: Serialize {\n // TODO(#4738): Uncomment the following assert\n // assert(\n // self.context.public.unwrap_unchecked().is_deployment(), \"SharedImmutable can only be initialized during contract deployment\"\n // );\n\n // We check that the struct is not yet initialized by checking if the initialization slot is 0\n let initialization_slot = INITIALIZATION_SLOT_SEPARATOR + self.storage_slot;\n let fields_read: [Field; 1] = storage_read(initialization_slot);\n assert(fields_read[0] == 0, \"SharedImmutable already initialized\");\n\n // We populate the initialization slot with a non-zero value to indicate that the struct is initialized\n storage_write(initialization_slot, [0xdead]);\n\n let fields_write = T::serialize(value);\n storage_write(self.storage_slot, fields_write);\n }\n\n pub fn read_public(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n\nimpl SharedImmutable {\n pub fn read_public(self) -> T where T: Deserialize {\n let fields = storage_read(self.storage_slot);\n T::deserialize(fields)\n }\n}\n\nimpl SharedImmutable {\n pub fn read_private(self) -> T where T: Deserialize {\n let header = self.context.get_header();\n let mut fields = [0; T_SERIALIZED_LEN];\n\n for i in 0..fields.len() {\n fields[i] =\n header.public_storage_historical_read(\n self.storage_slot + i as Field,\n (*self.context).this_address()\n );\n }\n T::deserialize(fields)\n }\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"21":{"path":"std/field/bn254.nr","source":"use crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\nglobal TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n let x_bytes = x.to_le_bytes(32);\n\n let mut low: Field = 0;\n let mut high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n low += (x_bytes[i] as Field) * offset;\n high += (x_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n\n (low, high)\n}\n\nunconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nfn compute_lt(x: Field, y: Field, num_bytes: u32) -> bool {\n let x_bytes = x.to_le_radix(256, num_bytes);\n let y_bytes = y.to_le_radix(256, num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i];\n let y_byte = y_bytes[num_bytes - 1 - i];\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\nfn compute_lte(x: Field, y: Field, num_bytes: u32) -> bool {\n if x == y {\n true\n } else {\n compute_lt(x, y, num_bytes)\n }\n}\n\nunconstrained fn lt_32_hint(x: Field, y: Field) -> bool {\n compute_lt(x, y, 32)\n}\n\nunconstrained fn lte_16_hint(x: Field, y: Field) -> bool {\n compute_lte(x, y, 16)\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n let borrow = lte_16_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size(128);\n rhi.assert_max_bit_size(128);\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size(128);\n xhi.assert_max_bit_size(128);\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(compute_lt(b, a, 32));\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n compute_lt(b, a, 32)\n } else if a == b {\n false\n } else {\n // Take a hint of the comparison and verify it\n if lt_32_hint(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{decompose_hint, decompose, compute_lt, assert_gt, gt, lt, TWO_POW_128, compute_lte, PLO, PHI};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_decompose_unconstrained() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n fn check_compute_lt() {\n assert(compute_lt(0, 1, 16));\n assert(compute_lt(0, 0x100, 16));\n assert(compute_lt(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lt(0, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_compute_lte() {\n assert(compute_lte(0, 1, 16));\n assert(compute_lte(0, 0x100, 16));\n assert(compute_lte(0x100, TWO_POW_128 - 1, 16));\n assert(!compute_lte(0, TWO_POW_128, 16));\n\n assert(compute_lte(0, 0, 16));\n assert(compute_lte(0x100, 0x100, 16));\n assert(compute_lte(TWO_POW_128 - 1, TWO_POW_128 - 1, 16));\n assert(compute_lte(TWO_POW_128, TWO_POW_128, 16));\n }\n\n #[test]\n fn check_assert_gt() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n unconstrained fn check_assert_gt_unconstrained() {\n assert_gt(1, 0);\n assert_gt(0x100, 0);\n assert_gt((0 - 1), (0 - 2));\n assert_gt(TWO_POW_128, 0);\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n unconstrained fn check_gt_unconstrained() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"232":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/debug_log.nr","source":"// Utility function to console.log data in the acir simulator\n// WARNING: sometimes when using debug logs the ACVM errors with: `thrown: \"solver opcode resolution error: cannot solve opcode: expression has too many unknowns x155\"`\n\n#[oracle(debugLog)]\nunconstrained fn debug_log_oracle(_msg: str, args: [Field]) {}\n\n/// NOTE: call this with a str msg of form\n/// \"some string with {0} and {1} ... {N}\"\n/// and an array of N field which will be formatted\n/// into the string in the simulator.\n/// Example:\n/// debug_log_format(\"get_2(slot:{0}) =>\\n\\t0:{1}\\n\\t1:{2}\", [storage_slot, note0_hash, note1_hash]);\n/// debug_log_format(\"whole array: {}\", [e1, e2, e3, e4]);\nunconstrained pub fn debug_log_format(msg: str, args: [Field; N]) {\n debug_log_oracle(msg, args.as_slice());\n}\n\n/// NOTE: call this with a str msg of length > 1\n/// Example:\n/// `debug_log(\"blah blah this is a debug string\");`\nunconstrained pub fn debug_log(msg: str) {\n debug_log_format(msg, []);\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"236":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr","source":"use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}};\n\nstruct PublicDataTreeLeafPreimage {\n slot : Field,\n value: Field,\n next_slot :Field,\n next_index : u32,\n}\n\nimpl Empty for PublicDataTreeLeafPreimage {\n fn empty() -> Self {\n Self {\n slot: 0,\n value: 0,\n next_slot: 0,\n next_index: 0,\n }\n }\n}\n\nimpl Hash for PublicDataTreeLeafPreimage {\n fn hash(self) -> Field {\n if self.is_empty() {\n 0\n } else {\n dep::std::hash::pedersen_hash([self.slot, self.value, (self.next_index as Field), self.next_slot])\n }\n }\n}\n\nimpl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage {\n fn get_key(self) -> Field {\n self.slot\n }\n\n fn get_next_key(self) -> Field {\n self.next_slot\n }\n\n fn as_leaf(self) -> Field {\n self.hash()\n }\n}\n\nimpl PublicDataTreeLeafPreimage {\n pub fn is_empty(self) -> bool {\n (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0)\n }\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"244":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_instance.nr","source":"use crate::{\n address::{\n aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,\n public_keys_hash::PublicKeysHash\n},\n contract_class_id::ContractClassId,\n constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},\n traits::{Deserialize, Hash, Serialize}\n};\n\nstruct ContractInstance {\n salt : Field,\n deployer: AztecAddress,\n contract_class_id : ContractClassId,\n initialization_hash : Field,\n public_keys_hash : PublicKeysHash,\n}\n\nimpl Eq for ContractInstance {\n fn eq(self, other: Self) -> bool {\n self.public_keys_hash.eq(other.public_keys_hash) &\n self.initialization_hash.eq(other.initialization_hash) &\n self.contract_class_id.eq(other.contract_class_id) &\n self.salt.eq(other.salt)\n }\n}\n\nimpl Serialize for ContractInstance {\n fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {\n [\n self.salt,\n self.deployer.to_field(),\n self.contract_class_id.to_field(),\n self.initialization_hash,\n self.public_keys_hash.to_field()\n ]\n }\n}\n\nimpl Deserialize for ContractInstance {\n fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {\n Self {\n salt: serialized[0],\n deployer: AztecAddress::from_field(serialized[1]),\n contract_class_id: ContractClassId::from_field(serialized[2]),\n initialization_hash: serialized[3],\n public_keys_hash: PublicKeysHash::from_field(serialized[4]),\n }\n }\n}\n\nimpl Hash for ContractInstance {\n fn hash(self) -> Field {\n self.to_address().to_field()\n }\n}\n\nimpl ContractInstance {\n fn to_address(self) -> AztecAddress {\n AztecAddress::compute(\n self.public_keys_hash,\n PartialAddress::compute(\n self.contract_class_id,\n self.salt,\n self.initialization_hash,\n self.deployer\n )\n )\n }\n}\n"},"246":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/contract_class_id.nr","source":"use crate::constants::GENERATOR_INDEX__CONTRACT_LEAF;\nuse crate::traits::{ToField, FromField, Hash, Serialize, Deserialize};\n\nstruct ContractClassId {\n inner: Field\n}\n\nimpl Eq for ContractClassId {\n fn eq(self, other: ContractClassId) -> bool {\n other.inner == self.inner\n }\n}\n\nimpl ToField for ContractClassId {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for ContractClassId {\n fn from_field(value: Field) -> Self {\n Self { inner: value }\n }\n}\n\nimpl Serialize<1> for ContractClassId {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner]\n }\n}\n\nimpl Deserialize<1> for ContractClassId {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self { inner: fields[0] }\n }\n}\n\nimpl ContractClassId {\n pub fn compute(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field\n ) -> Self {\n let hash = dep::std::hash::pedersen_hash_with_separator(\n [\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ],\n GENERATOR_INDEX__CONTRACT_LEAF\n ); // TODO(@spalladino): Update generator index\n\n ContractClassId::from_field(hash)\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"282":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr","source":"use crate::{\n address::{\n eth_address::EthAddress, salted_initialization_hash::SaltedInitializationHash,\n aztec_address::AztecAddress\n},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId,\n hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize}\n};\n\nglobal PARTIAL_ADDRESS_LENGTH = 1;\n\n// Partial address\nstruct PartialAddress {\n inner : Field\n}\n\nimpl ToField for PartialAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for PartialAddress {\n fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for PartialAddress {\n fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self {\n PartialAddress { inner: fields[0] }\n }\n}\n\nimpl PartialAddress {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(\n contract_class_id: ContractClassId,\n salt: Field,\n initialization_hash: Field,\n deployer: AztecAddress\n ) -> Self {\n PartialAddress::compute_from_salted_initialization_hash(\n contract_class_id,\n SaltedInitializationHash::compute(salt, initialization_hash, deployer)\n )\n }\n\n pub fn compute_from_salted_initialization_hash(\n contract_class_id: ContractClassId,\n salted_initialization_hash: SaltedInitializationHash\n ) -> Self {\n PartialAddress::from_field(\n pedersen_hash(\n [\n contract_class_id.to_field(),\n salted_initialization_hash.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn to_field(self) -> Field {\n self.inner\n }\n\n pub fn is_zero(self) -> bool {\n self.to_field() == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"283":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/salted_initialization_hash.nr","source":"use crate::{\n address::{eth_address::EthAddress, aztec_address::AztecAddress},\n constants::GENERATOR_INDEX__PARTIAL_ADDRESS, hash::pedersen_hash, traits::ToField\n};\n\n// Salted initialization hash. Used in the computation of a partial address.\nstruct SaltedInitializationHash {\n inner: Field\n}\n\nimpl ToField for SaltedInitializationHash {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl SaltedInitializationHash {\n pub fn from_field(field: Field) -> Self {\n Self { inner: field }\n }\n\n pub fn compute(salt: Field, initialization_hash: Field, deployer: AztecAddress) -> Self {\n SaltedInitializationHash::from_field(\n pedersen_hash(\n [\n salt,\n initialization_hash,\n deployer.to_field()\n ],\n GENERATOR_INDEX__PARTIAL_ADDRESS\n )\n )\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n}\n"},"285":{"path":"/usr/src/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr","source":"mod lib;\n\ncontract GasToken {\n use dep::aztec::{\n protocol_types::{\n contract_class_id::ContractClassId, abis::function_selector::FunctionSelector,\n address::{AztecAddress, EthAddress},\n constants::{DEPLOYER_CONTRACT_ADDRESS, REGISTERER_CONTRACT_ADDRESS}\n },\n state_vars::{SharedImmutable, PublicMutable, Map},\n oracle::get_contract_instance::get_contract_instance, deploy::deploy_contract\n };\n\n use dep::deployer::ContractInstanceDeployer;\n use dep::registerer::ContractClassRegisterer;\n\n use crate::lib::{calculate_fee, get_bridge_gas_msg_hash};\n\n #[aztec(storage)]\n struct Storage {\n // This map is accessed directly by protocol circuits to check balances for fee payment.\n // Do not change this storage layout unless you also update the base rollup circuits.\n balances: Map>,\n portal_address: SharedImmutable,\n }\n\n // Not flagged as initializer to reduce cost of checking init nullifier in all functions.\n // This function should be called as entrypoint to initialize the contract by minting itself funds.\n #[aztec(private)]\n fn deploy(\n artifact_hash: Field,\n private_functions_root: Field,\n public_bytecode_commitment: Field,\n portal_address: EthAddress\n ) {\n // Validate contract class parameters are correct\n let self = context.this_address();\n let instance = get_contract_instance(self);\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n assert(\n instance.contract_class_id == contract_class_id, \"Invalid contract class id computed for gas token\"\n );\n\n // Increase self balance and set as fee payer, and end setup\n let deploy_fees = 20000000000;\n GasToken::at(self)._increase_public_balance(self, deploy_fees).enqueue(&mut context);\n context.set_as_fee_payer();\n context.end_setup();\n\n // Register class and publicly deploy contract\n let _register = ContractClassRegisterer::at(AztecAddress::from_field(REGISTERER_CONTRACT_ADDRESS)).register(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ).call(&mut context);\n let _deploy = ContractInstanceDeployer::at(AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS)).deploy(\n instance.salt,\n instance.contract_class_id,\n instance.initialization_hash,\n instance.public_keys_hash,\n true\n ).call(&mut context);\n\n // Enqueue call to set the portal address\n GasToken::at(self).set_portal(portal_address).enqueue(&mut context);\n }\n\n // We purposefully not set this function as an initializer so we do not bind\n // the contract to a specific L1 portal address, since the gas token address\n // is a hardcoded constant in the rollup circuits.\n #[aztec(public)]\n fn set_portal(portal_address: EthAddress) {\n assert(storage.portal_address.read_public().is_zero());\n storage.portal_address.initialize(portal_address);\n }\n\n #[aztec(private)]\n fn claim(to: AztecAddress, amount: Field, secret: Field) {\n let content_hash = get_bridge_gas_msg_hash(to, amount);\n let portal_address = storage.portal_address.read_private();\n assert(!portal_address.is_zero());\n\n // Consume message and emit nullifier\n context.consume_l1_to_l2_message(content_hash, secret, portal_address);\n\n // TODO(palla/gas) Emit an unencrypted log to announce which L1 to L2 message has been claimed\n // Otherwise, we cannot trace L1 deposits to their corresponding claims on L2\n\n GasToken::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context);\n }\n\n #[aztec(public)]\n #[aztec(internal)]\n fn _increase_public_balance(to: AztecAddress, amount: Field) {\n let new_balance = storage.balances.at(to).read().add(U128::from_integer(amount));\n storage.balances.at(to).write(new_balance);\n }\n\n // TODO(palla/gas) Remove this function and use the private claim flow only\n #[aztec(public)]\n fn claim_public(to: AztecAddress, amount: Field, secret: Field, leaf_index: Field) {\n let content_hash = get_bridge_gas_msg_hash(to, amount);\n let portal_address = storage.portal_address.read_public();\n assert(!portal_address.is_zero());\n\n // Consume message and emit nullifier\n context.consume_l1_to_l2_message(content_hash, secret, portal_address, leaf_index);\n\n let new_balance = storage.balances.at(to).read() + U128::from_integer(amount);\n storage.balances.at(to).write(new_balance);\n }\n\n // TODO(@just-mitch): remove this function before mainnet deployment\n // convenience function for testing\n // the true canonical gas token contract will not have this function\n #[aztec(public)]\n fn mint_public(to: AztecAddress, amount: Field) {\n let amount = U128::from_integer(amount);\n let new_balance = storage.balances.at(to).read().add(amount);\n\n storage.balances.at(to).write(new_balance);\n }\n\n #[aztec(public)]\n #[aztec(view)]\n fn check_balance(fee_limit: Field) {\n let fee_limit = U128::from_integer(fee_limit);\n assert(storage.balances.at(context.msg_sender()).read() >= fee_limit, \"Balance too low\");\n }\n\n // utility function for testing\n #[aztec(public)]\n #[aztec(view)]\n fn balance_of_public(owner: AztecAddress) -> pub Field {\n storage.balances.at(owner).read().to_field()\n }\n}\n"},"286":{"path":"/usr/src/noir-projects/noir-contracts/contracts/gas_token_contract/src/lib.nr","source":"use dep::aztec::prelude::{AztecAddress, EthAddress};\nuse dep::aztec::context::PublicContext;\nuse dep::aztec::protocol_types::hash::sha256_to_field;\n\npub fn calculate_fee(context: PublicContext) -> Field {\n context.transaction_fee()\n}\n\npub fn get_bridge_gas_msg_hash(owner: AztecAddress, amount: Field) -> Field {\n let mut hash_bytes = [0; 68];\n let recipient_bytes = owner.to_field().to_be_bytes(32);\n let amount_bytes = amount.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i + 4] = recipient_bytes[i];\n hash_bytes[i + 36] = amount_bytes[i];\n }\n\n // Function selector: 0x3e87b9be keccak256('mint_public(bytes32,uint256)')\n hash_bytes[0] = 0x3e;\n hash_bytes[1] = 0x87;\n hash_bytes[2] = 0xb9;\n hash_bytes[3] = 0xbe;\n\n let content_hash = sha256_to_field(hash_bytes);\n content_hash\n}\n"},"288":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_instance_deployer_contract/src/main.nr","source":"mod events;\n\ncontract ContractInstanceDeployer {\n use dep::aztec::protocol_types::{\n address::{AztecAddress, EthAddress, PublicKeysHash, PartialAddress},\n contract_class_id::ContractClassId, constants::DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE,\n traits::Serialize\n };\n\n use crate::events::{instance_deployed::ContractInstanceDeployed};\n\n #[aztec(private)]\n fn deploy(\n salt: Field,\n contract_class_id: ContractClassId,\n initialization_hash: Field,\n public_keys_hash: PublicKeysHash,\n universal_deploy: bool\n ) {\n // TODO(@spalladino): assert nullifier_exists silo(contract_class_id, ContractClassRegisterer)\n\n let deployer = if universal_deploy {\n AztecAddress::zero()\n } else {\n context.msg_sender()\n };\n\n let partial_address = PartialAddress::compute(contract_class_id, salt, initialization_hash, deployer);\n\n let address = AztecAddress::compute(public_keys_hash, partial_address);\n\n // Emit the address as a nullifier to be able to prove that this instance has been (not) deployed\n context.push_new_nullifier(address.to_field(), 0);\n\n // Broadcast the event\n let event = ContractInstanceDeployed { contract_class_id, address, public_keys_hash, initialization_hash, salt, deployer, version: 1 };\n let event_payload = event.serialize();\n dep::aztec::oracle::debug_log::debug_log_format(\"ContractInstanceDeployed: {}\", event_payload);\n context.emit_unencrypted_log(event_payload);\n }\n}\n"},"29":{"path":"std/hash.nr","source":"mod poseidon;\nmod mimc;\nmod poseidon2;\n\nuse crate::default::Default;\nuse crate::uint128::U128;\nuse crate::sha256::{digest, sha256_var};\nuse crate::embedded_curve_ops::EmbeddedCurvePoint;\n\n#[foreign(sha256)]\n// docs:start:sha256\npub fn sha256(input: [u8; N]) -> [u8; 32]\n// docs:end:sha256\n{}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n#[foreign(blake3)]\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[foreign(pedersen_commitment)]\npub fn __pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> [Field; 2] {}\n\npub fn pedersen_commitment_with_separator(input: [Field; N], separator: u32) -> EmbeddedCurvePoint {\n let values = __pedersen_commitment_with_separator(input, separator);\n EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: false }\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[foreign(pedersen_hash)]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {}\n\npub fn hash_to_field(inputs: [Field]) -> Field {\n let mut sum = 0;\n\n for input in inputs {\n let input_bytes: [u8; 32] = input.to_le_bytes(32).as_array();\n sum += crate::field::bytes32_to_field(blake2s(input_bytes));\n }\n\n sum\n}\n\n#[foreign(keccak256)]\n// docs:start:keccak256\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32]\n// docs:end:keccak256\n{}\n\n#[foreign(poseidon2_permutation)]\npub fn poseidon2_permutation(_input: [Field; N], _state_length: u32) -> [Field; N] {}\n\n#[foreign(sha256_compression)]\npub fn sha256_compression(_input: [u32; 16], _state: [u32; 8]) -> [u32; 8] {}\n\n// Generic hashing support. \n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\ntrait Hash{\n fn hash(self, state: &mut H) where H: Hasher;\n}\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\ntrait Hasher{\n fn finish(self) -> Field;\n \n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\ntrait BuildHasher where H: Hasher{\n fn build_hasher(self) -> H;\n}\n\nstruct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn build_hasher(_self: Self) -> H{\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere \n H: Hasher + Default\n{\n fn default() -> Self{\n BuildHasherDefault{}\n } \n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H) where H: Hasher {}\n}\n\nimpl Hash for U128 {\n fn hash(self, state: &mut H) where H: Hasher{\n H::write(state, self.lo as Field);\n H::write(state, self.hi as Field);\n }\n}\n\nimpl Hash for [T; N] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T] where T: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B) where A: Hash, B: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C) where A: Hash, B: Hash, C: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D) where A: Hash, B: Hash, C: Hash, D: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E) where A: Hash, B: Hash, C: Hash, D: Hash, E: Hash {\n fn hash(self, state: &mut H) where H: Hasher{\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n"},"293":{"path":"/usr/src/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr","source":"mod events;\nmod capsule;\n\ncontract ContractClassRegisterer {\n use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector};\n use dep::aztec::protocol_types::{\n contract_class_id::ContractClassId,\n constants::{\n ARTIFACT_FUNCTION_TREE_MAX_HEIGHT, FUNCTION_TREE_HEIGHT,\n MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE\n },\n traits::Serialize\n };\n\n use crate::events::{\n class_registered::ContractClassRegistered,\n private_function_broadcasted::{ClassPrivateFunctionBroadcasted, PrivateFunction},\n unconstrained_function_broadcasted::{ClassUnconstrainedFunctionBroadcasted, UnconstrainedFunction}\n };\n\n // docs:start:import_pop_capsule\n use crate::capsule::pop_capsule;\n // docs:end:import_pop_capsule\n\n #[aztec(private)]\n fn register(artifact_hash: Field, private_functions_root: Field, public_bytecode_commitment: Field) {\n // TODO: Validate public_bytecode_commitment is the correct commitment of packed_public_bytecode\n // TODO: Validate packed_public_bytecode is legit public bytecode\n\n // docs:start:pop_capsule\n let packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS] = pop_capsule();\n // docs:end:pop_capsule\n\n // Compute contract class id from preimage\n let contract_class_id = ContractClassId::compute(\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n );\n\n // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered\n let event = ContractClassRegistered { contract_class_id, version: 1, artifact_hash, private_functions_root, packed_public_bytecode };\n context.push_new_nullifier(contract_class_id.to_field(), 0);\n\n // Broadcast class info including public bytecode\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ContractClassRegistered: {}\",\n [\n contract_class_id.to_field(),\n artifact_hash,\n private_functions_root,\n public_bytecode_commitment\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_private_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n unconstrained_functions_artifact_tree_root: Field,\n private_function_tree_sibling_path: [Field; FUNCTION_TREE_HEIGHT],\n private_function_tree_leaf_index: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: PrivateFunction\n ) {\n let event = ClassPrivateFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n private_function_tree_sibling_path,\n private_function_tree_leaf_index,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassPrivateFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n unconstrained_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.vk_hash,\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n\n #[aztec(private)]\n fn broadcast_unconstrained_function(\n contract_class_id: ContractClassId,\n artifact_metadata_hash: Field,\n private_functions_artifact_tree_root: Field,\n artifact_function_tree_sibling_path: [Field; ARTIFACT_FUNCTION_TREE_MAX_HEIGHT],\n artifact_function_tree_leaf_index: Field,\n function_data: UnconstrainedFunction\n ) {\n let event = ClassUnconstrainedFunctionBroadcasted {\n contract_class_id,\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n artifact_function_tree_sibling_path,\n artifact_function_tree_leaf_index,\n function: function_data\n };\n dep::aztec::oracle::debug_log::debug_log_format(\n \"ClassUnconstrainedFunctionBroadcasted: {}\",\n [\n contract_class_id.to_field(),\n artifact_metadata_hash,\n private_functions_artifact_tree_root,\n function_data.selector.to_field(),\n function_data.metadata_hash\n ]\n );\n context.emit_contract_class_unencrypted_log(event.serialize());\n }\n}\n"},"3":{"path":"std/cmp.nr","source":"// docs:start:eq-trait\ntrait Eq {\n fn eq(self, other: Self) -> bool;\n}\n// docs:end:eq-trait\n\nimpl Eq for Field { fn eq(self, other: Field) -> bool { self == other } }\n\nimpl Eq for u64 { fn eq(self, other: u64) -> bool { self == other } }\nimpl Eq for u32 { fn eq(self, other: u32) -> bool { self == other } }\nimpl Eq for u8 { fn eq(self, other: u8) -> bool { self == other } }\nimpl Eq for u1 { fn eq(self, other: u1) -> bool { self == other } }\n\nimpl Eq for i8 { fn eq(self, other: i8) -> bool { self == other } }\nimpl Eq for i32 { fn eq(self, other: i32) -> bool { self == other } }\nimpl Eq for i64 { fn eq(self, other: i64) -> bool { self == other } }\n\nimpl Eq for () { fn eq(_self: Self, _other: ()) -> bool { true } }\nimpl Eq for bool { fn eq(self, other: bool) -> bool { self == other } }\n\nimpl Eq for [T; N] where T: Eq {\n fn eq(self, other: [T; N]) -> bool {\n let mut result = true;\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for [T] where T: Eq {\n fn eq(self, other: [T]) -> bool {\n let mut result = self.len() == other.len();\n for i in 0 .. self.len() {\n result &= self[i].eq(other[i]);\n }\n result\n }\n}\n\nimpl Eq for str {\n fn eq(self, other: str) -> bool {\n let self_bytes = self.as_bytes();\n let other_bytes = other.as_bytes();\n self_bytes == other_bytes\n }\n}\n\nimpl Eq for (A, B) where A: Eq, B: Eq {\n fn eq(self, other: (A, B)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1)\n }\n}\n\nimpl Eq for (A, B, C) where A: Eq, B: Eq, C: Eq {\n fn eq(self, other: (A, B, C)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2)\n }\n}\n\nimpl Eq for (A, B, C, D) where A: Eq, B: Eq, C: Eq, D: Eq {\n fn eq(self, other: (A, B, C, D)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3)\n }\n}\n\nimpl Eq for (A, B, C, D, E) where A: Eq, B: Eq, C: Eq, D: Eq, E: Eq {\n fn eq(self, other: (A, B, C, D, E)) -> bool {\n self.0.eq(other.0) & self.1.eq(other.1) & self.2.eq(other.2) & self.3.eq(other.3) & self.4.eq(other.4)\n }\n}\n\nimpl Eq for Ordering {\n fn eq(self, other: Ordering) -> bool {\n self.result == other.result\n }\n}\n\n// Noir doesn't have enums yet so we emulate (Lt | Eq | Gt) with a struct\n// that has 3 public functions for constructing the struct.\nstruct Ordering {\n result: Field,\n}\n\nimpl Ordering {\n // Implementation note: 0, 1, and 2 for Lt, Eq, and Gt are built\n // into the compiler, do not change these without also updating\n // the compiler itself!\n pub fn less() -> Ordering {\n Ordering { result: 0 }\n }\n\n pub fn equal() -> Ordering {\n Ordering { result: 1 }\n }\n\n pub fn greater() -> Ordering {\n Ordering { result: 2 }\n }\n}\n\n// docs:start:ord-trait\ntrait Ord {\n fn cmp(self, other: Self) -> Ordering;\n}\n// docs:end:ord-trait\n\n// Note: Field deliberately does not implement Ord\n\nimpl Ord for u64 {\n fn cmp(self, other: u64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u32 {\n fn cmp(self, other: u32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for u8 {\n fn cmp(self, other: u8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i8 {\n fn cmp(self, other: i8) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i32 {\n fn cmp(self, other: i32) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for i64 {\n fn cmp(self, other: i64) -> Ordering {\n if self < other {\n Ordering::less()\n } else if self > other {\n Ordering::greater()\n } else {\n Ordering::equal()\n }\n }\n}\n\nimpl Ord for () {\n fn cmp(_self: Self, _other: ()) -> Ordering {\n Ordering::equal()\n }\n}\n\nimpl Ord for bool {\n fn cmp(self, other: bool) -> Ordering {\n if self {\n if other {\n Ordering::equal()\n } else {\n Ordering::greater()\n }\n } else {\n if other {\n Ordering::less()\n } else {\n Ordering::equal()\n }\n }\n }\n}\n\nimpl Ord for [T; N] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T; N]) -> Ordering {\n let mut result = Ordering::equal();\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for [T] where T: Ord {\n // The first non-equal element of both arrays determines\n // the ordering for the whole array.\n fn cmp(self, other: [T]) -> Ordering {\n let mut result = self.len().cmp(other.len());\n for i in 0 .. self.len() {\n if result == Ordering::equal() {\n let result_i = self[i].cmp(other[i]);\n\n if result_i == Ordering::less() {\n result = result_i;\n } else if result_i == Ordering::greater() {\n result = result_i;\n }\n }\n }\n result\n }\n}\n\nimpl Ord for (A, B) where A: Ord, B: Ord {\n fn cmp(self, other: (A, B)) -> Ordering {\n let result = self.0.cmp(other.0);\n\n if result != Ordering::equal() {\n result\n } else {\n self.1.cmp(other.1)\n }\n }\n}\n\nimpl Ord for (A, B, C) where A: Ord, B: Ord, C: Ord {\n fn cmp(self, other: (A, B, C)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D) where A: Ord, B: Ord, C: Ord, D: Ord {\n fn cmp(self, other: (A, B, C, D)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n result\n }\n}\n\nimpl Ord for (A, B, C, D, E) where A: Ord, B: Ord, C: Ord, D: Ord, E: Ord {\n fn cmp(self, other: (A, B, C, D, E)) -> Ordering {\n let mut result = self.0.cmp(other.0);\n\n if result == Ordering::equal() {\n result = self.1.cmp(other.1);\n }\n\n if result == Ordering::equal() {\n result = self.2.cmp(other.2);\n }\n\n if result == Ordering::equal() {\n result = self.3.cmp(other.3);\n }\n\n if result == Ordering::equal() {\n result = self.4.cmp(other.4);\n }\n\n result\n }\n}\n\n// Compares and returns the maximum of two values.\n//\n// Returns the second argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::max(1, 2), 2);\n// assert_eq(cmp::max(2, 2), 2);\n// ```\npub fn max(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v1 } else { v2 }\n}\n\n// Compares and returns the minimum of two values.\n//\n// Returns the first argument if the comparison determines them to be equal.\n//\n// # Examples\n//\n// ```\n// use std::cmp;\n//\n// assert_eq(cmp::min(1, 2), 1);\n// assert_eq(cmp::min(2, 2), 2);\n// ```\npub fn min(v1: T, v2: T) -> T where T: Ord {\n if v1 > v2 { v2 } else { v1 }\n}\n\nmod cmp_tests {\n use crate::cmp::{min, max};\n\n #[test]\n fn sanity_check_min() {\n assert_eq(min(0 as u64, 1 as u64), 0);\n assert_eq(min(0 as u64, 0 as u64), 0);\n assert_eq(min(1 as u64, 1 as u64), 1);\n assert_eq(min(255 as u8, 0 as u8), 0);\n }\n\n #[test]\n fn sanity_check_max() {\n assert_eq(max(0 as u64, 1 as u64), 1);\n assert_eq(max(0 as u64, 0 as u64), 0);\n assert_eq(max(1 as u64, 1 as u64), 1);\n assert_eq(max(255 as u8, 0 as u8), 255);\n }\n}\n"},"31":{"path":"std/merkle.nr","source":"// Regular merkle tree means a append-only merkle tree (Explain why this is the only way to have privacy and alternatives if you don't want it)\n// Currently we assume that it is a binary tree, so depth k implies a width of 2^k\n// XXX: In the future we can add an arity parameter\n// Returns the merkle root of the tree from the provided leaf, its hashpath, using a pedersen hash function.\npub fn compute_merkle_root(leaf: Field, index: Field, hash_path: [Field; N]) -> Field {\n let n = hash_path.len();\n let index_bits = index.to_le_bits(n as u32);\n let mut current = leaf;\n for i in 0..n {\n let path_bit = index_bits[i] as bool;\n let (hash_left, hash_right) = if path_bit {\n (hash_path[i], current)\n } else {\n (current, hash_path[i])\n };\n current = crate::hash::pedersen_hash([hash_left, hash_right]);\n }\n current\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"79":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/history/public_storage.nr","source":"use dep::protocol_types::{\n constants::GENERATOR_INDEX__PUBLIC_LEAF_INDEX, hash::pedersen_hash, address::AztecAddress,\n header::Header, utils::field::full_field_less_than\n};\nuse dep::std::merkle::compute_merkle_root;\n\nuse crate::{context::PrivateContext, oracle::get_public_data_witness::get_public_data_witness};\n\ntrait PublicStorageHistoricalRead {\n fn public_storage_historical_read(header: Header, storage_slot: Field, contract_address: AztecAddress) -> Field;\n}\n\nimpl PublicStorageHistoricalRead for Header { \n fn public_storage_historical_read(self, storage_slot: Field, contract_address: AztecAddress) -> Field {\n // 1) Compute the leaf slot by siloing the storage slot with the contract address\n let public_value_leaf_slot = pedersen_hash(\n [contract_address.to_field(), storage_slot],\n GENERATOR_INDEX__PUBLIC_LEAF_INDEX\n );\n\n // 2) Get the membership witness of the slot\n let witness = get_public_data_witness(\n self.global_variables.block_number as u32,\n public_value_leaf_slot\n );\n\n // 3) Extract the value from the witness leaf and check that the storage slot is correct\n let preimage = witness.leaf_preimage;\n\n // Here we have two cases. Code based on same checks in `validate_public_data_reads` in `base_rollup_inputs`\n // 1. The value is the same as the one in the witness\n // 2. The value was never initialized and is zero\n let is_less_than_slot = full_field_less_than(preimage.slot, public_value_leaf_slot);\n let is_next_greater_than = full_field_less_than(public_value_leaf_slot, preimage.next_slot);\n let is_max = ((preimage.next_index == 0) & (preimage.next_slot == 0));\n let is_in_range = is_less_than_slot & (is_next_greater_than | is_max);\n\n let value = if is_in_range {\n 0\n } else {\n assert_eq(preimage.slot, public_value_leaf_slot, \"Public data slot doesn't match witness\");\n preimage.value\n };\n\n // 4) Prove that the leaf exists in the public data tree. Note that `hash` returns not just the hash of the value\n // but also the metadata (slot, next index and next slot).\n assert(\n self.state.partial.public_data_tree.root\n == compute_merkle_root(preimage.hash(), witness.index, witness.path), \"Proving public value inclusion failed\"\n );\n\n value\n }\n}\n"},"84":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/messaging.nr","source":"use crate::{\n hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier},\n oracle::get_l1_to_l2_membership_witness::get_l1_to_l2_membership_witness\n};\n\nuse dep::std::merkle::compute_merkle_root;\nuse dep::protocol_types::{constants::L1_TO_L2_MSG_TREE_HEIGHT, address::{AztecAddress, EthAddress}, utils::arr_copy_slice};\n\npub fn process_l1_to_l2_message(\n l1_to_l2_root: Field,\n storage_contract_address: AztecAddress,\n portal_contract_address: EthAddress,\n chain_id: Field,\n version: Field,\n content: Field,\n secret: Field\n) -> Field {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n portal_contract_address,\n chain_id,\n storage_contract_address,\n version,\n content,\n secret_hash\n );\n\n let returned_message = get_l1_to_l2_membership_witness(storage_contract_address, message_hash, secret);\n let leaf_index = returned_message[0];\n let sibling_path = arr_copy_slice(returned_message, [0; L1_TO_L2_MSG_TREE_HEIGHT], 1);\n\n // Check that the message is in the tree\n // This is implicitly checking that the values of the message are correct\n let root = compute_merkle_root(message_hash, leaf_index, sibling_path);\n assert(root == l1_to_l2_root, \"Message not in state\");\n\n compute_message_nullifier(message_hash, secret, leaf_index)\n}\n"},"87":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/packed_returns.nr","source":"use crate::{hash::hash_args_array, oracle::returns::unpack_returns};\nuse dep::protocol_types::traits::Deserialize;\n\nstruct PackedReturns {\n packed_returns: Field,\n}\n\nimpl PackedReturns {\n pub fn new(packed_returns: Field) -> Self {\n PackedReturns { packed_returns }\n }\n\n pub fn assert_empty(self) {\n assert_eq(self.packed_returns, 0);\n }\n\n pub fn raw(self) -> Field {\n self.packed_returns\n }\n\n pub fn unpack(self) -> [Field; N] {\n let unpacked: [Field; N] = unpack_returns(self.packed_returns);\n assert_eq(self.packed_returns, hash_args_array(unpacked));\n unpacked\n }\n\n pub fn unpack_into(self) -> T where T: Deserialize {\n let unpacked: [Field; N] = self.unpack();\n Deserialize::deserialize(unpacked)\n }\n}\n"},"90":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/call_interfaces.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress, traits::Deserialize\n};\n\nuse crate::context::{\n private_context::PrivateContext, public_context::PublicContext, gas::GasOpts,\n public_context::FunctionReturns, inputs::{PrivateContextInputs, PublicContextInputs}\n};\n\nuse crate::oracle::arguments;\n\ntrait CallInterface {\n fn get_args(self) -> [Field];\n fn get_original(self) -> fn[Env](T) -> P;\n fn get_selector(self) -> FunctionSelector;\n fn get_name(self) -> str;\n fn get_contract_address(self) -> AztecAddress;\n fn get_is_static(self) -> bool;\n}\n\nimpl CallInterface for PrivateCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateCallInterface {\n pub fn call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n );\n let unpacked: T = returns.unpack_into();\n unpacked\n }\n\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateVoidCallInterface {\n pub fn call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(\n self.target_contract,\n self.selector,\n self.args_hash,\n false,\n false\n ).assert_empty();\n }\n\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n\n pub fn delegate_call(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty();\n }\n}\n\nimpl CallInterface for PrivateStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticCallInterface {\n pub fn view(self, context: &mut PrivateContext) -> T where T: Deserialize {\n let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false);\n returns.unpack_into()\n }\n}\n\nimpl CallInterface for PrivateStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PrivateStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args_hash: Field,\n args: [Field],\n original: fn[Env](PrivateContextInputs) -> PrivateCircuitPublicInputs,\n is_static: bool\n}\n\nimpl PrivateStaticVoidCallInterface {\n pub fn view(self, context: &mut PrivateContext) {\n context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty();\n }\n}\n\nimpl CallInterface for PublicCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.deserialize_into()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.deserialize_into()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn call(self, context: &mut PublicContext) {\n let returns = context.call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn delegate_call(self, context: &mut PublicContext) {\n let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args);\n returns.assert_empty()\n }\n\n pub fn enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ false\n )\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n\n pub fn delegate_enqueue(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ false,\n /*delegate=*/ true\n )\n }\n}\n\nimpl CallInterface for PublicStaticCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> T {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> T,\n is_static: bool\n}\n\nimpl PublicStaticCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) -> T where T: Deserialize {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n let unpacked: T = returns.deserialize_into();\n unpacked\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n\nimpl CallInterface for PublicStaticVoidCallInterface {\n fn get_args(self) -> [Field] {\n self.args\n }\n\n fn get_original(self) -> fn[Env](PublicContextInputs) -> () {\n self.original\n }\n\n fn get_selector(self) -> FunctionSelector {\n self.selector\n }\n\n fn get_name(self) -> str {\n self.name\n }\n\n fn get_contract_address(self) -> AztecAddress {\n self.target_contract\n }\n\n fn get_is_static(self) -> bool {\n self.is_static\n }\n}\n\nstruct PublicStaticVoidCallInterface {\n target_contract: AztecAddress,\n selector: FunctionSelector,\n name: str,\n args: [Field],\n gas_opts: GasOpts,\n original: fn[Env](PublicContextInputs) -> (),\n is_static: bool\n}\n\nimpl PublicStaticVoidCallInterface {\n pub fn with_gas(self: &mut Self, gas_opts: GasOpts) -> &mut Self {\n self.gas_opts = gas_opts;\n self\n }\n\n pub fn view(self, context: &mut PublicContext) {\n let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, self.gas_opts);\n returns.assert_empty()\n }\n\n pub fn enqueue_view(self, context: &mut PrivateContext) {\n // This packing is only here because PrivateContext's call_public* functions do not accept a slice for the args.\n let args_hash = arguments::pack_arguments(self.args);\n context.call_public_function_with_packed_args(\n self.target_contract,\n self.selector,\n args_hash,\n /*static=*/ true,\n /*delegate=*/ false\n )\n }\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json b/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json deleted file mode 100644 index bb634cf16c13..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/KeyRegistry.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"KeyRegistry","functions":[{"name":"register","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"partial_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::partial_address::PartialAddress"},"visibility":"private"},{"name":"keys","type":{"fields":[{"name":"npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ivpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ovpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"tpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}}],"kind":"struct","path":"aztec::keys::public_keys::PublicKeys"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"7b3vjiu7duT5LvezMUiSi//8KoPBwN3tHhgwrhtt9wAD47776PStpFS7mJup5DqSgis++dhWVTJ+lVsRi0oF//Mv/+2f/8v/+n/+73/563//t3//yz/+n//5l3/9t//6T//xL//219v/9p9/2f4Pv/3v/+u//49/+usf/4d//49/+p//8Zd/3P7hL//81/92+59/+4e//Pd/+dd//ss/hih/+7/+4Y8fcM/+gH/2B8KzPyDP/kB89gfSsz+Qn/2B8uwP1Cd/IDz7lw7P/qVD9y/t3Za/fsY7V7792D/8eHWM9evFJUt7beq9tCbZX1vz5tuLfaidVwfZVxHKfRG+9F6aouyvTdn//sVpC1+vTZs8vvTvSAKR/IpEiORXJJFIfkWSiORXJJlIfkVSiORXJJVIfkEiG5H8isQRya9ImF5/IGF6/YFELCIJ++9NMf5EYjK9/h6JyfT6eyQm0+vvkZhMr79HYjK9/hZJNBnVfo/EZFT7PRKTUe33SIRIfkXCqPYDCaPaDySMaj+QMKr9QMKo9iuSZHKj8fdImF5/IGF6/YGE6fUHEiGSX5Ewvf5AwvT6AwnT6w8kTK8/kDC9/ookM73+QML0+gMJ0+sPJEyvP5AIkfyKhOn1BxKm1x9ImF5/IGF6/YGE6fVXJIXp9QcSptcfSJhefyBhev2BRIjkVyRMrz+QMKr9QMKo9gMJo9qvSCqj2g8kjGo/kDCq/UDCqPYDiRDJr0gY1X4g4UbjDyRMrz+QML3+QML0+isSt60fX7+Erh9Kv4SuHzW/hK4fIL+EihWh64e9L6HrR7gvoesHsy+h68etL6Hrh6i/C3VWkpGzkoyclWTkrCQjJ1aEWklGzkoyclaSkbOSjJyVZOStJCNvJRl5K8nIW0lG3koy8laSkbeSjLyVZOStJCNvJRkFK8koWElGBo4B+RJqJRkZOLLjS6iVZGTgeI0voVaSkYGjML6EWklGBo6t+BJqJRkZOGLiS6iVZGTgOIgvoVaSkYGjG76EWklGBo5Z+BJqJRlFK8nIwNkPX0KtJCMD5zR8CRUrQq0kIwMnJXwJtZKMDJxq8CXUSjIycALBl1AryWidHvjahOat87XKddrdR0IXedcVl/dfLK7Gyy/+orLIW7QulVU6uZWpLPLmr0xlkRlamcoiA7cyFSGVDpVFIogylUXmfmUqi2wSKFNhtu1RYbbtUFmlsVuZCrNtjwqzbY8Ks22PipBKhwqzbY8Ks22PCrNtjwqzbY8Ks22HyioV58pUmG17VJhte1SYbXtUxCAV72PY5fkcOlQsZtsxFYvZ1vvg71SkQ8ViXvFS9xf7uG0/qPhVOq2VqVjMK2MqFvPKmIrFvDKmIqTSoWIyrwypmMwrQyoW9+LGVCzuxY2pMNt2qKzSSq5Mhdm2R4XZtkdFSKVDhSmuR4UprkfFpDMXaTuUJcnvXxxCbquQ7efGnV+lQvudCE16vi5CkwFBF6HJnTJdhEKEswhNpjddhCajni5Ck7t7ughNbgXqIuR0MotwlRr7dyLkdDKNkNPJNEKGmgHCXNLXa3PtbHWt0rj+NoCrlCf/eQBre/KxxtwBKAQ4B5D/hEcA8/6UaS2xA5AzySRATiRzAFepSH4fQE4jkwA5i0wCZA6cBCgEOAeQn5FMAuRmwiRATiKTADmJTALkJDIA6LYQv17sttLZUl2llPydCDmNTCPkPDKNkBPJNEIhwlmEnEqmEXIumUbIyWQaIWeTaYScTmYRmjxiQxkhp5NphJxOphFyOplGKEQ4i5DTyTRCTifTCDmdTCPkdDKNkNPJLEKTh6Q8h9CVhtCV1EHI6WQaIaeTaYScTqYRChHOIuR0Mo2Q08k0Qk4n0wg5ncwiNHlGizJCRutphIzW0wgZracRChHOImS0nkbIaD2NkNF6GiGj9TRCbvxPIgw2T2TSRcjpZBohp5NphJxOphEKEc4i5HQyjZDTySxCm0fxPIXQu4bQu9pByFAzjZB2MkQYpCGU0EFIO5lGSDuZRsjNrmmE3OyaRsjNrlmEPNtpHiFz4TRCbnZNI+Rm1zRCIcJZhJxOphFyOplGyOlkGiGnk2mEnE5mEfJsp3mEnE6mEXI6mUbI6UQ6VIRUOlQ4Q/SocCzoUWHS71FheO9RYR7vUBFG7B4VpuYeFQbhHhVm2x4VIZUOFWbbHhVm2x4VZtseFWbbDhWbR/5VX3Z5NfgOFZPOPKRi8t22RteodP8FmXy3HVIx+W47pGJyJ2FExeZhY0MqJncShlRs5pURFZt5ZURFSKVDxeROwpAKs22PisVsm/cnEnLsELGYa39PxGKm/S0Rk8dT/Z6IxSz7eyIWc+zviVjMsL8nIiTyCxGL2fX3RCzm1t8TYWb9lQgz669EmFl/IWLyxJ3fE2FC+5UIE9qvRIREfiHChPYrEYsJLdxr5YKrpUPFYkobU7GY1MZULKa1IRWTZ+GMqVjMsWMqFrPsmIpJZ/Z+23+x953P/EweRzGiIia7/YMvdyo1d6iYfLcdUjH5bjukYnH3YExFSKVDxeIuwpiKzbwyomIzr4yomNxJGFIxuZMwomLyiIcxFWbbHhWT2fbhF4fUo2Iy2w6pCKl0qJjMtkMqJrPtkIrJbBty+8W3+bhDxWSKG1ExeSDDmIrJFDekYjPFjajYTHEjKkIqHSo2U9yIis0UN6LCFNejYnKHckiF2bZDxWSd/5gKs22PCrNtjwqzbY+KkEqHCrNtjwqzbY8Ks22PCrNtjwqzbYeKyR79MRVm2x4VZtseFWbbHhUhlQ4VZtseFWbbHhVm2x4VZtseFWbbDpXIbNujwmzbo8Js26PCbNujIqTSocJs26PCbNujwmzbo8Js26PCbNuhYvLUkjEVZtseFWbbHhVm2x4V6VLZWpmNdyENqLjbjt7Xq12MjxdxrwQTUtyb8ULK/vcvTtt+UmHqYonE0sOSiKWHJRNLD0shlh6WSiwdLAfnmJjH4oilh8UTSw9LIJYeFiGWHham3C4Wqyk37L83xdjBYjXlDrBYTbkDLFZT7u+xFKspd4DFasodYLGacgdYrKbcARYhlh4Wqyl3gIUpt4uFKbeLhSm3i4Upt4elMuV2sTDldrEw5XaxMOV2sQix9LAw5XaxMOV2sTDldrEw5XaxMOV2sMSNKbeLhSm3i4Upt4uFKbeLRYilh4Upt4uFKbeLhSm3i4Upt4uFKbeHxTHldrEw5XaxMOV2sTDldrEIsfSwMOV2sTDOdbEwznWxMM71sHjGuS4WxrkuFsa5LhbGuS4WIZYeFsa5LhZuWnaxMOV2sTDldrEw5fawBBMp90uriej6pdVEHv3SaiJkfmkVQ1pNxMEvrSYy3pdWE8HtS6uJNPal1UTE+rtWMZSbxFBuEkO5SQzlJjGUm8RQbhJDuUkM5SYxlJvEUG6KhnJTNJSboqHcFA3lpmgoN0VDuSkayk3RUG6KhnJTNJSbkqHclAzlpmQoNyVDucnGcTFfWg3lJhsHu3xpNZSbbBzB8qXVUG6ycVjKl1ZDucnGsSZfWg3lJhsHkHxpNZSbbBwV8qXVUG6ycajHl1ZDucnG8RtfWg3lJhsHZXxpNZSbbBxp8aXVUG6ycfjEl1ZDucnGMRFfWg3lJhsHOnxpNZSblirTr01r3jrfCV2qIX+kdZ33YXF5/8Xiarz84i8w67xpq4JJC5WZK4NZxw6UwawzcyuDWWdAVwYjBNMHs040UQazzj6BMph1NhWUwTD5HoBh8u2DWajgXBkMk+8BGCbfAzBMvgdghGD6YJh8D8Aw+R6AYfI9AMPkewCGybcPZqEueGUwTL4HYJh8D8Aw+R6AEZtgvI9hV+hz6IAxmnzHYIwmX++Dv4ORDhijOcZL3V/s47b9BLNQ27cyGKM5ZgzGaI4ZgzGaY8ZghGD6YKzmmCEYqzlmCMboDt4YjNEdvDEYJt8+mIX62pXBMPkegGHyPQAjBNMHw4B3AIYB7wCMVbsu0rY2S5LfvziE3FYhW2e7b6FO8XdStBoEdClaTQ26FK1urulSFFJUoGg11elStBoBdSla3RDUpWh191CXImcXBYoL9fq/kyJnFw2KnF00KDLpjCnmsuvLtbMvtlDz/NsYLtQa/ecxrO0Ryxpzh6GQ4TRD/ls+wTDvT7TW0nk2fKGW5fcx5LwyzXChVuj3MeSsMs+Qk8o8Q+bDeYZChtMM+fnKPEPuOcwz5Jwyz5BzyjxDziljhm4LOw63lc4u7EI97O+kyFlFgyKnFQ2KnFc0KAopKlDkzKJBkVOLBkXOLRoUObloUOTsMk8xWz1hRJkiZxcNipxdNChydtGgKKSoQJGziwZFzi4aFDm7aFDk7KJBkbOLAkWrZ8Q8R9E1HLf/TB2KnF00KHJ20aDI2UWDopCiAkXOLhoUObtoUOTsokGRs4sCRavn0yhTZOrWoMjUrUGRqVuDopCiAkWmbg2KTN0aFJm6NSgydWtQ5CcGChTNnkmlS5GziwZFzi4aFDm7aFAUUlSgyNlFgyJnFwWKZs8geoqid42id7VDkUlHgyLd5QzFII2ihA5FuosGRbqLBkXujGlQ5M6YBkXujClQ5LlWKhSZFzUocmdMgyJ3xjQoCikqUOTsokGRs4sGRc4uGhQ5u2hQ5OyiQJHnWqlQ5OyiQZGziwZFzi6/UvwCIwTTB8MJ4wAMh4YDMJwDDsAw2h+AYVrvg8kM4AdgmKkPwDAmH4Bh8j0AIwTTB8PkewCGyfcADJPvARgm3z4Ys2cgVl92hTX4Dhirdj0EY/XNt0bXwHT/KVl98x2CsfrmOwRjddthBMbsuWtDMFa3HYZgzOaYERizOWYERgimD8bqtsMQDJPvARijyTfvzzrk2IFiNPX+HorRxPs7KMXqSV2/h2I06f4eitGU+3soRhPu76EIofyEYjTZ/h6K0VT7eyhMtB0oTLQdKEy0P6FYPXno91AY3jpQGN46UIRQfkJheOtAMRrewr0lL7haOmCMBrgxGKMhbgzGaJAbgrF6LNAYjNGUOwZjNOmOwVi1a++3/Rd7Lx0wVu16BMbquQbBlzuYmjtgrL75DsFYffMdgjG61TAGIwTTB2N0y2EMxmyOGYExm2NGYKxuOwzBWN12GIGxes7FGAyT7wEYq8n34ReH1ANjNfkOwQjB9MFYTb5DMFaT7xCM1eQbcvvFsnV28KyeYjEEY/VgijEYqwFvCMZswBuBMRvwRmCEYPpgzAa8ERizAW8EhgHvAIzVrc0hGCbfPhirxxqMwTD5HoBh8j0Aw+R7AEYIpg+GyfcADJPvARgm3wMwTL4HYJh8+2CsnicwBsPkewCGyfcADJPvARghmD4YJt8DMEy+B2CYfA/AMPkegGHy7YMpTL4HYJh8D8Aw+R6AYfI9ACME0wfD5HsAhsn3AAyT7wEYJt8DMEy+fTBWD3MZg2HyPQDD5HsAhsn3AIx0wbgoDUzx38B8/Vy8+HPp4s/liz9XLv5cvfRz9eBIgvHPuYs/5y/+XLj4c3Lx5+LFn0sXfy5f/Lly8ecu3i/u4v3iLt4v7uL94i7eL+7i/eIu3i/u4v3iLt4v7uL94i7eL/7i/eIv3i/+4v3iL94v/uL94i/eL/7i/eIv3i/+4v3iL94v4eL9Ei7eL+Hi/RIu3i/h4v0SLt4v4eL9Ei7eL+Hi/RIu3i9y8X6Ri/eLXLxf5OL9IhfvF7l4v8jF+0Uu3i9y8X6Ri/dLvHi/xIv3S7x4v8SL90u8eL/Ei/dLvHi/xIv3S7x4v8SL90u6eL+ki/dLuni/pIv3S7p4v6SL90u6eL+ki/dLuni/pIv3S754v+SL90u+eL/ki/dLvni/5Iv3S754v+SL90u+eL/ki/dLuXi/lIv3S7l4v5SL90u5eL+Ui/dLuXi/lIv3S7l4v5SL90u9eL/Ui/dLvXi/1Iv3y8X93Xpxf7de3N+tF/d368X93Xpxf9dtFzd4bz/orv6gv/qD4eoPytUfjFd/MF39wXz1B8vVH7x657ird467eue4q3eOu3rnuKt3jrt657ird467eue4q3eOu3rn+Kt3jr965/ird46/euf4q3eOv3rn+Kt3jr965/ird46/eueEq3dOuHrnhKt3Trh654Srd064eueEq3dOuHrnhKt3Trh658jVO0eu3jly9c6Rq3eOXL1z5OqdI1fvHLl658jVO0eu3jnx6p0Tr9458eqdE6/eOfHqnROv3jnx6p0Tr9458eqdE6/eOenqnZOu3jnp6p2Trt456eqdk67eOenqnZOu3jnp6p2Trt45+eqdk6/eOfnqnZOv3jn56p2Tr945+eqdk6/eOfnqnZOv3jnl6p1Trt455eqdU67eOeXqnVOu3jnl6p1Trt455eqdU67eOfXqnVOv3jn16p1Tr9459eqdU6/eOfXqnVOv3jn16p1zdQ/ZXd1Ddlf3kN3VPWR3dQ/5Nj9c/cF49QfT1R/MV3+wXP3Bq3fO1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95Dd1T1kd3UP2V3dQ3ZX95DdwR6yT/tXrXzY4rcf7HzjK5SvF9eH73A58b3vksX9RLZvx5370Pu90bv9F8fy8IWvUNvyI/byE/byM/byC/byK/TyDz4ugVm+x15+wF4+tm0Jtm0Jtm0Jtm0Jtm0Jtm0dfMgLs3xs140KrvvHZ5j7mm67AwMB+/K3wW/1t89i9zXcPs25/9aY2+ID8uIFefERefEJefEZefEFefEVePFpQ168Q148ssMmZIdNyA6bkB02ITtsQnbYhOywCdlhM7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkhy3IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IjtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bAV2WL8BO6zfgB3Wb8AO6zdgh/UbsMP6Ddhh/QbssH4Ddli/ATus35Ad1iE7rEN2WIfssA7ZYR2ywzpkh3XIDuuQHdYhO6xDdliP7LAe2WE9ssN6ZIf1yA7rkR3WIzusR3ZYj+ywHtlhA7LDBmSHDcgOG5AdVqM46X2LR3bYgOywAdlhA7LDBmSHFWSHFWSHFWSHFWSH1eh4et/ikR1WkB1WkB1WkB1WkB02IjtsRHZY5E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzoF5E6ngNzpFJA7nQJyp1PYgB02IHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU6C3OkkyJ1OgtzpJMidTrIBO6wgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6yUGnUwilLT7L4DK1vbiWMli6i/viXb2/1vvQ+73R78uvsdwR+lDb8gP28gV7+RF7+Ql7+Rl7+RV6+QclSTDLd9jLx7YtwbYtwbYtwbYtwbYtwbatg9IkmOUruO7bhpW4IS/eIS/eIy8+IC9ekBcfkRefkBefkRdfkBeP7LAJ2WETssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bEV22ArssHEDdti4ATts3IAdNm7ADhs3YIeNG7DDxg3YYeMG7LBxA3bYuCE7rEN2WIfssA7ZYR2ywzpkh3XIDuuQHdYhO6xDdliH7LAe2WE9ssN6ZIf1yA7rkR3WIzusR3ZYj+ywHtlhPbLDBmSHDcgOG5AdNiA7rEZl0vsWj+ywAdlhA7LDBmSHDcgOK8gOK8gOK8gOK8gOq9Hu9L7FIzusIDusIDusIDsscqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidTgm50ykhdzol5E6nhNzplDZgh03InU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0LudErInU4JudMpIXc6JeROp4Tc6ZSQO50ScqdTQu50SsidTgm50ykhdzol5E6nhNzplJA7nRJyp1NC7nRKyJ1OCbnTKSF3OiXkTqeE3OmUkDudEnKnU0budMrInU4ZudMpI3c65Q3YYTNyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO53yQaeTbG3xInFwmdqU1lIGS3dxX7yr99d6H3q/N/p9+TWW+yp8qG35Hnv5AXv5gr38iL38hL38gr38Cr38g5okmOVj21bAtq2AbVsB27YCtm0FbNs6KE2CWb6C675tWAkVePGyIS/eIS/eIy8+IC9ekBcfkRefkBefkReP7LCC7LAR2WEjssNGZIeNyA4bkR02IjtsRHbYiOywEdlhI7LDJmSHTcgOm5AdNiE7bEJ22ITssAnZYROywyZkh03IDpuRHTYjO2xGdtiM7LAZ2WEzssNmZIfNyA6bkR02IztsQXbYguywBdlhC7LDFmSHLcgOW5AdtiA7bEF22ILssBXZYSuyw1Zkh63IDluRHbYiO2xFdtiK7LAV2WErsMOWDdhhywbssGUDdtiyATts2YAdtmzADls2YIctG7DDlg3YYcuG7LAO2WEdssM6ZId1yA7rkB3WITusQ3ZYh+ywDtlhHbLDemSH9cgO65Ed1iM7rEZh0vsWj+ywHtlhPbLDemSH9cgOG5AdNiA7bEB22IDssBrdTu9bPLLDBmSHDcgOi9zpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpIHc6FeROp4Lc6VSQO50KcqdTQe50KsidTgW506kgdzoV5E6ngtzpVJA7nQpyp1NB7nQqyJ1OBbnTqSB3OhXkTqeC3OlUkDudCnKnU0HudCrInU4FudOpInc6VeROp4rc6VSRO53qBuywFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1NF7nSqyJ1OFbnTqSJ3OlXkTqeK3OlUkTudKnKnU0XudKrInU4VudOpInc6VeROp4rc6VSRO50qcqdTRe50qsidThW506kidzpV5E6nitzpVJE7nSpyp1MF7nTyG3Cn023xuA57Wzyuw94Wj+uwt8XjOuxt8bgOe1s8rsPeFo/rsLfF4zrsbfHIDnvU6ZTr/oPRpcFlatiV3jYjBkt3cV/8bfhvr/U+9H5v9Pvyayx3hD7UtnyHvXyPvfyAvXzBXn7EXn7GXn7BXn6FXr7Hti2PbVse27Y8tm15bNvy2LZ1VJqEsnwF133bsOIL8uIr8OLDhrx4h7x4j7z4gLx4QV58RF58Ql48ssMGZIcNyA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4ryA4bkR02IjtsRHbYiOywEdlhI7LDRmSHjcgOG5EdNiI7bEJ22ITssAnZYROywyZkh03IDpuQHTYhO2xCdtiE7LAZ2WEzssNmZIfNyA6bkR02IztsRnbYjOywGdlhM7LDFmSHLcgOW5AdtiA7bEF22ILssAXZYQuywxZkhy3IDluRHbYiO2xFdtiK7LAV2WErssNWZIetyA5bkR22Ajus24Ad1m3ADus2YId1G7DDug3YYd0G7LBuA3ZYtwE7rNuAHdZtyA7rkB3WITusQ3ZYh+ywGnVJ71s8ssM6ZId1yA7rkB3WITusR3ZYj+ywHtlhPbLDajQ7vW/xyA7rkR0WudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJIXc6OeROJ4fc6eSQO50ccqeTQ+50csidTg6508khdzo55E4nh9zp5JA7nRxyp5ND7nRyyJ1ODrnTySF3OjnkTieH3OnkkDudHHKnk0PudHLInU4OudPJI3c6eeROJ4/c6eSRO538BuywHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudPHKnk0fudPLInU4eudPJI3c6eeROJ4/c6eSRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5M/6HSKcWuLL3lwmRrK14trKYOlu/aLXb2/1vvQ+73R78uvscT7q0P9Wn44aHWCWb7DXr7HXn7AXr5gLz9hLz9jL79gLx/bthy2bTls23LYtuWwbcth29ZBaRLM8hVc913DSnAZefEFefEVePF+Q168Q168R158QF68IC8+Ii8e2WE9ssN6ZIf1yA4bkB02IDtsQHbYgOywAdlhA7LDBmSHDcgOG5AdNiA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7rCA7bER22IjssBHZYSOyw0Zkh43IDhuRHTYiO2xEdtiI7LAJ2WETssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDZmSHzcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDluQHbYgO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsRXbYiuywFdlhK7LDVmSHrcgOW5EdtiI7bEV22ArssLIBO6xswA4rG7DDygbssLIBO6xswA4rG7DDygbssLIBO6xsyA7rkB3WITusQ3ZYh+ywGr1O71s8ssMidzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp5MgdzoJcqeTIHc6CXKnkyB3Oglyp1NE7nSKyJ1OEbnTKSJ3OsUN2GEjcqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1OEbnTKSJ3OkXkTqeI3OkUkTudInKnU0TudIrInU4RudMpInc6ReROp4jc6RSRO50icqdTRO50isidThG50ykidzpF5E6niNzpFJE7nSJyp1NE7nSKyJ1O8aDTKfn2gymWwWVqKF8vrqUMlu4aFVfvr/U+9H5vbKuot/v7/upQ2/Ir9PIPep1glu+wl++xlx+wlx+xl5+wl5+xl49tWxXattIGbVtpg7attEHbVtqgbSttgr18Bdd917CStoS8+Iy8+IK8+Aq8eLchL94hL94jLz4gL16QF4/ssA7ZYR2ywzpkh3XIDuuRHdYjO6xHdliP7LAe2WE9ssN6ZIf1yA7rkR3WIztsQHbYgOywAdlhA7LDBmSHDcgOG5AdNiA7bEB22IDssILssILssILssILssILssILssILssILssILssILssBHZYSOyw0Zkh43IDhuRHTYiO2xEdtiI7LAR2WEjssMmZIdNyA6bkB02ITtsQnbYhOywCdlhE7LDJmSHTcgOm5EdNiM7bEZ22IzssBnZYTOyw2Zkh83IDpuRHTYjO2xBdtiC7LAF2WELssMWZIctyA5bkB22IDtsQXbYguywFdlhK7LDVmSHrcgOW5EdtiI7bEV22IrssBXZYSuww+YN2GHzBuyweQN22LwBO2zegB02I3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6njNzplJE7nTJyp1NG7nTKyJ1OGbnTKSN3OmXkTqeM3OmUkTudMnKnU0budMrInU4ZudMpI3c6ZeROp4zc6ZSRO50ycqdTRu50ysidThm50ykjdzpl5E6n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yA4bkR02IjtsRHbYiOywEdlhI7LDJmSHTcgOm5AdNiE7bEJ22ITssAnZYROywyZkh03IDpuRHTYjO2xGdtiM7LAaLU/vWzyyw2Zkh83IDpuRHTYjO2xBdtiC7LAF2WGRO508cqeTR+508sidTh6508kjdzp55E4nj9zp5JE7nTxyp5NH7nTyyJ1OHrnTySN3OnnkTieP3OnkkTudAnKnU0DudArInU4BudMpbMAOG5A7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E6ngNzpFJA7nQJyp1NA7nQKyJ1OAbnTKSB3OgXkTqeA3OkUkDudAnKnU0DudArInU4BudMpIHc6BeROp4Dc6RSQO50CcqdTQO50CsidTgG50ykgdzoF5E4nQe50EuROJ0HudBLkTifZgB1WkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSZA7nQS500mQO50EudNJkDudBLnTSQ46ncqW9x8ssY4uU2rdX119+HaZn6++ZcF9UTd/z4NX+5jT/ruTS4NX19h+d40ltlf7UJvgZE1wtia4WBNcjQk+6LVaWLCzJthbExysCRZrgq0lrWQtaSVrSStZS1rJWtLKb0ha23YXXEaCt7L/6iDttSl1XhrKjkb8A0dfu0vewQRXvr125+LIpcvFk0uXSyCXLhchly6X+NlcXA2NS/w9l5LivoyS0qODpaY2mVKbTaktptRWS2rLh6dD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"},{"name":"rotate_npk_m","is_unconstrained":true,"custom_attributes":["aztec(public)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"selector","type":{"kind":"field"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"aztec::context::inputs::public_context_inputs::PublicContextInputs"},"visibility":"private"},{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"new_npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"}],"return_type":null},"bytecode":"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","debug_symbols":"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"},{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/fMxopWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLLX/ent52x9uL03n3fp7ut6Pupv3x6fY0Pu+m58PL/vrc2+e3u9tohdF2I6PIqGS0lVGTUZfRLKMhIyliK0U0KaJJEU2KaFJEkyKaFNGkiCZFNCmiSRFdiuhSRJciuhTRpYguRXQpoksRXYroUsQsRcxSxCxFzFLELEXMUsQsRcxSxCxFzFLEkCKGFDGkiCFFDCliSBFDihhSxJAihhSxSBGLFLFIEYsUsUgRixSxSBGLFLFIEYsUsUoRqxSxShGrFLFKEasUsUoRqxSxShGrFJHNhlahVdFqS6tGq06rmVaDVgutqI1QG6E2Qm2E2gi1EWoj1EaojVAboTaK2ihqo6iNojaK2ihqo6iNojYINEOiGSLNkGmGUDOkmiHWDLlmCDZDshmizZBthnAzpJsh3gz5Zgg4Q8IZIs6QcYaQM6ScIeYMOWcIOkPSGaLOkHWGsDOknSHuDHlnCDxD4hkiz5B5htAzpJ4h9gy5Zwg+Q/IZos+QfYbwM6SfIf4M+WcIQEMCGiLQkIGGEDSkoCEGDTloCEJDEhqi0JCFhjA0pKEhDg15aAhEQyIaItGQiYZQNKSiIRYNuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlokYsWuWiRixa5aJGLFrlo2UVPctEiFy1y0SIXLXLRIhctctH6bxe9nn7u3g+7h5f97W7v7ePH8fHfVd/r8fzr7e+X67+/AQ=="}],"outputs":{"globals":{"storage":[{"fields":[{"name":"npk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000001"}}],"kind":"struct"}},{"name":"npk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000002"}}],"kind":"struct"}},{"name":"ivpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000003"}}],"kind":"struct"}},{"name":"ivpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000004"}}],"kind":"struct"}},{"name":"ovpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000005"}}],"kind":"struct"}},{"name":"ovpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000006"}}],"kind":"struct"}},{"name":"tpk_m_x_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000007"}}],"kind":"struct"}},{"name":"tpk_m_y_registry","value":{"fields":[{"name":"slot","value":{"kind":"integer","sign":false,"value":"0000000000000000000000000000000000000000000000000000000000000008"}}],"kind":"struct"}}],"kind":"struct"}]},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"partial_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::partial_address::PartialAddress"}},{"name":"keys","type":{"fields":[{"name":"npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ivpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"ovpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"tpk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}}],"kind":"struct","path":"aztec::keys::public_keys::PublicKeys"}}],"kind":"struct","path":"KeyRegistry::register_parameters"}}],"kind":"struct","path":"KeyRegistry::register_abi"},{"fields":[{"name":"parameters","type":{"fields":[{"name":"address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"new_npk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"KeyRegistry::rotate_npk_m_parameters"}}],"kind":"struct","path":"KeyRegistry::rotate_npk_m_abi"}]}},"file_map":{"129":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\n\n#[oracle(storageRead)]\nunconstrained fn storage_read_oracle(_storage_slot: Field, _number_of_elements: Field) -> [Field; N] {}\n\nunconstrained fn storage_read_oracle_wrapper(_storage_slot: Field) -> [Field; N] {\n storage_read_oracle(_storage_slot, N)\n}\n\npub fn storage_read(storage_slot: Field) -> [Field; N] {\n storage_read_oracle_wrapper(storage_slot)\n}\n\n#[oracle(storageWrite)]\nunconstrained fn storage_write_oracle(_storage_slot: Field, _values: [Field; N]) -> [Field; N] {}\n\nunconstrained pub fn storage_write(storage_slot: Field, fields: [Field; N]) {\n let _hash = storage_write_oracle(storage_slot, fields);\n}\n"},"142":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/map.nr","source":"use dep::protocol_types::{hash::pedersen_hash, storage::map::derive_storage_slot_in_map, traits::ToField};\nuse crate::state_vars::storage::Storage;\n\n// docs:start:map\nstruct Map {\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V,\n}\n// docs:end:map\n\nimpl Storage for Map {}\n\nimpl Map {\n // docs:start:new\n pub fn new(\n context: Context,\n storage_slot: Field,\n state_var_constructor: fn(Context, Field) -> V\n ) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Map { context, storage_slot, state_var_constructor }\n }\n // docs:end:new\n\n // docs:start:at\n pub fn at(self, key: K) -> V where K: ToField {\n // TODO(#1204): use a generator index for the storage slot\n let derived_storage_slot = derive_storage_slot_in_map(self.storage_slot, key);\n\n let state_var_constructor = self.state_var_constructor;\n state_var_constructor(self.context, derived_storage_slot)\n }\n // docs:end:at\n}\n"},"152":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_delay_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to store the minimum delay with which a ScheduledValueChange object can\n// schedule a change.\n// This delay is initally equal to INITIAL_DELAY, and can be safely mutated to any other value over time. This mutation \n// is performed via `schedule_change` in order to satisfy ScheduleValueChange constraints: if e.g. we allowed for the \n// delay to be decreased immediately then it'd be possible for the state variable to schedule a value change with a \n// reduced delay, invalidating prior private reads.\nstruct ScheduledDelayChange {\n // Both pre and post are stored in public storage, so by default they are zeroed. By wrapping them in an Option, \n // they default to Option::none(), which we detect and replace with INITIAL_DELAY. The end result is that a\n // ScheduledDelayChange that has not been initialized has a delay equal to INITIAL_DELAY, which is the desired\n // effect. Once initialized, the Option will never be none again.\n pre: Option,\n post: Option,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n // The _dummy variable forces INITIAL_DELAY to be interpreted as a numeric value. This is a workaround to\n // https://github.com/noir-lang/noir/issues/4633. Remove once resolved.\n _dummy: [Field; INITIAL_DELAY],\n}\n\nimpl ScheduledDelayChange {\n pub fn new(pre: Option, post: Option, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change, _dummy: [0; INITIAL_DELAY] }\n }\n\n /// Returns the current value of the delay stored in the data structure.\n /// This function only returns a meaningful value when called in public with the current block number - for\n /// historical private reads use `get_effective_minimum_delay_at` instead.\n pub fn get_current(self, current_block_number: u32) -> u32 {\n // The post value becomes the current one at the block of change, so any transaction that is included in the\n // block of change will use the post value.\n\n if current_block_number < self.block_of_change {\n self.pre.unwrap_or(INITIAL_DELAY)\n } else {\n self.post.unwrap_or(INITIAL_DELAY)\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change delay and the block at which it will become the current\n /// delay. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (u32, u32) {\n (self.post.unwrap_or(INITIAL_DELAY), self.block_of_change)\n }\n\n /// Mutates the delay change by scheduling a change at the current block number. This function is only meaningful\n /// when called in public with the current block number.\n /// The block at which the new delay will become effective is determined automatically:\n /// - when increasing the delay, the change is effective immediately\n /// - when reducing the delay, the change will take effect after a delay equal to the difference between old and\n /// new delay. For example, if reducing from 3 days to 1 day, the reduction will be scheduled to happen after 2\n /// days.\n pub fn schedule_change(&mut self, new: u32, current_block_number: u32) {\n let current = self.get_current(current_block_number);\n\n // When changing the delay value we must ensure that it is not possible to produce a value change with a delay\n // shorter than the current one.\n let blocks_until_change = if new > current {\n // Increasing the delay value can therefore be done immediately: this does not invalidate prior contraints\n // about how quickly a value might be changed (indeed it strengthens them).\n 0\n } else {\n // Decreasing the delay requires waiting for the difference between current and new delay in order to ensure\n // that overall the current delay is respected.\n //\n // current delay earliest value block of change\n // block block of change if delay remained unchanged\n // =======N=========================|================================X=================>\n // ^ ^ ^\n // |-------------------------|--------------------------------|\n // | blocks until change new delay |\n // ------------------------------------------------------------\n // current delay\n current - new\n };\n\n self.pre = Option::some(current);\n self.post = Option::some(new);\n self.block_of_change = current_block_number + blocks_until_change;\n }\n\n /// Returns the minimum delay before a value might mutate due to a scheduled change, from the perspective of some\n /// historical block number. It only returns a meaningful value when called in private with historical blocks. This \n /// function can be used alongside `ScheduledValueChange.get_block_horizon` to properly constrain the\n /// `max_block_number` transaction property when reading mutable shared state.\n /// This value typically equals the current delay at the block following the historical one (the earliest one in\n /// which a value change could be scheduled), but it also considers scenarios in which a delay reduction is \n /// scheduled to happen in the near future, resulting in a way to schedule a change with an overall delay lower than\n /// the current one.\n pub fn get_effective_minimum_delay_at(self, historical_block_number: u32) -> u32 {\n if self.block_of_change <= historical_block_number {\n // If no delay changes were scheduled, then the delay value at the historical block (post) is guaranteed to\n // hold due to how further delay changes would be scheduled by `schedule_change`.\n self.post.unwrap_or(INITIAL_DELAY)\n } else {\n // If a change is scheduled, then the effective delay might be lower than the current one (pre). At the\n // block of change the current delay will be the scheduled one, with an overall delay from the historical\n // block number equal to the number of blocks until the change plus the new delay. If this value is lower\n // than the current delay, then that is the effective minimum delay.\n //\n // historical\n // block delay actual earliest value\n // v block of change block of change\n // =========NS=====================|=============================X===========Y=====>\n // ^ ^ ^ ^\n // earliest block in | | |\n // which to schedule change | | |\n // | | | |\n // |----------------------|------------------------------ |\n // | blocks new delay |\n // | until change |\n // | |\n // |----------------------------------------------------------------|\n // current delay at the earliest block in \n // which to scheduled value change\n\n let blocks_until_change = self.block_of_change - (historical_block_number + 1);\n\n min(\n self.pre.unwrap_or(INITIAL_DELAY),\n blocks_until_change + self.post.unwrap_or(INITIAL_DELAY)\n )\n }\n }\n}\n\nimpl Serialize<1> for ScheduledDelayChange {\n fn serialize(self) -> [Field; 1] {\n // We pack all three u32 values into a single U128, which is made up of two u64 limbs.\n // Low limb: [ pre_inner: u32 | post_inner: u32 ]\n // High limb: [ empty | pre_is_some: u8 | post_is_some: u8 | block_of_change: u32 ]\n\n let lo = ((self.pre.unwrap_unchecked() as u64) * (1 << 32))\n + (self.post.unwrap_unchecked() as u64);\n\n let hi = (self.pre.is_some() as u64) * (1 << 33) \n + (self.post.is_some() as u64 * (1 << 32)) \n + self.block_of_change as u64;\n\n let packed = U128::from_u64s_le(lo, hi);\n\n [packed.to_integer()]\n }\n}\n\nimpl Deserialize<1> for ScheduledDelayChange {\n fn deserialize(input: [Field; 1]) -> Self {\n let packed = U128::from_integer(input[0]);\n\n // We use division and modulo to clear the bits that correspond to other values when unpacking.\n\n let pre_is_some = ((packed.hi as u64) / (1 << 33)) as bool;\n let pre_inner = ((packed.lo as u64) / (1 << 32)) as u32;\n\n let post_is_some = (((packed.hi as u64) / (1 << 32)) % (1 << 1)) as bool;\n let post_inner = ((packed.lo as u64) % (1 << 32)) as u32;\n\n let block_of_change = ((packed.hi as u64) % (1 << 32)) as u32;\n\n Self {\n pre: if pre_is_some { Option::some(pre_inner) } else { Option::none() },\n post: if post_is_some { Option::some(post_inner) } else { Option::none() },\n block_of_change,\n _dummy: [0; INITIAL_DELAY],\n }\n }\n}\n"},"156":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/scheduled_value_change.nr","source":"use dep::protocol_types::traits::{Serialize, Deserialize, FromField, ToField};\nuse dep::std::cmp::min;\n\nmod test;\n\n// This data structure is used by SharedMutable to represent a value that changes from `pre` to `post` at some block\n// called the `block_of_change`. The value can only be made to change by scheduling a change event at some future block\n// of change after some minimum delay measured in blocks has elapsed. This means that at any given block number we know\n// both the current value and the smallest block number at which the value might change - this is called the\n// 'block horizon'.\nstruct ScheduledValueChange {\n pre: T,\n post: T,\n // Block at which `post` value is used instead of `pre`\n block_of_change: u32,\n}\n\nimpl ScheduledValueChange {\n pub fn new(pre: T, post: T, block_of_change: u32) -> Self {\n Self { pre, post, block_of_change }\n }\n\n /// Returns the value stored in the data structure at a given block. This function can be called both in public\n /// (where `block_number` is simply the current block number, i.e. the number of the block in which the current\n /// transaction will be included) and in private (where `block_number` is the historical block number that is used\n /// to construct the proof).\n /// Reading in private is only safe if the transaction's `max_block_number` property is set to a value lower or\n /// equal to the block horizon (see `get_block_horizon()`).\n pub fn get_current_at(self, block_number: u32) -> T {\n // The post value becomes the current one at the block of change. This means different things in each realm:\n // - in public, any transaction that is included in the block of change will use the post value\n // - in private, any transaction that includes the block of change as part of the historical state will use the\n // post value (barring any follow-up changes)\n\n if block_number < self.block_of_change {\n self.pre\n } else {\n self.post\n }\n }\n\n /// Returns the scheduled change, i.e. the post-change value and the block at which it will become the current\n /// value. Note that this block may be in the past if the change has already taken place.\n /// Additionally, further changes might be later scheduled, potentially canceling the one returned by this function.\n pub fn get_scheduled(self) -> (T, u32) {\n (self.post, self.block_of_change)\n }\n\n /// Returns the largest block number at which the value returned by `get_current_at` is known to remain the current\n /// value. This value is only meaningful in private when constructing a proof at some `historical_block_number`,\n /// since due to its asynchronous nature private execution cannot know about any later scheduled changes.\n /// The caller of this function must know how quickly the value can change due to a scheduled change in the form of\n /// `minimum_delay`. If the delay itself is immutable, then this is just its duration. If the delay is mutable\n /// however, then this value is the 'effective minimum delay' (obtained by calling\n /// `ScheduledDelayChange.get_effective_minimum_delay_at`), which equals the minimum number of blocks that need to\n /// elapse from the next block until the value changes, regardless of further delay changes.\n /// The value returned by `get_current_at` in private when called with a historical block number is only safe to use\n /// if the transaction's `max_block_number` property is set to a value lower or equal to the block horizon computed\n /// using the same historical block number.\n pub fn get_block_horizon(self, historical_block_number: u32, minimum_delay: u32) -> u32 {\n // The block horizon is the very last block in which the current value is known. Any block past the horizon\n // (i.e. with a block number larger than the block horizon) may have a different current value. Reading the\n // current value in private typically requires constraining the maximum valid block number to be equal to the\n // block horizon.\n\n if historical_block_number >= self.block_of_change {\n // Once the block of change has been mined, the current value (post) will not change unless a new value\n // change is scheduled. This did not happen at the historical block number (or else it would not be\n // greater or equal to the block of change), and therefore could only happen after the historical block\n // number. The earliest would be the immediate next block, and so the smallest possible next block of change\n // equals `historical_block_number + 1 + minimum_delay`. Our block horizon is simply the previous block to\n // that one.\n //\n // block of historical\n // change block block horizon\n // =======|=============N===================H===========>\n // ^ ^\n // ---------------------\n // minimum delay\n\n historical_block_number + minimum_delay\n } else {\n // If the block of change has not yet been mined however, then there are two possible scenarios.\n // a) It could be so far into the future that the block horizon is actually determined by the minimum\n // delay, because a new change could be scheduled and take place _before_ the currently scheduled one.\n // This is similar to the scenario where the block of change is in the past: the time horizon is the\n // block prior to the earliest one in which a new block of change might land.\n //\n // historical\n // block block horizon block of change\n // =====N=================================H=================|=========>\n // ^ ^\n // | |\n // -----------------------------------\n // minimum delay\n //\n // b) It could be fewer than `minimum_delay` blocks away from the historical block number, in which case\n // the block of change would become the limiting factor for the time horizon, which would equal the\n // block right before the block of change (since by definition the value changes at the block of\n // change).\n //\n // historical block horizon\n // block block of change if not scheduled\n // =======N=============|===================H=================>\n // ^ ^ ^\n // | actual horizon |\n // -----------------------------------\n // minimum delay\n //\n // Note that the current implementation does not allow the caller to set the block of change to an arbitrary\n // value, and therefore scenario a) is not currently possible. However implementing #5501 would allow for\n // this to happen.\n\n // Because historical_block_number < self.block_of_change, then block_of_change > 0 and we can safely\n // subtract 1.\n min(\n self.block_of_change - 1,\n historical_block_number + minimum_delay\n )\n }\n }\n\n /// Mutates the value by scheduling a change at the current block number. This function is only meaningful when\n /// called in public with the current block number.\n pub fn schedule_change(\n &mut self,\n new_value: T,\n current_block_number: u32,\n minimum_delay: u32,\n block_of_change: u32\n ) {\n assert(block_of_change >= current_block_number + minimum_delay);\n\n self.pre = self.get_current_at(current_block_number);\n self.post = new_value;\n self.block_of_change = block_of_change;\n }\n}\n\nimpl Serialize<3> for ScheduledValueChange {\n fn serialize(self) -> [Field; 3] where T: ToField {\n [self.pre.to_field(), self.post.to_field(), self.block_of_change.to_field()]\n }\n}\n\nimpl Deserialize<3> for ScheduledValueChange {\n fn deserialize(input: [Field; 3]) -> Self where T: FromField {\n Self {\n pre: FromField::from_field(input[0]),\n post: FromField::from_field(input[1]),\n block_of_change: FromField::from_field(input[2]),\n }\n }\n}\n"},"157":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr","source":"use dep::protocol_types::{hash::pedersen_hash, traits::FromField};\n\nuse crate::context::{PrivateContext, PublicContext};\nuse crate::public_storage;\nuse crate::state_vars::{\n storage::Storage,\n shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange}\n};\n\nmod test;\n\nstruct SharedMutable {\n context: Context,\n storage_slot: Field,\n}\n\n// This will make the Aztec macros require that T implements the Serialize trait, and allocate N storage slots to\n// this state variable. This is incorrect, since what we actually store is:\n// - a ScheduledValueChange, which requires 1 + 2 * M storage slots, where M is the serialization length of T\n// - a ScheduledDelayChange, which requires another storage slot\n//\n// TODO https://github.com/AztecProtocol/aztec-packages/issues/5736: change the storage allocation scheme so that we \n// can actually use it here\nimpl Storage for SharedMutable {}\n\n// SharedMutable stores a value of type T that is:\n// - publicly known (i.e. unencrypted)\n// - mutable in public\n// - readable in private with no contention (i.e. multiple parties can all read the same value without blocking one\n// another nor needing to coordinate)\n// This is famously a hard problem to solve. SharedMutable makes it work by introducing a delay to public mutation:\n// the value is not changed immediately but rather a value change is scheduled to happen in the future after some delay\n// measured in blocks. Reads in private are only valid as long as they are included in a block not too far into the \n// future, so that they can guarantee the value will not have possibly changed by then (because of the delay).\n// The delay for changing a value is initially equal to INITIAL_DELAY, but can be changed by calling \n// `schedule_delay_change`.\nimpl SharedMutable {\n pub fn new(context: Context, storage_slot: Field) -> Self {\n assert(storage_slot != 0, \"Storage slot 0 not allowed. Storage slots must start from 1.\");\n Self { context, storage_slot }\n }\n\n // Since we can't rely on the native storage allocation scheme, we hash the storage slot to get a unique location in\n // which we can safely store as much data as we need. \n // See https://github.com/AztecProtocol/aztec-packages/issues/5492 and \n // https://github.com/AztecProtocol/aztec-packages/issues/5736\n fn get_value_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 0], 0)\n }\n\n fn get_delay_change_storage_slot(self) -> Field {\n pedersen_hash([self.storage_slot, 1], 0)\n }\n}\n\nimpl SharedMutable {\n pub fn schedule_value_change(self, new_value: T) {\n let mut value_change = self.read_value_change();\n let delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n let current_delay = delay_change.get_current(block_number);\n\n // TODO: make this configurable\n // https://github.com/AztecProtocol/aztec-packages/issues/5501\n let block_of_change = block_number + current_delay;\n value_change.schedule_change(new_value, block_number, current_delay, block_of_change);\n\n self.write_value_change(value_change);\n }\n\n pub fn schedule_delay_change(self, new_delay: u32) {\n let mut delay_change = self.read_delay_change();\n\n let block_number = self.context.block_number() as u32;\n\n delay_change.schedule_change(new_delay, block_number);\n\n self.write_delay_change(delay_change);\n }\n\n pub fn get_current_value_in_public(self) -> T {\n let block_number = self.context.block_number() as u32;\n self.read_value_change().get_current_at(block_number)\n }\n\n pub fn get_current_delay_in_public(self) -> u32 {\n let block_number = self.context.block_number() as u32;\n self.read_delay_change().get_current(block_number)\n }\n\n pub fn get_scheduled_value_in_public(self) -> (T, u32) {\n self.read_value_change().get_scheduled()\n }\n\n pub fn get_scheduled_delay_in_public(self) -> (u32, u32) {\n self.read_delay_change().get_scheduled()\n }\n\n fn read_value_change(self) -> ScheduledValueChange {\n public_storage::read(self.get_value_change_storage_slot())\n }\n\n fn read_delay_change(self) -> ScheduledDelayChange {\n public_storage::read(self.get_delay_change_storage_slot())\n }\n\n fn write_value_change(self, value_change: ScheduledValueChange) {\n public_storage::write(self.get_value_change_storage_slot(), value_change);\n }\n\n fn write_delay_change(self, delay_change: ScheduledDelayChange) {\n public_storage::write(self.get_delay_change_storage_slot(), delay_change);\n }\n}\n\nimpl SharedMutable {\n pub fn get_current_value_in_private(self) -> T where T: FromField {\n // When reading the current value in private we construct a historical state proof for the public value.\n // However, since this value might change, we must constrain the maximum transaction block number as this proof\n // will only be valid for however many blocks we can ensure the value will not change, which will depend on the\n // current delay and any scheduled delay changes.\n\n let (value_change, delay_change, historical_block_number) = self.historical_read_from_public_storage(*self.context);\n\n // We use the effective minimum delay as opposed to the current delay at the historical block as this one also\n // takes into consideration any scheduled delay changes. \n // For example, consider a scenario in which at block 200 the current delay was 50. We may naively think that\n // the earliest we could change the value would be at block 251 by scheduling immediately after the historical\n // block, i.e. at block 201. But if there was a delay change scheduled for block 210 to reduce the delay to 20 \n // blocks, then if a value change was scheduled at block 210 it would go into effect at block 230, which is \n // earlier than what we'd expect if we only considered the current delay.\n let effective_minimum_delay = delay_change.get_effective_minimum_delay_at(historical_block_number);\n let block_horizon = value_change.get_block_horizon(historical_block_number, effective_minimum_delay);\n\n // We prevent this transaction from being included in any block after the block horizon, ensuring that the \n // historical public value matches the current one, since it can only change after the horizon.\n self.context.set_tx_max_block_number(block_horizon);\n value_change.get_current_at(historical_block_number)\n }\n\n fn historical_read_from_public_storage(\n self,\n context: PrivateContext\n ) -> (ScheduledValueChange, ScheduledDelayChange, u32) where T: FromField {\n let header = context.get_header();\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let value_change_slot = self.get_value_change_storage_slot();\n let mut raw_value_change_fields = [0; 3];\n for i in 0..3 {\n raw_value_change_fields[i] = header.public_storage_historical_read(\n value_change_slot + i as Field,\n context.this_address()\n );\n }\n\n // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet.\n let delay_change_slot = self.get_delay_change_storage_slot();\n let raw_delay_change_fields = [header.public_storage_historical_read(delay_change_slot, context.this_address())];\n\n let value_change = ScheduledValueChange::deserialize(raw_value_change_fields);\n let delay_change = ScheduledDelayChange::deserialize(raw_delay_change_fields);\n\n let historical_block_number = context.historical_header.global_variables.block_number as u32;\n\n (value_change, delay_change, historical_block_number)\n }\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"223":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/storage/map.nr","source":"use crate::{hash::pedersen_hash, traits::ToField};\n\npub fn derive_storage_slot_in_map(storage_slot: Field, key: K) -> Field where K: ToField {\n pedersen_hash([storage_slot, key.to_field()], 0)\n}\n"},"230":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/type_serialization.nr","source":"use crate::traits::{Serialize, Deserialize};\n\nglobal BOOL_SERIALIZED_LEN: Field = 1;\nglobal U8_SERIALIZED_LEN: Field = 1;\nglobal U32_SERIALIZED_LEN: Field = 1;\nglobal U64_SERIALIZED_LEN: Field = 1;\nglobal U128_SERIALIZED_LEN: Field = 1;\nglobal FIELD_SERIALIZED_LEN: Field = 1;\n\nimpl Serialize for bool {\n fn serialize(self) -> [Field; BOOL_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for bool {\n fn deserialize(fields: [Field; BOOL_SERIALIZED_LEN]) -> bool {\n fields[0] as bool\n }\n}\n\nimpl Serialize for u8 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u8 {\n fn deserialize(fields: [Field; U8_SERIALIZED_LEN]) -> Self {\n fields[0] as u8\n }\n}\n\nimpl Serialize for u32 {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u32 {\n fn deserialize(fields: [Field; U32_SERIALIZED_LEN]) -> Self {\n fields[0] as u32\n }\n}\n\nimpl Serialize for u64 {\n fn serialize(self) -> [Field; U64_SERIALIZED_LEN] {\n [self as Field]\n }\n}\n\nimpl Deserialize for u64 {\n fn deserialize(fields: [Field; U64_SERIALIZED_LEN]) -> Self {\n fields[0] as u64\n }\n}\n\nimpl Serialize for U128 {\n fn serialize(self) -> [Field; 1] {\n [self.to_integer()]\n }\n\n}\n\nimpl Deserialize for U128 {\n fn deserialize(fields: [Field; U128_SERIALIZED_LEN]) -> Self {\n U128::from_integer(fields[0])\n }\n}\n\nimpl Serialize for Field {\n fn serialize(self) -> [Field; U32_SERIALIZED_LEN] {\n [self]\n }\n}\n\nimpl Deserialize for Field {\n fn deserialize(fields: [Field; FIELD_SERIALIZED_LEN]) -> Self {\n fields[0]\n }\n}\n"},"231":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr","source":"use dep::std::cmp::Eq;\nuse crate::utils::field::field_from_bytes;\n\n// Trait: is_empty\n//\n// The general is_empty trait checks if a data type is is empty,\n// and it defines empty for the basic data types as 0.\n//\n// If a Field is equal to zero, then it is regarded as zero.\n// We will go with this definition for now, however it can be problematic \n// if a value can actually be zero. In a future refactor, we can \n// use the optional type for safety. Doing it now would lead to a worse devex\n// and would make it harder to sync up with the cpp code.\n// Preferred over Default trait to convey intent, as default doesn't necessarily mean empty.\ntrait Empty {\n fn empty() -> Self;\n}\n\nimpl Empty for Field { fn empty() -> Self {0} }\n\nimpl Empty for u1 { fn empty() -> Self {0} }\nimpl Empty for u8 { fn empty() -> Self {0} }\nimpl Empty for u32 { fn empty() -> Self {0} }\nimpl Empty for u64 { fn empty() -> Self {0} }\nimpl Empty for U128 { fn empty() -> Self {U128::from_integer(0)} }\n\npub fn is_empty(item: T) -> bool where T: Empty + Eq {\n item.eq(T::empty())\n}\n\npub fn is_empty_array(array: [T; N]) -> bool where T: Empty + Eq {\n array.all(|elem| is_empty(elem))\n}\n\ntrait Hash {\n fn hash(self) -> Field;\n}\n\ntrait ToField {\n fn to_field(self) -> Field;\n}\n\nimpl ToField for Field {\n fn to_field(self) -> Field {\n self\n }\n}\n\nimpl ToField for bool { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u1 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u8 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u32 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for u64 { fn to_field(self) -> Field { self as Field } }\nimpl ToField for U128 {\n fn to_field(self) -> Field {\n self.to_integer()\n }\n}\nimpl ToField for str {\n fn to_field(self) -> Field {\n assert(N < 32, \"String doesn't fit in a field, consider using Serialize instead\");\n field_from_bytes(self.as_bytes(), true)\n }\n}\n\ntrait FromField {\n fn from_field(value: Field) -> Self;\n}\n\nimpl FromField for Field {\n fn from_field(value: Field) -> Self {\n value\n }\n}\n\nimpl FromField for bool { fn from_field(value: Field) -> Self { value as bool } }\nimpl FromField for u1 { fn from_field(value: Field) -> Self { value as u1 } }\nimpl FromField for u8 { fn from_field(value: Field) -> Self { value as u8 } }\nimpl FromField for u32 { fn from_field(value: Field) -> Self { value as u32 } }\nimpl FromField for u64 { fn from_field(value: Field) -> Self { value as u64 } }\nimpl FromField for U128 {\n fn from_field(value: Field) -> Self {\n U128::from_integer(value)\n }\n}\n\n// docs:start:serialize\ntrait Serialize {\n fn serialize(self) -> [Field; N];\n}\n// docs:end:serialize\n\nimpl Serialize for [Field; N] {\n fn serialize(self) -> [Field; N] {\n self\n }\n}\nimpl Serialize for str {\n fn serialize(self) -> [Field; N] {\n let mut result = [0; N];\n let bytes: [u8; N] = self.as_bytes();\n for i in 0..N {\n result[i] = field_from_bytes([bytes[i];1], true);\n }\n result\n }\n}\n\n// docs:start:deserialize\ntrait Deserialize {\n fn deserialize(fields: [Field; N]) -> Self;\n}\n// docs:end:deserialize\n\nimpl Deserialize for [Field; N] {\n fn deserialize(fields: [Field; N]) -> Self {\n fields\n }\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"267":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/field.nr","source":"pub fn field_from_bytes(bytes: [u8; N], big_endian: bool) -> Field {\n assert(bytes.len() < 32, \"field_from_bytes: N must be less than 32\");\n let mut as_field = 0;\n let mut offset = 1;\n for i in 0..N {\n let mut index = i;\n if big_endian {\n index = N - i - 1;\n }\n as_field += (bytes[index] as Field) * offset;\n offset *= 256;\n }\n\n as_field\n}\n\n// Convert a 32 byte array to a field element by truncating the final byte\npub fn field_from_bytes_32_trunc(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..15 {\n // covers bytes 16..30 (31 is truncated and ignored)\n low = low + (bytes32[15 + 15 - i] as Field) * v;\n v = v * 256;\n // covers bytes 0..14\n high = high + (bytes32[14 - i] as Field) * v;\n }\n // covers byte 15\n low = low + (bytes32[15] as Field) * v;\n\n low + high * v\n}\n\n// TODO to radix returns u8, so we cannot use bigger radixes. It'd be ideal to use a radix of the maximum range-constrained integer noir supports\npub fn full_field_less_than(lhs: Field, rhs: Field) -> bool {\n lhs.lt(rhs)\n}\n\npub fn full_field_greater_than(lhs: Field, rhs: Field) -> bool {\n rhs.lt(lhs)\n}\n\n#[test]\nunconstrained fn bytes_field_test() {\n // Tests correctness of field_from_bytes_32_trunc against existing methods\n // Bytes representing 0x543e0a6642ffeb8039296861765a53407bba62bd1c97ca43374de950bbe0a7\n let inputs = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167\n ];\n let field = field_from_bytes(inputs, true);\n let return_bytes = field.to_be_bytes(31);\n for i in 0..31 {\n assert_eq(inputs[i], return_bytes[i]);\n }\n // 32 bytes - we remove the final byte, and check it matches the field\n let inputs2 = [\n 84, 62, 10, 102, 66, 255, 235, 128, 57, 41, 104, 97, 118, 90, 83, 64, 123, 186, 98, 189, 28, 151, 202, 67, 55, 77, 233, 80, 187, 224, 167, 158\n ];\n let field2 = field_from_bytes_32_trunc(inputs2);\n let return_bytes2 = field.to_be_bytes(31);\n\n for i in 0..31 {\n assert_eq(return_bytes2[i], return_bytes[i]);\n }\n assert_eq(field2, field);\n}\n"},"28":{"path":"std/hash/poseidon2.nr","source":"use crate::hash::Hasher;\nuse crate::default::Default;\n\nglobal RATE: u32 = 3;\n\nstruct Poseidon2 {\n cache: [Field;3],\n state: [Field;4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n if message_size == N {\n Poseidon2::hash_internal(input, N, false)\n } else {\n Poseidon2::hash_internal(input, message_size, true)\n }\n }\n\n fn new(iv: Field) -> Poseidon2 {\n let mut result = Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) -> [Field; RATE] {\n // zero-pad the cache\n for i in 0..RATE {\n if i >= self.cache_size {\n self.cache[i] = 0;\n }\n }\n // add the cache into sponge state\n for i in 0..RATE {\n self.state[i] += self.cache[i];\n }\n self.state = crate::hash::poseidon2_permutation(self.state, 4);\n // return `RATE` number of field elements from the sponge state.\n let mut result = [0; RATE];\n for i in 0..RATE {\n result[i] = self.state[i];\n }\n result\n }\n\n fn absorb(&mut self, input: Field) {\n if (!self.squeeze_mode) & (self.cache_size == RATE) {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n let _ = self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else if (!self.squeeze_mode) & (self.cache_size != RATE) {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n } else if self.squeeze_mode {\n // If we're in squeeze mode, switch to absorb mode and add the input into the cache.\n // N.B. I don't think this code path can be reached?!\n self.cache[0] = input;\n self.cache_size = 1;\n self.squeeze_mode = false;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n if self.squeeze_mode & (self.cache_size == 0) {\n // If we're in squeze mode and the cache is empty, there is nothing left to squeeze out of the sponge!\n // Switch to absorb mode.\n self.squeeze_mode = false;\n self.cache_size = 0;\n }\n if !self.squeeze_mode {\n // If we're in absorb mode, apply sponge permutation to compress the cache, populate cache with compressed\n // state and switch to squeeze mode. Note: this code block will execute if the previous `if` condition was\n // matched\n let new_output_elements = self.perform_duplex();\n self.squeeze_mode = true;\n for i in 0..RATE {\n self.cache[i] = new_output_elements[i];\n }\n self.cache_size = RATE;\n }\n // By this point, we should have a non-empty cache. Pop one item off the top of the cache and return it.\n let result = self.cache[0];\n for i in 1..RATE {\n if i < self.cache_size {\n self.cache[i - 1] = self.cache[i];\n }\n }\n self.cache_size -= 1;\n self.cache[self.cache_size] = 0;\n result\n }\n\n fn hash_internal(input: [Field; N], in_len: u32, is_variable_length: bool) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv : Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\nstruct Poseidon2Hasher{\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv : Field = (self._state.len() as Field)*18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field){\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher {\n _state: &[],\n }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"354":{"path":"/usr/src/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr","source":"contract KeyRegistry {\n use dep::authwit::auth::assert_current_call_valid_authwit_public;\n\n use dep::aztec::{\n keys::PublicKeys, state_vars::{SharedMutable, Map},\n protocol_types::{grumpkin_point::GrumpkinPoint, address::{AztecAddress, PartialAddress}}\n };\n\n global KEY_ROTATION_DELAY = 5;\n\n #[aztec(storage)]\n struct Storage {\n // The following stores a hash of individual master public keys\n // If you change slots of vars below, you must update the slots in `SharedMutablePrivateGetter` in aztec-nr/keys.\n // We store x and y coordinates in individual shared mutables as shared mutable currently supports only 1 field\n npk_m_x_registry: Map>,\n npk_m_y_registry: Map>,\n\n ivpk_m_x_registry: Map>,\n ivpk_m_y_registry: Map>,\n \n ovpk_m_x_registry: Map>,\n ovpk_m_y_registry: Map>,\n \n tpk_m_x_registry: Map>,\n tpk_m_y_registry: Map>,\n }\n\n #[aztec(public)]\n fn rotate_npk_m(address: AztecAddress, new_npk_m: GrumpkinPoint, nonce: Field) {\n // TODO: (#6137)\n if (!address.eq(context.msg_sender())) {\n assert_current_call_valid_authwit_public(&mut context, address);\n } else {\n assert(nonce == 0, \"invalid nonce\");\n }\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n npk_m_x_registry.schedule_value_change(new_npk_m.x);\n npk_m_y_registry.schedule_value_change(new_npk_m.y);\n }\n\n #[aztec(public)]\n fn register(address: AztecAddress, partial_address: PartialAddress, keys: PublicKeys) {\n let computed_address = AztecAddress::compute(keys.hash(), partial_address);\n\n assert(computed_address.eq(address), \"Computed address does not match supplied address\");\n\n let npk_m_x_registry = storage.npk_m_x_registry.at(address);\n let npk_m_y_registry = storage.npk_m_y_registry.at(address);\n let ivpk_m_x_registry = storage.ivpk_m_x_registry.at(address);\n let ivpk_m_y_registry = storage.ivpk_m_y_registry.at(address);\n let ovpk_m_x_registry = storage.ovpk_m_x_registry.at(address);\n let ovpk_m_y_registry = storage.ovpk_m_y_registry.at(address);\n let tpk_m_x_registry = storage.tpk_m_x_registry.at(address);\n let tpk_m_y_registry = storage.tpk_m_y_registry.at(address);\n\n npk_m_x_registry.schedule_value_change(keys.npk_m.x);\n npk_m_y_registry.schedule_value_change(keys.npk_m.y);\n ivpk_m_x_registry.schedule_value_change(keys.ivpk_m.x);\n ivpk_m_y_registry.schedule_value_change(keys.ivpk_m.y);\n ovpk_m_x_registry.schedule_value_change(keys.ovpk_m.x);\n ovpk_m_y_registry.schedule_value_change(keys.ovpk_m.y);\n tpk_m_x_registry.schedule_value_change(keys.tpk_m.x);\n tpk_m_y_registry.schedule_value_change(keys.tpk_m.y);\n }\n}\n"},"44":{"path":"std/uint128.nr","source":"use crate::ops::{Add, Sub, Mul, Div, Rem, Not, BitOr, BitAnd, BitXor, Shl, Shr};\nuse crate::cmp::{Eq, Ord, Ordering};\nuse crate::println;\n\nglobal pow64 : Field = 18446744073709551616; //2^64;\nglobal pow63 : Field = 9223372036854775808; // 2^63;\nstruct U128 {\n lo: Field,\n hi: Field,\n}\n\nimpl U128 {\n\n pub fn from_u64s_le(lo: u64, hi: u64) -> U128 {\n // in order to handle multiplication, we need to represent the product of two u64 without overflow\n assert(crate::field::modulus_num_bits() as u32 > 128);\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n pub fn from_u64s_be(hi: u64, lo: u64) -> U128 {\n U128::from_u64s_le(lo, hi)\n }\n\n pub fn zero() -> U128 {\n U128 { lo: 0, hi: 0 }\n }\n\n pub fn one() -> U128 {\n U128 { lo: 1, hi: 0 }\n }\n pub fn from_le_bytes(bytes: [u8; 16]) -> U128 {\n let mut lo = 0;\n let mut base = 1;\n for i in 0..8 {\n lo += (bytes[i] as Field)*base;\n base *= 256;\n }\n let mut hi = 0;\n base = 1;\n for i in 8..16 {\n hi += (bytes[i] as Field)*base;\n base *= 256;\n }\n U128 { lo, hi }\n }\n\n pub fn to_be_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_be_bytes(8);\n let hi = self.hi.to_be_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = hi[i];\n bytes[i+8] = lo[i];\n }\n bytes\n }\n\n pub fn to_le_bytes(self: Self) -> [u8; 16] {\n let lo = self.lo.to_le_bytes(8);\n let hi = self.hi.to_le_bytes(8);\n let mut bytes = [0; 16];\n for i in 0..8 {\n bytes[i] = lo[i];\n bytes[i+8] = hi[i];\n }\n bytes\n }\n\n pub fn from_hex(hex: str) -> U128 {\n let N = N as u32;\n let bytes = hex.as_bytes();\n // string must starts with \"0x\"\n assert((bytes[0] == 48) & (bytes[1] == 120), \"Invalid hexadecimal string\");\n assert(N < 35, \"Input does not fit into a U128\");\n\n let mut lo = 0;\n let mut hi = 0;\n let mut base = 1;\n if N <= 18 {\n for i in 0..N - 2 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n } else {\n for i in 0..16 {\n lo += U128::decode_ascii(bytes[N-i-1])*base;\n base = base*16;\n }\n base = 1;\n for i in 17..N - 1 {\n hi += U128::decode_ascii(bytes[N-i])*base;\n base = base*16;\n }\n }\n U128 { lo: lo as Field, hi: hi as Field }\n }\n\n unconstrained fn uconstrained_check_is_upper_ascii(ascii: u8) -> bool {\n ((ascii >= 65) & (ascii <= 90)) // Between 'A' and 'Z'\n }\n\n fn decode_ascii(ascii: u8) -> Field {\n if ascii < 58 {\n ascii - 48\n } else {\n let ascii = ascii + 32 * (U128::uconstrained_check_is_upper_ascii(ascii) as u8);\n assert(ascii >= 97); // enforce >= 'a'\n assert(ascii <= 102); // enforce <= 'f'\n ascii - 87\n } as Field\n }\n\n // TODO: Replace with a faster version. \n // A circuit that uses this function can be slow to compute\n // (we're doing up to 127 calls to compute the quotient)\n unconstrained fn unconstrained_div(self: Self, b: U128) -> (U128, U128) {\n if b == U128::zero() {\n // Return 0,0 to avoid eternal loop\n (U128::zero(), U128::zero())\n } else if self < b {\n (U128::zero(), self)\n } else if self == b {\n (U128::one(), U128::zero())\n } else {\n let (q,r) = if b.hi as u64 >= pow63 as u64 {\n // The result of multiplication by 2 would overflow\n (U128::zero(), self)\n } else {\n self.unconstrained_div(b * U128::from_u64s_le(2, 0))\n };\n let q_mul_2 = q * U128::from_u64s_le(2, 0);\n if r < b {\n (q_mul_2, r)\n } else {\n (q_mul_2 + U128::one(), r - b)\n }\n }\n }\n\n pub fn from_integer(i: T) -> U128 {\n let f = crate::as_field(i);\n // Reject values which would overflow a u128\n f.assert_max_bit_size(128);\n let lo = f as u64 as Field;\n let hi = (f - lo) / pow64;\n U128 { lo, hi }\n }\n\n pub fn to_integer(self) -> T {\n crate::from_field(self.lo + self.hi * pow64)\n }\n\n fn wrapping_mul(self: Self, b: U128) -> U128 {\n let low = self.lo * b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = self.lo * b.hi + self.hi * b.lo + carry;\n let hi = high as u64 as Field;\n U128 { lo, hi }\n }\n}\n\nimpl Add for U128 {\n fn add(self: Self, b: U128) -> U128 {\n let low = self.lo + b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64; \n let high = self.hi + b.hi + carry;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to add with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Sub for U128 {\n fn sub(self: Self, b: U128) -> U128 {\n let low = pow64 + self.lo - b.lo;\n let lo = low as u64 as Field;\n let borrow = (low == lo) as Field;\n let high = self.hi - b.hi - borrow;\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to subtract with underflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Mul for U128 {\n fn mul(self: Self, b: U128) -> U128 {\n assert(self.hi*b.hi == 0, \"attempt to multiply with overflow\");\n let low = self.lo*b.lo;\n let lo = low as u64 as Field;\n let carry = (low - lo) / pow64;\n let high = if crate::field::modulus_num_bits() as u32 > 196 {\n (self.lo+self.hi)*(b.lo+b.hi) - low + carry\n } else {\n self.lo*b.hi + self.hi*b.lo + carry\n };\n let hi = high as u64 as Field;\n assert(hi == high, \"attempt to multiply with overflow\");\n U128 {\n lo,\n hi,\n }\n }\n}\n\nimpl Div for U128 {\n fn div(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n q\n }\n}\n\nimpl Rem for U128 {\n fn rem(self: Self, b: U128) -> U128 {\n let (q,r) = self.unconstrained_div(b);\n let a = b * q + r;\n assert_eq(self, a);\n assert(r < b);\n r\n }\n}\n\nimpl Eq for U128 {\n fn eq(self: Self, b: U128) -> bool {\n (self.lo == b.lo) & (self.hi == b.hi)\n }\n}\n\nimpl Ord for U128 {\n fn cmp(self, other: Self) -> Ordering {\n let hi_ordering = (self.hi as u64).cmp((other.hi as u64));\n let lo_ordering = (self.lo as u64).cmp((other.lo as u64));\n \n if hi_ordering == Ordering::equal() {\n lo_ordering\n } else {\n hi_ordering\n }\n }\n}\n\nimpl Not for U128 { \n fn not(self) -> U128 {\n U128 {\n lo: (!(self.lo as u64)) as Field,\n hi: (!(self.hi as u64)) as Field\n }\n }\n}\n\nimpl BitOr for U128 { \n fn bitor(self, other: U128) -> U128 {\n U128 {\n lo: ((self.lo as u64) | (other.lo as u64)) as Field,\n hi: ((self.hi as u64) | (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitAnd for U128 {\n fn bitand(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) & (other.lo as u64)) as Field,\n hi: ((self.hi as u64) & (other.hi as u64)) as Field\n }\n }\n}\n\nimpl BitXor for U128 {\n fn bitxor(self, other: U128) -> U128 { \n U128 {\n lo: ((self.lo as u64) ^ (other.lo as u64)) as Field,\n hi: ((self.hi as u64) ^ (other.hi as u64)) as Field\n }\n }\n}\n\nimpl Shl for U128 { \n fn shl(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift left with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self.wrapping_mul(U128::from_integer(y))\n } \n}\n\nimpl Shr for U128 { \n fn shr(self, other: u8) -> U128 { \n assert(other < 128, \"attempt to shift right with overflow\");\n let exp_bits = (other as Field).to_be_bits(7);\n\n let mut r: Field = 2;\n let mut y: Field = 1;\n for i in 1..8 {\n y = (exp_bits[7-i] as Field) * (r * y) + (1 - exp_bits[7-i] as Field) * y;\n r *= r;\n }\n self / U128::from_integer(y)\n } \n}\n\nmod tests {\n use crate::uint128::{U128, pow64, pow63};\n\n #[test]\n fn test_not() {\n let num = U128::from_u64s_le(0, 0);\n let not_num = num.not();\n\n let max_u64: Field = pow64 - 1;\n assert_eq(not_num.hi, max_u64);\n assert_eq(not_num.lo, max_u64);\n\n let not_not_num = not_num.not();\n assert_eq(num, not_not_num);\n }\n #[test]\n fn test_construction() {\n // Check little-endian u64 is inversed with big-endian u64 construction\n let a = U128::from_u64s_le(2, 1);\n let b = U128::from_u64s_be(1, 2);\n assert_eq(a, b);\n // Check byte construction is equivalent\n let c = U128::from_le_bytes([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);\n let d = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n assert_eq(c, d);\n }\n #[test]\n fn test_byte_decomposition() {\n let a = U128::from_u64s_le(0x0706050403020100, 0x0f0e0d0c0b0a0908);\n // Get big-endian and little-endian byte decompostions\n let le_bytes_a= a.to_le_bytes();\n let be_bytes_a= a.to_be_bytes();\n\n // Check equivalence\n for i in 0..16 {\n assert_eq(le_bytes_a[i], be_bytes_a[15 - i]);\n }\n // Reconstruct U128 from byte decomposition\n let b= U128::from_le_bytes(le_bytes_a);\n // Check that it's the same element\n assert_eq(a, b);\n }\n #[test]\n fn test_hex_constuction() {\n let a = U128::from_u64s_le(0x1, 0x2);\n let b = U128::from_hex(\"0x20000000000000001\");\n assert_eq(a, b);\n\n let c= U128::from_hex(\"0xffffffffffffffffffffffffffffffff\");\n let d= U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff);\n assert_eq(c, d);\n\n let e= U128::from_hex(\"0x00000000000000000000000000000000\");\n let f= U128::from_u64s_le(0, 0);\n assert_eq(e, f);\n }\n\n // Ascii decode tests\n\n #[test]\n fn test_ascii_decode_correct_range() {\n // '0'..'9' range\n for i in 0..10 {\n let decoded= U128::decode_ascii(48 + i);\n assert_eq(decoded, i as Field);\n }\n // 'A'..'F' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(65 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n // 'a'..'f' range\n for i in 0..6 {\n let decoded = U128::decode_ascii(97 + i);\n assert_eq(decoded, (i + 10) as Field);\n }\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_0() {\n crate::println(U128::decode_ascii(0));\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_less_than_48_fails_1() {\n crate::println(U128::decode_ascii(47));\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_0() {\n let _ = U128::decode_ascii(58);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_58_64_fails_1() {\n let _ = U128::decode_ascii(64);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_0() {\n let _ = U128::decode_ascii(71);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_71_96_fails_1() {\n let _ = U128::decode_ascii(96);\n }\n #[test(should_fail)]\n fn test_ascii_decode_range_greater_than_102_fails() {\n let _ = U128::decode_ascii(103);\n }\n\n #[test(should_fail)]\n fn test_ascii_decode_regression() {\n // This code will actually fail because of ascii_decode,\n // but in the past it was possible to create a value > (1<<128)\n let a = U128::from_hex(\"0x~fffffffffffffffffffffffffffffff\");\n let b:Field= a.to_integer();\n let c= b.to_le_bytes(17);\n assert(c[16] != 0);\n }\n\n #[test]\n fn test_unconstrained_div() {\n // Test the potential overflow case\n let a= U128::from_u64s_le(0x0, 0xffffffffffffffff);\n let b= U128::from_u64s_le(0x0, 0xfffffffffffffffe);\n let c= U128::one();\n let d= U128::from_u64s_le(0x0, 0x1);\n let (q,r) = a.unconstrained_div(b);\n assert_eq(q, c);\n assert_eq(r, d);\n\n let a = U128::from_u64s_le(2, 0);\n let b = U128::one();\n // Check the case where a is a multiple of b\n let (c,d ) = a.unconstrained_div(b);\n assert_eq((c, d), (a, U128::zero()));\n\n // Check where b is a multiple of a\n let (c,d) = b.unconstrained_div(a);\n assert_eq((c, d), (U128::zero(), b));\n\n // Dividing by zero returns 0,0\n let a = U128::from_u64s_le(0x1, 0x0);\n let b = U128::zero();\n let (c,d)= a.unconstrained_div(b);\n assert_eq((c, d), (U128::zero(), U128::zero()));\n\n // Dividing 1<<127 by 1<<127 (special case)\n let a = U128::from_u64s_le(0x0, pow63 as u64);\n let b = U128::from_u64s_le(0x0, pow63 as u64);\n let (c,d )= a.unconstrained_div(b);\n assert_eq((c, d), (U128::one(), U128::zero()));\n }\n\n #[test]\n fn integer_conversions() {\n // Maximum\n let start:Field = 0xffffffffffffffffffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Minimum\n let start:Field = 0x0;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // Low limb\n let start:Field = 0xffffffffffffffff;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n\n // High limb\n let start:Field = 0xffffffffffffffff0000000000000000;\n let a = U128::from_integer(start);\n let end = a.to_integer();\n assert_eq(start, end);\n }\n #[test]\n fn test_wrapping_mul() {\n // 1*0==0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::one()));\n\n // 0*1==0\n assert_eq(U128::zero(), U128::one().wrapping_mul(U128::zero()));\n\n // 1*1==1\n assert_eq(U128::one(), U128::one().wrapping_mul(U128::one()));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(U128::zero(), U128::zero().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::zero()));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::from_u64s_le(0, 1).wrapping_mul(U128::one()));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(U128::from_u64s_le(0, 1), U128::one().wrapping_mul(U128::from_u64s_le(0, 1)));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(U128::zero(), U128::from_u64s_le(0, 1).wrapping_mul(U128::from_u64s_le(0, 1)));\n // -1 * -1 == 1\n assert_eq(\n U128::one(), U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff).wrapping_mul(U128::from_u64s_le(0xffffffffffffffff, 0xffffffffffffffff))\n );\n }\n}\n"},"51":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/auth.nr","source":"use dep::aztec::protocol_types::{\n abis::function_selector::FunctionSelector, address::AztecAddress,\n constants::{\n GENERATOR_INDEX__AUTHWIT_INNER, GENERATOR_INDEX__AUTHWIT_OUTER, GENERATOR_INDEX__AUTHWIT_NULLIFIER,\n CANONICAL_AUTH_REGISTRY_ADDRESS\n},\n hash::pedersen_hash\n};\nuse dep::aztec::{prelude::Deserialize, context::{PrivateContext, PublicContext, gas::GasOpts}, hash::hash_args_array};\n\nglobal IS_VALID_SELECTOR = 0xabf64ad4; // 4 first bytes of keccak256(\"IS_VALID()\")\n\n// docs:start:assert_current_call_valid_authwit\n// Assert that `on_behalf_of` have authorized the current call with a valid authentication witness\npub fn assert_current_call_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash([context.msg_sender().to_field(), context.selector().to_field(), context.args_hash]);\n assert_inner_hash_valid_authwit(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit\n\npub fn assert_inner_hash_valid_authwit(context: &mut PrivateContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n // We perform a static call here and not a standard one to ensure that the account contract cannot re-enter.\n let result: Field = context.static_call_private_function(\n on_behalf_of,\n FunctionSelector::from_signature(\"verify_private_authwit(Field)\"),\n [inner_hash]\n ).unpack_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n // Compute the nullifier, similar computation to the outer hash, but without the chain_id and version.\n // Those should already be handled in the verification, so we just need something to nullify, that allow same inner_hash for multiple actors.\n let nullifier = compute_authwit_nullifier(on_behalf_of, inner_hash);\n context.push_new_nullifier(nullifier, 0);\n}\n\n// docs:start:assert_current_call_valid_authwit_public\n// Assert that `on_behalf_of` have authorized the current call in a public context\npub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress) {\n let inner_hash = compute_inner_authwit_hash(\n [(*context).msg_sender().to_field(), (*context).selector().to_field(), (*context).get_args_hash()]\n );\n assert_inner_hash_valid_authwit_public(context, on_behalf_of, inner_hash);\n}\n// docs:end:assert_current_call_valid_authwit_public\n\npub fn assert_inner_hash_valid_authwit_public(context: &mut PublicContext, on_behalf_of: AztecAddress, inner_hash: Field) {\n let result: Field = context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"consume((Field),Field)\"),\n [on_behalf_of.to_field(), inner_hash].as_slice(),\n GasOpts::default()\n ).deserialize_into();\n assert(result == IS_VALID_SELECTOR, \"Message not authorized by account\");\n}\n\n// docs:start:compute_call_authwit_hash\n// Compute the message hash to be used by an authentication witness \npub fn compute_call_authwit_hash(\n caller: AztecAddress,\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n selector: FunctionSelector,\n args: [Field; N]\n) -> Field {\n let args_hash = hash_args_array(args);\n let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]);\n compute_outer_authwit_hash(consumer, chain_id, version, inner_hash)\n}\n// docs:end:compute_call_authwit_hash\n\npub fn compute_inner_authwit_hash(args: [Field; N]) -> Field {\n pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER)\n}\n\npub fn compute_authwit_nullifier(on_behalf_of: AztecAddress, inner_hash: Field) -> Field {\n pedersen_hash(\n [on_behalf_of.to_field(), inner_hash],\n GENERATOR_INDEX__AUTHWIT_NULLIFIER\n )\n}\n\npub fn compute_outer_authwit_hash(\n consumer: AztecAddress,\n chain_id: Field,\n version: Field,\n inner_hash: Field\n) -> Field {\n pedersen_hash(\n [\n consumer.to_field(),\n chain_id,\n version,\n inner_hash\n ],\n GENERATOR_INDEX__AUTHWIT_OUTER\n )\n}\n\n/**\n * Helper function to set the authorization status of a message hash\n * \n * @param message_hash The hash of the message to authorize\n * @param authorize True if the message should be authorized, false if it should be revoked\n */\npub fn set_authorized(context: &mut PublicContext, message_hash: Field, authorize: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_authorized(Field,bool)\"),\n [message_hash, authorize as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n\n/**\n * Helper function to reject all authwits\n *\n * @param reject True if all authwits should be rejected, false otherwise \n */\npub fn set_reject_all(context: &mut PublicContext, reject: bool) {\n context.call_public_function(\n AztecAddress::from_field(CANONICAL_AUTH_REGISTRY_ADDRESS),\n FunctionSelector::from_signature(\"set_reject_all(bool)\"),\n [context.this_address().to_field(), reject as Field].as_slice(),\n GasOpts::default()\n ).assert_empty();\n}\n"},"64":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/keys/public_keys.nr","source":"use dep::protocol_types::{\n address::PublicKeysHash, constants::GENERATOR_INDEX__PUBLIC_KEYS_HASH, hash::poseidon2_hash,\n grumpkin_point::GrumpkinPoint, traits::{Deserialize, Serialize}\n};\nuse crate::keys::constants::{NUM_KEY_TYPES, NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX};\n\nglobal PUBLIC_KEYS_LENGTH = 8;\n\nstruct PublicKeys {\n npk_m: GrumpkinPoint,\n ivpk_m: GrumpkinPoint,\n ovpk_m: GrumpkinPoint,\n tpk_m: GrumpkinPoint,\n}\n\nimpl PublicKeys {\n pub fn hash(self) -> PublicKeysHash {\n PublicKeysHash::from_field(\n poseidon2_hash(\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n GENERATOR_INDEX__PUBLIC_KEYS_HASH\n ]\n )\n )\n }\n\n pub fn get_key_by_index(self, index: Field) -> GrumpkinPoint {\n assert(index as u8 < NUM_KEY_TYPES, \"Invalid key index\");\n if index == NULLIFIER_INDEX {\n self.npk_m\n } else if index == INCOMING_INDEX {\n self.ivpk_m\n } else if index == OUTGOING_INDEX {\n self.ovpk_m\n } else {\n self.tpk_m\n }\n }\n}\n\nimpl Serialize for PublicKeys {\n fn serialize(self) -> [Field; PUBLIC_KEYS_LENGTH] {\n [\n self.npk_m.x,\n self.npk_m.y,\n self.ivpk_m.x,\n self.ivpk_m.y,\n self.ovpk_m.x,\n self.ovpk_m.y,\n self.tpk_m.x,\n self.tpk_m.y,\n ]\n }\n}\n\nimpl Deserialize for PublicKeys {\n fn deserialize(serialized: [Field; PUBLIC_KEYS_LENGTH]) -> PublicKeys {\n PublicKeys {\n npk_m: GrumpkinPoint { x: serialized[0], y: serialized[1] },\n ivpk_m: GrumpkinPoint { x: serialized[2], y: serialized[3] },\n ovpk_m: GrumpkinPoint { x: serialized[4], y: serialized[5] },\n tpk_m: GrumpkinPoint { x: serialized[6], y: serialized[7] },\n }\n }\n}\n\n#[test]\nfn compute_public_keys_hash() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let actual = keys.hash();\n let expected_public_keys_hash = 0x2406c1c88b7afc13052335bb9af43fd35034b5ba0a9caab76eda2833cf8ec717;\n\n assert(actual.to_field() == expected_public_keys_hash);\n}\n\n#[test]\nfn test_public_keys_serialization() {\n let keys = PublicKeys {\n npk_m: GrumpkinPoint { x: 1, y: 2 },\n ivpk_m: GrumpkinPoint { x: 3, y: 4 },\n ovpk_m: GrumpkinPoint { x: 5, y: 6 },\n tpk_m: GrumpkinPoint { x: 7, y: 8 }\n };\n\n let serialized = keys.serialize();\n let deserialized = PublicKeys::deserialize(serialized);\n\n assert_eq(keys.npk_m.x, deserialized.npk_m.x);\n assert_eq(keys.npk_m.y, deserialized.npk_m.y);\n assert_eq(keys.ivpk_m.x, deserialized.ivpk_m.x);\n assert_eq(keys.ivpk_m.y, deserialized.ivpk_m.y);\n assert_eq(keys.ovpk_m.x, deserialized.ovpk_m.x);\n assert_eq(keys.ovpk_m.y, deserialized.ovpk_m.y);\n assert_eq(keys.tpk_m.x, deserialized.tpk_m.x);\n assert_eq(keys.tpk_m.y, deserialized.tpk_m.y);\n}\n"},"66":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/public_storage.nr","source":"use dep::protocol_types::traits::{Deserialize, Serialize};\nuse crate::oracle::storage::{storage_read, storage_write};\n\npub fn read(storage_slot: Field) -> T where T: Deserialize {\n T::deserialize(storage_read(storage_slot))\n}\n\npub fn write(storage_slot: Field, value: T) where T: Serialize {\n storage_write(storage_slot, value.serialize());\n}\n\n// Ideally we'd do the following, but we cannot because of https://github.com/noir-lang/noir/issues/4633\n// pub fn read_historical(\n// storage_slot: Field,\n// context: PrivateContext\n// ) -> T where T: Deserialize {\n// let mut fields = [0; N];\n// for i in 0..N {\n// fields[i] = public_storage_historical_read(\n// context,\n// storage_slot + i as Field,\n// context.this_address()\n// );\n// }\n// T::deserialize(fields)\n// }\n\nmod tests {\n use dep::std::test::OracleMock;\n use dep::protocol_types::traits::{Deserialize, Serialize};\n use crate::public_storage;\n\n struct TestStruct {\n a: Field,\n b: Field,\n }\n\n impl Deserialize<2> for TestStruct {\n fn deserialize(fields: [Field; 2]) -> TestStruct {\n TestStruct { a: fields[0], b: fields[1] }\n }\n }\n\n impl Serialize<2> for TestStruct {\n fn serialize(self) -> [Field; 2] {\n [self.a, self.b]\n }\n }\n\n #[test]\n fn test_read() {\n let slot = 7;\n let written = TestStruct { a: 13, b: 42 };\n\n OracleMock::mock(\"storageRead\").with_params((slot, 2)).returns(written.serialize());\n\n let read: TestStruct = public_storage::read(slot);\n assert_eq(read.a, 13);\n assert_eq(read.b, 42);\n }\n\n #[test]\n fn test_write() {\n let slot = 7;\n let to_write = TestStruct { a: 13, b: 42 };\n\n let mock = OracleMock::mock(\"storageWrite\").returns([0; 2]); // The return value is unused\n\n public_storage::write(slot, to_write);\n assert_eq(mock.get_last_params(), (slot, to_write.serialize()));\n }\n}\n"},"93":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/public_context.nr","source":"use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier};\nuse dep::protocol_types::address::{AztecAddress, EthAddress};\nuse dep::protocol_types::traits::{Serialize, Deserialize, Empty};\nuse dep::protocol_types::abis::function_selector::FunctionSelector;\nuse crate::context::inputs::public_context_inputs::PublicContextInputs;\nuse crate::context::gas::GasOpts;\n\nstruct PublicContext {\n inputs: PublicContextInputs,\n}\n\nimpl PublicContext {\n pub fn new(inputs: PublicContextInputs) -> Self {\n PublicContext { inputs }\n }\n\n pub fn storage_address(self) -> AztecAddress {\n storage_address()\n }\n pub fn fee_per_l2_gas(self) -> Field {\n fee_per_l2_gas()\n }\n pub fn fee_per_da_gas(self) -> Field {\n fee_per_da_gas()\n }\n /**\n * Emit a log with the given event selector and message.\n *\n * @param event_selector The event selector for the log.\n * @param message The message to emit in the log.\n */\n pub fn emit_unencrypted_log_with_selector(\n &mut self,\n event_selector: Field,\n log: T\n ) where T: Serialize {\n emit_unencrypted_log(event_selector, Serialize::serialize(log).as_slice());\n }\n // For compatibility with the selector-less API. We'll probably rename the above one.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: Serialize {\n self.emit_unencrypted_log_with_selector(/*event_selector=*/ 5, log);\n }\n pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool {\n note_hash_exists(note_hash, leaf_index) == 1\n }\n pub fn l1_to_l2_msg_exists(self, msg_hash: Field, msg_leaf_index: Field) -> bool {\n l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1\n }\n\n fn block_number(self) -> Field {\n block_number()\n }\n\n fn timestamp(self) -> u64 {\n timestamp()\n }\n\n fn transaction_fee(self) -> Field {\n transaction_fee()\n }\n\n fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {\n nullifier_exists(unsiloed_nullifier, address.to_field()) == 1\n }\n\n fn consume_l1_to_l2_message(\n &mut self,\n content: Field,\n secret: Field,\n sender: EthAddress,\n leaf_index: Field\n ) {\n let secret_hash = compute_secret_hash(secret);\n let message_hash = compute_message_hash(\n sender,\n self.chain_id(),\n /*recipient=*/ self.this_address(),\n self.version(),\n content,\n secret_hash\n );\n let nullifier = compute_message_nullifier(message_hash, secret, leaf_index);\n\n assert(\n !self.nullifier_exists(nullifier, self.this_address()), \"L1-to-L2 message is already nullified\"\n );\n assert(\n self.l1_to_l2_msg_exists(message_hash, leaf_index), \"Tried to consume nonexistent L1-to-L2 message\"\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0);\n }\n\n fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg(recipient, content);\n }\n\n fn call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let results = call(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n let data_to_return: [Field; RETURNS_COUNT] = results.0;\n let success: u8 = results.1;\n assert(success == 1, \"Nested call failed!\");\n\n FunctionReturns::new(data_to_return)\n }\n\n fn static_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n temporary_function_selector: FunctionSelector,\n args: [Field],\n gas_opts: GasOpts\n ) -> FunctionReturns {\n let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static(\n gas_for_call(gas_opts),\n contract_address,\n args,\n temporary_function_selector.to_field()\n );\n\n assert(success == 1, \"Nested static call failed!\");\n FunctionReturns::new(data_to_return)\n }\n\n fn delegate_call_public_function(\n self: &mut Self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field]\n ) -> FunctionReturns {\n assert(false, \"'delegate_call_public_function' not implemented!\");\n FunctionReturns::new([0; RETURNS_COUNT])\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n emit_note_hash(note_hash);\n }\n fn push_new_nullifier(&mut self, nullifier: Field, _nullified_commitment: Field) {\n // Cannot nullify pending commitments in AVM, so `nullified_commitment` is not used\n emit_nullifier(nullifier);\n }\n fn msg_sender(self) -> AztecAddress {\n sender()\n }\n fn this_address(self) -> AztecAddress {\n address()\n }\n fn chain_id(self) -> Field {\n chain_id()\n }\n fn version(self) -> Field {\n version()\n }\n fn selector(self) -> FunctionSelector {\n FunctionSelector::from_field(self.inputs.selector)\n }\n fn get_args_hash(self) -> Field {\n self.inputs.args_hash\n }\n fn l2_gas_left(self) -> Field {\n l2_gas_left()\n }\n fn da_gas_left(self) -> Field {\n da_gas_left()\n }\n}\n\n// Helper functions\nfn gas_for_call(user_gas: GasOpts) -> [Field; 2] {\n // It's ok to use the max possible gas here, because the gas will be\n // capped by the gas left in the (STATIC)CALL instruction.\n let MAX_POSSIBLE_FIELD: Field = 0 - 1;\n [\n user_gas.l2_gas.unwrap_or(MAX_POSSIBLE_FIELD),\n user_gas.da_gas.unwrap_or(MAX_POSSIBLE_FIELD)\n ]\n}\n\n// Unconstrained opcode wrappers (do not use directly).\n// TODO(https://github.com/AztecProtocol/aztec-packages/issues/6420): reconsider.\nunconstrained fn address() -> AztecAddress {\n address_opcode()\n}\nunconstrained fn storage_address() -> AztecAddress {\n storage_address_opcode()\n}\nunconstrained fn sender() -> AztecAddress {\n sender_opcode()\n}\nunconstrained fn portal() -> EthAddress {\n portal_opcode()\n}\nunconstrained fn fee_per_l2_gas() -> Field {\n fee_per_l2_gas_opcode()\n}\nunconstrained fn fee_per_da_gas() -> Field {\n fee_per_da_gas_opcode()\n}\nunconstrained fn transaction_fee() -> Field {\n transaction_fee_opcode()\n}\nunconstrained fn chain_id() -> Field {\n chain_id_opcode()\n}\nunconstrained fn version() -> Field {\n version_opcode()\n}\nunconstrained fn block_number() -> Field {\n block_number_opcode()\n}\nunconstrained fn timestamp() -> u64 {\n timestamp_opcode()\n}\nunconstrained fn l2_gas_left() -> Field {\n l2_gas_left_opcode()\n}\nunconstrained fn da_gas_left() -> Field {\n da_gas_left_opcode()\n}\nunconstrained fn note_hash_exists(note_hash: Field, leaf_index: Field) -> u8 {\n note_hash_exists_opcode(note_hash, leaf_index)\n}\nunconstrained fn emit_note_hash(note_hash: Field) {\n emit_note_hash_opcode(note_hash)\n}\nunconstrained fn nullifier_exists(nullifier: Field, address: Field) -> u8 {\n nullifier_exists_opcode(nullifier, address)\n}\nunconstrained fn emit_nullifier(nullifier: Field) {\n emit_nullifier_opcode(nullifier)\n}\nunconstrained fn emit_unencrypted_log(event_selector: Field, message: [Field]) {\n emit_unencrypted_log_opcode(event_selector, message)\n}\nunconstrained fn l1_to_l2_msg_exists(msg_hash: Field, msg_leaf_index: Field) -> u8 {\n l1_to_l2_msg_exists_opcode(msg_hash, msg_leaf_index)\n}\nunconstrained fn send_l2_to_l1_msg(recipient: EthAddress, content: Field) {\n send_l2_to_l1_msg_opcode(recipient, content)\n}\nunconstrained fn call(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_opcode(gas, address, args, function_selector)\n}\nunconstrained fn call_static(\n gas: [Field; 2],\n address: AztecAddress,\n args: [Field],\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {\n call_static_opcode(gas, address, args, function_selector)\n}\n\nimpl Empty for PublicContext {\n fn empty() -> Self {\n PublicContext::new(PublicContextInputs::empty())\n }\n}\n\n// AVM oracles (opcodes) follow, do not use directly.\n#[oracle(avmOpcodeAddress)]\nunconstrained fn address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeStorageAddress)]\nunconstrained fn storage_address_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodeSender)]\nunconstrained fn sender_opcode() -> AztecAddress {}\n\n#[oracle(avmOpcodePortal)]\nunconstrained fn portal_opcode() -> EthAddress {}\n\n#[oracle(avmOpcodeFeePerL2Gas)]\nunconstrained fn fee_per_l2_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeFeePerDaGas)]\nunconstrained fn fee_per_da_gas_opcode() -> Field {}\n\n#[oracle(avmOpcodeTransactionFee)]\nunconstrained fn transaction_fee_opcode() -> Field {}\n\n#[oracle(avmOpcodeChainId)]\nunconstrained fn chain_id_opcode() -> Field {}\n\n#[oracle(avmOpcodeVersion)]\nunconstrained fn version_opcode() -> Field {}\n\n#[oracle(avmOpcodeBlockNumber)]\nunconstrained fn block_number_opcode() -> Field {}\n\n#[oracle(avmOpcodeTimestamp)]\nunconstrained fn timestamp_opcode() -> u64 {}\n\n#[oracle(avmOpcodeL2GasLeft)]\nunconstrained fn l2_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeDaGasLeft)]\nunconstrained fn da_gas_left_opcode() -> Field {}\n\n#[oracle(avmOpcodeNoteHashExists)]\nunconstrained fn note_hash_exists_opcode(note_hash: Field, leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNoteHash)]\nunconstrained fn emit_note_hash_opcode(note_hash: Field) {}\n\n#[oracle(avmOpcodeNullifierExists)]\nunconstrained fn nullifier_exists_opcode(nullifier: Field, address: Field) -> u8 {}\n\n#[oracle(avmOpcodeEmitNullifier)]\nunconstrained fn emit_nullifier_opcode(nullifier: Field) {}\n\n#[oracle(amvOpcodeEmitUnencryptedLog)]\nunconstrained fn emit_unencrypted_log_opcode(event_selector: Field, message: [Field]) {}\n\n#[oracle(avmOpcodeL1ToL2MsgExists)]\nunconstrained fn l1_to_l2_msg_exists_opcode(msg_hash: Field, msg_leaf_index: Field) -> u8 {}\n\n#[oracle(avmOpcodeSendL2ToL1Msg)]\nunconstrained fn send_l2_to_l1_msg_opcode(recipient: EthAddress, content: Field) {}\n\n#[oracle(avmOpcodeCall)]\nunconstrained fn call_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\n#[oracle(avmOpcodeStaticCall)]\nunconstrained fn call_static_opcode(\n gas: [Field; 2], // gas allocation: [l2_gas, da_gas]\n address: AztecAddress,\n args: [Field],\n // TODO(5110): consider passing in calldata directly\n function_selector: Field\n) -> ([Field; RET_SIZE], u8) {}\n// ^ return data ^ success\n\nstruct FunctionReturns {\n values: [Field; N]\n}\n\nimpl FunctionReturns {\n pub fn new(values: [Field; N]) -> FunctionReturns {\n FunctionReturns { values }\n }\n\n pub fn assert_empty(returns: FunctionReturns<0>) {\n assert(returns.values.len() == 0);\n }\n\n pub fn raw(self) -> [Field; N] {\n self.values\n }\n\n pub fn deserialize_into(self) -> T where T: Deserialize {\n Deserialize::deserialize(self.raw())\n }\n}\n"}}} \ No newline at end of file diff --git a/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json b/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json deleted file mode 100644 index 7fcee3263181..000000000000 --- a/yarn-project/protocol-contracts/src/artifacts/MultiCallEntrypoint.json +++ /dev/null @@ -1 +0,0 @@ -{"transpiled":true,"noir_version":"0.30.0+48d9df4ff227c08a6e66f21c0286bc6349151671","name":"MultiCallEntrypoint","functions":[{"name":"compute_note_hash_and_optionally_a_nullifier","is_unconstrained":true,"custom_attributes":[],"abi":{"error_types":{},"parameters":[{"name":"contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"},"visibility":"private"},{"name":"nonce","type":{"kind":"field"},"visibility":"private"},{"name":"storage_slot","type":{"kind":"field"},"visibility":"private"},{"name":"note_type_id","type":{"kind":"field"},"visibility":"private"},{"name":"compute_nullifier","type":{"kind":"boolean"},"visibility":"private"},{"name":"serialized_note","type":{"kind":"array","length":0,"type":{"kind":"field"}},"visibility":"private"}],"return_type":{"abi_type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"}},"bytecode":"H4sIAAAAAAAA/+2b227aQBCG18RJTJ24YGMMgQQIyUXvDA2nO16mfe3eV+orVM2YnTJsp2hRx1tWYqWIsb2e/5t/D1jICdSuRe9/gY6v9eeN+rNhn63+LP+tzQRzlXVyBp5wNjzhvPKEMxTkDBhO+Ax1DOsO1tytOlyPv9tWqChTlELBBLoi19URwIMboUU6oBfHUuDrcnNDklNwpcFDfQ0/ASfW1yhYrIus+pBzWGiDnEOdK3IOd0bUibQpwvUuoj2yXN73CQA1NHUu5I5JTK8NiXVhTTVey9f4VsuYlLtVjGNyrXPfkmP0Cj0U/OaYUe1A/zWJptJjhPGA9MV+6EeDjDG0e7Wf180j94XGfQnpc8PUPxau/9bgMecsjEFLx204xj2BsH0g9W1l2ErIG8vnndExCHVu5I9JTYm43/M15L9Th838VhqTOCE89+I85ayeOndj95Gwy+RdvIFXLcOrO8OrhPShDK0a/AuILubG4xajLefFcg3abQsv2gxP27EXbUZb0IsNaKcWXqQMT+rYi5TRlvNi9Rm0MwsvMoYnc+xFxmjLeTGvni06Fl50GJ6OYy86jLbgGqnmRW7hRc7w5I69yBltQS++gnbXwosuw9N17EWX0Rb04gtoFxZeFAxP4diLgtEW3Dur54uehRc9hqfn2Iseoy3oxRy0+xZe9BmevmMv+oy24BqptB8svHhgeB4ce4F6pzJ3PGQuPGTOzoA5MmIZ7WW1fw4svBgwPAPHXtDfck5hzs+AOTJiGe3lArSHFl4MGZ6hYy9Q71Tm1EPmzEPmrofMuYfMhYfM5zCfIyOW0V5Ve+ijhRePDM+jYy9Q71Tm1EPmgYfM2RkwR0Yso72qfpt7svDiieF5cuwF6p3K3POQuX0GzJERy2ivlqA9svBixPCMHHuBeqcy9z1kLjxkHnjInHnI3PWQOfeQ+bIG3TCnZ8AM773gOzA/auWZb2KDBz1TBqMyGGMSJ4QR+26V3PsqiVE7ak3E/diNjzlf8HhSq/Z8DXmn8jVVz/IvOhe+wzdlanrVcSDs5wvJGxAdPB+S+Dvpi/3QD1y3yA7vXD3r+PXIfSPjvoT0eWbqHwvXPzV4pgYzjMk3wlHH3LKZ1y21X8ufCE8N++AbfScXm82+Q/cYQZ5ZTXWW9B2+n0p2TU8Mr5qGVwnpQ/fo/7VvXpgvzH9jps8TTXKO8uC5hlEL/f+GCcnxC57ToyHuNQAA","debug_symbols":"ndpRattAGIXRveg5FN/f0swoWymlOIlTDMEJsVMoJnuv3dIF9LxpJN237+kwl+lp//Dx4/vh+Px6mu6/XqaX18fd+fB6vJ4u0+ZLjT9vT2+74+3F6bx7P0/321530/74dHvqn3fT8+Flf30e9fnt7jZaYbTdyCgyKhltZTTLaJFRk1GXkRSxlSJmKWKWImYpYpYiZililiJmKWKWImYpYpYiFilikSIWKWKRIhYpYpEiFilikSIWKWKRIpoU0aSIJkU0KaJJEU2KaFJEkyKaFNGkiC5FdCmiSxFdiuhSRJciuhTRpYguRXQpYkgRQ4oYUsSQIoYUMaSIIUUMKWJIEUOKWKWIVYpYpYhVililiFWKWKWIVYpYpYhVishmQ6vQqmi1pdVMq4VWjVadVoNW1EaojVAboTZCbYTaCLURaiPURqiNUBtFbRS1UdRGURtFbRS1UdRGURsEmiHRDJFmyDRDqBlSzRBrhlwzBJsh2QzRZsg2Q7gZ0s0Qb4Z8MwScIeEMEWfIOEPIGVLOEHOGnDMEnSHpDFFnyDpD2BnSzhB3hrwzBJ4h8QyRZ8g8Q+gZUs8Qe4bcMwSfIfkM0WfIPkP4GdLPEH+G/DMEoCEBDRFoyEBDCBpS0BCDhhw0BKEhCQ1RaMhCQxga0tAQh4Y8NASiIRENkWjIREMoGlLREIuGXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y0yEWLXLTIRYtctMhFi1y07KInuWiRixa5aJGLFrlokYsWuWj9t4teTz9374fdw8v+drf39vHj+Pjvqu/1eP719vfL9d/f"},{"name":"entrypoint","is_unconstrained":false,"custom_attributes":["aztec(private)"],"abi":{"error_types":{},"parameters":[{"name":"inputs","type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"aztec::context::inputs::private_context_inputs::PrivateContextInputs"},"visibility":"private"},{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"},"visibility":"private"}],"return_type":{"abi_type":{"fields":[{"name":"call_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"is_delegate_call","type":{"kind":"boolean"}},{"name":"is_static_call","type":{"kind":"boolean"}},{"name":"side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::call_context::CallContext"}},{"name":"args_hash","type":{"kind":"field"}},{"name":"returns_hash","type":{"kind":"field"}},{"name":"min_revertible_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"is_fee_payer","type":{"kind":"boolean"}},{"name":"max_block_number","type":{"fields":[{"name":"_opt","type":{"fields":[{"name":"_is_some","type":{"kind":"boolean"}},{"name":"_value","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"std::option::Option"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::max_block_number::MaxBlockNumber"}},{"name":"note_hash_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"nullifier_read_requests","type":{"kind":"array","length":32,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::read_request::ReadRequest"}}},{"name":"key_validation_requests_and_generators","type":{"kind":"array","length":16,"type":{"fields":[{"name":"request","type":{"fields":[{"name":"pk_m","type":{"fields":[{"name":"x","type":{"kind":"field"}},{"name":"y","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::grumpkin_point::GrumpkinPoint"}},{"name":"sk_app","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request::KeyValidationRequest"}},{"name":"sk_app_generator","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::validation_requests::key_validation_request_and_generator::KeyValidationRequestAndGenerator"}}},{"name":"new_note_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::note_hash::NoteHash"}}},{"name":"new_nullifiers","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::nullifier::Nullifier"}}},{"name":"private_call_requests","type":{"kind":"array","length":4,"type":{"fields":[{"name":"hash","type":{"kind":"field"}},{"name":"caller_context","type":{"fields":[{"name":"msg_sender","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"storage_contract_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_static_call","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::caller_context::CallerContext"}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_call_request::PrivateCallRequest"}}},{"name":"public_call_stack_hashes","type":{"kind":"array","length":16,"type":{"kind":"field"}}},{"name":"public_teardown_function_hash","type":{"kind":"field"}},{"name":"new_l2_to_l1_msgs","type":{"kind":"array","length":2,"type":{"fields":[{"name":"recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"content","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::messaging::l2_to_l1_message::L2ToL1Message"}}},{"name":"start_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"end_side_effect_counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"note_encrypted_logs_hashes","type":{"kind":"array","length":16,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"note_hash_counter","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::NoteLogHash"}}},{"name":"encrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}},{"name":"randomness","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::EncryptedLogHash"}}},{"name":"unencrypted_logs_hashes","type":{"kind":"array","length":4,"type":{"fields":[{"name":"value","type":{"kind":"field"}},{"name":"counter","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"length","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::log_hash::LogHash"}}},{"name":"historical_header","type":{"fields":[{"name":"last_archive","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"content_commitment","type":{"fields":[{"name":"tx_tree_height","type":{"kind":"field"}},{"name":"txs_effects_hash","type":{"kind":"field"}},{"name":"in_hash","type":{"kind":"field"}},{"name":"out_hash","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::content_commitment::ContentCommitment"}},{"name":"state","type":{"fields":[{"name":"l1_to_l2_message_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"partial","type":{"fields":[{"name":"note_hash_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"nullifier_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}},{"name":"public_data_tree","type":{"fields":[{"name":"root","type":{"kind":"field"}},{"name":"next_available_leaf_index","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot"}}],"kind":"struct","path":"authwit::aztec::protocol_types::partial_state_reference::PartialStateReference"}}],"kind":"struct","path":"authwit::aztec::protocol_types::state_reference::StateReference"}},{"name":"global_variables","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"block_number","type":{"kind":"field"}},{"name":"timestamp","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"coinbase","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::eth_address::EthAddress"}},{"name":"fee_recipient","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"gas_fees","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::global_variables::GlobalVariables"}},{"name":"total_fees","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::header::Header"}},{"name":"tx_context","type":{"fields":[{"name":"chain_id","type":{"kind":"field"}},{"name":"version","type":{"kind":"field"}},{"name":"gas_settings","type":{"fields":[{"name":"gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"teardown_gas_limits","type":{"fields":[{"name":"da_gas","type":{"kind":"integer","sign":"unsigned","width":32}},{"name":"l2_gas","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas::Gas"}},{"name":"max_fees_per_gas","type":{"fields":[{"name":"fee_per_da_gas","type":{"kind":"field"}},{"name":"fee_per_l2_gas","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_fees::GasFees"}},{"name":"inclusion_fee","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::gas_settings::GasSettings"}}],"kind":"struct","path":"authwit::aztec::protocol_types::transaction::tx_context::TxContext"}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::private_circuit_public_inputs::PrivateCircuitPublicInputs"},"visibility":"public"}},"bytecode":"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","debug_symbols":"7P3drmy5spwJvsu5FgrBf1Kv0mg01H1UDQEFqVBSXQl69xr77IyIuc6aEYMzl4+gG810U1IhdiTdPJM085j8+D//5V//8//3//7//3/+y3/93//bf/+X//j/+p//8n/8t//ff/of/+W//dfj//U//yW2f/v/99//z//0X//x//zv/+M//V//41/+4+0//Mt//q//evx//9d/+Jf//b/8H//5X/5j6vF//YffPhdbSX99NLZWHp8OoX7z6RxD++vTOfZ88ulRYvjr06P053fHNP7X//s//EvsqAsfH1x4uuX7wlP9w4Wn258sPKdUH0tp8fHpEf7tu8OF3x2/++6c79+e2zj5/jAeMoaR0uPTJX334RrK/cM1PZce+z9Xk1ytJrtaTfnz1Yx4/88j1pPVxJzy49O51PHv/8WpH15OGeGxnJp+Wc7vH0853b875a87QWrffLqN+w7Wb88vDr3/W6GNpdDOUuggKTTfWAoNLIVGlkITS6GZpdDCUqhvZ1Ta3WWmGsZZoe1RaHiuI9bbdwu59XvQiCE+vzmG248l9O25ICT07eYgJPTtExEkLL4dKISEvr0thIS+XTOEhL79OISEWRL+qYS+MwSEhKzp5BivPyTs8RcJ/yELa+I4kYU1RZzIwpoM3stSWd3+iSysDv5EFlZXfiILq9M+kSVLlu9kYXXEJ7KwutwjHjxW/eUPTu6ysLrcE1lYXe6JLKwu970sjdXlnsjC6nJPZGF1uSeysLrcE1myZPlOFlaXeyILrcut/bHqY6z972WhdbnvZaF1ue9loXW5b2XptC73vSy0Lve9LLQu970stC73vSxZsnwnC63LfS/Lp11uzeMhS6+397LE2up9JUcdt39/wbI36NV36NUP5NWPm+/V9/hl9b/dDx0BevURevUJevUZevUFevXOz9qT1Ts/a3t/+K06fl+987P2ZPXOz9r3qw8374ftyfK9n7Yny/d+3J4s3/t5e7J85wfu6PcsGdst9t+W7/zEPVu+8yP3bPm+z9wWviChjp/Tflu+70O3xfT4eEu39NvyfZ+6Z8sPvk/d0+X7PnVPl+/71G0jPHeeMfJvy/d96p4u3/ep22/psXH2r3fO7sv3feqeLt/3qXu6/E+fun08RvR5xPrberqz9Xz6XBzt+VPK6PF9e/u4/5Iy4vPfhFC/+yElxPSgAsbx9ceR/M2n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jt526uhtp47edurobadO3nbq5G2nTt526uRtp07edurkbadO3nbq5G2nTt526uRtp87edursbafO3nbq7G2nzt526uxtp87edursbafO3nbq7G2nLt526uJtpy7eduribacu3nbq4m2nLt526uJtpy7eduribaeu3nbq6m2nrt526uptp67edurqbaeu3nbq6m2nrt526uptp27edurmbadu3nbq5m2nbt526uZtp27edurmbadu3nbq5m2n7t526u5tp+7edurubafu3nbq7m2n7t526u5tp+7edurubace3nbq4W2n9nZHcXi7ozi83VEc3u4oDm93FIe3O4rD2x3F4eyOYrw5u6N4LMjXTn0syNdOfSzI1059LMjXTn0syNdOfSzI1059LMjXTn0syNdOfSzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzI207t7I7isSBvO7WzO4rHgrzt1M7uKB4L8rZTO7ujeCzo0zv1GPenKP5BWv5mQdXbgpq3BXVvCxrOFvTxO4qnCwreFhS9LejDO/W4jfpYUGj99wVlbwsq3hZUvS3owzv1iF/+pT7+l78vqHtb0Id36jHG49O344eN3xb06TuK5wsK3hb02Z36H38N/FxQuKXfF5S8LSh7W1DxtqDqbUHN24K6twWNDy8oxPhcUP19QR++ozixoOBtQZ/eqWMbjwWl3H5f0Kd36vQYNvzj99Xx+4KytwUVbwv68E4djp+d758OId5+X1DztqAP79QhlMd/ZSGW8vuChq8FhQ/fUZxY0Id36tCeO3Vo6Zed+rvv7vfQFHOJjw/H23dfPkoMf316lP6sNabxV7GRqdgPnzChltuj2B5Oii3lPi8o7fnR/NfSM+7SC+7SK+7SG+7Su+elv3mc/Fj6gF16uOEuPeAuPeIu3fVp+n7prk/T90t3fZq+X7rr0/T90l2fpu+XjnuaBtzTNOKephH3NI24p2nEPU0/fJvZdOm4p2nEPU0j7mkacU/TiHuaJtzTNOGepgn3NE24p+mHb5ybLh33NE24p2nCPU0T7mmacE/TjHuaZtzTNOOephn3NP0wFcB06binacY9TTPuaZpxT9OMe5oW3NO04J6mBfc0Lbin6YfJDaZLxz1NC+5pWnBP04J7mhbc07TinqYV9zStuKdpxT1NP0zXMF067mlacU/TinuaVtzTtOKepg33NG24p2nDPU0b7mn6YQKK6dJxT9OGe5o23NO04Z6mDfc07binacc9TTvuadpxT9NPU2osl457mnbc07TjnqYd9zT9c+7OPx6rvy8mfsHEfL/03Ee/fzqP+Bv/K/w5d8d6QcHbgqK3BSVvC8reFlS8Lah6W1DztqDubUHOdur4/aX5+3JuJ4vJKd0JDjm1+Pu3x0u/PV367fnSby+Xfnu99Nvbpd/eL/32ceW3f3/f1+zbnT0MEL09YBu9PWAbvT1gG709YBu9PWAbvT1gG709YBu9PWAbvT1gm4ozI5yKMyOcijMjnKqzkUWqzkYWqTobWaSP/9HXQmpl+vifiS0tthAV264Ma6m1S7+9X/rtV4a11G+Xfnu49Nu9OZ7uLJumD/90ObEgZ9k0dWfZNHVf2TSV/+37cHqcFs8Xi8JzTSG1+/9u/L3/3fdRb+J/F/7m/y7+jf9diPF/ezGl67c7B3+M/OV/F5//u/H3/nffT9Ym/nfhb/7v4t/836W/+b/Lf/N/9+2uEm63u+cItxx/+V9+Z8trevT7y38G3/uZGu4nU01fvE+9PddUHa6pOVxTd7imce2a7v+cFzud/T8nfOifEz/0z0kf+ufkD/1zyof+OfVD/5z2oX9O/9A/x2A/iLf8fEBo3E72qBDa48XMeHs+mBl7eKwq31yuKnx6Va3fH7Hp4df9/JvPtvb4bPp2788RfP0JfP0ZfP0FfP0VfP0NfP0dfP0De/3lBr5+8PO3gJ+/Bfz8LeDnbwE/fwv4+VvAz98Cfv4W8PO3gp+/Ffz8reDnbwU/fyv4+VvBz9/qev8v+f4nOiW/WL/r/f98/c31/lPK/a/xSm3fr9/1/jOxftf7z8T6Xe8/E+t37f8n1u/a/0+s3/X+f/7bdXO9/5+vv7v2/xPrd+3/J9bv+vydWL/r83di/a7P34n1uz5/J9bv+vydWL/r83di/eDnbwc/fwf4+Ts+f/6+nCn8/tkQHte5Qrx9caBf/oJmRPgKEnwFGb6CAl9Bha+gwVfQ/VTwWNNwt6Z0szg1j4bc1xRqPllTCM/7KSF/+VvMkJ+rCi5XFT+9KtNfCNItga8/g6+/gK+/gq+/ga+/g69/YK8/3MDXH8DXD37+BvDzN4CfvwH8/A3g528AP38D+PkbwM/fCH7+RvDzN4KfvxH8/I3g528EP38j+Pkbwc/fCH7+RvDzN4Gfv8n1/n/6F8Ypud7/J9bvev85/QvLlFzvPxPrd73/nK8/u95/Jtbv2v9PrN+1/59Yv+v9//QvhFJ2vf9PrN+1/59Yv2v/P7F+1+fvxPpdn78T63d9/p6vv7g+fyfW7/r8nVi/6/N3Yv3g568JYWTl+sHP3/L58/cnf5V468+/ILt9+cu8L39BVhp8BR2+goFeQb3BVxDgK4jwFSTfFTzi/FFB+KWCb755PL759oV43/uz2kxVbaGq1rcv+OUvy1/8t+jbF8xU4NsXzFTg2xdMVNB8+4KZCnz7gpkKfPuCmQp8+4KJezomJKC1Ffg+v2cqcHQmP9bk6JR9rMnk3Bz3lyBiPH3RMJTHsxElf7+m4W9NJnSdH63J9m9PTOg6K9cfwdefwNefwddfwNdfwdffwNffwdc/sNc/wM/fAX7+DvDzd4CfvyZcnZXrBz9/B/j5O8DP3wF+/g7s8zffsM/ffMM+f/MN+/zNN+zzN9+wz998wz5/8w37/M037PM337DP33wDP38D+PkbwM/fAH7+BvDz14b9s3D94OdvAD9/A/j5G8DP3wB+/kbw8zeCn78R/PyN4OevDftn4frBz98Ifv5G8PM3gp+/Efz8TeDnbwI/fxP4+ZvAz18b9tLC9YOfvwn8/E3g528CP38T+Pmbwc/fDH7+ZvDzN4Ofvzbsq4XrBz9/M/j5m8HP3wx+/mbw87eAn78F/Pwt4OdvAT9/bdhXC9cPfv4W8PO3gJ+/Bfz8LeDnbwU/fyv4+VvBz98Kfv7a8KsWrh/8/K3g528FP38r+Plbwc/fBn7+NvDzt4Gfvw38/LVhSi1cP/j528DP3wZ+/jbw87eBn7/g/KsMzr/K4PyrDM6/yuD8qwzOv8rg/KsMzr/K4PyrDM6/yuD8qwzOv8rg/KsMzr/K4PyrDM6/yuD8qwzOv8rg/KsMzr8q4PyrAs6/KuD8qwLOvyo37PO3gPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868KOP+qgPOvCjj/qoDzrwo4/6qA868qOP+qgvOvKjj/qoLzr+oN+/yt4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsKzr+q4PyrCs6/quD8qwrOv6rg/KsGzr9q4PyrBs6/auD8q3bDPn8bOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qB868aOP+qgfOvGjj/qoHzrxo4/6qD8686OP+qg/OvOjj/qt+wz98Ozr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ov+rg/KsOzr/q4PyrDs6/6uD8qw7Ovxrg/KsBzr8a4PyrAc6/Gjfs83eA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzrwY4/2qA868GOP9qgPOvBjj/aoDzr46FYh/A/1goegHYR/CxUOwz+Fgo9iF8LBT7FD4Win0MHwvFPoePhWIfxMdC0U9icBTWUQD6SQwOwzoKQD+JwXFYRwHoJzE4EOsoAP0kBkdiHQWgn8TgUKyjAPSTGByLdRSAfhKDg7GOAtBPYnA01lEA+kkMDsc6CkA/icHxWEcB6CcxOCDrKAD9JAZHZB0FoJ/E4JCsowD0kxgck3UUgH4Sg4OyjtWhn8TgqKxjdegnMTgs61gd+kkMjss6Vod+EoMDs47VoZ/E4MisowD0kxgcmnUUgH4Sg2OzjgLQT2JwcNZRAPpJDI7OOgpAP4nB4VlHAegnMTg+6ygA/SQGB2gdBaCfxOAIraMA9JMYHKJ1FIB+EoNjtI4C0E9icJDWUQD6SQyO0joKQD+JwWFaRwHoJzE4TusoAP0kBgdqHQWgn8TgSK2jAPSTGByqdRSAfhKDY7WOAtBPYnCw1lEA+kkMjtY6CkA/icHhWkcB6CcxOF7rKAD9JAYHbB0FoJ/E4IitowDwkzigM7YCOmMroDO2Ajpj61geegHgJ3FAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkBnbAV0xlZAZ2wFdMZWQGdsBXTGVkRnbEV0xlZEZ2xFdMZWvIGfxBGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xFdEZWxGdsRXRGVsRnbEV0RlbEZ2xldAZWwmdsZXQGVsJnbGVbuAncUJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsJXTGVkJnbCV0xlZCZ2wldMZWQmdsZXTGVkZnbGV0xlZGZ2zlG/hJnNEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbGZ2xldEZWxmdsZXRGVsZnbGV0RlbBZ2xVdAZWwWdsVXQGVvlBn4SF3TGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWQWdsFXTGVkFnbBV0xlZBZ2wVdMZWRWdsVXTGVkVnbFV0xla9gZ/EFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbFV0RlbFZ2xVdEZWxWdsVXRGVsVnbHV0BlbDZ2x1dAZWw2dsdVu4CdxQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZWQ2dsNXTGVkNnbDV0xlZDZ2w1dMZW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W5frnJJtXi6Xq6pcrso5A9283MxVLpercs5ANy+Xy1U5Z6Cbl8vlqpwz0M3L5XJVzhno5uVyuSrnDHTzcrlclXNeunm5XK6Ki60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6pGLrR652OqRi60eudjqkYutHrnY6omLrZ642OqJi62euNjq6Za5yqVyVYmLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqiYutnrjY6omLrZ642OqJi62euNjqmYutnrnY6pmLrZ652Or5lrnKpXJVmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqmYutnrnY6pmLrZ652OqZi62eudjqeScc9Wjx/uGWXpS70UE0Ue5OwOLR+/3Do70od6OtaqbcjbaqmXIzV7kbBcCZcjcKgDPl7nTuTpS707k7Ue5GAXCi3J2AxTPlcrmqnYDFM+XCuqpnCRm/BN/up8VxL6HHdhbDb6PeVx3Cl1XX8qVg3/7ngoJ9O6ALCvbtgS4o2LcLsi/YOWL4goJ9O6ELCvbthS4o2LcbuqDgzFYwm9Nyjhu+oGA2p+UcOXxBwWxOyzl2+IKC2ZyWc/TwBQWzOS3n+OELCmZzWs4RxBcUzOa0nGOILyiY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8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VBe+/quD9VxW8/6qC919V8P6rCt5/VcH7ryp4/1UF77+q4P1XFbz/qoL3X1Xw/qsK3n9VwfuvKnj/VQXvv6rg/VcVvP+qgvdfVfD+qwref1XB+68qeP9VA++/auD9Vw28/6qB91+1G/b7t4H3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XDbz/qoH3XzXw/qsG3n/VwPuvGnj/VQPvv2rg/VcNvP+qgfdfNfD+qwbef9XA+68aeP9VA++/auD9Vw28/6qB91818P6rBt5/1cD7rxp4/1UD779q4P1XHbz/qoP3X3Xw/qsO3n/Vb9jv3w7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfdfD+qw7ef9XB+686eP9VB++/6uD9Vx28/6qD91918P6rDt5/1cH7rzp4/1UH77/q4P1XHbz/qoP3X3Xw/qsO3n/VwfuvOnj/VQfvv+rg/VcdvP+qg/dfDfD+qwHefzXA+68GeP/VuGG/fwd4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/NcD7rwZ4/9UA778a4P1XA7z/aoD3Xw3w/qsB3n81wPuvBnj/1QDvvxrg/VcDvP9qgPdfDfD+qwHefzXA+68GeP/VAO+/GuD9VwO8/2qA918N8P6rAd5/dX9Q7Bfwfx4UXQD2K/j+oNjv4PuDYr+E7w+K/Ra+Pyj2a/j+oNjv4fuDYr+I7w+K/iYGr8K6C0B/E4OXYd0FoL+Jweuw7gLQ38TghVh3AehvYvBKrLsA9DcxeCnWXQD6mxi8FusuAP1NDF6MdReA/iYGr8a6C0B/E4OXY90FoL+Jweux7gLQ38TgBVl3AehvYvCKrLsA9DcxeEnWXQD6mxi8JusuAP1NDF6UdX869DcxeFXW/enQ38TgZVn3p0N/E4PXZd2fDv1NDF6YdX869DcxeGXWXQD6mxi8NOsuAP1NDF6bdReA/iYGL866C0B/E4NXZ90FoL+Jwcuz7gLQ38Tg9Vl3AehvYvACrbsA9DcxeIXWXQD6mxi8ROsuAP1NDF6jdReA/iYGL9K6C0B/E4NXad0FoL+Jwcu07gLQ38TgdVp3AehvYvBCrbsA9DcxeKXWXQD6mxi8VOsuAP1NDF6rdReA/iYGL9a6C0B/E4NXa90FoL+Jwcu17gLQ38Tg9Vp3AehvYvCCrbsA9DcxeMXWXQD4m3hD79ja0Du2NvSOrQ29Y+v+eOgCwN/EG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWhd2xt6B1bG3rH1obesbWjd2zt6B1bO3rH1o7esbXfwN/EO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2zt6B1bO3rH1o7esbWjd2wd6B1bB3rH1oHesXWgd2wdN/A38YHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd6B1bB3rH1oHesXWgd2wd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D76ue+Pruje+rnvj67o3vq57uxmfZDr3ZXxd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13VvfF33xtd1b3xd98bXdW98XffG13Vf+LruC1/XfeHrui98XfflZnyS6dxX4eu6L3xd94Wv677wdd0Xvq77wtd1X/i67gtf133h67ovfF33ha/rvvB13Re+rvvC13Vf+LruC1/XfeHrui98XfeFr+u+8HXdF76u+8LXdV9ytaCPtv/66tF+/94vwaneyjOCU31aj94fgkc7EZzqs3pGcKpP6hnBqT6nZwSnysgzglMl5AnBufqwZwTneg9PCE6VjWcEp0rGM4KNTTCb00LuwH6JAHZPLxHBHVE7bs8H6fbpP73/FNf++vL/FMf9OapH76m+QHL0nuorJAf3RVdIDu6MrpAc3BtdIdn4JAf3R1dIDu6QrpAc3E9dIZnPfUXvqb5AcvSe6isk87mv6D3VV0jmc1/Re6qvkMznvqL3VF8hmc99Re+pvkIyn/uK3lN9hWQ+9xW9p/oKyXzuK3pP9RWS+dxX9J7qKyTzua/oPdVXSOZzX9F7qq+QzOe+ovdUXyGZz31F76m+QjKf+4reU32FZD73Fb2n+grJfO4rek/1FZL53Ff0nuorJPO5r+g91VdI5nNf0Xuqr5DM576i91RfIZnOfdXoPdVXSKZzXzV6T/UVkuncV70Zn2Q691Wj91RfIZnOfdXoPdVXSOZzX9F7qq+QzOe+ovdUXyGZz31F76m+QjKf+4reU32FZD73Fb2n+grJfO4rek/1FZL53Ff0nuorJPO5r+g91VdI5nNf0Xuqr5DM5752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d/IJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xid8j9cJ3+N1wvd4nfA9Xhd8j9cF3+N1wfd4XfA9XtcD/Z18wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j9cF3+N1wfd4XfA9Xhd8j5fB93gZfI+Xwfd4GXyPlz3Q38kG3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G3+Nl8D1eBt/jZfA9Xgbf42XwPV4G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XQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpO10Pf6XroO10Pfafroe8Po1PM5rk6XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dD3TB3lo52vL25//85vehO9jaf0JnpOj95fXzzaJ72JntJTehM9o6f0JnpCT+lNlIln9GZqrJ7Sm+n9O6M30/t3Rm+iLDyl18j0kvmrTC3VU3ph/dWbBljP9KYhtg+62tc/JRsPl2QevEd6heLYXmiF4thuaIXi2H5ohWKjUxzbE61QHNsVrVAc2xetUBzbRa1QTOe5gvdIr1BM57mC90ivUEznuYL3SK9QTOe5gvdIr1BM57mC90ivUMzmuUbwHukVitk81wjeI71CMZvnGg+jU8zmuUbwHukVitk81wjeI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4jvUIxnecK3iO9QjGd5wreI71CMZ3nCt4j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/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvN7L+diPrbzey/nYj6283sv52I+tvt0x916Odry9u1ye9id5HM3oz9SGP3l9fPNonvYmeV1N6Ez2vpvQamd5EeXBKb6I8OKU30/t3Rm+m9++M3kR5cEZvpj7kKb1k/ipTH/KUXlh/9abBEmiI7YPaOV4a+tl+yuWPUV+f+jjePnUt74pjO6EVimN7oRWKY7uhFYpj+6EFioM3GK9QHNsTrVAc2xWtUBzbF61QbHSK6TxX8DbjFYrpPFfwRuMViuk8V/BW4xWK6TxX8GbjFYrpPFfwduMViuk8V/CG4xWK6TxX8JbjFYrZPFcJ3nS8QjGb5yrB245XKGbzXOVhdIrZPFcJ3nq8QjGb5yrBm49XKKbzXMHbj1copvNcwRuQVyim81zBW5BXKKbzXMGbkFcopvNcwduQVyim81zBG5FXKKbzXMFbkVcopvNcwZuRVyim81zB25FXKKbzXMEbklcopvNcwVuSVyim81zBm5JXKKbzXMHbklcopvNcwRuTVyim81zBW5NXKKbzXMGbk1copvNcwduTVyim81zBG5RXKKbzXMFblFcopvNcwZuUVyim81zB25RXKKbzXMEblVcopvNcxegU03muQue5gneFr1BM57kKneeqdJ4reCf8CsV0nit4L/wKxUanmM5zBW+HX6GYznMFb4hfoZjOcwVviV+hmM5zBW+KX6GYznMFb5ZfoZjOc9H10Be6HvpC10Nf6HroC10PfaHroS90PfSFroe+0PXQF7oe+kLXQ1/oeugLXQ99oeuhL3Q99IWuh77Q9dAXuh76QtdDX+h66AtdD32h66EvdD30ha6HvtL10Fe6HvpK10Nf6Xro68PoFLN5rkrXQ1/peugrXQ99peuhr3Q99JWuh77S9dBXuh76StdDX+l66CtdD32l66GvdD30la6HvtL10Fe6HvpK10Nf6XroK10Pfc3UUf786tcXt79/5ze9id7GM3ozdVeP3l9fPNonvYme0lN6Ez2jp/QmekJP6U2Uiaf0JkrEU3ozvX9n9GZ6/87oTZSFZ/Rmaqqe0kvmrzK1VE/phfVXbxosgYbYPqiX9vVPqdSfkrmdX8ncrvL91W28K47thFYoju2FViiO7YZWKI7thxYoDt4jvUJxbE+0QnFsV7RCcWxftEKx0Smm81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKKbzXMF7pFcopvNcwXukVyim81zBe6RXKGbzXC14j/QKxWyeqwXvkV6hmM1ztYfRKWbzXC14j/QKxWyeqwXvkV6hmM5zBe+RXqGYznMF75FeoZjOcwXvkV6hmM5zBe+RXqGYznMF75FeoZjOcwXvkV6hmM5zBe+RXqGYznMF75FeoZjOc510nit4V/gKxXSe66TzXBed5wreCb9CMZ3nCt4Lv0Kx0Smm81zB2+FXKKbzXMEb4lcopvNcwVviVyim81zBm+JXKKbzXMGb5VcopvNcdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroG10PfaProW90PfSNroe+0fXQN7oe+kbXQ9/oeugbXQ99o+uhb3Q99I2uh77R9dA3uh76RtdD3+h66BtdD32j66FvdD30ja6HvtH10De6HvpG10Pf6HroO10Pfafroe90PfSdroe+P4xOMZvn6nQ99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3+l66DtdD32n66HvdD30na6HvtP10He6HvpO10Pf6XroO10Pfafroe90PfSdroe+0/XQd7oe+k7XQ9/peug7XQ99p+uh73Q99J2uh77T9dB3uh76TtdD3zN1lI92vr64/f07v+lN9Dae0pvoOT16//ri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pRtL5R4/lso9fiyVe/xYKvf4sVTu8WLZo19phWKp3OPHUrnHj6Vyjx9LI2b5i09il70WRXaVt03Ro77TZE4+/jSZs48/Teb040+TOf/402ROQO40o19sBaPJnIJ+RbM/vmj28Ykmcw7yp8mchPxpmmg60lQW8qSpLORJU1nIk6ay0O9pjvqJprKQI83oV1zBaCoLzdG04ytZ2vkpWUa/5ApGU1nIk6aJpiNNZSFPmspCnjSVhTxpKgtN0izXF816fqKpLORIM9ct4+00lYU8aSoLedJUFvKkaaLpSFNZ6P+5aTPpzJemp/gor9zzUQK556NMccuH+dL0FB/5/ns+qZz8xO3xnuvG85Rio1OcyrVOKU7lQ6cUp3KWU4pTecUpxanc34ziXNd2pxSncmhTiuk8V677slOKjU4xnefKdVF1SjGd58p1nXRKMZ3nynXpc0oxnefKdTVzSjGd58p1gXJKMZ3nynXNcUoxnefKdRlxSjGd58p1ZXBKMZ3nynWxb0oxnefKdf1uSjGd58p1SW5KMZ3nanSeq9F5rk7nuXLdGpxSTOe5Op3n6kanmM5z5bqgOKWYznPlukY4pZjOc+W67DelmM5z5bqSN6WYznPlujg3pZjOc+W63jalmM5z5bqENqWYzXONXFfFphSzea6R60LXlGI2zzUeRqeYzXONXFejphSzea6R6/rSlGI6z5XritGUYjrPlesa0JRiOs+V66rOlGI6z5XrOs2UYjrPlevKy5RiOs+V61rKlGI6z5Xr6siUYjrPlet6x5RiOs+V6wrGlGI6z5XrmsSUYjrPlesqw5RiOs+V67rBlGI6z5XrSsCUYjrPlaubf0oxnefK1Z8/pZjOc+XquJ9STOe56HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HftD10A+6HvpB10M/6HroB10P/aDroR90PfSDrod+0PXQD7oe+kHXQz/oeugHXQ/9oOuhH3Q99IOuh37Q9dAPuh76QddDP+h66AddD/2g66EfdD30g66HfuTqKH9+7u8vP8cP37318fVJzh++ttj519cWuz6wzNV+vpllKg+xmWUqd7KZZSrfs5mliaUby1RebTPLVC5wM8tUO73NLFNtCzezVO5xYtkf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"}],"outputs":{"globals":{},"structs":{"functions":[{"fields":[{"name":"parameters","type":{"fields":[{"name":"app_payload","type":{"fields":[{"name":"function_calls","type":{"kind":"array","length":4,"type":{"fields":[{"name":"args_hash","type":{"kind":"field"}},{"name":"function_selector","type":{"fields":[{"name":"inner","type":{"kind":"integer","sign":"unsigned","width":32}}],"kind":"struct","path":"authwit::aztec::protocol_types::abis::function_selector::FunctionSelector"}},{"name":"target_address","type":{"fields":[{"name":"inner","type":{"kind":"field"}}],"kind":"struct","path":"authwit::aztec::protocol_types::address::aztec_address::AztecAddress"}},{"name":"is_public","type":{"kind":"boolean"}},{"name":"is_static","type":{"kind":"boolean"}}],"kind":"struct","path":"authwit::entrypoint::function_call::FunctionCall"}}},{"name":"nonce","type":{"kind":"field"}}],"kind":"struct","path":"authwit::entrypoint::app::AppPayload"}}],"kind":"struct","path":"MultiCallEntrypoint::entrypoint_parameters"}}],"kind":"struct","path":"MultiCallEntrypoint::entrypoint_abi"}]}},"file_map":{"116":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/hash.nr","source":"use dep::protocol_types::{\n address::{AztecAddress, EthAddress},\n constants::{\n GENERATOR_INDEX__SECRET_HASH, GENERATOR_INDEX__MESSAGE_NULLIFIER, ARGS_HASH_CHUNK_COUNT,\n GENERATOR_INDEX__FUNCTION_ARGS, ARGS_HASH_CHUNK_LENGTH\n},\n traits::Hash, hash::{pedersen_hash, compute_siloed_nullifier, sha256_to_field}\n};\nuse crate::oracle::logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog};\n\npub fn compute_secret_hash(secret: Field) -> Field {\n pedersen_hash([secret], GENERATOR_INDEX__SECRET_HASH)\n}\n\npub fn compute_unencrypted_log_hash(\n contract_address: AztecAddress,\n event_selector: Field,\n log: T\n) -> Field where T: ToBytesForUnencryptedLog {\n let message_bytes: [u8; N] = log.to_be_bytes_arr();\n // can't use N - not in scope error\n let n = message_bytes.len();\n let mut hash_bytes = [0; M];\n // Address is converted to 32 bytes in ts\n let address_bytes = contract_address.to_be_bytes_arr();\n for i in 0..32 {\n hash_bytes[i] = address_bytes[i];\n }\n let event_bytes = event_selector.to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[32 + i] = event_bytes[i];\n }\n let len_bytes = (n as Field).to_be_bytes(4);\n for i in 0..4 {\n hash_bytes[36 + i] = len_bytes[i];\n }\n for i in 0..n {\n hash_bytes[40 + i] = message_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\npub fn compute_message_hash(\n sender: EthAddress,\n chain_id: Field,\n recipient: AztecAddress,\n version: Field,\n content: Field,\n secret_hash: Field\n) -> Field {\n let mut hash_bytes = [0 as u8; 192];\n let sender_bytes = sender.to_field().to_be_bytes(32);\n let chain_id_bytes = chain_id.to_be_bytes(32);\n let recipient_bytes = recipient.to_field().to_be_bytes(32);\n let version_bytes = version.to_be_bytes(32);\n let content_bytes = content.to_be_bytes(32);\n let secret_hash_bytes = secret_hash.to_be_bytes(32);\n\n for i in 0..32 {\n hash_bytes[i] = sender_bytes[i];\n hash_bytes[i + 32] = chain_id_bytes[i];\n hash_bytes[i + 64] = recipient_bytes[i];\n hash_bytes[i + 96] = version_bytes[i];\n hash_bytes[i + 128] = content_bytes[i];\n hash_bytes[i + 160] = secret_hash_bytes[i];\n }\n\n sha256_to_field(hash_bytes)\n}\n\n// The nullifier of a l1 to l2 message is the hash of the message salted with the secret and index of the message hash\n// in the L1 to L2 message tree\npub fn compute_message_nullifier(message_hash: Field, secret: Field, leaf_index: Field) -> Field {\n pedersen_hash(\n [message_hash, secret, leaf_index],\n GENERATOR_INDEX__MESSAGE_NULLIFIER\n )\n}\n\nstruct ArgsHasher {\n fields: [Field],\n}\n\nimpl Hash for ArgsHasher {\n fn hash(self) -> Field {\n hash_args(self.fields)\n }\n}\n\nimpl ArgsHasher {\n pub fn new() -> Self {\n Self { fields: [] }\n }\n\n pub fn add(&mut self, field: Field) {\n self.fields = self.fields.push_back(field);\n }\n\n pub fn add_multiple(&mut self, fields: [Field; N]) {\n for i in 0..N {\n self.fields = self.fields.push_back(fields[i]);\n }\n }\n}\n\npub fn hash_args_array(args: [Field; N]) -> Field {\n hash_args(args.as_slice())\n}\n\npub fn hash_args(args: [Field]) -> Field {\n if args.len() == 0 {\n 0\n } else {\n assert(args.len() < ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH);\n let mut chunks_hashes = [0; ARGS_HASH_CHUNK_COUNT];\n let mut current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n\n let mut current_chunk_index = 0;\n let mut index_inside_current_chunk = 0;\n for i in 0..args.len() {\n current_chunk_values[index_inside_current_chunk] = args[i];\n index_inside_current_chunk+=1;\n if index_inside_current_chunk == ARGS_HASH_CHUNK_LENGTH {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n current_chunk_values = [0; ARGS_HASH_CHUNK_LENGTH];\n current_chunk_index+=1;\n index_inside_current_chunk = 0;\n }\n }\n if index_inside_current_chunk > 0 {\n chunks_hashes[current_chunk_index] = pedersen_hash(current_chunk_values, GENERATOR_INDEX__FUNCTION_ARGS);\n }\n pedersen_hash(chunks_hashes, GENERATOR_INDEX__FUNCTION_ARGS)\n }\n}\n\n#[test]\nfn compute_var_args_hash() {\n let mut input = ArgsHasher::new();\n for i in 0..800 {\n input.add(i as Field);\n }\n let hash = input.hash();\n assert(hash == 0x05a1023fef839ac88731f49ae983e172c1b600a3c8f3393ad0ac25d819ac0f0f);\n}\n\n#[test]\nfn compute_unenc_log_hash_array() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = [\n 0x20660de09f35f876e3e69d227b2a35166ad05f09d82d06366ec9b6f65a51fec2,\n 0x1b52bfe3b8689761916f76dc3d38aa8810860db325cd39ca611eed980091f01c,\n 0x2e559c4045c378a56ad13b9edb1e8de4e7ad3b3aa35cc7ba9ec77f7a68fa43a4,\n 0x25d0f689c4a4178a29d59306f2675824d19be6d25e44fa03b03f49c263053dd2,\n 0x2d513a722d6f352dc0961f156afdc5e31495b9f0e35cb069261a8e55e2df67fd\n ];\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00846d6969c8c2f61d39cd2762efcb0abb14f88d59c2675910251ef2bcffe9a7);\n}\n\n#[test]\nfn compute_unenc_log_hash_addr() {\n let contract_address = AztecAddress::from_field(0x233a3e0df23b2b15b324194cb4a151f26c0b7333250781d34cc269d85dc334c6);\n let event_selector = 5;\n let log = AztecAddress::from_field(0x26aa302d4715fd8a687453cb26d616b0768027bd54bcae56b09d908ecd9f8303);\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00880a801230ea08c98a802a11b4786cba474513875f0fc69a615e81c5f9f21c);\n}\n\n#[test]\nfn compute_unenc_log_hash_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"dummy\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x00a78b5347813624ecfd26e5b8bc6146f418b0cfcc8296b5112d09b8ebba9496);\n}\n\n#[test]\nfn compute_unenc_log_hash_longer_str() {\n let contract_address = AztecAddress::from_field(0x1b401e1146c5c507962287065c81f0ef7590adae3802c533d7549d6bf0a41bd8);\n let event_selector = 5;\n let log = \"Hello this is a string\";\n let hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n assert(hash == 0x001f3390ea242afee7ce46dafdbdc4bd4f1cf20cd63850d12d60ff9956712c4f);\n}\n"},"132":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/call_private_function.nr","source":"use dep::protocol_types::{\n abis::{function_selector::FunctionSelector, private_call_stack_item::PrivateCallStackItem},\n address::AztecAddress, constants::PRIVATE_CALL_STACK_ITEM_LENGTH\n};\n\n#[oracle(callPrivateFunction)]\nunconstrained fn call_private_function_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _start_side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {}\n\nunconstrained pub fn call_private_function_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n start_side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> PrivateCallStackItem {\n let fields = call_private_function_oracle(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n PrivateCallStackItem::deserialize(fields)\n}\n"},"137":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/oracle/enqueue_public_function_call.nr","source":"use dep::protocol_types::{\n abis::{\n function_selector::FunctionSelector, public_call_stack_item::PublicCallStackItem,\n function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs,\n call_context::CallContext, read_request::ReadRequest, note_hash::NoteHash, nullifier::Nullifier,\n log_hash::LogHash, global_variables::GlobalVariables, gas::Gas\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n messaging::l2_to_l1_message::L2ToL1Message, header::Header, address::AztecAddress,\n utils::reader::Reader,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH\n}\n};\n\n#[oracle(enqueuePublicFunctionCall)]\nunconstrained fn enqueue_public_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn enqueue_public_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n enqueue_public_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\n#[oracle(setPublicTeardownFunctionCall)]\nunconstrained fn set_public_teardown_function_call_oracle(\n _contract_address: AztecAddress,\n _function_selector: FunctionSelector,\n _args_hash: Field,\n _side_effect_counter: u32,\n _is_static_call: bool,\n _is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {}\n\nunconstrained pub fn set_public_teardown_function_call_internal(\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n side_effect_counter: u32,\n is_static_call: bool,\n is_delegate_call: bool\n) -> [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH] {\n set_public_teardown_function_call_oracle(\n contract_address,\n function_selector,\n args_hash,\n side_effect_counter,\n is_static_call,\n is_delegate_call\n )\n}\n\npub fn parse_public_call_stack_item_from_oracle(fields: [Field; ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_LENGTH]) -> PublicCallStackItem {\n let mut reader = Reader::new(fields);\n\n // Note: Not using PublicCirclePublicInputs::deserialize here, because everything below args_hash is 0 and\n // there is no more data in fields because there is only ENQUEUE_PUBLIC_FUNCTION_CALL_RETURN_SIZE fields!\n // WARNING: if updating, see comment in public_call_stack_item.ts's PublicCallStackItem.hash()\n let item = PublicCallStackItem {\n contract_address: AztecAddress::from_field(reader.read()),\n function_data: FunctionData { selector: FunctionSelector::from_field(reader.read()), is_private: false },\n public_inputs: PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0\n },\n is_execution_request: true\n };\n reader.finish();\n\n item\n}\n"},"163":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{GAS_LENGTH, FIXED_DA_GAS}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered, utils::reader::Reader,\n abis::gas_fees::GasFees\n};\nuse dep::std::ops::{Add, Sub};\n\nstruct Gas {\n da_gas: u32,\n l2_gas: u32,\n}\n\nimpl Gas {\n pub fn new(da_gas: u32, l2_gas: u32) -> Self {\n Self { da_gas, l2_gas }\n }\n\n pub fn tx_overhead() -> Self {\n Self { da_gas: FIXED_DA_GAS, l2_gas: 0 }\n }\n\n pub fn compute_fee(self, fees: GasFees) -> Field {\n (self.da_gas as Field) * fees.fee_per_da_gas + (self.l2_gas as Field) * fees.fee_per_l2_gas\n }\n\n pub fn is_empty(self) -> bool {\n (self.da_gas == 0) & (self.l2_gas == 0)\n }\n\n pub fn within(self, limits: Gas) -> bool {\n (self.da_gas <= limits.da_gas) & (self.l2_gas <= limits.l2_gas)\n }\n}\n\nimpl Add for Gas {\n fn add(self, other: Gas) -> Self {\n Gas::new(self.da_gas + other.da_gas, self.l2_gas + other.l2_gas)\n }\n}\n\nimpl Sub for Gas {\n fn sub(self, other: Gas) -> Self {\n Gas::new(self.da_gas - other.da_gas, self.l2_gas - other.l2_gas)\n }\n}\n\nimpl Serialize for Gas {\n fn serialize(self) -> [Field; GAS_LENGTH] {\n [self.da_gas as Field, self.l2_gas as Field]\n }\n}\n\nimpl Deserialize for Gas {\n fn deserialize(serialized: [Field; GAS_LENGTH]) -> Gas {\n Gas::new(serialized[0] as u32, serialized[1] as u32)\n }\n}\n\nimpl Eq for Gas {\n fn eq(self, other : Gas) -> bool {\n (self.da_gas == other.da_gas) & (self.l2_gas == other.l2_gas)\n }\n}\n\nimpl Empty for Gas {\n fn empty() -> Self {\n Gas::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Gas::empty();\n let serialized = item.serialize();\n let deserialized = Gas::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n"},"165":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/note_hash.nr","source":"use crate::{\n abis::read_request::ScopedReadRequest, address::AztecAddress,\n abis::side_effect::{Ordered, OrderedValue, Readable, Scoped},\n constants::{NOTE_HASH_LENGTH, SCOPED_NOTE_HASH_LENGTH}, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct NoteHash {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for NoteHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteHash {\n fn eq(self, other: NoteHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter) \n }\n}\n\nimpl Empty for NoteHash {\n fn empty() -> Self {\n NoteHash {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteHash {\n fn serialize(self) -> [Field; NOTE_HASH_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for NoteHash {\n fn deserialize(values: [Field; NOTE_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl NoteHash {\n pub fn scope(self, nullifier_counter: u32, contract_address: AztecAddress) -> ScopedNoteHash {\n ScopedNoteHash { note_hash: self, nullifier_counter, contract_address }\n }\n}\n\nstruct ScopedNoteHash {\n note_hash: NoteHash,\n nullifier_counter: u32,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNoteHash {\n fn inner(self) -> NoteHash {\n self.note_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNoteHash {\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedNoteHash {\n fn value(self) -> Field {\n self.note_hash.value\n }\n fn counter(self) -> u32 {\n self.note_hash.counter\n }\n}\n\nimpl Eq for ScopedNoteHash {\n fn eq(self, other: ScopedNoteHash) -> bool {\n (self.note_hash == other.note_hash)\n & (self.nullifier_counter == other.nullifier_counter)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedNoteHash {\n fn empty() -> Self {\n ScopedNoteHash {\n note_hash: NoteHash::empty(),\n nullifier_counter: 0,\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedNoteHash {\n fn serialize(self) -> [Field; SCOPED_NOTE_HASH_LENGTH] {\n array_concat(self.note_hash.serialize(), [self.nullifier_counter as Field, self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNoteHash {\n fn deserialize(values: [Field; SCOPED_NOTE_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n note_hash: reader.read_struct(NoteHash::deserialize),\n nullifier_counter: reader.read_u32(),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNoteHash {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.note_hash.value, read_request.value(), \"Value of the note hash does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the note hash does not match read request\");\n assert(\n read_request.counter() > self.note_hash.counter, \"Read request counter must be greater than the counter of the note hash\"\n );\n assert(\n (self.nullifier_counter == 0) | (read_request.counter() < self.nullifier_counter), \"Read request counter must be less than the nullifier counter of the note hash\"\n );\n }\n}\n\nimpl ScopedNoteHash {\n pub fn expose_to_public(self) -> NoteHash {\n // Hide the actual counter when exposing it to the public kernel.\n NoteHash { value: self.note_hash.value, counter: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = NoteHash::empty();\n let serialized = item.serialize();\n let deserialized = NoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNoteHash::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNoteHash::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"166":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_fees.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::GAS_FEES_LENGTH, hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty},\n abis::side_effect::Ordered, utils::reader::Reader\n};\n\nstruct GasFees {\n fee_per_da_gas: Field,\n fee_per_l2_gas: Field,\n}\n\nimpl GasFees {\n pub fn new(fee_per_da_gas: Field, fee_per_l2_gas: Field) -> Self {\n Self { fee_per_da_gas, fee_per_l2_gas }\n }\n\n pub fn default() -> Self {\n GasFees::new(1, 1)\n }\n\n pub fn is_empty(self) -> bool {\n (self.fee_per_da_gas == 0) & (self.fee_per_l2_gas == 0)\n }\n}\n\nimpl Serialize for GasFees {\n fn serialize(self) -> [Field; GAS_FEES_LENGTH] {\n [self.fee_per_da_gas, self.fee_per_l2_gas]\n }\n}\n\nimpl Deserialize for GasFees {\n fn deserialize(serialized: [Field; GAS_FEES_LENGTH]) -> GasFees {\n GasFees::new(serialized[0], serialized[1])\n }\n}\n\nimpl Eq for GasFees {\n fn eq(self, other : GasFees) -> bool {\n (self.fee_per_da_gas == other.fee_per_da_gas) & (self.fee_per_l2_gas == other.fee_per_l2_gas)\n }\n}\n\nimpl Empty for GasFees {\n fn empty() -> Self {\n GasFees::new(0, 0)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasFees::empty();\n let serialized = item.serialize();\n let deserialized = GasFees::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"167":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr","source":"use crate::abis::{function_data::FunctionData, public_circuit_public_inputs::PublicCircuitPublicInputs};\nuse crate::address::AztecAddress;\nuse crate::constants::GENERATOR_INDEX__CALL_STACK_ITEM;\nuse crate::traits::Hash;\n\nstruct PublicCallStackItem {\n contract_address: AztecAddress,\n public_inputs: PublicCircuitPublicInputs,\n function_data: FunctionData,\n // True if this call stack item represents a request to execute a function rather than a\n // fulfilled execution. Used when enqueuing calls from private to public functions.\n is_execution_request: bool,\n}\n\nimpl Hash for PublicCallStackItem {\n fn hash(self) -> Field {\n let item = if self.is_execution_request {\n self.as_execution_request()\n } else {\n self\n };\n\n dep::std::hash::pedersen_hash_with_separator([\n item.contract_address.to_field(),\n item.function_data.hash(),\n item.public_inputs.hash(),\n ], GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl PublicCallStackItem {\n fn as_execution_request(self) -> Self {\n // WARNING: if updating, see comment in public_call_stack_item.ts's `PublicCallStackItem.hash()`\n let public_inputs = self.public_inputs;\n let mut request_public_inputs = PublicCircuitPublicInputs::empty();\n request_public_inputs.call_context = public_inputs.call_context;\n request_public_inputs.args_hash = public_inputs.args_hash;\n\n let call_stack_item = PublicCallStackItem {\n contract_address: self.contract_address,\n function_data: self.function_data,\n is_execution_request: true,\n public_inputs: request_public_inputs\n };\n call_stack_item\n }\n}\n\nmod tests {\n use crate::{\n abis::{\n function_data::FunctionData, function_selector::FunctionSelector, note_hash::NoteHash,\n public_circuit_public_inputs::PublicCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem\n },\n address::AztecAddress, constants::GENERATOR_INDEX__CALL_STACK_ITEM, traits::Hash\n };\n\n #[test]\n fn compute_call_stack_item_request_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item request hash\" test\n let test_data_call_stack_item_request_hash = 0x2751111aa213d9d21279da53531bf90c2da272cf3f959e2a2a1dfceb487bf102;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash);\n }\n\n #[test]\n fn compute_call_stack_item_hash() {\n let contract_address = AztecAddress::from_field(1);\n let function_data = FunctionData { selector: FunctionSelector::from_u32(2), is_private: false };\n\n let mut public_inputs = PublicCircuitPublicInputs::empty();\n public_inputs.new_note_hashes[0] = NoteHash {\n value: 1,\n counter: 0,\n };\n\n let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data };\n\n // Value from public_call_stack_item.test.ts \"Computes a callstack item hash\" test\n let test_data_call_stack_item_hash = 0x1860d00d9602966e398c6d585216baba2ffa8c5eddda5faee041136665d8482a;\n assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash);\n }\n}\n"},"168":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, max_block_number::MaxBlockNumber, gas_settings::GasSettings,\n validation_requests::KeyValidationRequestAndGenerator, note_hash::NoteHash, nullifier::Nullifier,\n private_call_request::PrivateCallRequest, read_request::ReadRequest,\n log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n constants::{\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NEW_L2_TO_L1_MSGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH,\n GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL,\n MAX_UNENCRYPTED_LOGS_PER_CALL, MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n transaction::tx_context::TxContext, utils::arrays::validate_array\n};\n\nstruct PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: u32,\n nullifier_read_requests: u32,\n key_validation_requests_and_generators: u32,\n new_note_hashes: u32,\n new_nullifiers: u32,\n new_l2_to_l1_msgs: u32,\n private_call_requests: u32,\n public_call_stack_hashes: u32,\n note_encrypted_logs_hashes: u32,\n encrypted_logs_hashes: u32,\n unencrypted_logs_hashes: u32,\n}\n\nimpl PrivateCircuitPublicInputsArrayLengths {\n pub fn new(public_inputs: PrivateCircuitPublicInputs) -> Self {\n PrivateCircuitPublicInputsArrayLengths {\n note_hash_read_requests: validate_array(public_inputs.note_hash_read_requests),\n nullifier_read_requests: validate_array(public_inputs.nullifier_read_requests),\n key_validation_requests_and_generators: validate_array(public_inputs.key_validation_requests_and_generators),\n new_note_hashes: validate_array(public_inputs.new_note_hashes),\n new_nullifiers: validate_array(public_inputs.new_nullifiers),\n new_l2_to_l1_msgs: validate_array(public_inputs.new_l2_to_l1_msgs),\n private_call_requests: validate_array(public_inputs.private_call_requests),\n public_call_stack_hashes: validate_array(public_inputs.public_call_stack_hashes),\n note_encrypted_logs_hashes: validate_array(public_inputs.note_encrypted_logs_hashes),\n encrypted_logs_hashes: validate_array(public_inputs.encrypted_logs_hashes),\n unencrypted_logs_hashes: validate_array(public_inputs.unencrypted_logs_hashes)\n }\n }\n}\n\nstruct PrivateCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator; MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest; MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter : u32,\n end_side_effect_counter : u32,\n note_encrypted_logs_hashes: [NoteLogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash; MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n // Note: The chain_id and version here are not redundant to the values in self.historical_header.global_variables because\n // they can be different in case of a protocol upgrade. In such a situation we could be using header from a block\n // before the upgrade took place but be using the updated protocol to execute and prove the transaction.\n tx_context: TxContext,\n}\n\nimpl Eq for PrivateCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.call_context.eq(other.call_context) &\n self.args_hash.eq(other.args_hash) &\n (self.returns_hash == other.returns_hash) &\n (self.min_revertible_side_effect_counter == other.min_revertible_side_effect_counter) &\n (self.is_fee_payer == other.is_fee_payer) &\n (self.max_block_number == other.max_block_number) &\n (self.note_hash_read_requests == other.note_hash_read_requests) &\n (self.nullifier_read_requests == other.nullifier_read_requests) &\n (self.key_validation_requests_and_generators == other.key_validation_requests_and_generators) &\n (self.new_note_hashes == other.new_note_hashes) &\n (self.new_nullifiers == other.new_nullifiers) &\n (self.private_call_requests == other.private_call_requests) &\n (self.public_call_stack_hashes == other.public_call_stack_hashes) &\n (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) &\n (self.start_side_effect_counter == other.start_side_effect_counter) &\n (self.end_side_effect_counter == other.end_side_effect_counter) &\n (self.note_encrypted_logs_hashes == other.note_encrypted_logs_hashes) &\n (self.encrypted_logs_hashes == other.encrypted_logs_hashes) &\n (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) &\n self.historical_header.eq(other.historical_header) &\n self.tx_context.eq(other.tx_context)\n }\n}\n\nimpl Serialize for PrivateCircuitPublicInputs {\n fn serialize(self) -> [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n\n fields.push(self.min_revertible_side_effect_counter as Field);\n fields.push(if self.is_fee_payer { 1 } else { 0 } as Field);\n\n fields.extend_from_array(self.max_block_number.serialize());\n\n for i in 0..self.note_hash_read_requests.len() {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..self.nullifier_read_requests.len() {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..self.key_validation_requests_and_generators.len() {\n fields.extend_from_array(self.key_validation_requests_and_generators[i].serialize());\n }\n for i in 0..self.new_note_hashes.len() {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..self.new_nullifiers.len() {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..self.private_call_requests.len() {\n fields.extend_from_array(self.private_call_requests[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n fields.push(self.public_teardown_function_hash);\n for i in 0..self.new_l2_to_l1_msgs.len() {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n for i in 0..self.note_encrypted_logs_hashes.len() {\n fields.extend_from_array(self.note_encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.encrypted_logs_hashes.len() {\n fields.extend_from_array(self.encrypted_logs_hashes[i].serialize());\n }\n for i in 0..self.unencrypted_logs_hashes.len() {\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.tx_context.serialize());\n\n assert_eq(fields.len(), PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCircuitPublicInputs {\n fn deserialize(serialized: [Field; PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = Self {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n min_revertible_side_effect_counter: reader.read() as u32,\n is_fee_payer: reader.read() == 1,\n max_block_number: reader.read_struct(MaxBlockNumber::deserialize),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n key_validation_requests_and_generators: reader.read_struct_array(KeyValidationRequestAndGenerator::deserialize, [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n private_call_requests: reader.read_struct_array(PrivateCallRequest::deserialize, [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n public_teardown_function_hash: reader.read(),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n note_encrypted_logs_hashes: reader.read_struct_array(NoteLogHash::deserialize, [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL]),\n encrypted_logs_hashes: reader.read_struct_array(EncryptedLogHash::deserialize, [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]),\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n tx_context: reader.read_struct(TxContext::deserialize),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PrivateCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PrivateCircuitPublicInputs {\n fn empty() -> Self {\n PrivateCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n key_validation_requests_and_generators: [KeyValidationRequestAndGenerator::empty(); MAX_KEY_VALIDATION_REQUESTS_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n private_call_requests: [PrivateCallRequest::empty(); MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter : 0 as u32,\n end_side_effect_counter : 0 as u32,\n note_encrypted_logs_hashes: [NoteLogHash::empty(); MAX_NOTE_ENCRYPTED_LOGS_PER_CALL],\n encrypted_logs_hashes: [EncryptedLogHash::empty(); MAX_ENCRYPTED_LOGS_PER_CALL],\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n tx_context: TxContext::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PrivateCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PrivateCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PrivateCircuitPublicInputs::empty();\n let hash = inputs.hash();\n // Value from private_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x1970bf189adc837d1769f9f44a8b55c97d45690e7744859b71b647e808ee8622;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"170":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/global_variables.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::{AztecAddress, EthAddress}, abis::gas_fees::GasFees,\n constants::{GENERATOR_INDEX__GLOBAL_VARIABLES, GLOBAL_VARIABLES_LENGTH},\n traits::{Deserialize, Empty, Hash, Serialize}, utils::reader::Reader\n};\n\n// docs:start:global-variables\nstruct GlobalVariables {\n chain_id : Field,\n version : Field,\n block_number : Field,\n timestamp : u64,\n coinbase : EthAddress,\n fee_recipient : AztecAddress,\n gas_fees : GasFees\n}\n// docs:end:global-variables\n\nimpl GlobalVariables {\n fn is_empty(self) -> bool {\n (self.chain_id == 0)\n & (self.version == 0)\n & (self.block_number == 0)\n & (self.timestamp == 0)\n & (self.coinbase.is_zero())\n & (self.fee_recipient.is_zero())\n & (self.gas_fees.is_empty())\n }\n}\n\nimpl Serialize for GlobalVariables {\n fn serialize(self) -> [Field; GLOBAL_VARIABLES_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.chain_id);\n serialized.push(self.version);\n serialized.push(self.block_number);\n serialized.push(self.timestamp as Field);\n serialized.push(self.coinbase.to_field());\n serialized.push(self.fee_recipient.to_field());\n serialized.extend_from_array(self.gas_fees.serialize());\n\n serialized.storage\n }\n}\n\nimpl Deserialize for GlobalVariables {\n fn deserialize(serialized: [Field; GLOBAL_VARIABLES_LENGTH]) -> GlobalVariables {\n let mut reader = Reader::new(serialized);\n GlobalVariables {\n chain_id: reader.read(),\n version: reader.read(),\n block_number: reader.read(),\n timestamp: reader.read() as u64,\n coinbase: EthAddress::from_field(reader.read()),\n fee_recipient: AztecAddress::from_field(reader.read()),\n gas_fees: reader.read_struct(GasFees::deserialize)\n }\n }\n}\n\nimpl Eq for GlobalVariables {\n fn eq(self, other : GlobalVariables) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.block_number == other.block_number) &\n (self.timestamp == other.timestamp) &\n (self.coinbase == other.coinbase) &\n (self.fee_recipient == other.fee_recipient) &\n (self.gas_fees == other.gas_fees) \n }\n}\n\nimpl Empty for GlobalVariables {\n fn empty() -> Self {\n Self {\n chain_id: 0,\n version: 0,\n block_number: 0,\n timestamp: 0,\n coinbase: EthAddress::empty(),\n fee_recipient: AztecAddress::empty(),\n gas_fees: GasFees::empty()\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let vars = GlobalVariables::empty();\n let _serialized = vars.serialize();\n let _deserialized = GlobalVariables::deserialize(_serialized);\n}\n"},"171":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/read_request.nr","source":"use crate::{\n abis::side_effect::{Ordered, Scoped}, traits::{Empty, Serialize, Deserialize},\n address::AztecAddress, constants::{READ_REQUEST_LENGTH, SCOPED_READ_REQUEST_LEN},\n utils::{arrays::array_concat, reader::Reader}\n};\nuse dep::std::cmp::Eq;\n\nstruct ReadRequest {\n value: Field,\n counter: u32,\n}\n\nimpl Ordered for ReadRequest {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for ReadRequest {\n fn eq(self, read_request: ReadRequest) -> bool {\n (self.value == read_request.value)\n & (self.counter == read_request.counter)\n }\n}\n\nimpl Empty for ReadRequest {\n fn empty() -> Self {\n ReadRequest {\n value: 0,\n counter: 0,\n }\n }\n}\n\nimpl Serialize for ReadRequest {\n fn serialize(self) -> [Field; READ_REQUEST_LENGTH] {\n [self.value, self.counter as Field]\n }\n}\n\nimpl Deserialize for ReadRequest {\n fn deserialize(values: [Field; READ_REQUEST_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n }\n }\n}\n\nimpl ReadRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedReadRequest {\n ScopedReadRequest { read_request: self, contract_address }\n }\n}\n\nstruct ScopedReadRequest {\n read_request: ReadRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedReadRequest {\n fn inner(self) -> ReadRequest {\n self.read_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Eq for ScopedReadRequest {\n fn eq(self, other: ScopedReadRequest) -> bool {\n (self.read_request == other.read_request)\n & (self.contract_address.eq(other.contract_address))\n }\n}\n\nimpl Empty for ScopedReadRequest {\n fn empty() -> Self {\n ScopedReadRequest {\n read_request: ReadRequest::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedReadRequest {\n fn serialize(self) -> [Field; SCOPED_READ_REQUEST_LEN] {\n array_concat(self.read_request.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedReadRequest {\n fn deserialize(values: [Field; SCOPED_READ_REQUEST_LEN]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n read_request: reader.read_struct(ReadRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl ScopedReadRequest {\n pub fn value(self) -> Field {\n self.read_request.value\n }\n pub fn counter(self) -> u32 {\n self.read_request.counter\n }\n}\n\n#[test]\nfn serialization_of_empty_read() {\n let item = ReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedReadRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedReadRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"174":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request_and_generator.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n address::AztecAddress,\n abis::validation_requests::{\n key_validation_request::KeyValidationRequest,\n scoped_key_validation_request_and_generator::ScopedKeyValidationRequestAndGenerator\n},\n constants::KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH, traits::{Empty, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct KeyValidationRequestAndGenerator {\n request: KeyValidationRequest,\n sk_app_generator: Field,\n}\n\nimpl Eq for KeyValidationRequestAndGenerator {\n fn eq(self, other: KeyValidationRequestAndGenerator) -> bool {\n (self.request == other.request) & (self.sk_app_generator == other.sk_app_generator)\n }\n}\n\nimpl Empty for KeyValidationRequestAndGenerator {\n fn empty() -> Self {\n KeyValidationRequestAndGenerator {\n request: KeyValidationRequest::empty(),\n sk_app_generator: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequestAndGenerator {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH] {\n array_concat(self.request.serialize(), [self.sk_app_generator])\n }\n}\n\nimpl Deserialize for KeyValidationRequestAndGenerator {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_AND_GENERATOR_LENGTH]) -> Self {\n let mut reader = Reader::new(fields);\n let res = Self {\n request: reader.read_struct(KeyValidationRequest::deserialize),\n sk_app_generator: reader.read(),\n };\n reader.finish();\n res\n }\n}\n\nimpl KeyValidationRequestAndGenerator {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedKeyValidationRequestAndGenerator {\n ScopedKeyValidationRequestAndGenerator { request: self, contract_address }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = KeyValidationRequestAndGenerator::empty();\n let serialized = item.serialize();\n let deserialized = KeyValidationRequestAndGenerator::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"175":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/validation_requests/key_validation_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n constants::KEY_VALIDATION_REQUEST_LENGTH, traits::{Empty, Serialize, Deserialize},\n grumpkin_point::GrumpkinPoint\n};\n\nstruct KeyValidationRequest {\n pk_m: GrumpkinPoint,\n sk_app: Field, // not a grumpkin scalar because it's output of poseidon2\n}\n\nimpl Eq for KeyValidationRequest {\n fn eq(self, request: KeyValidationRequest) -> bool {\n (request.pk_m.eq(self.pk_m))\n & (request.sk_app.eq(self.sk_app))\n }\n}\n\nimpl Empty for KeyValidationRequest {\n fn empty() -> Self {\n KeyValidationRequest {\n pk_m: GrumpkinPoint::zero(),\n sk_app: 0,\n }\n }\n}\n\nimpl Serialize for KeyValidationRequest {\n fn serialize(self) -> [Field; KEY_VALIDATION_REQUEST_LENGTH] {\n [\n self.pk_m.x,\n self.pk_m.y,\n self.sk_app,\n ]\n }\n}\n\nimpl Deserialize for KeyValidationRequest {\n fn deserialize(fields: [Field; KEY_VALIDATION_REQUEST_LENGTH]) -> Self {\n Self {\n pk_m: GrumpkinPoint::new(fields[0], fields[1]),\n sk_app: fields[2],\n }\n }\n}\n\n"},"179":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/nullifier.nr","source":"use crate::{\n abis::{side_effect::{Ordered, OrderedValue, Readable, Scoped}, read_request::ScopedReadRequest},\n address::AztecAddress, constants::{NULLIFIER_LENGTH, SCOPED_NULLIFIER_LENGTH},\n hash::compute_siloed_nullifier, traits::{Empty, Hash, Serialize, Deserialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct Nullifier {\n value: Field,\n counter: u32,\n note_hash: Field,\n}\n\nimpl Ordered for Nullifier {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for Nullifier {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for Nullifier {\n fn eq(self, other: Nullifier) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.note_hash == other.note_hash) \n }\n}\n\nimpl Empty for Nullifier {\n fn empty() -> Self {\n Nullifier {\n value: 0,\n counter: 0,\n note_hash: 0,\n }\n }\n}\n\nimpl Serialize for Nullifier {\n fn serialize(self) -> [Field; NULLIFIER_LENGTH] {\n [self.value, self.counter as Field, self.note_hash]\n }\n}\n\nimpl Deserialize for Nullifier {\n fn deserialize(values: [Field; NULLIFIER_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n note_hash: values[2],\n }\n }\n}\n\nimpl Readable for Nullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n // Public kernels output Nullifier instead of ScopedNullifier.\n // The nullifier value has been siloed.\n let siloed_request_value = compute_siloed_nullifier(read_request.contract_address, read_request.value());\n assert_eq(self.value, siloed_request_value, \"Value of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl Nullifier {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedNullifier {\n ScopedNullifier { nullifier: self, contract_address }\n }\n}\n\nstruct ScopedNullifier {\n nullifier: Nullifier,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedNullifier {\n fn inner(self) -> Nullifier {\n self.nullifier\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedNullifier {\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl OrderedValue for ScopedNullifier {\n fn value(self) -> Field {\n self.nullifier.value\n }\n fn counter(self) -> u32 {\n self.nullifier.counter\n }\n}\n\nimpl Eq for ScopedNullifier {\n fn eq(self, other: ScopedNullifier) -> bool {\n (self.nullifier == other.nullifier)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedNullifier {\n fn empty() -> Self {\n ScopedNullifier {\n nullifier: Nullifier::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedNullifier {\n fn serialize(self) -> [Field; SCOPED_NULLIFIER_LENGTH] {\n array_concat(self.nullifier.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedNullifier {\n fn deserialize(values: [Field; SCOPED_NULLIFIER_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n nullifier: reader.read_struct(Nullifier::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nimpl Readable for ScopedNullifier {\n fn assert_match_read_request(self, read_request: ScopedReadRequest) {\n assert_eq(self.nullifier.value, read_request.value(), \"Value of the nullifier does not match read request\");\n assert_eq(self.contract_address, read_request.contract_address, \"Contract address of the nullifier does not match read request\");\n assert(\n read_request.counter() > self.nullifier.counter, \"Read request counter must be greater than the counter of the nullifier\"\n );\n }\n}\n\nimpl ScopedNullifier {\n pub fn nullified_note_hash(self) -> Field {\n self.nullifier.note_hash\n }\n\n pub fn expose_to_public(self) -> Nullifier {\n // Hide the actual counter and note hash when exposing it to the public kernel.\n Nullifier { value: self.nullifier.value, counter: 0, note_hash: 0 }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = Nullifier::empty();\n let serialized = item.serialize();\n let deserialized = Nullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped() {\n let item = ScopedNullifier::empty();\n let serialized = item.serialize();\n let deserialized = ScopedNullifier::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"188":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_selector.nr","source":"use crate::utils::field::field_from_bytes;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Serialize, Deserialize, FromField, ToField, Empty};\n\nglobal SELECTOR_SIZE = 4;\n\nstruct FunctionSelector {\n // 1st 4-bytes of abi-encoding of function.\n inner: u32,\n}\n\nimpl Eq for FunctionSelector {\n fn eq(self, function_selector: FunctionSelector) -> bool {\n function_selector.inner == self.inner\n }\n}\n\nimpl Serialize<1> for FunctionSelector {\n fn serialize(self: Self) -> [Field; 1] {\n [self.inner as Field]\n }\n}\n\nimpl Deserialize<1> for FunctionSelector {\n fn deserialize(fields: [Field; 1]) -> Self {\n Self {\n inner: fields[0] as u32\n }\n }\n}\n\nimpl FromField for FunctionSelector {\n fn from_field(field: Field) -> Self {\n Self { inner: field as u32 }\n }\n}\n\nimpl ToField for FunctionSelector {\n fn to_field(self) -> Field {\n self.inner as Field\n }\n}\n\nimpl Empty for FunctionSelector {\n fn empty() -> Self {\n Self { inner: 0 as u32 }\n }\n}\n\nimpl FunctionSelector {\n pub fn from_u32(value: u32) -> Self {\n Self { inner: value }\n }\n\n pub fn from_signature(signature: str) -> Self {\n let bytes = signature.as_bytes();\n let hash = dep::std::hash::keccak256(bytes, bytes.len() as u32);\n\n let mut selector_be_bytes = [0; SELECTOR_SIZE];\n for i in 0..SELECTOR_SIZE {\n selector_be_bytes[i] = hash[i];\n }\n\n FunctionSelector::from_field(field_from_bytes(selector_be_bytes, true))\n }\n\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n}\n"},"189":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_request.nr","source":"use dep::std::cmp::Eq;\nuse crate::{\n abis::{caller_context::CallerContext, side_effect::{Ordered, RangeOrdered, Scoped}},\n address::AztecAddress, constants::{PRIVATE_CALL_REQUEST_LENGTH, SCOPED_PRIVATE_CALL_REQUEST_LENGTH},\n traits::{Empty, Serialize, Deserialize}, utils::reader::Reader\n};\n\nstruct PrivateCallRequest {\n hash: Field,\n caller_context: CallerContext,\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n}\n\nimpl Ordered for PrivateCallRequest {\n fn counter(self) -> u32 {\n self.start_side_effect_counter\n }\n}\n\nimpl RangeOrdered for PrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.start_side_effect_counter\n }\n fn counter_end(self) -> u32 {\n self.end_side_effect_counter\n }\n}\n\nimpl Eq for PrivateCallRequest {\n fn eq(self, other: PrivateCallRequest) -> bool {\n (self.hash == other.hash)\n & (self.caller_context == other.caller_context)\n & (self.start_side_effect_counter == other.start_side_effect_counter)\n & (self.end_side_effect_counter == other.end_side_effect_counter)\n }\n}\n\nimpl Empty for PrivateCallRequest {\n fn empty() -> Self {\n PrivateCallRequest {\n hash: 0,\n caller_context: CallerContext::empty(),\n start_side_effect_counter: 0,\n end_side_effect_counter: 0,\n }\n }\n}\n\nimpl Serialize for PrivateCallRequest {\n fn serialize(self) -> [Field; PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.hash);\n fields.extend_from_array(self.caller_context.serialize());\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n assert_eq(fields.len(), PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallRequest {\n fn deserialize(fields: [Field; PRIVATE_CALL_REQUEST_LENGTH]) -> PrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = PrivateCallRequest {\n hash: reader.read(),\n caller_context: reader.read_struct(CallerContext::deserialize),\n start_side_effect_counter: reader.read_u32(),\n end_side_effect_counter: reader.read_u32(),\n };\n reader.finish();\n item\n }\n}\n\nimpl PrivateCallRequest {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedPrivateCallRequest {\n ScopedPrivateCallRequest { call_request: self, contract_address }\n }\n}\n\nstruct ScopedPrivateCallRequest {\n call_request: PrivateCallRequest,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedPrivateCallRequest {\n fn inner(self) -> PrivateCallRequest {\n self.call_request\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedPrivateCallRequest {\n fn counter(self) -> u32 {\n self.call_request.counter_start()\n }\n}\n\nimpl RangeOrdered for ScopedPrivateCallRequest {\n fn counter_start(self) -> u32 {\n self.call_request.counter_start()\n }\n fn counter_end(self) -> u32 {\n self.call_request.counter_end()\n }\n}\n\nimpl Eq for ScopedPrivateCallRequest {\n fn eq(self, other: ScopedPrivateCallRequest) -> bool {\n (self.call_request == other.call_request)\n & (self.contract_address == other.contract_address)\n }\n}\n\nimpl Empty for ScopedPrivateCallRequest {\n fn empty() -> Self {\n ScopedPrivateCallRequest {\n call_request: PrivateCallRequest::empty(),\n contract_address: AztecAddress::zero(),\n }\n }\n}\n\nimpl Serialize for ScopedPrivateCallRequest {\n fn serialize(self) -> [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.call_request.serialize());\n fields.extend_from_array(self.contract_address.serialize());\n\n assert_eq(fields.len(), SCOPED_PRIVATE_CALL_REQUEST_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ScopedPrivateCallRequest {\n fn deserialize(fields: [Field; SCOPED_PRIVATE_CALL_REQUEST_LENGTH]) -> ScopedPrivateCallRequest {\n let mut reader = Reader::new(fields);\n let item = ScopedPrivateCallRequest {\n call_request: reader.read_struct(PrivateCallRequest::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = ScopedPrivateCallRequest::empty();\n let serialized = item.serialize();\n let deserialized = ScopedPrivateCallRequest::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"194":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/gas_settings.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress}, abis::gas::Gas,\n abis::gas_fees::GasFees,\n constants::{\n GAS_SETTINGS_LENGTH, DEFAULT_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_INCLUSION_FEE\n},\n hash::pedersen_hash, traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n utils::reader::Reader\n};\n\nstruct GasSettings {\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field,\n}\n\nimpl GasSettings {\n pub fn new(\n gas_limits: Gas,\n teardown_gas_limits: Gas,\n max_fees_per_gas: GasFees,\n inclusion_fee: Field\n ) -> Self {\n Self { gas_limits, teardown_gas_limits, max_fees_per_gas, inclusion_fee }\n }\n\n pub fn default() -> Self {\n GasSettings::new(\n Gas::new(DEFAULT_GAS_LIMIT, DEFAULT_GAS_LIMIT),\n Gas::new(DEFAULT_TEARDOWN_GAS_LIMIT, DEFAULT_TEARDOWN_GAS_LIMIT),\n GasFees::new(DEFAULT_MAX_FEE_PER_GAS, DEFAULT_MAX_FEE_PER_GAS),\n DEFAULT_INCLUSION_FEE\n )\n }\n}\n\nimpl Eq for GasSettings {\n fn eq(self, other: Self) -> bool {\n (self.gas_limits == other.gas_limits) & (self.teardown_gas_limits == other.teardown_gas_limits) & (self.max_fees_per_gas == other.max_fees_per_gas) & (self.inclusion_fee == other.inclusion_fee)\n }\n}\n\nimpl Empty for GasSettings {\n fn empty() -> Self {\n GasSettings::new(\n Gas::empty(), Gas::empty(), GasFees::empty(), 0\n )\n }\n}\n\nimpl Serialize for GasSettings {\n fn serialize(self) -> [Field; GAS_SETTINGS_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.extend_from_array(self.gas_limits.serialize());\n serialized.extend_from_array(self.teardown_gas_limits.serialize());\n serialized.extend_from_array(self.max_fees_per_gas.serialize());\n serialized.push(self.inclusion_fee);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for GasSettings {\n fn deserialize(serialized: [Field; GAS_SETTINGS_LENGTH]) -> GasSettings {\n let mut reader = Reader::new(serialized);\n GasSettings::new(reader.read_struct(Gas::deserialize), reader.read_struct(Gas::deserialize), reader.read_struct(GasFees::deserialize), reader.read())\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = GasSettings::empty();\n let serialized = item.serialize();\n let deserialized = GasSettings::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"203":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr","source":"use crate::{\n abis::{function_data::FunctionData, private_circuit_public_inputs::PrivateCircuitPublicInputs},\n address::AztecAddress,\n constants::{GENERATOR_INDEX__CALL_STACK_ITEM, PRIVATE_CALL_STACK_ITEM_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader\n};\n\nstruct PrivateCallStackItem {\n // This is the _actual_ contract address relating to where this function's code resides in the\n // contract tree. Regardless of whether this is a call or delegatecall, this\n // `contract_address` _does not change_. Amongst other things, it's used as a lookup for\n // getting the correct code from the tree. There is a separate `storage_contract_address`\n // within a CallStackItem which varies depending on whether this is a call or delegatecall.\n contract_address: AztecAddress,\n function_data: FunctionData,\n public_inputs: PrivateCircuitPublicInputs,\n}\n\nimpl Eq for PrivateCallStackItem {\n fn eq(self, other: Self) -> bool {\n self.contract_address.eq(other.contract_address) &\n self.function_data.eq(other.function_data) &\n self.public_inputs.eq(other.public_inputs)\n }\n}\n\nimpl Serialize for PrivateCallStackItem {\n fn serialize(self) -> [Field; PRIVATE_CALL_STACK_ITEM_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.contract_address.to_field());\n fields.extend_from_array(self.function_data.serialize());\n fields.extend_from_array(self.public_inputs.serialize());\n\n assert_eq(fields.len(), PRIVATE_CALL_STACK_ITEM_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for PrivateCallStackItem {\n fn deserialize(serialized: [Field; PRIVATE_CALL_STACK_ITEM_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let item = Self {\n contract_address: reader.read_struct(AztecAddress::deserialize),\n function_data: reader.read_struct(FunctionData::deserialize),\n public_inputs: reader.read_struct(PrivateCircuitPublicInputs::deserialize),\n };\n\n reader.finish();\n item\n }\n}\n\nimpl Hash for PrivateCallStackItem {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_STACK_ITEM)\n }\n}\n\nimpl Empty for PrivateCallStackItem {\n fn empty() -> Self {\n PrivateCallStackItem {\n contract_address: AztecAddress::empty(),\n function_data: FunctionData::empty(),\n public_inputs: PrivateCircuitPublicInputs::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = PrivateCallStackItem::empty();\n let serialized = item.serialize();\n let deserialized = PrivateCallStackItem::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let mut item = PrivateCallStackItem::empty();\n item.function_data.is_private = true;\n let hash = item.hash();\n\n // Value from private_call_stack_item.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x22786e4f971661d2e49095e6b038e5170bc47b795253916d5657c4bdd1df50bf;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"204":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/caller_context.nr","source":"use crate::address::AztecAddress;\nuse dep::std::cmp::Eq;\nuse crate::traits::{Empty, Serialize, Deserialize};\nuse crate::constants::CALLER_CONTEXT_LENGTH;\nuse crate::utils::reader::Reader;\n\nstruct CallerContext {\n msg_sender: AztecAddress,\n storage_contract_address: AztecAddress,\n is_static_call: bool,\n}\n\nimpl Eq for CallerContext {\n fn eq(self, other: CallerContext) -> bool {\n other.msg_sender.eq(self.msg_sender)\n & other.storage_contract_address.eq(self.storage_contract_address)\n & other.is_static_call == self.is_static_call\n }\n}\n\nimpl Empty for CallerContext {\n fn empty() -> Self {\n CallerContext {\n msg_sender: AztecAddress::zero(),\n storage_contract_address: AztecAddress::zero(),\n is_static_call: false,\n }\n }\n}\n\nimpl CallerContext {\n pub fn is_empty(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero() & !self.is_static_call\n }\n\n // Different to an empty context, a hidden context won't reveal the caller's msg_sender and storage_contract_address,\n // but will still propagate the is_static_call flag.\n pub fn is_hidden(self) -> bool {\n self.msg_sender.is_zero() & self.storage_contract_address.is_zero()\n }\n}\n\nimpl Serialize for CallerContext {\n fn serialize(self) -> [Field; CALLER_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.msg_sender.serialize());\n fields.extend_from_array(self.storage_contract_address.serialize());\n fields.push(self.is_static_call as Field);\n\n assert_eq(fields.len(), CALLER_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for CallerContext {\n fn deserialize(fields: [Field; CALLER_CONTEXT_LENGTH]) -> CallerContext {\n let mut reader = Reader::new(fields);\n\n let item = CallerContext {\n msg_sender: reader.read_struct(AztecAddress::deserialize),\n storage_contract_address: reader.read_struct(AztecAddress::deserialize),\n is_static_call: reader.read_bool(),\n };\n reader.finish();\n item\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = CallerContext::empty();\n let serialized = item.serialize();\n let deserialized = CallerContext::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"206":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/log_hash.nr","source":"use crate::{\n abis::side_effect::{Ordered, OrderedValue, Scoped}, address::AztecAddress,\n constants::{\n LOG_HASH_LENGTH, NOTE_LOG_HASH_LENGTH, ENCRYPTED_LOG_HASH_LENGTH, SCOPED_LOG_HASH_LENGTH,\n SCOPED_ENCRYPTED_LOG_HASH_LENGTH\n},\n traits::{Empty, Serialize, Deserialize}, utils::{arrays::array_concat, reader::Reader}\n};\n\nstruct LogHash {\n value: Field,\n counter: u32,\n length: Field,\n}\n\nimpl Ordered for LogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for LogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for LogHash {\n fn eq(self, other: LogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n }\n}\n\nimpl Empty for LogHash {\n fn empty() -> Self {\n LogHash {\n value: 0,\n counter: 0,\n length: 0,\n }\n }\n}\n\nimpl Serialize for LogHash {\n fn serialize(self) -> [Field; LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length]\n }\n}\n\nimpl Deserialize for LogHash {\n fn deserialize(values: [Field; LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n }\n }\n}\n\nimpl LogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedLogHash {\n ScopedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedLogHash {\n log_hash: LogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedLogHash {\n fn inner(self) -> LogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedLogHash {\n fn eq(self, other: ScopedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedLogHash {\n fn empty() -> Self {\n ScopedLogHash {\n log_hash: LogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedLogHash {\n fn serialize(self) -> [Field; SCOPED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedLogHash {\n fn deserialize(values: [Field; SCOPED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(LogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct EncryptedLogHash {\n value: Field,\n counter: u32,\n length: Field,\n randomness: Field,\n}\n\nimpl Ordered for EncryptedLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for EncryptedLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for EncryptedLogHash {\n fn eq(self, other: EncryptedLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.randomness == other.randomness) \n }\n}\n\nimpl Empty for EncryptedLogHash {\n fn empty() -> Self {\n EncryptedLogHash {\n value: 0,\n counter: 0,\n length: 0,\n randomness: 0,\n }\n }\n}\n\nimpl Serialize for EncryptedLogHash {\n fn serialize(self) -> [Field; ENCRYPTED_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.randomness]\n }\n}\n\nimpl Deserialize for EncryptedLogHash {\n fn deserialize(values: [Field; ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n randomness: values[3],\n }\n }\n}\n\nimpl EncryptedLogHash {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedEncryptedLogHash {\n ScopedEncryptedLogHash { log_hash: self, contract_address }\n }\n}\n\nstruct ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedEncryptedLogHash {\n fn inner(self) -> EncryptedLogHash {\n self.log_hash\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl ScopedEncryptedLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the secret randomness and counter when exposing to public\n // Expose as a LogHash rather than EncryptedLogHash to avoid bringing an unnec. 0 value around\n // The log hash will already be silo'd when we call this\n LogHash { value: self.log_hash.value, counter: 0, length: self.log_hash.length }\n }\n}\n\nimpl Ordered for ScopedEncryptedLogHash {\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl OrderedValue for ScopedEncryptedLogHash {\n fn value(self) -> Field {\n self.log_hash.value\n }\n fn counter(self) -> u32 {\n self.log_hash.counter\n }\n}\n\nimpl Eq for ScopedEncryptedLogHash {\n fn eq(self, other: ScopedEncryptedLogHash) -> bool {\n (self.log_hash == other.log_hash)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedEncryptedLogHash {\n fn empty() -> Self {\n ScopedEncryptedLogHash {\n log_hash: EncryptedLogHash::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedEncryptedLogHash {\n fn serialize(self) -> [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH] {\n array_concat(self.log_hash.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedEncryptedLogHash {\n fn deserialize(values: [Field; SCOPED_ENCRYPTED_LOG_HASH_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n log_hash: reader.read_struct(EncryptedLogHash::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\nstruct NoteLogHash {\n value: Field,\n counter: u32,\n length: Field,\n note_hash_counter: u32,\n}\n\nimpl NoteLogHash {\n pub fn expose_to_public(self) -> LogHash {\n // Hide the actual counter and note hash counter when exposing it to the public kernel.\n // The counter is usually note_hash.counter + 1, so it can be revealing.\n // Expose as a LogHash rather than NoteLogHash to avoid bringing an unnec. 0 value around\n LogHash { value: self.value, counter: 0, length: self.length }\n }\n}\n\nimpl Ordered for NoteLogHash {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl OrderedValue for NoteLogHash {\n fn value(self) -> Field {\n self.value\n }\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Eq for NoteLogHash {\n fn eq(self, other: NoteLogHash) -> bool {\n (self.value == other.value)\n & (self.counter == other.counter)\n & (self.length == other.length) \n & (self.note_hash_counter == other.note_hash_counter) \n }\n}\n\nimpl Empty for NoteLogHash {\n fn empty() -> Self {\n NoteLogHash {\n value: 0,\n counter: 0,\n length: 0,\n note_hash_counter: 0,\n }\n }\n}\n\nimpl Serialize for NoteLogHash {\n fn serialize(self) -> [Field; NOTE_LOG_HASH_LENGTH] {\n [self.value, self.counter as Field, self.length, self.note_hash_counter as Field]\n }\n}\n\nimpl Deserialize for NoteLogHash {\n fn deserialize(values: [Field; NOTE_LOG_HASH_LENGTH]) -> Self {\n Self {\n value: values[0],\n counter: values[1] as u32,\n length: values[2],\n note_hash_counter: values[3] as u32,\n }\n }\n}\n"},"209":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/append_only_tree_snapshot.nr","source":"use dep::std::cmp::Eq;\n\nstruct AppendOnlyTreeSnapshot {\n root : Field,\n // TODO(Alvaro) change this to a u64\n next_available_leaf_index : u32\n}\n\nglobal APPEND_ONLY_TREE_SNAPSHOT_LENGTH: u32 = 2;\n\nimpl AppendOnlyTreeSnapshot {\n pub fn serialize(self) -> [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH] {\n [self.root, self.next_available_leaf_index as Field]\n }\n\n pub fn deserialize(serialized: [Field; APPEND_ONLY_TREE_SNAPSHOT_LENGTH]) -> AppendOnlyTreeSnapshot {\n AppendOnlyTreeSnapshot { root: serialized[0], next_available_leaf_index: serialized[1] as u32 }\n }\n\n pub fn zero() -> Self {\n Self { root: 0, next_available_leaf_index: 0 }\n }\n}\n\nimpl Eq for AppendOnlyTreeSnapshot {\n fn eq(self, other : AppendOnlyTreeSnapshot) -> bool {\n (self.root == other.root) & (self.next_available_leaf_index == other.next_available_leaf_index)\n }\n}\n"},"210":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/call_context.nr","source":"use crate::{\n abis::function_selector::FunctionSelector, address::{EthAddress, AztecAddress},\n constants::{CALL_CONTEXT_LENGTH, GENERATOR_INDEX__CALL_CONTEXT}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, abis::side_effect::Ordered,\n abis::{gas_settings::GasSettings, gas::Gas}, utils::reader::Reader\n};\n\n// docs:start:call-context\nstruct CallContext {\n msg_sender : AztecAddress,\n storage_contract_address : AztecAddress,\n function_selector : FunctionSelector,\n\n is_delegate_call : bool,\n is_static_call : bool,\n\n side_effect_counter : u32,\n}\n// docs:end:call-context\n\nimpl CallContext {\n fn assert_is_zero(self) {\n let serialized: [Field; CALL_CONTEXT_LENGTH] = self.serialize();\n\n for i in 0..CALL_CONTEXT_LENGTH {\n assert(serialized[i] == 0);\n }\n }\n}\n\nimpl Eq for CallContext {\n fn eq(self, other: CallContext) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Hash for CallContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__CALL_CONTEXT)\n }\n}\n\nimpl Serialize for CallContext {\n fn serialize(self) -> [Field; CALL_CONTEXT_LENGTH] {\n let mut serialized: BoundedVec = BoundedVec::new();\n\n serialized.push(self.msg_sender.to_field());\n serialized.push(self.storage_contract_address.to_field());\n serialized.push(self.function_selector.to_field());\n serialized.push(self.is_delegate_call as Field);\n serialized.push(self.is_static_call as Field);\n serialized.push(self.side_effect_counter as Field);\n \n serialized.storage\n }\n}\n\nimpl Deserialize for CallContext {\n fn deserialize(serialized: [Field; CALL_CONTEXT_LENGTH]) -> CallContext {\n let mut reader = Reader::new(serialized);\n CallContext {\n msg_sender: AztecAddress::from_field(reader.read()),\n storage_contract_address: AztecAddress::from_field(reader.read()),\n function_selector: FunctionSelector::from_field(reader.read()),\n is_delegate_call: reader.read() as bool,\n is_static_call: reader.read() as bool,\n side_effect_counter: reader.read() as u32,\n }\n }\n}\n\nimpl Empty for CallContext {\n fn empty() -> Self {\n CallContext {\n msg_sender: AztecAddress::empty(),\n storage_contract_address: AztecAddress::empty(),\n function_selector: FunctionSelector::empty(),\n is_delegate_call: false,\n is_static_call: false,\n side_effect_counter: 0,\n }\n }\n}\n\n#[test]\nfn serialize_deserialize_of_empty() {\n let context = CallContext::empty();\n let serialized = context.serialize();\n let deserialized = CallContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn assert_is_zero() {\n let context = CallContext::empty();\n context.assert_is_zero();\n}\n\n#[test(should_fail)]\nfn not_zero_assert_is_zero() {\n let mut context = CallContext::empty();\n context.is_delegate_call = true;\n context.assert_is_zero();\n}\n\n#[test]\nfn test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = true;\n\n let address: AztecAddress = AztecAddress::from_field(69420);\n context1.msg_sender = address;\n context2.msg_sender = address;\n\n assert(context1.eq(context2));\n}\n\n#[test(should_fail)]\nfn not_eq_test_eq() {\n let mut context1 = CallContext::empty();\n let mut context2 = CallContext::empty();\n\n context1.is_delegate_call = true;\n context2.is_delegate_call = false;\n\n let address1: AztecAddress = AztecAddress::from_field(69420);\n let address2: AztecAddress = AztecAddress::from_field(42069);\n\n context1.msg_sender = address1;\n context2.msg_sender = address2;\n\n assert(context1.eq(context2));\n}\n\n#[test]\nfn hash_smoke() {\n let context = CallContext::empty();\n let _hashed = context.hash();\n}\n"},"211":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/max_block_number.nr","source":"use crate::{constants::MAX_BLOCK_NUMBER_LENGTH, traits::{Deserialize, Serialize, Empty}};\n\nstruct MaxBlockNumber {\n _opt: Option\n}\n\nimpl Empty for MaxBlockNumber {\n fn empty() -> Self {\n Self { _opt: Option::none() }\n }\n}\n\nimpl Eq for MaxBlockNumber {\n fn eq(self, other: Self) -> bool {\n self._opt == other._opt\n }\n}\n\nimpl Serialize for MaxBlockNumber {\n fn serialize(self) -> [Field; MAX_BLOCK_NUMBER_LENGTH] {\n [self._opt._is_some as Field, self._opt._value as Field]\n }\n}\n\nimpl Deserialize for MaxBlockNumber {\n fn deserialize(serialized: [Field; MAX_BLOCK_NUMBER_LENGTH]) -> MaxBlockNumber {\n MaxBlockNumber {\n _opt: Option {\n _is_some: serialized[0] as bool,\n _value: serialized[1] as u32,\n }\n }\n }\n}\n\nimpl MaxBlockNumber {\n pub fn new(max_block_number: u32) -> Self {\n Self { _opt: Option::some(max_block_number) }\n }\n\n pub fn is_none(self) -> bool {\n self._opt.is_none()\n }\n\n pub fn is_some(self) -> bool {\n self._opt.is_some()\n }\n\n pub fn unwrap(self) -> u32 {\n self._opt.unwrap()\n }\n\n pub fn unwrap_unchecked(self) -> u32 {\n self._opt.unwrap_unchecked()\n }\n\n pub fn min(lhs: MaxBlockNumber, rhs: MaxBlockNumber) -> MaxBlockNumber {\n if rhs.is_none() {\n lhs // lhs might also be none, but in that case both would be\n } else {\n MaxBlockNumber::min_with_u32(lhs, rhs.unwrap_unchecked())\n }\n }\n\n pub fn min_with_u32(lhs: MaxBlockNumber, rhs: u32) -> MaxBlockNumber {\n if lhs._opt.is_none() {\n MaxBlockNumber::new(rhs)\n } else {\n let lhs_value = lhs._opt.unwrap_unchecked();\n\n MaxBlockNumber::new(if lhs_value < rhs { lhs_value } else { rhs })\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let item = MaxBlockNumber::empty();\n let serialized = item.serialize();\n let deserialized = MaxBlockNumber::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn zeroed_is_none() {\n // Large parts of the kernel rely on zeroed to initialize structs. This conveniently matches what `default` does,\n // and though we should eventually move everything to use `default`, it's good to check for now that both are\n // equivalent.\n let a = MaxBlockNumber::empty();\n assert(a.is_none());\n}\n\n#[test]\nfn serde_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert(b.is_none());\n}\n\n#[test]\nfn serde_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::deserialize(a.serialize());\n assert_eq(b.unwrap(), 13);\n}\n\n#[test(should_fail)]\nfn default_unwrap_panics() {\n let a = MaxBlockNumber::empty();\n let _ = a.unwrap();\n}\n\n#[test]\nfn min_default_default() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::empty();\n\n assert(MaxBlockNumber::min(a, b).is_none());\n}\n\n#[test]\nfn min_default_some() {\n let a = MaxBlockNumber::empty();\n let b = MaxBlockNumber::new(13);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_some_some() {\n let a = MaxBlockNumber::new(13);\n let b = MaxBlockNumber::new(42);\n\n assert_eq(MaxBlockNumber::min(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min(b, a).unwrap(), 13);\n}\n\n#[test]\nfn min_with_u32_default() {\n let a = MaxBlockNumber::empty();\n let b = 42;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 42);\n}\n\n#[test]\nfn min_with_u32_some() {\n let a = MaxBlockNumber::new(13);\n let b = 42;\n let c = 8;\n\n assert_eq(MaxBlockNumber::min_with_u32(a, b).unwrap(), 13);\n assert_eq(MaxBlockNumber::min_with_u32(a, c).unwrap(), 8);\n}\n"},"212":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr","source":"use crate::{\n abis::{\n call_context::CallContext, note_hash::NoteHash, nullifier::Nullifier, read_request::ReadRequest,\n gas::Gas, global_variables::GlobalVariables, log_hash::LogHash\n},\n address::AztecAddress,\n constants::{\n MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL,\n MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL,\n MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL,\n MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL,\n MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS,\n PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, MAX_UNENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message,\n traits::{Hash, Serialize, Deserialize, Empty}, utils::reader::Reader\n};\n\nstruct PublicCircuitPublicInputs {\n call_context: CallContext,\n\n args_hash: Field,\n returns_hash: Field,\n\n note_hash_read_requests: [ReadRequest; MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest; MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest; MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest; MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead; MAX_PUBLIC_DATA_READS_PER_CALL],\n\n // todo: add sideeffect ranges for the input to these hashes\n public_call_stack_hashes: [Field; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash; MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier; MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message; MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n\n start_side_effect_counter: u32,\n end_side_effect_counter: u32,\n\n unencrypted_logs_hashes: [LogHash; MAX_UNENCRYPTED_LOGS_PER_CALL],\n\n // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block\n // previous to the one in which the tx is included.\n historical_header: Header,\n\n // Global variables injected into this circuit\n global_variables: GlobalVariables,\n\n prover_address: AztecAddress,\n\n revert_code: u8,\n \n start_gas_left: Gas,\n end_gas_left: Gas,\n transaction_fee: Field,\n}\n\nimpl Eq for PublicCircuitPublicInputs {\n fn eq(self, other: Self) -> bool {\n self.serialize() == other.serialize()\n }\n}\n\nimpl Serialize for PublicCircuitPublicInputs {\n fn serialize(self) -> [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n fields.extend_from_array(self.call_context.serialize());\n fields.push(self.args_hash);\n fields.push(self.returns_hash);\n for i in 0..MAX_NOTE_HASH_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.note_hash_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_read_requests[i].serialize());\n }\n for i in 0..MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.nullifier_non_existent_read_requests[i].serialize());\n }\n for i in 0..MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL {\n fields.extend_from_array(self.l1_to_l2_msg_read_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL {\n fields.extend_from_array(self.contract_storage_update_requests[i].serialize());\n }\n for i in 0..MAX_PUBLIC_DATA_READS_PER_CALL {\n fields.extend_from_array(self.contract_storage_reads[i].serialize());\n }\n fields.extend_from_array(self.public_call_stack_hashes);\n\n for i in 0..MAX_NEW_NOTE_HASHES_PER_CALL {\n fields.extend_from_array(self.new_note_hashes[i].serialize());\n }\n for i in 0..MAX_NEW_NULLIFIERS_PER_CALL {\n fields.extend_from_array(self.new_nullifiers[i].serialize());\n }\n for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL {\n fields.extend_from_array(self.new_l2_to_l1_msgs[i].serialize());\n }\n\n fields.push(self.start_side_effect_counter as Field);\n fields.push(self.end_side_effect_counter as Field);\n\n for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{\n fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize());\n }\n fields.extend_from_array(self.historical_header.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.prover_address.to_field());\n fields.push(self.revert_code as Field);\n fields.extend_from_array(self.start_gas_left.serialize());\n fields.extend_from_array(self.end_gas_left.serialize());\n fields.push(self.transaction_fee);\n fields.storage\n }\n}\n\nimpl Deserialize for PublicCircuitPublicInputs {\n fn deserialize(serialized: [Field; PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n let inputs = PublicCircuitPublicInputs {\n call_context: reader.read_struct(CallContext::deserialize),\n args_hash: reader.read(),\n returns_hash: reader.read(),\n note_hash_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL]),\n nullifier_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL]),\n nullifier_non_existent_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL]),\n l1_to_l2_msg_read_requests: reader.read_struct_array(ReadRequest::deserialize, [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL]),\n contract_storage_update_requests: reader.read_struct_array(StorageUpdateRequest::deserialize, [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL]),\n contract_storage_reads: reader.read_struct_array(StorageRead::deserialize, [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL]),\n public_call_stack_hashes: reader.read_array([0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL]),\n new_note_hashes: reader.read_struct_array(NoteHash::deserialize, [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL]),\n new_nullifiers: reader.read_struct_array(Nullifier::deserialize, [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL]),\n new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]),\n start_side_effect_counter: reader.read() as u32,\n end_side_effect_counter: reader.read() as u32,\n unencrypted_logs_hashes: reader.read_struct_array(LogHash::deserialize, [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]),\n historical_header: reader.read_struct(Header::deserialize),\n global_variables: reader.read_struct(GlobalVariables::deserialize),\n prover_address: reader.read_struct(AztecAddress::deserialize),\n revert_code: reader.read() as u8,\n start_gas_left: reader.read_struct(Gas::deserialize),\n end_gas_left: reader.read_struct(Gas::deserialize),\n transaction_fee: reader.read(),\n };\n\n reader.finish();\n inputs\n }\n}\n\nimpl Hash for PublicCircuitPublicInputs {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS)\n }\n}\n\nimpl Empty for PublicCircuitPublicInputs {\n fn empty() -> Self {\n PublicCircuitPublicInputs {\n call_context: CallContext::empty(),\n args_hash: 0,\n returns_hash: 0,\n note_hash_read_requests: [ReadRequest::empty(); MAX_NOTE_HASH_READ_REQUESTS_PER_CALL],\n nullifier_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_READ_REQUESTS_PER_CALL],\n nullifier_non_existent_read_requests: [ReadRequest::empty(); MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL],\n l1_to_l2_msg_read_requests: [ReadRequest::empty(); MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL],\n contract_storage_update_requests: [StorageUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL],\n contract_storage_reads: [StorageRead::empty(); MAX_PUBLIC_DATA_READS_PER_CALL],\n public_call_stack_hashes: [0; MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL],\n new_note_hashes: [NoteHash::empty(); MAX_NEW_NOTE_HASHES_PER_CALL],\n new_nullifiers: [Nullifier::empty(); MAX_NEW_NULLIFIERS_PER_CALL],\n new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL],\n start_side_effect_counter: 0 as u32,\n end_side_effect_counter: 0 as u32,\n unencrypted_logs_hashes: [LogHash::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL],\n historical_header: Header::empty(),\n global_variables: GlobalVariables::empty(),\n prover_address: AztecAddress::zero(),\n revert_code: 0 as u8,\n start_gas_left: Gas::empty(),\n end_gas_left: Gas::empty(),\n transaction_fee: 0,\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let pcpi = PublicCircuitPublicInputs::empty();\n let serialized = pcpi.serialize();\n let deserialized = PublicCircuitPublicInputs::deserialize(serialized);\n assert(pcpi.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let inputs = PublicCircuitPublicInputs::empty();\n let hash = inputs.hash();\n\n // Value from public_circuit_public_inputs.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x01681b19fb7fe21aa9c2cf9fb47520149f46edd679b2e7c2b2c4a279fd685125;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"214":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/abis/function_data.nr","source":"use crate::{\n abis::function_selector::FunctionSelector,\n constants::{GENERATOR_INDEX__FUNCTION_DATA, FUNCTION_DATA_LENGTH}, hash::pedersen_hash,\n traits::{Serialize, Hash, Deserialize, Empty}\n};\n\nstruct FunctionData {\n selector : FunctionSelector,\n is_private : bool,\n}\n\nimpl Eq for FunctionData {\n fn eq(self, other: Self) -> bool {\n self.selector.eq(other.selector) &\n (self.is_private == other.is_private)\n }\n}\n\nimpl Serialize for FunctionData {\n // A field is ~256 bits\n // TODO(https://github.com/AztecProtocol/aztec-packages/issues/3057): Since, function data can fit into a Field,\n // This method will simply return a bit packed Field instead of hashing\n fn serialize(self) -> [Field; FUNCTION_DATA_LENGTH] {\n [\n self.selector.to_field(),\n self.is_private as Field,\n ]\n }\n}\n\nimpl Deserialize for FunctionData {\n fn deserialize(serialized: [Field; FUNCTION_DATA_LENGTH]) -> Self {\n Self {\n selector: FunctionSelector::from_field(serialized[0]),\n is_private: serialized[1] as bool,\n }\n }\n}\n\nimpl Hash for FunctionData {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__FUNCTION_DATA)\n }\n}\n\nimpl Empty for FunctionData {\n fn empty() -> Self {\n FunctionData {\n selector: FunctionSelector::empty(),\n is_private: false\n }\n }\n\n}\n\n#[test]\nfn serialization_of_empty() {\n let data = FunctionData::empty();\n let serialized = data.serialize();\n let deserialized = FunctionData::deserialize(serialized);\n assert(data.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let data = FunctionData::empty();\n let hash = data.hash();\n\n // Value from function_data.test.ts \"computes empty function data hash\" test\n let test_data_empty_hash = 0x27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"22":{"path":"std/field.nr","source":"mod bn254;\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n pub fn to_le_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_le_bits(bit_size)\n }\n\n pub fn to_be_bits(self: Self, bit_size: u32) -> [u1] {\n crate::assert_constant(bit_size);\n self.__to_be_bits(bit_size)\n }\n\n #[builtin(to_le_bits)]\n fn __to_le_bits(self, _bit_size: u32) -> [u1] {}\n\n #[builtin(to_be_bits)]\n fn __to_be_bits(self, bit_size: u32) -> [u1] {}\n\n #[builtin(apply_range_constraint)]\n fn __assert_max_bit_size(self, bit_size: u32) {}\n\n pub fn assert_max_bit_size(self: Self, bit_size: u32) {\n crate::assert_constant(bit_size);\n assert(bit_size < modulus_num_bits() as u32);\n self.__assert_max_bit_size(bit_size);\n }\n\n pub fn to_le_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_le_radix(256, byte_size)\n }\n\n pub fn to_be_bytes(self: Self, byte_size: u32) -> [u8] {\n self.to_be_radix(256, byte_size)\n }\n\n pub fn to_le_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_le_radix(radix, result_len)\n }\n\n pub fn to_be_radix(self: Self, radix: u32, result_len: u32) -> [u8] {\n crate::assert_constant(radix);\n crate::assert_constant(result_len);\n self.__to_be_radix(radix, result_len)\n }\n\n // decompose `_self` into a `_result_len` vector over the `_radix` basis\n // `_radix` must be less than 256\n #[builtin(to_le_radix)]\n fn __to_le_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n #[builtin(to_be_radix)]\n fn __to_be_radix(self, radix: u32, result_len: u32) -> [u8] {}\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b = exponent.to_le_bits(32);\n\n for i in 1..33 {\n r *= r;\n r = (b[32-i] as Field) * (r * self) + (1 - b[32-i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x ∈ {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n}\n\n#[builtin(modulus_num_bits)]\npub fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub fn modulus_le_bytes() -> [u8] {}\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n let num_bytes = (modulus_num_bits() as u32 + 7) / 8;\n let x_bytes = x.to_le_bytes(num_bytes);\n let y_bytes = y.to_le_bytes(num_bytes);\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..num_bytes {\n if (!done) {\n let x_byte = x_bytes[num_bytes - 1 - i] as u8;\n let y_byte = y_bytes[num_bytes - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n}\n\n"},"221":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils.nr","source":"// general util packages/modules are usually bad practice\n// because there is no criteria for what we should not put in here.\n// Reducing the size of this package would be welcome.\n\nmod arrays;\nmod field;\nmod reader;\nmod uint256;\n\n// if predicate == true then return lhs, else return rhs\npub fn conditional_assign(predicate: bool, lhs: Field, rhs: Field) -> Field {\n if predicate { lhs } else { rhs }\n}\n\npub fn arr_copy_slice(src: [T; N], mut dst: [T; M], offset: u32) -> [T; M] {\n let iterator_len = if N > M { M } else { N };\n for i in 0..iterator_len {\n dst[i] = src[i + offset];\n }\n dst\n}\n"},"222":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/messaging/l2_to_l1_message.nr","source":"use crate::{\n address::{AztecAddress, EthAddress},\n constants::{L2_TO_L1_MESSAGE_LENGTH, SCOPED_L2_TO_L1_MESSAGE_LENGTH},\n abis::side_effect::{Ordered, Scoped}, traits::{Deserialize, Empty, Serialize},\n utils::{arrays::array_concat, reader::Reader}\n};\n\n// Note: Not to be confused with L2ToL1Msg in Solidity\nstruct L2ToL1Message {\n recipient: EthAddress,\n content: Field,\n counter: u32,\n}\n\nimpl Ordered for L2ToL1Message {\n fn counter(self) -> u32 {\n self.counter\n }\n}\n\nimpl Empty for L2ToL1Message {\n fn empty() -> Self {\n Self {\n recipient: EthAddress::empty(),\n content: 0,\n counter: 0,\n }\n }\n}\n\nimpl Eq for L2ToL1Message {\n fn eq(self, other: Self) -> bool {\n (self.recipient == other.recipient) & (self.content == other.content) & (self.counter == other.counter)\n }\n}\n\nimpl Serialize for L2ToL1Message {\n fn serialize(self) -> [Field; L2_TO_L1_MESSAGE_LENGTH] {\n [self.recipient.to_field(), self.content, self.counter as Field]\n }\n}\n\nimpl Deserialize for L2ToL1Message {\n fn deserialize(values: [Field; L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n Self {\n recipient: EthAddress::from_field(values[0]),\n content: values[1],\n counter: values[2] as u32,\n }\n }\n}\n\nimpl L2ToL1Message {\n pub fn scope(self, contract_address: AztecAddress) -> ScopedL2ToL1Message {\n ScopedL2ToL1Message { message: self, contract_address }\n }\n}\n\nstruct ScopedL2ToL1Message {\n message: L2ToL1Message,\n contract_address: AztecAddress,\n}\n\nimpl Scoped for ScopedL2ToL1Message {\n fn inner(self) -> L2ToL1Message {\n self.message\n }\n fn contract_address(self) -> AztecAddress {\n self.contract_address\n }\n}\n\nimpl Ordered for ScopedL2ToL1Message {\n fn counter(self) -> u32 {\n self.message.counter\n }\n}\n\nimpl Eq for ScopedL2ToL1Message {\n fn eq(self, other: ScopedL2ToL1Message) -> bool {\n (self.message == other.message)\n & (self.contract_address == other.contract_address) \n }\n}\n\nimpl Empty for ScopedL2ToL1Message {\n fn empty() -> Self {\n ScopedL2ToL1Message {\n message: L2ToL1Message::empty(),\n contract_address: AztecAddress::empty(),\n }\n }\n}\n\nimpl Serialize for ScopedL2ToL1Message {\n fn serialize(self) -> [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH] {\n array_concat(self.message.serialize(), [self.contract_address.to_field()])\n }\n}\n\nimpl Deserialize for ScopedL2ToL1Message {\n fn deserialize(values: [Field; SCOPED_L2_TO_L1_MESSAGE_LENGTH]) -> Self {\n let mut reader = Reader::new(values);\n let res = Self {\n message: reader.read_struct(L2ToL1Message::deserialize),\n contract_address: reader.read_struct(AztecAddress::deserialize),\n };\n reader.finish();\n res\n }\n}\n\n#[test]\nfn serialization_of_empty_l2() {\n let item = L2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = L2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n\n#[test]\nfn serialization_of_empty_scoped_l2() {\n let item = ScopedL2ToL1Message::empty();\n let serialized = item.serialize();\n let deserialized = ScopedL2ToL1Message::deserialize(serialized);\n assert(item.eq(deserialized));\n}\n"},"235":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr","source":"use crate::{\n constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct ContentCommitment {\n tx_tree_height: Field,\n txs_effects_hash: Field,\n in_hash: Field,\n out_hash: Field,\n}\n\nimpl Serialize for ContentCommitment {\n fn serialize(self) -> [Field; CONTENT_COMMITMENT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.tx_tree_height);\n fields.push(self.txs_effects_hash);\n fields.push(self.in_hash);\n fields.push(self.out_hash);\n\n fields.storage\n }\n}\n\nimpl Deserialize for ContentCommitment {\n fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self {\n let tx_tree_height = serialized[0];\n\n let txs_effects_hash = serialized[1];\n\n let in_hash = serialized[2];\n\n let out_hash = serialized[3];\n\n Self {\n tx_tree_height,\n txs_effects_hash,\n in_hash,\n out_hash,\n }\n }\n}\n\nimpl Empty for ContentCommitment {\n fn empty() -> Self {\n Self {\n tx_tree_height: 0,\n txs_effects_hash: 0,\n in_hash: 0,\n out_hash: 0,\n }\n }\n}\n\nimpl Eq for ContentCommitment {\n fn eq(self, other: Self) -> bool {\n (self.tx_tree_height == other.tx_tree_height)\n & (self.txs_effects_hash == other.txs_effects_hash)\n & (self.in_hash == other.in_hash)\n & (self.out_hash == other.out_hash)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let empty = ContentCommitment::empty();\n let serialized = empty.serialize();\n let deserialized = ContentCommitment::deserialize(serialized);\n\n assert(empty.eq(deserialized));\n}\n"},"238":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/header.nr","source":"use crate::{\n abis::{\n append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n global_variables::{GlobalVariables, GLOBAL_VARIABLES_LENGTH}\n},\n constants::{GENERATOR_INDEX__BLOCK_HASH, HEADER_LENGTH, STATE_REFERENCE_LENGTH, CONTENT_COMMITMENT_LENGTH},\n hash::pedersen_hash, state_reference::StateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice, content_commitment::ContentCommitment\n};\n\n// docs:start:header\nstruct Header {\n last_archive: AppendOnlyTreeSnapshot,\n content_commitment: ContentCommitment,\n state: StateReference,\n global_variables: GlobalVariables,\n total_fees: Field\n}\n// docs:end:header\n\nimpl Eq for Header {\n fn eq(self, other: Self) -> bool {\n self.last_archive.eq(other.last_archive) &\n self.content_commitment.eq(other.content_commitment) &\n self.state.eq(other.state) &\n self.global_variables.eq(other.global_variables) &\n self.total_fees.eq(other.total_fees)\n }\n}\n\nimpl Serialize for Header {\n fn serialize(self) -> [Field; HEADER_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.last_archive.serialize());\n fields.extend_from_array(self.content_commitment.serialize());\n fields.extend_from_array(self.state.serialize());\n fields.extend_from_array(self.global_variables.serialize());\n fields.push(self.total_fees);\n\n fields.storage\n }\n}\n\nimpl Deserialize for Header {\n fn deserialize(serialized: [Field; HEADER_LENGTH]) -> Self {\n let mut offset = 0;\n\n let last_archive_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let content_commitment_fields = arr_copy_slice(serialized, [0; CONTENT_COMMITMENT_LENGTH], offset);\n offset = offset + CONTENT_COMMITMENT_LENGTH;\n\n let state_fields = arr_copy_slice(serialized, [0; STATE_REFERENCE_LENGTH], offset);\n offset = offset + STATE_REFERENCE_LENGTH;\n\n let global_variables_fields = arr_copy_slice(serialized, [0; GLOBAL_VARIABLES_LENGTH], offset);\n offset = offset + GLOBAL_VARIABLES_LENGTH;\n\n let total_fees = serialized[offset];\n\n Header {\n last_archive: AppendOnlyTreeSnapshot::deserialize(last_archive_fields),\n content_commitment: ContentCommitment::deserialize(content_commitment_fields),\n state: StateReference::deserialize(state_fields),\n global_variables: GlobalVariables::deserialize(global_variables_fields),\n total_fees\n }\n }\n}\n\nimpl Empty for Header {\n fn empty() -> Self {\n Self {\n last_archive: AppendOnlyTreeSnapshot::zero(),\n content_commitment: ContentCommitment::empty(),\n state: StateReference::empty(),\n global_variables: GlobalVariables::empty(),\n total_fees: 0\n }\n }\n}\n\nimpl Hash for Header {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__BLOCK_HASH)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let header = Header::empty();\n let serialized = header.serialize();\n let deserialized = Header::deserialize(serialized);\n assert(header.eq(deserialized));\n}\n\n#[test]\nfn hash_smoke() {\n let header = Header::empty();\n let _hashed = header.hash();\n}\n\n#[test]\nfn empty_hash_is_zero() {\n let header = Header::empty();\n let hash = header.hash();\n\n // Value from new_contract_data.test.ts \"computes empty hash\" test\n let test_data_empty_hash = 0x124e8c40a6eca2e3ad10c04050b01a3fad00df3cea47b13592c7571b6914c7a7;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"239":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr","source":"use crate::{\n abis::{\n contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage,\n function_selector::FunctionSelector, log_hash::{LogHash, ScopedLogHash, ScopedEncryptedLogHash},\n note_hash::ScopedNoteHash, nullifier::ScopedNullifier\n},\n address::{AztecAddress, EthAddress},\n constants::{\n FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER,\n GENERATOR_INDEX__VK, GENERATOR_INDEX__NOTE_HASH_NONCE, GENERATOR_INDEX__UNIQUE_NOTE_HASH,\n MAX_ENCRYPTED_LOGS_PER_TX, MAX_NOTE_ENCRYPTED_LOGS_PER_TX\n},\n contract_class_id::ContractClassId, merkle_tree::root::root_from_sibling_path,\n messaging::l2_to_l1_message::{L2ToL1Message, ScopedL2ToL1Message},\n recursion::verification_key::VerificationKey, traits::{Hash, is_empty},\n utils::{uint256::U256, field::field_from_bytes_32_trunc}\n};\nuse dep::std::hash::{pedersen_hash_with_separator, sha256};\n\npub fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field {\n let sha256_hashed = sha256(bytes_to_hash);\n let hash_in_a_field = field_from_bytes_32_trunc(sha256_hashed);\n\n hash_in_a_field\n}\n\npub fn private_functions_root_from_siblings(\n selector: FunctionSelector,\n vk_hash: Field,\n function_leaf_index: Field,\n function_leaf_sibling_path: [Field; FUNCTION_TREE_HEIGHT]\n) -> Field {\n let function_leaf_preimage = ContractClassFunctionLeafPreimage { selector, vk_hash };\n let function_leaf = function_leaf_preimage.hash();\n root_from_sibling_path(function_leaf, function_leaf_index, function_leaf_sibling_path)\n}\n\npub fn compute_note_hash_nonce(first_nullifier: Field, note_hash_index: u32) -> Field {\n pedersen_hash(\n [\n first_nullifier,\n note_hash_index as Field\n ],\n GENERATOR_INDEX__NOTE_HASH_NONCE\n )\n}\n\npub fn compute_unique_note_hash(nonce: Field, inner_note_hash: Field) -> Field {\n let inputs = [nonce, inner_note_hash];\n pedersen_hash(inputs, GENERATOR_INDEX__UNIQUE_NOTE_HASH)\n}\n\npub fn compute_siloed_note_hash(app: AztecAddress, unique_note_hash: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n unique_note_hash\n ],\n GENERATOR_INDEX__SILOED_NOTE_HASH\n )\n}\n\npub fn silo_note_hash(note_hash: ScopedNoteHash, first_nullifier: Field, index: u32) -> Field {\n if note_hash.contract_address.is_zero() {\n 0\n } else {\n let nonce = compute_note_hash_nonce(first_nullifier, index);\n let unique_note_hash = compute_unique_note_hash(nonce, note_hash.value());\n compute_siloed_note_hash(note_hash.contract_address, unique_note_hash)\n }\n}\n\npub fn compute_siloed_nullifier(app: AztecAddress, nullifier: Field) -> Field {\n pedersen_hash(\n [\n app.to_field(),\n nullifier\n ],\n GENERATOR_INDEX__OUTER_NULLIFIER\n )\n}\n\npub fn silo_nullifier(nullifier: ScopedNullifier) -> Field {\n if nullifier.contract_address.is_zero() {\n nullifier.value() // Return value instead of 0 because the first nullifier's contract address is zero.\n } else {\n compute_siloed_nullifier(nullifier.contract_address, nullifier.value())\n }\n}\n\npub fn compute_siloed_encrypted_log_hash(address: AztecAddress, randomness: Field, log_hash: Field) -> Field {\n // TODO: Using 0 GENERATOR_INDEX here as interim before we move to posiedon\n // NB: A unique separator will be needed for masked_contract_address\n let mut masked_contract_address = pedersen_hash([address.to_field(), randomness], 0);\n if randomness == 0 {\n // In some cases, we actually want to reveal the contract address we are siloing with:\n // e.g. 'handshaking' contract w/ known address\n // An app providing randomness = 0 signals to not mask the address.\n masked_contract_address = address.to_field();\n }\n accumulate_sha256([masked_contract_address, log_hash])\n}\n\npub fn silo_encrypted_log_hash(log_hash: ScopedEncryptedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_encrypted_log_hash(\n log_hash.contract_address,\n log_hash.log_hash.randomness,\n log_hash.log_hash.value\n )\n }\n}\n\npub fn compute_siloed_unencrypted_log_hash(address: AztecAddress, log_hash: Field) -> Field {\n accumulate_sha256([address.to_field(), log_hash])\n}\n\npub fn silo_unencrypted_log_hash(log_hash: ScopedLogHash) -> Field {\n if log_hash.contract_address.is_zero() {\n 0\n } else {\n compute_siloed_unencrypted_log_hash(log_hash.contract_address, log_hash.value())\n }\n}\n\npub fn merkle_hash(left: Field, right: Field) -> Field {\n pedersen_hash([left, right], 0)\n}\n\npub fn stdlib_recursion_verification_key_compress_native_vk(_vk: VerificationKey) -> Field {\n // Original cpp code\n // stdlib::recursion::verification_key::compress_native(private_call.vk, GeneratorIndex::VK);\n // The above cpp method is only ever called on verification key, so it has been special cased here\n let _hash_index = GENERATOR_INDEX__VK;\n 0\n}\n\npub fn compute_l2_to_l1_hash(\n contract_address: AztecAddress,\n recipient: EthAddress,\n content: Field,\n rollup_version_id: Field,\n chain_id: Field\n) -> Field {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n let inputs = [contract_address.to_field(), rollup_version_id, recipient.to_field(), chain_id, content];\n for i in 0..inputs.len() {\n // TODO are bytes be in fr.to_buffer() ?\n let item_bytes = inputs[i].to_be_bytes(32);\n for j in 0..32 {\n bytes.push(item_bytes[j]);\n }\n }\n\n sha256_to_field(bytes.storage)\n}\n\npub fn silo_l2_to_l1_message(msg: ScopedL2ToL1Message, rollup_version_id: Field, chain_id: Field) -> Field {\n if msg.contract_address.is_zero() {\n 0\n } else {\n compute_l2_to_l1_hash(\n msg.contract_address,\n msg.message.recipient,\n msg.message.content,\n rollup_version_id,\n chain_id\n )\n }\n}\n\n// Computes sha256 hash of 2 input hashes.\n//\n// NB: This method now takes in two 31 byte fields - it assumes that any input\n// is the result of a sha_to_field hash and => is truncated\n//\n// TODO(Jan and David): This is used for the encrypted_log hashes.\n// Can we check to see if we can just use hash_to_field or pedersen_compress here?\n//\npub fn accumulate_sha256(input: [Field; 2]) -> Field {\n // This is a note about the cpp code, since it takes an array of Fields\n // instead of a U128.\n // 4 Field elements when converted to bytes will usually \n // occupy 4 * 32 = 128 bytes.\n // However, this function is making the assumption that each Field \n // only occupies 128 bits.\n //\n // TODO(David): This does not seem to be getting guaranteed anywhere in the code?\n\n // Concatentate two fields into 32x2 = 64 bytes\n // accumulate_sha256 assumes that the inputs are pre-truncated 31 byte numbers\n let mut hash_input_flattened = [0; 64];\n for offset in 0..input.len() {\n let input_as_bytes = input[offset].to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n\n sha256_to_field(hash_input_flattened)\n}\n\n// Computes the final logs hash for a tx.\n// NB: this assumes MAX_ENCRYPTED_LOGS_PER_TX == MAX_UNENCRYPTED_LOGS_PER_TX\n// to avoid doubling code, since we can't define the byte len to be 32*N directly. \npub fn compute_tx_logs_hash(logs: [LogHash; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn compute_tx_note_logs_hash(logs: [LogHash; MAX_NOTE_ENCRYPTED_LOGS_PER_TX]) -> Field {\n // Convert each field element into a byte array and append the bytes to `hash_input_flattened`\n let mut hash_input_flattened = [0; MAX_NOTE_ENCRYPTED_LOGS_PER_TX * 32];\n for offset in 0..MAX_NOTE_ENCRYPTED_LOGS_PER_TX {\n let input_as_bytes = logs[offset].value.to_be_bytes(32);\n for byte_index in 0..32 {\n hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index];\n }\n }\n // Ideally we would push to a slice then hash, but there is no sha_slice\n // Hardcode to 256 bytes for now\n let mut hash = sha256_to_field(hash_input_flattened);\n // Not having a 0 value hash for empty logs causes issues with empty txs\n // used for padding. Returning early is currently unsupported.\n // We always provide sorted logs here, so 0 being empty means all are empty.\n if is_empty(logs[0]) {\n hash = 0;\n }\n hash\n}\n\npub fn pedersen_hash(inputs: [Field; N], hash_index: u32) -> Field {\n dep::std::hash::pedersen_hash_with_separator(inputs, hash_index)\n}\n\npub fn poseidon2_hash(inputs: [Field; N]) -> Field {\n dep::std::hash::poseidon2::Poseidon2::hash(inputs, N)\n}\n\n#[test]\nfn smoke_sha256_to_field() {\n let full_buffer = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159\n ];\n let result = sha256_to_field(full_buffer);\n\n assert(result == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184c7);\n\n // to show correctness of the current ver (truncate one byte) vs old ver (mod full bytes):\n let result_bytes = sha256(full_buffer);\n let truncated_field = crate::utils::field::field_from_bytes_32_trunc(result_bytes);\n assert(truncated_field == result);\n let mod_res = result + (result_bytes[31] as Field);\n assert(mod_res == 0x448ebbc9e1a31220a2f3830c18eef61b9bd070e5084b7fa2a359fe729184e0);\n}\n\n#[test]\nfn compute_l2_l1_hash() {\n // All zeroes\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(0), EthAddress::zero(), 0, 0, 0);\n assert(hash_result == 0xb393978842a0fa3d3e1470196f098f473f9678e72463cb65ec4ab5581856c2);\n\n // Non-zero case\n let hash_result = compute_l2_to_l1_hash(AztecAddress::from_field(1), EthAddress::from_field(3), 5, 2, 4);\n assert(hash_result == 0x3f88c1044a05e5340ed20466276500f6d45ca5603913b9091e957161734e16);\n}\n"},"240":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/partial_state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::PARTIAL_STATE_REFERENCE_LENGTH,\n traits::{Deserialize, Empty, Serialize}\n};\n\nstruct PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot,\n nullifier_tree: AppendOnlyTreeSnapshot,\n public_data_tree: AppendOnlyTreeSnapshot,\n}\n\nimpl Eq for PartialStateReference {\n fn eq(self, other: PartialStateReference) -> bool {\n self.note_hash_tree.eq(other.note_hash_tree) &\n self.nullifier_tree.eq(other.nullifier_tree) &\n self.public_data_tree.eq(other.public_data_tree)\n }\n}\n\nimpl Serialize for PartialStateReference {\n fn serialize(self) -> [Field; PARTIAL_STATE_REFERENCE_LENGTH] {\n let serialized_note_hash_tree = self.note_hash_tree.serialize();\n let serialized_nullifier_tree = self.nullifier_tree.serialize();\n let serialized_public_data_tree = self.public_data_tree.serialize();\n\n [\n serialized_note_hash_tree[0], \n serialized_note_hash_tree[1],\n serialized_nullifier_tree[0],\n serialized_nullifier_tree[1],\n serialized_public_data_tree[0],\n serialized_public_data_tree[1],\n ]\n }\n}\n\nimpl Deserialize for PartialStateReference {\n fn deserialize(serialized: [Field; PARTIAL_STATE_REFERENCE_LENGTH]) -> PartialStateReference {\n PartialStateReference {\n note_hash_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[0], serialized[1]]\n ),\n nullifier_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[2], serialized[3]]\n ),\n public_data_tree: AppendOnlyTreeSnapshot::deserialize(\n [serialized[4], serialized[5]]\n ),\n }\n }\n}\n\nimpl Empty for PartialStateReference {\n fn empty() -> Self {\n Self {\n note_hash_tree: AppendOnlyTreeSnapshot::zero(),\n nullifier_tree: AppendOnlyTreeSnapshot::zero(),\n public_data_tree: AppendOnlyTreeSnapshot::zero(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let partial = PartialStateReference::empty();\n let _serialized = partial.serialize();\n let _deserialized = PartialStateReference::deserialize(_serialized);\n}\n"},"242":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/transaction/tx_context.nr","source":"use crate::{\n constants::{GENERATOR_INDEX__TX_CONTEXT, TX_CONTEXT_LENGTH}, hash::pedersen_hash,\n traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader,\n abis::gas_settings::GasSettings\n};\n\n// docs:start:tx-context\nstruct TxContext {\n chain_id : Field,\n version : Field,\n gas_settings: GasSettings,\n}\n// docs:end:tx-context\n\nimpl TxContext {\n pub fn new(chain_id: Field, version: Field, gas_settings: GasSettings) -> Self {\n TxContext { chain_id, version, gas_settings }\n }\n}\n\nimpl Eq for TxContext {\n fn eq(self, other: Self) -> bool {\n (self.chain_id == other.chain_id) &\n (self.version == other.version) &\n (self.gas_settings.eq(other.gas_settings))\n }\n}\n\nimpl Empty for TxContext {\n fn empty() -> Self {\n TxContext {\n chain_id: 0,\n version: 0,\n gas_settings: GasSettings::empty(),\n }\n }\n}\n\nimpl Serialize for TxContext {\n fn serialize(self) -> [Field; TX_CONTEXT_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.push(self.chain_id);\n fields.push(self.version);\n fields.extend_from_array(self.gas_settings.serialize());\n\n assert_eq(fields.len(), TX_CONTEXT_LENGTH);\n\n fields.storage\n }\n}\n\nimpl Deserialize for TxContext {\n fn deserialize(serialized: [Field; TX_CONTEXT_LENGTH]) -> Self {\n // TODO(#4390): This should accept a reader ^ to avoid copying data.\n let mut reader = Reader::new(serialized);\n\n let context = Self {\n chain_id: reader.read(),\n version: reader.read(),\n gas_settings: reader.read_struct(GasSettings::deserialize),\n };\n\n reader.finish();\n context\n }\n}\n\nimpl Hash for TxContext {\n fn hash(self) -> Field {\n pedersen_hash(self.serialize(), GENERATOR_INDEX__TX_CONTEXT)\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let context = TxContext::empty();\n let serialized = context.serialize();\n let deserialized = TxContext::deserialize(serialized);\n assert(context.eq(deserialized));\n}\n\n#[test]\nfn empty_hash() {\n let context = TxContext::empty();\n let hash = context.hash();\n\n // Value from tx_context.test.ts \"computes empty item hash\" test\n let test_data_empty_hash = 0x17e4357684c5a4349b4587c95b0b6161dcb4a3c5b02d4eb2ecc3b02c80193261;\n assert_eq(hash, test_data_empty_hash);\n}\n"},"248":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/state_reference.nr","source":"use crate::{\n abis::append_only_tree_snapshot::{AppendOnlyTreeSnapshot, APPEND_ONLY_TREE_SNAPSHOT_LENGTH},\n constants::{PARTIAL_STATE_REFERENCE_LENGTH, STATE_REFERENCE_LENGTH},\n partial_state_reference::PartialStateReference, traits::{Deserialize, Empty, Hash, Serialize},\n utils::arr_copy_slice\n};\n\nstruct StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot,\n partial: PartialStateReference,\n}\n\nimpl Eq for StateReference {\n fn eq(self, other: StateReference) -> bool {\n self.l1_to_l2_message_tree.eq(other.l1_to_l2_message_tree) &\n self.partial.eq(other.partial)\n }\n}\n\nimpl Serialize for StateReference {\n fn serialize(self) -> [Field; STATE_REFERENCE_LENGTH] {\n let mut fields: BoundedVec = BoundedVec::new();\n\n fields.extend_from_array(self.l1_to_l2_message_tree.serialize());\n fields.extend_from_array(self.partial.serialize());\n\n fields.storage\n }\n}\n\nimpl Deserialize for StateReference {\n fn deserialize(serialized: [Field; STATE_REFERENCE_LENGTH]) -> StateReference {\n let mut offset = 0;\n\n let l1_to_l2_message_tree_fields = arr_copy_slice(serialized, [0; APPEND_ONLY_TREE_SNAPSHOT_LENGTH], offset);\n offset = offset + APPEND_ONLY_TREE_SNAPSHOT_LENGTH;\n\n let partial_fields = arr_copy_slice(serialized, [0; PARTIAL_STATE_REFERENCE_LENGTH], offset);\n\n StateReference {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::deserialize(l1_to_l2_message_tree_fields),\n partial: PartialStateReference::deserialize(partial_fields),\n }\n }\n}\n\nimpl Empty for StateReference {\n fn empty() -> Self {\n Self {\n l1_to_l2_message_tree: AppendOnlyTreeSnapshot::zero(),\n partial: PartialStateReference::empty(),\n }\n }\n}\n\n#[test]\nfn serialization_of_empty() {\n let state = StateReference::empty();\n let _serialized = state.serialize();\n let _deserialized = StateReference::deserialize(_serialized);\n}\n"},"260":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/utils/reader.nr","source":"struct Reader {\n data: [Field; N],\n offset: u32,\n}\n\nimpl Reader {\n pub fn new(data: [Field; N]) -> Self {\n Self { data, offset: 0 }\n }\n\n pub fn read(&mut self) -> Field {\n let result = self.data[self.offset];\n self.offset += 1;\n result\n }\n\n pub fn read_u32(&mut self) -> u32 {\n self.read() as u32\n }\n\n pub fn read_bool(&mut self) -> bool {\n self.read() as bool\n }\n\n pub fn read_array(&mut self, mut result: [Field; K]) -> [Field; K] {\n for i in 0..K {\n result[i] = self.data[self.offset + i];\n }\n self.offset += K;\n result\n }\n\n // TODO(#4394)\n pub fn read_struct(&mut self, deserialise: fn([Field; K]) -> T) -> T {\n let result = deserialise(self.read_array([0; K]));\n result\n }\n\n pub fn read_struct_array(&mut self, deserialise: fn([Field; K]) -> T, mut result: [T; C]) -> [T; C] {\n for i in 0..C {\n result[i] = self.read_struct(deserialise);\n }\n result\n }\n\n pub fn finish(self) {\n assert(self.offset == self.data.len(), \"Reader did not read all data\");\n }\n}\n"},"280":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/eth_address.nr","source":"use crate::{\n constants::ETH_ADDRESS_LENGTH, hash::pedersen_hash,\n traits::{Empty, ToField, Serialize, Deserialize}, utils\n};\n\nstruct EthAddress{\n inner : Field\n}\n\nimpl Eq for EthAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for EthAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for EthAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl Serialize for EthAddress {\n fn serialize(self: Self) -> [Field; ETH_ADDRESS_LENGTH] {\n [self.inner]\n }\n}\n\nimpl Deserialize for EthAddress {\n fn deserialize(fields: [Field; ETH_ADDRESS_LENGTH]) -> Self {\n EthAddress::from_field(fields[0])\n }\n}\n\nimpl EthAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn from_field(field: Field) -> Self {\n field.assert_max_bit_size(160);\n Self { inner: field }\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n"},"281":{"path":"/usr/src/noir-projects/noir-protocol-circuits/crates/types/src/address/aztec_address.nr","source":"use crate::{\n crate::address::{eth_address::EthAddress, partial_address::PartialAddress, public_keys_hash::PublicKeysHash},\n constants::{AZTEC_ADDRESS_LENGTH, GENERATOR_INDEX__CONTRACT_ADDRESS_V1},\n contract_class_id::ContractClassId, hash::poseidon2_hash, grumpkin_point::GrumpkinPoint,\n traits::{Empty, FromField, ToField, Serialize, Deserialize}, utils\n};\n\n// Aztec address\nstruct AztecAddress {\n inner : Field\n}\n\nimpl Eq for AztecAddress {\n fn eq(self, other : Self) -> bool {\n self.to_field() == other.to_field()\n }\n}\n\nimpl Empty for AztecAddress {\n fn empty() -> Self {\n Self {\n inner : 0\n }\n }\n}\n\nimpl ToField for AztecAddress {\n fn to_field(self) -> Field {\n self.inner\n }\n}\n\nimpl FromField for AztecAddress {\n fn from_field(value: Field) -> AztecAddress {\n AztecAddress { inner: value }\n }\n}\n\nimpl Serialize for AztecAddress {\n fn serialize(self: Self) -> [Field; AZTEC_ADDRESS_LENGTH] {\n [self.to_field()]\n }\n}\n\nimpl Deserialize for AztecAddress {\n fn deserialize(fields: [Field; AZTEC_ADDRESS_LENGTH]) -> Self {\n FromField::from_field(fields[0])\n }\n}\n\nimpl AztecAddress {\n pub fn zero() -> Self {\n Self { inner: 0 }\n }\n\n pub fn compute(pub_keys_hash: PublicKeysHash, partial_address: PartialAddress) -> AztecAddress {\n AztecAddress::from_field(\n poseidon2_hash([pub_keys_hash.to_field(), partial_address.to_field(), GENERATOR_INDEX__CONTRACT_ADDRESS_V1])\n )\n }\n\n pub fn is_zero(self) -> bool {\n self.inner == 0\n }\n\n pub fn assert_is_zero(self) {\n assert(self.to_field() == 0);\n }\n\n pub fn conditional_assign(predicate: bool, lhs: Self, rhs: Self) -> Self {\n let result = utils::conditional_assign(predicate, rhs.to_field(), lhs.to_field());\n Self { inner: result }\n }\n}\n\n#[test]\nfn compute_address_from_partial_and_pub_keys_hash() {\n let pub_keys_hash = PublicKeysHash::from_field(1);\n let partial_address = PartialAddress::from_field(2);\n\n let address = AztecAddress::compute(pub_keys_hash, partial_address);\n let expected_computed_address_from_partial_and_pubkey = 0x1b6ead051e7b42665064ca6cf1ec77da0a36d86e00d1ff6e44077966c0c3a9fa;\n assert(address.to_field() == expected_computed_address_from_partial_and_pubkey);\n}\n\n#[test]\nfn from_field_to_field() {\n let address = AztecAddress { inner: 37 };\n assert_eq(FromField::from_field(address.to_field()), address);\n}\n\n#[test]\nfn serde() {\n let address = AztecAddress { inner: 37 };\n assert_eq(Deserialize::deserialize(address.serialize()), address);\n}\n"},"382":{"path":"/usr/src/noir-projects/noir-contracts/contracts/multi_call_entrypoint_contract/src/main.nr","source":"// An entrypoint contract that allows everything to go through. Only used for testing\n// Pair this with SignerlessWallet to perform multiple actions before any account contracts are deployed (and without authentication)\ncontract MultiCallEntrypoint {\n use dep::std;\n\n use dep::aztec::prelude::AztecAddress;\n use dep::authwit::entrypoint::app::AppPayload;\n\n #[aztec(private)]\n fn entrypoint(app_payload: AppPayload) {\n app_payload.execute_calls(&mut context);\n }\n}\n"},"4":{"path":"std/collections/bounded_vec.nr","source":"use crate::{cmp::Eq, convert::From};\n\nstruct BoundedVec {\n storage: [T; MaxLen],\n len: u32,\n}\n\nimpl BoundedVec {\n pub fn new() -> Self {\n let zeroed = crate::unsafe::zeroed();\n BoundedVec { storage: [zeroed; MaxLen], len: 0 }\n }\n\n pub fn get(mut self: Self, index: u32) -> T {\n assert(index < self.len);\n self.storage[index]\n }\n\n pub fn get_unchecked(mut self: Self, index: u32) -> T {\n self.storage[index]\n }\n\n pub fn push(&mut self, elem: T) {\n assert(self.len < MaxLen, \"push out of bounds\");\n\n self.storage[self.len] = elem;\n self.len += 1;\n }\n\n pub fn len(self) -> u32 {\n self.len\n }\n\n pub fn max_len(_self: BoundedVec) -> u32 {\n MaxLen\n }\n\n // This is a intermediate method, while we don't have an\n // .extend method\n pub fn storage(self) -> [T; MaxLen] {\n self.storage\n }\n\n pub fn extend_from_array(&mut self, array: [T; Len]) {\n let new_len = self.len + array.len();\n assert(new_len <= MaxLen, \"extend_from_array out of bounds\");\n for i in 0..array.len() {\n self.storage[self.len + i] = array[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_slice(&mut self, slice: [T]) {\n let new_len = self.len + slice.len();\n assert(new_len <= MaxLen, \"extend_from_slice out of bounds\");\n for i in 0..slice.len() {\n self.storage[self.len + i] = slice[i];\n }\n self.len = new_len;\n }\n\n pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) {\n let append_len = vec.len();\n let new_len = self.len + append_len;\n assert(new_len <= MaxLen, \"extend_from_bounded_vec out of bounds\");\n\n let mut exceeded_len = false;\n for i in 0..Len {\n exceeded_len |= i == append_len;\n if !exceeded_len {\n self.storage[self.len + i] = vec.get_unchecked(i);\n }\n }\n self.len = new_len;\n }\n\n pub fn from_array(array: [T; Len]) -> Self {\n assert(Len <= MaxLen, \"from array out of bounds\");\n let mut vec: BoundedVec = BoundedVec::new();\n vec.extend_from_array(array);\n vec\n }\n\n pub fn pop(&mut self) -> T {\n assert(self.len > 0);\n self.len -= 1;\n\n let elem = self.storage[self.len];\n self.storage[self.len] = crate::unsafe::zeroed();\n elem\n }\n\n pub fn any(self, predicate: fn[Env](T) -> bool) -> bool {\n let mut ret = false;\n let mut exceeded_len = false;\n for i in 0..MaxLen {\n exceeded_len |= i == self.len;\n if !exceeded_len {\n ret |= predicate(self.storage[i]);\n }\n }\n ret\n }\n}\n\nimpl Eq for BoundedVec where T: Eq {\n fn eq(self, other: BoundedVec) -> bool {\n // TODO: https://github.com/noir-lang/noir/issues/4837\n //\n // We make the assumption that the user has used the proper interface for working with `BoundedVec`s\n // rather than directly manipulating the internal fields as this can result in an inconsistent internal state.\n \n (self.len == other.len) & (self.storage == other.storage)\n }\n}\n\nimpl From<[T; Len]> for BoundedVec {\n fn from(array: [T; Len]) -> BoundedVec {\n BoundedVec::from_array(array)\n }\n}\n\nmod bounded_vec_tests {\n // TODO: Allow imports from \"super\"\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty_equality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n\n assert_eq(bounded_vec1, bounded_vec2);\n }\n\n #[test]\n fn inequality() {\n let mut bounded_vec1: BoundedVec = BoundedVec::new();\n let mut bounded_vec2: BoundedVec = BoundedVec::new();\n bounded_vec1.push(1);\n bounded_vec2.push(2);\n\n assert(bounded_vec1 != bounded_vec2);\n }\n\n mod from_array {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn empty() {\n let empty_array: [Field; 0] = [];\n let bounded_vec = BoundedVec::from_array([]);\n\n assert_eq(bounded_vec.max_len(), 0);\n assert_eq(bounded_vec.len(), 0);\n assert_eq(bounded_vec.storage(), empty_array);\n }\n\n #[test]\n fn equal_len() {\n let array = [1, 2, 3];\n let bounded_vec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 3);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage(), array);\n }\n\n #[test]\n fn max_len_greater_then_array_len() {\n let array = [1, 2, 3];\n let bounded_vec: BoundedVec = BoundedVec::from_array(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 3);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n assert_eq(bounded_vec.storage()[2], 3);\n }\n\n #[test(should_fail_with=\"from array out of bounds\")]\n fn max_len_lower_then_array_len() {\n let _: BoundedVec = BoundedVec::from_array([0; 3]);\n }\n }\n\n mod trait_from {\n use crate::collections::bounded_vec::BoundedVec;\n\n #[test]\n fn simple() {\n let array = [1, 2];\n let bounded_vec: BoundedVec = BoundedVec::from(array);\n\n assert_eq(bounded_vec.max_len(), 10);\n assert_eq(bounded_vec.len(), 2);\n assert_eq(bounded_vec.storage()[0], 1);\n assert_eq(bounded_vec.storage()[1], 2);\n }\n }\n}\n"},"53":{"path":"/usr/src/noir-projects/aztec-nr/authwit/src/entrypoint/app.nr","source":"use dep::aztec::prelude::PrivateContext;\nuse dep::aztec::protocol_types::{constants::GENERATOR_INDEX__SIGNATURE_PAYLOAD, hash::pedersen_hash, traits::{Hash, Serialize}};\n\nuse crate::entrypoint::function_call::{FunctionCall, FUNCTION_CALL_SIZE_IN_BYTES};\n\n// FUNCTION_CALL_SIZE * ACCOUNT_MAX_CALLS + 1\nglobal APP_PAYLOAD_SIZE: u64 = 21;\n// FUNCTION_CALL_SIZE_IN_BYTES * ACCOUNT_MAX_CALLS + 32\nglobal APP_PAYLOAD_SIZE_IN_BYTES: u64 = 424;\n\nglobal ACCOUNT_MAX_CALLS: u64 = 4;\n\n// Note: If you change the following struct you have to update default_entrypoint.ts\n// docs:start:app-payload-struct\nstruct AppPayload {\n function_calls: [FunctionCall; ACCOUNT_MAX_CALLS],\n nonce: Field,\n}\n// docs:end:app-payload-struct\n\nimpl Serialize for AppPayload {\n // Serializes the entrypoint struct\n fn serialize(self) -> [Field; APP_PAYLOAD_SIZE] {\n let mut fields: BoundedVec = BoundedVec::new();\n for call in self.function_calls {\n fields.extend_from_array(call.serialize());\n }\n fields.push(self.nonce);\n fields.storage\n }\n}\n\nimpl Hash for AppPayload {\n fn hash(self) -> Field {\n pedersen_hash(\n self.serialize(),\n GENERATOR_INDEX__SIGNATURE_PAYLOAD\n )\n }\n}\n\nimpl AppPayload {\n // Serializes the payload as an array of bytes. Useful for hashing with sha256.\n fn to_be_bytes(self) -> [u8; APP_PAYLOAD_SIZE_IN_BYTES] {\n let mut bytes: BoundedVec = BoundedVec::new();\n\n for i in 0..ACCOUNT_MAX_CALLS {\n bytes.extend_from_array(self.function_calls[i].to_be_bytes());\n }\n bytes.extend_from_slice(self.nonce.to_be_bytes(32));\n\n bytes.storage\n }\n\n // Executes all private and public calls\n // docs:start:entrypoint-execute-calls\n fn execute_calls(self, context: &mut PrivateContext) {\n for call in self.function_calls {\n if !call.target_address.is_zero() {\n if call.is_public {\n context.call_public_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n } else {\n let _result = context.call_private_function_with_packed_args(\n call.target_address,\n call.function_selector,\n call.args_hash,\n call.is_static,\n false\n );\n }\n }\n }\n }\n // docs:end:entrypoint-execute-calls\n}\n"},"91":{"path":"/usr/src/noir-projects/aztec-nr/aztec/src/context/private_context.nr","source":"use crate::{\n context::{inputs::PrivateContextInputs, packed_returns::PackedReturns},\n messaging::process_l1_to_l2_message,\n hash::{hash_args_array, ArgsHasher, compute_unencrypted_log_hash},\n keys::constants::{NULLIFIER_INDEX, OUTGOING_INDEX, NUM_KEY_TYPES, sk_generators},\n note::note_interface::NoteInterface,\n oracle::{\n key_validation_request::get_key_validation_request, arguments, returns::pack_returns,\n call_private_function::call_private_function_internal, header::get_header_at,\n logs::{\n emit_encrypted_note_log, emit_encrypted_event_log,\n emit_contract_class_unencrypted_log_private_internal, emit_unencrypted_log_private_internal\n},\n logs_traits::{LensForEncryptedLog, ToBytesForUnencryptedLog},\n enqueue_public_function_call::{\n enqueue_public_function_call_internal, set_public_teardown_function_call_internal,\n parse_public_call_stack_item_from_oracle\n}\n}\n};\nuse dep::protocol_types::{\n hash::sha256_to_field,\n abis::{\n caller_context::CallerContext, function_selector::FunctionSelector,\n max_block_number::MaxBlockNumber,\n validation_requests::{KeyValidationRequest, KeyValidationRequestAndGenerator},\n private_call_request::PrivateCallRequest, private_circuit_public_inputs::PrivateCircuitPublicInputs,\n public_call_stack_item::PublicCallStackItem, read_request::ReadRequest, note_hash::NoteHash,\n nullifier::Nullifier, log_hash::{LogHash, NoteLogHash, EncryptedLogHash}\n},\n address::{AztecAddress, EthAddress},\n constants::{\n MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL,\n MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,\n MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL,\n MAX_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL,\n MAX_NOTE_ENCRYPTED_LOGS_PER_CALL\n},\n contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest},\n grumpkin_private_key::GrumpkinPrivateKey, grumpkin_point::GrumpkinPoint, header::Header,\n messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{is_empty, Empty},\n utils::arrays::find_index\n};\n\n// When finished, one can call .finish() to convert back to the abi\nstruct PrivateContext {\n // docs:start:private-context\n inputs: PrivateContextInputs,\n side_effect_counter: u32,\n\n min_revertible_side_effect_counter: u32,\n is_fee_payer: bool,\n\n args_hash: Field,\n return_hash: Field,\n\n max_block_number: MaxBlockNumber,\n\n note_hash_read_requests: BoundedVec,\n nullifier_read_requests: BoundedVec,\n key_validation_requests_and_generators: BoundedVec,\n\n new_note_hashes: BoundedVec,\n new_nullifiers: BoundedVec,\n\n private_call_requests : BoundedVec,\n public_call_stack_hashes : BoundedVec,\n public_teardown_function_hash: Field,\n new_l2_to_l1_msgs : BoundedVec,\n // docs:end:private-context\n\n // Header of a block whose state is used during private execution (not the block the transaction is included in).\n historical_header: Header,\n\n note_encrypted_logs_hashes: BoundedVec,\n encrypted_logs_hashes: BoundedVec,\n unencrypted_logs_hashes: BoundedVec,\n\n // Contains the last key validation request for each key type. This is used to cache the last request and avoid\n // fetching the same request multiple times.\n // The index of the array corresponds to the key type (0 nullifier, 1 incoming, 2 outgoing, 3 tagging).\n last_key_validation_requests: [Option; NUM_KEY_TYPES],\n}\n\nimpl PrivateContext {\n pub fn new(inputs: PrivateContextInputs, args_hash: Field) -> PrivateContext {\n PrivateContext {\n inputs,\n side_effect_counter: inputs.start_side_effect_counter + 1,\n min_revertible_side_effect_counter: 0,\n is_fee_payer: false,\n args_hash,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n historical_header: inputs.historical_header,\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n\n fn msg_sender(self) -> AztecAddress {\n self.inputs.call_context.msg_sender\n }\n\n fn this_address(self) -> AztecAddress {\n self.inputs.call_context.storage_contract_address\n }\n\n fn chain_id(self) -> Field {\n self.inputs.tx_context.chain_id\n }\n\n fn version(self) -> Field {\n self.inputs.tx_context.version\n }\n\n fn selector(self) -> FunctionSelector {\n self.inputs.call_context.function_selector\n }\n\n fn get_args_hash(self) -> Field {\n self.args_hash\n }\n\n fn push_new_note_hash(&mut self, note_hash: Field) {\n self.new_note_hashes.push(NoteHash { value: note_hash, counter: self.next_counter() });\n }\n\n // TODO(#7112): This function is called with non-zero note hash only in 1 of 25 cases in aztec-packages repo\n // - consider creating a separate function with 1 arg for the zero note hash case.\n fn push_new_nullifier(&mut self, nullifier: Field, nullified_note_hash: Field) {\n self.new_nullifiers.push(Nullifier { value: nullifier, note_hash: nullified_note_hash, counter: self.next_counter() });\n }\n\n // Returns the header of a block whose state is used during private execution (not the block the transaction is\n // included in).\n fn get_header(self) -> Header {\n self.historical_header\n }\n\n // Returns the header of an arbitrary block whose block number is less than or equal to the block number\n // of historical header.\n pub fn get_header_at(self, block_number: u32) -> Header {\n get_header_at(block_number, self)\n }\n\n pub fn set_return_hash(&mut self, returns_hasher: ArgsHasher) {\n pack_returns(returns_hasher.fields);\n self.return_hash = returns_hasher.hash();\n }\n\n pub fn finish(self) -> PrivateCircuitPublicInputs {\n PrivateCircuitPublicInputs {\n call_context: self.inputs.call_context,\n args_hash: self.args_hash,\n returns_hash: self.return_hash,\n min_revertible_side_effect_counter: self.min_revertible_side_effect_counter,\n is_fee_payer: self.is_fee_payer,\n max_block_number: self.max_block_number,\n note_hash_read_requests: self.note_hash_read_requests.storage,\n nullifier_read_requests: self.nullifier_read_requests.storage,\n key_validation_requests_and_generators: self.key_validation_requests_and_generators.storage,\n new_note_hashes: self.new_note_hashes.storage,\n new_nullifiers: self.new_nullifiers.storage,\n private_call_requests: self.private_call_requests.storage,\n public_call_stack_hashes: self.public_call_stack_hashes.storage,\n public_teardown_function_hash: self.public_teardown_function_hash,\n new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage,\n start_side_effect_counter: self.inputs.start_side_effect_counter,\n end_side_effect_counter: self.side_effect_counter,\n note_encrypted_logs_hashes: self.note_encrypted_logs_hashes.storage,\n encrypted_logs_hashes: self.encrypted_logs_hashes.storage,\n unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage,\n historical_header: self.historical_header,\n tx_context: self.inputs.tx_context\n }\n }\n\n pub fn set_as_fee_payer(&mut self) {\n dep::protocol_types::debug_log::debug_log_format(\"Setting {0} as fee payer\", [self.this_address().to_field()]);\n self.is_fee_payer = true;\n }\n\n pub fn end_setup(&mut self) {\n // dep::protocol_types::debug_log::debug_log_format(\n // \"Ending setup at counter {0}\",\n // [self.side_effect_counter as Field]\n // );\n self.min_revertible_side_effect_counter = self.side_effect_counter;\n }\n\n // docs:start:max-block-number\n pub fn set_tx_max_block_number(&mut self, max_block_number: u32) {\n // docs:end:max-block-number\n self.max_block_number = MaxBlockNumber::min_with_u32(self.max_block_number, max_block_number);\n }\n\n pub fn push_note_hash_read_request(&mut self, note_hash: Field) {\n let side_effect = ReadRequest { value: note_hash, counter: self.next_counter() };\n self.note_hash_read_requests.push(side_effect);\n }\n\n pub fn push_nullifier_read_request(&mut self, nullifier: Field) {\n let request = ReadRequest { value: nullifier, counter: self.next_counter() };\n self.nullifier_read_requests.push(request);\n }\n\n pub fn request_nsk_app(&mut self, npk_m_hash: Field) -> Field {\n self.request_sk_app(npk_m_hash, NULLIFIER_INDEX)\n }\n\n pub fn request_ovsk_app(&mut self, ovpk_m_hash: Field) -> Field {\n self.request_sk_app(ovpk_m_hash, OUTGOING_INDEX)\n }\n\n fn request_sk_app(&mut self, pk_m_hash: Field, key_index: Field) -> Field {\n let cached_request = self.last_key_validation_requests[key_index].unwrap_or(KeyValidationRequest::empty());\n\n if cached_request.pk_m.hash() == pk_m_hash {\n // We get a match so the cached request is the latest one \n cached_request.sk_app\n } else {\n // We didn't get a match meaning the cached result is stale. We fetch new values from oracle and instruct\n // protocol circuits to validate them by storing the validation request in context.\n let request = get_key_validation_request(pk_m_hash, key_index);\n let request_and_generator = KeyValidationRequestAndGenerator { request, sk_app_generator: sk_generators[key_index] };\n // We constrain that the pk_m_hash matches the one in the request (otherwise we could get an arbitrary\n // valid key request and not the one corresponding to pk_m_hash).\n assert(request.pk_m.hash() == pk_m_hash);\n self.key_validation_requests_and_generators.push(request_and_generator);\n self.last_key_validation_requests[key_index] = Option::some(request);\n request.sk_app\n }\n }\n\n // docs:start:context_message_portal\n pub fn message_portal(&mut self, recipient: EthAddress, content: Field) {\n // docs:end:context_message_portal\n let message = L2ToL1Message { recipient, content, counter: self.next_counter() };\n self.new_l2_to_l1_msgs.push(message);\n }\n\n // docs:start:context_consume_l1_to_l2_message\n // docs:start:consume_l1_to_l2_message\n pub fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) {\n // docs:end:context_consume_l1_to_l2_message\n let nullifier = process_l1_to_l2_message(\n self.historical_header.state.l1_to_l2_message_tree.root,\n self.this_address(),\n sender,\n self.chain_id(),\n self.version(),\n content,\n secret\n );\n\n // Push nullifier (and the \"commitment\" corresponding to this can be \"empty\")\n self.push_new_nullifier(nullifier, 0)\n }\n // docs:end:consume_l1_to_l2_message\n\n // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy.\n // --> might be a better approach to force devs to make a public function call that emits the log if needed then\n // it would be less easy to accidentally leak information.\n // If we decide to keep this function around would make sense to wait for traits and then merge it with emit_unencrypted_log.\n pub fn emit_unencrypted_log(&mut self, log: T) where T: ToBytesForUnencryptedLog {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_slice = log.to_be_bytes_arr();\n let log_hash = compute_unencrypted_log_hash(contract_address, event_selector, log);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + log_slice.len().to_field();\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n // call oracle\n let _void = emit_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n }\n\n // This fn exists separately from emit_unencrypted_log because sha hashing the preimage\n // is too large to compile (16,200 fields, 518,400 bytes) => the oracle hashes it\n // It is ONLY used with contract_class_registerer_contract since we already assert correctness:\n // - Contract class -> we will commit to the packed bytecode (currently a TODO)\n // - Private function -> we provide a membership proof\n // - Unconstrained function -> we provide a membership proof\n // Ordinary logs are not protected by the above so this fn shouldn't be called by anything else\n pub fn emit_contract_class_unencrypted_log(&mut self, log: [Field; N]) {\n let event_selector = 5; // TODO: compute actual event selector.\n let contract_address = self.this_address();\n let counter = self.next_counter();\n let log_hash = emit_contract_class_unencrypted_log_private_internal(contract_address, event_selector, log, counter);\n // 44 = addr (32) + selector (4) + raw log len (4) + processed log len (4)\n let len = 44 + N * 32;\n let side_effect = LogHash { value: log_hash, counter, length: len };\n self.unencrypted_logs_hashes.push(side_effect);\n }\n\n // NB: A randomness value of 0 signals that the kernels should not mask the contract address\n // used in siloing later on e.g. 'handshaking' contract w/ known address.\n pub fn emit_raw_event_log_with_masked_address(&mut self, randomness: Field, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let contract_address = self.this_address();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = EncryptedLogHash { value: log_hash, counter, length: len, randomness };\n self.encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_event_log(contract_address, randomness, encrypted_log, counter);\n }\n\n pub fn emit_raw_note_log(&mut self, note_hash_counter: u32, encrypted_log: [u8; M]) {\n let counter = self.next_counter();\n let len = encrypted_log.len() as Field + 4;\n let log_hash = sha256_to_field(encrypted_log);\n let side_effect = NoteLogHash { value: log_hash, counter, length: len, note_hash_counter };\n self.note_encrypted_logs_hashes.push(side_effect);\n\n emit_encrypted_note_log(note_hash_counter, encrypted_log, counter);\n }\n\n pub fn call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_private_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) -> PackedReturns {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_private_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) -> PackedReturns {\n self.call_private_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_private_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) -> PackedReturns {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let start_side_effect_counter = self.side_effect_counter;\n let item = call_private_function_internal(\n contract_address,\n function_selector,\n args_hash,\n start_side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, start_side_effect_counter);\n assert_eq(item.public_inputs.start_side_effect_counter, start_side_effect_counter);\n let end_side_effect_counter = item.public_inputs.end_side_effect_counter;\n self.side_effect_counter = end_side_effect_counter + 1;\n\n // TODO (fees) figure out why this crashes the prover and enable it\n // we need this in order to pay fees inside child call contexts\n // assert(\n // (item.public_inputs.min_revertible_side_effect_counter == 0 as u32)\n // | (item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter)\n // );\n\n // if item.public_inputs.min_revertible_side_effect_counter\n // > self.min_revertible_side_effect_counter {\n // self.min_revertible_side_effect_counter = item.public_inputs.min_revertible_side_effect_counter;\n // }\n\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n\n let mut caller_context = CallerContext::empty();\n caller_context.is_static_call = self.inputs.call_context.is_static_call;\n if is_delegate_call {\n caller_context.msg_sender = self.inputs.call_context.msg_sender;\n caller_context.storage_contract_address = self.inputs.call_context.storage_contract_address;\n }\n self.private_call_requests.push(\n PrivateCallRequest { hash: item.hash(), caller_context, start_side_effect_counter, end_side_effect_counter }\n );\n\n PackedReturns::new(item.public_inputs.returns_hash)\n }\n\n pub fn call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn static_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false)\n }\n\n pub fn delegate_call_public_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true)\n }\n\n pub fn call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, false)\n }\n\n pub fn static_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, true, false)\n }\n\n pub fn delegate_call_public_function_no_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector\n ) {\n self.call_public_function_with_packed_args(contract_address, function_selector, 0, false, true)\n }\n\n pub fn call_public_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = enqueue_public_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_call_stack_hashes.push(item.hash());\n }\n\n pub fn set_public_teardown_function(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args: [Field; ARGS_COUNT]\n ) {\n let args_hash = hash_args_array(args);\n assert(args_hash == arguments::pack_arguments_array(args));\n self.set_public_teardown_function_with_packed_args(contract_address, function_selector, args_hash, false, false)\n }\n\n pub fn set_public_teardown_function_with_packed_args(\n &mut self,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n let mut is_static_call = is_static_call | self.inputs.call_context.is_static_call;\n let fields = set_public_teardown_function_call_internal(\n contract_address,\n function_selector,\n args_hash,\n self.side_effect_counter,\n is_static_call,\n is_delegate_call\n );\n\n let item = parse_public_call_stack_item_from_oracle(fields);\n self.validate_call_stack_item_from_oracle(\n item,\n contract_address,\n function_selector,\n args_hash,\n is_static_call,\n is_delegate_call\n );\n\n self.side_effect_counter = self.side_effect_counter + 1;\n self.public_teardown_function_hash = item.hash();\n }\n\n fn validate_call_stack_item_from_oracle(\n self,\n item: PublicCallStackItem,\n contract_address: AztecAddress,\n function_selector: FunctionSelector,\n args_hash: Field,\n is_static_call: bool,\n is_delegate_call: bool\n ) {\n assert(contract_address.eq(item.contract_address));\n assert(function_selector.eq(item.function_data.selector));\n\n assert_eq(item.public_inputs.call_context.side_effect_counter, self.side_effect_counter);\n\n assert(args_hash == item.public_inputs.args_hash);\n\n // Assert that the call context of the enqueued call generated by the oracle matches our request.\n assert(item.public_inputs.call_context.is_delegate_call == is_delegate_call);\n assert(item.public_inputs.call_context.is_static_call == is_static_call);\n\n if (is_delegate_call) {\n // For delegate calls, we also constrain the execution context address for the nested call to be equal to our address.\n assert(\n item.public_inputs.call_context.storage_contract_address.eq(self.inputs.call_context.storage_contract_address)\n );\n assert(item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.msg_sender));\n } else {\n // For non-delegate calls, we also constrain the execution context address for the nested call to be equal to the address we called.\n assert(item.public_inputs.call_context.storage_contract_address.eq(contract_address));\n assert(\n item.public_inputs.call_context.msg_sender.eq(self.inputs.call_context.storage_contract_address)\n );\n }\n }\n\n fn next_counter(&mut self) -> u32 {\n let counter = self.side_effect_counter;\n self.side_effect_counter += 1;\n counter\n }\n}\n\nimpl Empty for PrivateContext {\n fn empty() -> Self {\n PrivateContext {\n inputs: PrivateContextInputs::empty(),\n side_effect_counter: 0 as u32,\n min_revertible_side_effect_counter: 0 as u32,\n is_fee_payer: false,\n args_hash: 0,\n return_hash: 0,\n max_block_number: MaxBlockNumber::empty(),\n note_hash_read_requests: BoundedVec::new(),\n nullifier_read_requests: BoundedVec::new(),\n key_validation_requests_and_generators: BoundedVec::new(),\n new_note_hashes: BoundedVec::new(),\n new_nullifiers: BoundedVec::new(),\n private_call_requests: BoundedVec::new(),\n public_call_stack_hashes: BoundedVec::new(),\n public_teardown_function_hash: 0,\n new_l2_to_l1_msgs: BoundedVec::new(),\n historical_header: Header::empty(),\n note_encrypted_logs_hashes: BoundedVec::new(),\n encrypted_logs_hashes: BoundedVec::new(),\n unencrypted_logs_hashes: BoundedVec::new(),\n last_key_validation_requests: [Option::none(); NUM_KEY_TYPES]\n }\n }\n}\n"}}} \ No newline at end of file From 7afe45f5d63f531a7678e1a523a4c37ac32ecff0 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 3 Jul 2024 14:37:16 +0000 Subject: [PATCH 41/94] undo noir changes --- .../compiler/noirc_frontend/src/elaborator/patterns.rs | 2 +- .../compiler/noirc_frontend/src/hir/type_check/errors.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index 5b128d8ce1d6..8a2f305d8f68 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -605,4 +605,4 @@ impl<'context> Elaborator<'context> { let id = DefinitionId::dummy_id(); (HirIdent::non_trait_method(id, location), 0) } -} \ No newline at end of file +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index 470bf52677c0..9c6a39d19405 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -396,4 +396,4 @@ impl NoMatchingImplFoundError { Some(Self { constraints, span }) } -} \ No newline at end of file +} From 5e33a6ba7116ea74c0422f04c46b906899b0933c Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 4 Jul 2024 11:44:37 +0000 Subject: [PATCH 42/94] fix ETHEREUM_HOST in terraform --- .github/workflows/devnet-deploys.yml | 1 + yarn-project/aztec/terraform/node/main.tf | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 75df1925cc8d..2599855ce4b6 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -94,6 +94,7 @@ jobs: const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); return fileChanged + - name: Deploy L1 Contracts if: steps.check_changes_release.outputs.result == 'true' run: | diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index d446d334c89e..20725c32103d 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -193,7 +193,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "ETHEREUM_HOST", - "value": "https://aztec-dev-mainnet-fork.aztec.network:8545/${var.API_KEY}" + "value": "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" }, { "name": "DATA_DIRECTORY", From 6451d7c38e70602e4137b3d493781e52684231e6 Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 10:44:02 +0000 Subject: [PATCH 43/94] chore: deploy mainnet-fork, update devnet chainID --- .github/workflows/devnet-deploys.yml | 52 +++++++++++++------ iac/mainnet-fork/terraform/main.tf | 4 +- iac/mainnet-fork/terraform/variables.tf | 4 ++ yarn-project/aztec/terraform/node/main.tf | 13 +++-- .../aztec/terraform/node/variables.tf | 2 +- 5 files changed, 48 insertions(+), 27 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 2599855ce4b6..40336167ae7e 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -14,13 +14,15 @@ env: FILE_PATH: ./l1-contracts/addresses.txt # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol - TF_VAR_CHAIN_ID: 31337 + TF_VAR_CHAIN_ID: 677692 TF_VAR_BOOTNODE_1_PRIVATE_KEY: ${{ secrets.BOOTNODE_1_PRIVATE_KEY }} TF_VAR_BOOTNODE_2_PRIVATE_KEY: ${{ secrets.BOOTNODE_2_PRIVATE_KEY }} TF_VAR_SEQ_1_PUBLISHER_PRIVATE_KEY: ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} TF_VAR_SEQ_2_PUBLISHER_PRIVATE_KEY: ${{ secrets.SEQ_2_PUBLISHER_PRIVATE_KEY }} TF_VAR_DEPLOY_TAG: devnet TF_VAR_API_KEY: ${{ secrets.FORK_API_KEY }} + TF_VAR_FORK_MNEMONIC: ${{ secrets.FORK_MNEMONIC }} + TF_VAR_INFURA_API_KEY: ${{ secrets.INFURA_API_KEY }} jobs: setup: @@ -33,6 +35,9 @@ jobs: build: needs: setup runs-on: ${{ github.actor }}-x86 + outputs: + l1_contracts_changed: ${{ steps.check_l1_changes.outputs.result }} + mainnet_fork_changed: ${{ steps.check_fork_changes.outputs.result }} steps: - uses: actions/checkout@v4 with: @@ -49,7 +54,7 @@ jobs: earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} - name: Check if L1 contracts need deployment - id: check_changes_build + id: check_l1_changes uses: actions/github-script@v7 with: script: | @@ -58,13 +63,29 @@ jobs: const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); return fileChanged + - name: Check if mainnet fork needs deployment + id: check_fork_changes + uses: actions/github-script@v7 + with: + script: | + const { execSync } = require('child_process'); + const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); + const fileChanged = changedFiles.some(file => file.startsWith('iac/mainnet-fork')); + return fileChanged + - name: "Build & Push cli image" - if: steps.check_changes_build.outputs.result == 'true' + if: steps.check_l1_changes.outputs.result == 'true' timeout-minutes: 40 # Run the build steps for each image with version and arch, push to dockerhub run: | earthly-ci --no-output --push ./yarn-project+export-cli --DIST_TAG=${{ env.DEPLOY_TAG }} + - name: "Build & Push mainnet-fork image" + if: steps.check_fork_changes.outputs.result == 'true' + timeout-minutes: 40 + run: | + earthly-ci --no-output --push ./iac/mainnet-fork/+export-mainnet-fork --DIST_TAG=${{ env.DEPLOY_TAG }} + terraform_deploy: runs-on: ubuntu-latest needs: build @@ -83,20 +104,17 @@ jobs: with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-west-2 + aws-region: eu-west-2 - - name: Check if L1 contracts need deployment - id: check_changes_release - uses: actions/github-script@v7 - with: - script: | - const { execSync } = require('child_process'); - const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); - const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); - return fileChanged + - name: Deploy mainnet fork + if: needs.build.outputs.mainnet_fork_changed == 'true' + working-directory: ./iac/mainnet-fork + run: | + terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" + terraform apply -input=false -auto-approve - name: Deploy L1 Contracts - if: steps.check_changes_release.outputs.result == 'true' + if: needs.build.outputs.l1_contracts_changed == 'true' || needs.build.outputs.mainnet_fork_changed == 'true' run: | docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ @@ -106,7 +124,7 @@ jobs: ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - name: Apply l1-contracts Terraform - if: steps.check_changes_release.outputs.result == 'true' + if: needs.build.outputs.l1_contracts_changed == 'true' || needs.build.outputs.mainnet_fork_changed == 'true' working-directory: ./l1-contracts/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" @@ -124,10 +142,10 @@ jobs: terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/aztec-node" - name: Taint node filesystem if L1 contracts are redeployed - if: steps.check_changes_release.outputs.result == 'true' + if: needs.build.outputs.l1_contracts_changed == 'true' working-directory: ./yarn-project/aztec/terraform/node run: | - terraform state list | grep 'aws_efs_file_system.node_data_store' | xargs -n1 terraform taint + terraform taint aws_efs_file_system.node_data_store - name: Deploy Aztec Nodes working-directory: ./yarn-project/aztec/terraform/node diff --git a/iac/mainnet-fork/terraform/main.tf b/iac/mainnet-fork/terraform/main.tf index 026469d3920b..13d32e4afeb2 100644 --- a/iac/mainnet-fork/terraform/main.tf +++ b/iac/mainnet-fork/terraform/main.tf @@ -117,7 +117,7 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" { [ { "name": "${var.DEPLOY_TAG}-mainnet-fork", - "image": "${var.DOCKERHUB_ACCOUNT}/mainnet-fork:aztec-dev", + "image": "${var.DOCKERHUB_ACCOUNT}/mainnet-fork:${var.DEPLOY_TAG}", "essential": true, "environment": [ { @@ -134,7 +134,7 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" { }, { "name": "CHAIN_ID", - "value": "31337" + "value": "${var.CHAIN_ID}" }, { "name": "SNAPSHOT_FREQUENCY", diff --git a/iac/mainnet-fork/terraform/variables.tf b/iac/mainnet-fork/terraform/variables.tf index 6291254aa1e1..18efa1232060 100644 --- a/iac/mainnet-fork/terraform/variables.tf +++ b/iac/mainnet-fork/terraform/variables.tf @@ -17,3 +17,7 @@ variable "DOCKERHUB_ACCOUNT" { variable "DEPLOY_TAG" { type = string } + +variable "CHAIN_ID" { + type = string +} diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 20725c32103d..3fda57f65d15 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -103,7 +103,6 @@ resource "aws_service_discovery_service" "aztec-node" { # Configure an EFS filesystem. resource "aws_efs_file_system" "node_data_store" { - count = local.node_count creation_token = "${var.DEPLOY_TAG}-node-${count.index + 1}-data" throughput_mode = "provisioned" provisioned_throughput_in_mibps = 20 @@ -119,14 +118,14 @@ resource "aws_efs_file_system" "node_data_store" { resource "aws_efs_mount_target" "public_az1" { count = local.node_count - file_system_id = aws_efs_file_system.node_data_store[count.index].id + file_system_id = aws_efs_file_system.node_data_store.id subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_id security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] } resource "aws_efs_mount_target" "public_az2" { count = local.node_count - file_system_id = aws_efs_file_system.node_data_store[count.index].id + file_system_id = aws_efs_file_system.node_data_store.id subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_id security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] } @@ -145,7 +144,7 @@ resource "aws_ecs_task_definition" "aztec-node" { volume { name = "efs-data-store" efs_volume_configuration { - file_system_id = aws_efs_file_system.node_data_store[count.index].id + file_system_id = aws_efs_file_system.node_data_store.id } } @@ -254,7 +253,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { "name": "API_PREFIX", - "value": "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}" + "value": "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}" }, { "name": "P2P_TCP_LISTEN_ADDR", @@ -382,7 +381,7 @@ resource "aws_alb_target_group" "aztec-node-http" { deregistration_delay = 5 health_check { - path = "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/status" + path = "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}/status" matcher = "200" interval = 10 healthy_threshold = 2 @@ -407,7 +406,7 @@ resource "aws_lb_listener_rule" "api" { condition { path_pattern { - values = ["/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}*"] + values = ["/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}*"] } } } diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index 36cb280645fe..4ffc1affa9af 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -16,7 +16,7 @@ variable "SEQ_2_PUBLISHER_PRIVATE_KEY" { variable "CHAIN_ID" { type = string - default = 31337 + default = 677692 } variable "NODE_P2P_TCP_PORT" { From 46851262f21794c1fddbd7de21e156a3f9062f4d Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 11:01:05 +0000 Subject: [PATCH 44/94] redeploy l1 --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From f6bf309756f56323762f8bf87de3cbd45099b388 Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 11:01:46 +0000 Subject: [PATCH 45/94] use aztecprotocol account --- iac/mainnet-fork/Earthfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iac/mainnet-fork/Earthfile b/iac/mainnet-fork/Earthfile index fb480d1801de..22e9ab97f572 100644 --- a/iac/mainnet-fork/Earthfile +++ b/iac/mainnet-fork/Earthfile @@ -26,4 +26,4 @@ export-mainnet-fork: FROM +build ARG DIST_TAG="aztec-dev" ARG ARCH - SAVE IMAGE --push spypsy/mainnet-fork:${DIST_TAG}${ARCH:+-$ARCH} + SAVE IMAGE --push aztecprotocol/mainnet-fork:${DIST_TAG}${ARCH:+-$ARCH} From f2c24f23a1e06002666d76d7f0bbcabee1e0649b Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 11:30:29 +0000 Subject: [PATCH 46/94] fix fork working-directory --- .github/workflows/devnet-deploys.yml | 2 +- iac/mainnet-fork/Earthfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 40336167ae7e..c24c888f830a 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -108,7 +108,7 @@ jobs: - name: Deploy mainnet fork if: needs.build.outputs.mainnet_fork_changed == 'true' - working-directory: ./iac/mainnet-fork + working-directory: ./iac/mainnet-fork/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" terraform apply -input=false -auto-approve diff --git a/iac/mainnet-fork/Earthfile b/iac/mainnet-fork/Earthfile index 22e9ab97f572..29370d327e86 100644 --- a/iac/mainnet-fork/Earthfile +++ b/iac/mainnet-fork/Earthfile @@ -19,7 +19,7 @@ build: # Expose port 80 EXPOSE 80 - # Set entrypoint + # Set entrypoint. ENTRYPOINT ["sh", "-c", "./scripts/run_nginx_anvil.sh"] export-mainnet-fork: From dc33049f12551490cfb4cbd5d841f237e31dd783 Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 12:46:33 +0000 Subject: [PATCH 47/94] try jsonencode --- iac/mainnet-fork/terraform/main.tf | 98 +++++++++++++++--------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/iac/mainnet-fork/terraform/main.tf b/iac/mainnet-fork/terraform/main.tf index 13d32e4afeb2..0b5908fc2ea7 100644 --- a/iac/mainnet-fork/terraform/main.tf +++ b/iac/mainnet-fork/terraform/main.tf @@ -113,57 +113,55 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" { } } - container_definitions = < Date: Fri, 5 Jul 2024 12:57:19 +0000 Subject: [PATCH 48/94] fix node_data_store count reference --- yarn-project/aztec/terraform/node/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 3fda57f65d15..21e6dbdf2cb8 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -103,12 +103,12 @@ resource "aws_service_discovery_service" "aztec-node" { # Configure an EFS filesystem. resource "aws_efs_file_system" "node_data_store" { - creation_token = "${var.DEPLOY_TAG}-node-${count.index + 1}-data" + creation_token = "${var.DEPLOY_TAG}-node-data" throughput_mode = "provisioned" provisioned_throughput_in_mibps = 20 tags = { - Name = "${var.DEPLOY_TAG}-node-${count.index + 1}-data" + Name = "${var.DEPLOY_TAG}-node-data" } lifecycle_policy { From 8ded39bff042a401fc3b7789b1ec7ac1bd199dd4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Fri, 5 Jul 2024 13:27:41 +0000 Subject: [PATCH 49/94] remove count from mount targets --- yarn-project/aztec/terraform/node/main.tf | 2 -- 1 file changed, 2 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 21e6dbdf2cb8..ea36b58f75a6 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -117,14 +117,12 @@ resource "aws_efs_file_system" "node_data_store" { } resource "aws_efs_mount_target" "public_az1" { - count = local.node_count file_system_id = aws_efs_file_system.node_data_store.id subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_id security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] } resource "aws_efs_mount_target" "public_az2" { - count = local.node_count file_system_id = aws_efs_file_system.node_data_store.id subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_id security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_public_id] From c204257a04dcd447c1d5bb08fb6b9411cbe9e20b Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 8 Jul 2024 15:09:22 +0000 Subject: [PATCH 50/94] redeploy l1 contracts --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From 65b504f6eecdebe8a8e4a131ac589d0de62afd15 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 09:15:58 +0000 Subject: [PATCH 51/94] pass aws secrets --- .github/workflows/devnet-deploys.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 97d34fdf9855..ed05853a9ed6 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -12,6 +12,7 @@ env: GIT_COMMIT: ${{ github.sha }} DEPLOY_TAG: devnet FILE_PATH: ./l1-contracts/addresses.txt + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol TF_VAR_CHAIN_ID: 677692 @@ -51,7 +52,10 @@ jobs: timeout-minutes: 40 # Run the build steps for each image with version and arch, push to dockerhub run: | - earthly-ci --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} + earthly-ci \ + --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ + --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ + --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} - name: Check if L1 contracts need deployment id: check_l1_changes From 51aecb67b1fa5ff8e7239b83ebf0e283e12bfe8e Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 09:16:24 +0000 Subject: [PATCH 52/94] remove unnecessary ref --- .github/workflows/devnet-deploys.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index ed05853a9ed6..d1f880cb6f86 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -12,7 +12,6 @@ env: GIT_COMMIT: ${{ github.sha }} DEPLOY_TAG: devnet FILE_PATH: ./l1-contracts/addresses.txt - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol TF_VAR_CHAIN_ID: 677692 From 307cc831f16441094400b5bc8f7ad824cfeb7ef7 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 09:36:10 +0000 Subject: [PATCH 53/94] Redeploy L1 --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From 7d986e6390aa8f46cf4d20f8b74f85aabba1fe26 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 09:50:11 +0000 Subject: [PATCH 54/94] remove duplicate tasks --- .github/workflows/devnet-deploys.yml | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index d1f880cb6f86..26b08b4ed92b 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -133,32 +133,6 @@ jobs: terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" terraform apply -input=false -auto-approve - - name: Check if L1 contracts need deployment - id: check_changes_release - uses: actions/github-script@v7 - with: - script: | - const { execSync } = require('child_process'); - const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); - const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); - return fileChanged - - name: Deploy L1 Contracts - if: steps.check_changes_release.outputs.result == 'true' - run: | - docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} - docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ - deploy-l1-contracts -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ - -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ - | tee ${{ env.FILE_PATH }} - ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} - - - name: Apply l1-contracts Terraform - if: steps.check_changes_release.outputs.result == 'true' - working-directory: ./l1-contracts/terraform - run: | - terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/l1-contracts" - terraform apply -input=false -auto-approve - - name: Deploy P2P Bootstrap Nodes working-directory: ./yarn-project/p2p-bootstrap/terraform run: | From bcec41515d903574773777589746c9f55c967a3d Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 10:06:28 +0000 Subject: [PATCH 55/94] keep artifacts folder --- l1-contracts/REDEPLOY | 2 +- yarn-project/Earthfile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..5407c1d3c077 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 220f8292c8e6..11be6d1af3f5 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -197,7 +197,6 @@ cli-build: aztec.js/dest/main.js \ end-to-end \ **/src \ - **/artifacts SAVE ARTIFACT /usr/src /usr/src cli: From 3946297e0d0446451415abd386b32ab3827322a8 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 11:34:01 +0000 Subject: [PATCH 56/94] fix typo --- yarn-project/Earthfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/Earthfile b/yarn-project/Earthfile index 11be6d1af3f5..45e3cd2b0e5a 100644 --- a/yarn-project/Earthfile +++ b/yarn-project/Earthfile @@ -196,7 +196,7 @@ cli-build: ../barretenberg/ts/dest/browser \ aztec.js/dest/main.js \ end-to-end \ - **/src \ + **/src SAVE ARTIFACT /usr/src /usr/src cli: From ea015322f36b2bed3dc4b10a4822becf9338c414 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 11:43:17 +0000 Subject: [PATCH 57/94] Redeploy L1 again --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 5407c1d3c077..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -3 \ No newline at end of file +1 \ No newline at end of file From a888e254f1c75501319e139321c6eceb111fea7d Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 11:59:48 +0000 Subject: [PATCH 58/94] fix mnemonic issue --- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 4 +++- l1-contracts/REDEPLOY | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index 38788424ed74..6e4e4b330f6b 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -13,12 +13,14 @@ trap 'kill $(jobs -p)' SIGTERM HOST="0.0.0.0" PORT=8544 ETHEREUM_HOST=$HOST:$PORT +# Stripping double quotations from the mnemonic seed phrase +MNEMONIC_STRIPPED=${MNEMONIC//\"/} # Data directory for anvil state mkdir -p /data # Run anvil silently -.foundry/bin/anvil --silent --host $HOST -p $PORT -m "$MNEMONIC" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >/dev/null & +.foundry/bin/anvil --silent --host $HOST -p $PORT -m "$MNEMONIC_STRIPPED" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >/dev/null & echo "Waiting for ethereum host at $ETHEREUM_HOST..." while ! curl -s $ETHEREUM_HOST >/dev/null; do sleep 1; done diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From 8b81f0844c318086964f0fdf69c2d703c440d0a6 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 13:00:51 +0000 Subject: [PATCH 59/94] debug mnemonic issue --- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index 6e4e4b330f6b..dcc9169bf935 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -14,7 +14,9 @@ HOST="0.0.0.0" PORT=8544 ETHEREUM_HOST=$HOST:$PORT # Stripping double quotations from the mnemonic seed phrase +echo "stripping double quotations from the mnemonic seed phrase: ${MNEMONIC:0:10}..." MNEMONIC_STRIPPED=${MNEMONIC//\"/} +echo "result: ${MNEMONIC_STRIPPED:0:10}..." # Data directory for anvil state mkdir -p /data From e21f530344c99464bd13e48163cf0c494cef3236 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 14:29:22 +0000 Subject: [PATCH 60/94] redeploy fork, contracts --- .github/workflows/devnet-deploys.yml | 1 + l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 26b08b4ed92b..ac6534f0c9da 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -114,6 +114,7 @@ jobs: working-directory: ./iac/mainnet-fork/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" + terraform taint aws_ecs_service.aztec_mainnet_fork terraform apply -input=false -auto-approve - name: Deploy L1 Contracts diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..fe5516129dec 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From b17c018fba806337b7fa00d0183cc540bda76427 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 15:11:29 +0000 Subject: [PATCH 61/94] fix deploy-l1-contracts cmd --- l1-contracts/REDEPLOY | 2 +- .../archiver/src/archiver/archiver.ts | 2 +- yarn-project/archiver/src/archiver/config.ts | 7 ++++++ yarn-project/aztec-faucet/src/bin/index.ts | 4 +-- .../aztec-node/src/aztec-node/server.test.ts | 3 +-- .../aztec-node/src/aztec-node/server.ts | 2 +- yarn-project/aztec/src/sandbox.ts | 2 +- yarn-project/cli/src/cmds/bridge_l1_gas.ts | 4 +-- .../cli/src/cmds/deploy_l1_contracts.ts | 4 +-- yarn-project/cli/src/cmds/get_l1_balance.ts | 4 +-- yarn-project/cli/src/cmds/sequencers.ts | 6 ++--- yarn-project/cli/src/index.ts | 25 +++++++------------ yarn-project/cli/src/utils.ts | 4 +-- yarn-project/ethereum/src/index.ts | 14 ++++------- 14 files changed, 39 insertions(+), 44 deletions(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index fe5516129dec..90bef203f0ca 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Append value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index b03ce4d21153..7d8c179ac50c 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -108,7 +108,7 @@ export class Archiver implements ArchiveSource { telemetry: TelemetryClient, blockUntilSynced = true, ): Promise { - const chain = createEthereumChain(config.rpcUrl, config.apiKey); + const chain = createEthereumChain(config.rpcUrl); const publicClient = createPublicClient({ chain: chain.chainInfo, transport: http(chain.rpcUrl), diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index 6badf1a7dc8d..bd7911ede144 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -22,6 +22,11 @@ export interface ArchiverConfig { */ apiKey?: string; + /** + * The chain's ID + */ + chainId?: number; + /** * The polling interval in ms for retrieving new L2 blocks and encrypted logs. */ @@ -54,6 +59,7 @@ export interface ArchiverConfig { export function getConfigEnvVars(): ArchiverConfig { const { ETHEREUM_HOST, + CHAIN_ID, ARCHIVER_POLLING_INTERVAL_MS, ARCHIVER_VIEM_POLLING_INTERVAL_MS, AVAILABILITY_ORACLE_CONTRACT_ADDRESS, @@ -82,6 +88,7 @@ export function getConfigEnvVars(): ArchiverConfig { }; return { rpcUrl: ETHEREUM_HOST || '', + chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil archiverPollingIntervalMS: ARCHIVER_POLLING_INTERVAL_MS ? +ARCHIVER_POLLING_INTERVAL_MS : 1_000, viemPollingIntervalMS: ARCHIVER_VIEM_POLLING_INTERVAL_MS ? +ARCHIVER_VIEM_POLLING_INTERVAL_MS : 1_000, apiKey: API_KEY, diff --git a/yarn-project/aztec-faucet/src/bin/index.ts b/yarn-project/aztec-faucet/src/bin/index.ts index ad96b2839b6d..d433c7a6fe9d 100644 --- a/yarn-project/aztec-faucet/src/bin/index.ts +++ b/yarn-project/aztec-faucet/src/bin/index.ts @@ -60,7 +60,7 @@ function checkThrottle(address: Hex) { * @param address - Address to receive some ETH */ async function transferEth(address: string) { - const chain = createEthereumChain(rpcUrl, apiKey); + const chain = createEthereumChain(rpcUrl, chainId); const account = privateKeyToAccount(privateKey); const walletClient = createWalletClient({ @@ -114,7 +114,7 @@ function createRouter(apiPrefix: string) { async function main() { logger.info(`Setting up Aztec Faucet...`); - const chain = createEthereumChain(rpcUrl, apiKey); + const chain = createEthereumChain(rpcUrl, chainId); if (chain.chainInfo.id !== chainId) { throw new Error(`Incorrect chain id, expected ${chain.chainInfo.id}`); } diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts index a1d559bf498a..5b1ecc103f70 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.test.ts @@ -7,10 +7,9 @@ describe('aztec node service', () => { it('fails to create Aztec Node if given incorrect chain id', async () => { const config: Partial = { rpcUrl: 'testnet', - apiKey: '12345', chainId: 12345, // not the testnet chain id }; - const ethereumChain = createEthereumChain(config.rpcUrl!, config.apiKey); + const ethereumChain = createEthereumChain(config.rpcUrl!, config.chainId); await expect(() => AztecNodeService.createAndSync(config as AztecNodeConfig, new NoopTelemetryClient()), ).rejects.toThrow( diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 7a2e8a8ba045..e364df1892e9 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -132,7 +132,7 @@ export class AztecNodeService implements AztecNode { storeLog = createDebugLogger('aztec:node:lmdb'), ): Promise { telemetry ??= new NoopTelemetryClient(); - const ethereumChain = createEthereumChain(config.rpcUrl, config.apiKey); + const ethereumChain = createEthereumChain(config.rpcUrl, config.chainId); //validate that the actual chain id matches that specified in configuration if (config.chainId !== ethereumChain.chainInfo.id) { throw new Error( diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 437dbb99baac..d79a176651fd 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -54,7 +54,7 @@ const localAnvil = foundry; * Helper function that waits for the Ethereum RPC server to respond before deploying L1 contracts. */ async function waitThenDeploy(config: AztecNodeConfig, deployFunction: () => Promise) { - const chain = createEthereumChain(config.rpcUrl, config.apiKey); + const chain = createEthereumChain(config.rpcUrl, config.chainId); // wait for ETH RPC to respond to a request. const publicClient = createPublicClient({ chain: chain.chainInfo, diff --git a/yarn-project/cli/src/cmds/bridge_l1_gas.ts b/yarn-project/cli/src/cmds/bridge_l1_gas.ts index 08428f979bb8..4ad550ad770f 100644 --- a/yarn-project/cli/src/cmds/bridge_l1_gas.ts +++ b/yarn-project/cli/src/cmds/bridge_l1_gas.ts @@ -10,13 +10,13 @@ export async function bridgeL1Gas( recipient: AztecAddress, rpcUrl: string, l1RpcUrl: string, - apiKey: string, + chainId: number, mnemonic: string, log: LogFn, debugLogger: DebugLogger, ) { // Prepare L1 client - const chain = createEthereumChain(l1RpcUrl, apiKey); + const chain = createEthereumChain(l1RpcUrl, chainId); const { publicClient, walletClient } = createL1Clients(chain.rpcUrl, mnemonic, chain.chainInfo); // Prepare L2 client diff --git a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts b/yarn-project/cli/src/cmds/deploy_l1_contracts.ts index 629dcaec1c76..fbbfd5ecf9f8 100644 --- a/yarn-project/cli/src/cmds/deploy_l1_contracts.ts +++ b/yarn-project/cli/src/cmds/deploy_l1_contracts.ts @@ -4,13 +4,13 @@ import { deployAztecContracts } from '../utils.js'; export async function deployL1Contracts( rpcUrl: string, - apiKey: string, + chainId: number, privateKey: string, mnemonic: string, log: LogFn, debugLogger: DebugLogger, ) { - const { l1ContractAddresses } = await deployAztecContracts(rpcUrl, apiKey, privateKey, mnemonic, debugLogger); + const { l1ContractAddresses } = await deployAztecContracts(rpcUrl, chainId, privateKey, mnemonic, debugLogger); log('\n'); log(`Rollup Address: ${l1ContractAddresses.rollupAddress.toString()}`); diff --git a/yarn-project/cli/src/cmds/get_l1_balance.ts b/yarn-project/cli/src/cmds/get_l1_balance.ts index 26163191c427..7bc07a406b81 100644 --- a/yarn-project/cli/src/cmds/get_l1_balance.ts +++ b/yarn-project/cli/src/cmds/get_l1_balance.ts @@ -11,14 +11,14 @@ export async function getL1Balance( who: EthAddress, rpcUrl: string, l1RpcUrl: string, - apiKey: string, + chainId: number, log: LogFn, debugLogger: DebugLogger, ) { const client = await createCompatibleClient(rpcUrl, debugLogger); const { l1ContractAddresses } = await client.getNodeInfo(); - const chain = createEthereumChain(l1RpcUrl, apiKey); + const chain = createEthereumChain(l1RpcUrl, chainId); const publicClient = createPublicClient({ chain: chain.chainInfo, transport: http(chain.rpcUrl) }); const gasL1 = getContract({ diff --git a/yarn-project/cli/src/cmds/sequencers.ts b/yarn-project/cli/src/cmds/sequencers.ts index cc53c083547f..b0be25d3d656 100644 --- a/yarn-project/cli/src/cmds/sequencers.ts +++ b/yarn-project/cli/src/cmds/sequencers.ts @@ -13,7 +13,7 @@ export async function sequencers(opts: { mnemonic?: string; rpcUrl: string; l1RpcUrl: string; - apiKey: string; + chainId: number; blockNumber?: number; log: LogFn; debugLogger: DebugLogger; @@ -25,14 +25,14 @@ export async function sequencers(opts: { mnemonic, rpcUrl, l1RpcUrl, - apiKey, + chainId, log, debugLogger, } = opts; const client = await createCompatibleClient(rpcUrl, debugLogger); const { l1ContractAddresses } = await client.getNodeInfo(); - const chain = createEthereumChain(l1RpcUrl, apiKey); + const chain = createEthereumChain(l1RpcUrl, chainId); const publicClient = createPublicClient({ chain: chain.chainInfo, transport: http(chain.rpcUrl) }); const walletClient = mnemonic diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 786a0b09c747..7247b724e465 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -34,7 +34,7 @@ const getLocalhost = () => .catch(() => 'localhost'); const LOCALHOST = await getLocalhost(); -const { ETHEREUM_HOST = `http://${LOCALHOST}:8545`, PRIVATE_KEY, API_KEY, CLI_VERSION } = process.env; +const { ETHEREUM_HOST = `http://${LOCALHOST}:8545`, PRIVATE_KEY, CHAIN_ID = '31337', CLI_VERSION } = process.env; class Command extends CommanderCommand { addOptions(options: Option[]) { @@ -81,7 +81,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', ETHEREUM_HOST, ) - .option('-a, --api-key ', 'Api key for the ethereum host', API_KEY) + .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) .requiredOption('-p, --private-key ', 'The private key to use for deployment', PRIVATE_KEY) .option( '-m, --mnemonic ', @@ -90,14 +90,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { ) .action(async options => { const { deployL1Contracts } = await import('./cmds/deploy_l1_contracts.js'); - await deployL1Contracts( - options.rpcUrl, - options.apiKey ?? '', - options.privateKey, - options.mnemonic, - log, - debugLogger, - ); + await deployL1Contracts(options.rpcUrl, options.chainId, options.privateKey, options.mnemonic, log, debugLogger); }); program @@ -153,7 +146,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', ETHEREUM_HOST, ) - .option('-a, --api-key ', 'Api key for the ethereum host', API_KEY) + .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) .option( '-m, --mnemonic ', 'The mnemonic to use for deriving the Ethereum address that will mint and bridge', @@ -167,7 +160,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { recipient, options.rpcUrl, options.l1RpcUrl, - options.apiKey ?? '', + options.chainId, options.mnemonic, log, debugLogger, @@ -183,11 +176,11 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', ETHEREUM_HOST, ) - .option('-a, --api-key ', 'Api key for the ethereum host', API_KEY) + .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) .addOption(pxeOption) .action(async (who, options) => { const { getL1Balance } = await import('./cmds/get_l1_balance.js'); - await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.apiKey ?? '', log, debugLogger); + await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.chainId, log, debugLogger); }); program @@ -661,7 +654,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', ETHEREUM_HOST, ) - .option('-a, --api-key ', 'Api key for the ethereum host', API_KEY) + .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) .option( '-m, --mnemonic ', 'The mnemonic for the sender of the tx', @@ -677,7 +670,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { mnemonic: options.mnemonic, rpcUrl: options.rpcUrl, l1RpcUrl: options.l1RpcUrl, - apiKey: options.apiKey ?? '', + chainId: options.chainId, blockNumber: options.blockNumber, log, debugLogger, diff --git a/yarn-project/cli/src/utils.ts b/yarn-project/cli/src/utils.ts index 0d8d714d533c..e370d7c999fc 100644 --- a/yarn-project/cli/src/utils.ts +++ b/yarn-project/cli/src/utils.ts @@ -51,7 +51,7 @@ export function getFunctionArtifact(artifact: ContractArtifact, fnName: string): */ export async function deployAztecContracts( rpcUrl: string, - apiKey: string, + chainId: number, privateKey: string, mnemonic: string, debugLogger: DebugLogger, @@ -72,7 +72,7 @@ export async function deployAztecContracts( const account = !privateKey ? mnemonicToAccount(mnemonic!) : privateKeyToAccount(`${privateKey.startsWith('0x') ? '' : '0x'}${privateKey}` as `0x${string}`); - const chain = createEthereumChain(rpcUrl, apiKey); + const chain = createEthereumChain(rpcUrl, chainId); const l1Artifacts: L1ContractArtifactsForDeployment = { registry: { contractAbi: RegistryAbi, diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index 8ef2db852366..b7641d299d72 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -1,7 +1,6 @@ import { foundry } from 'viem/chains'; import { type EthereumChain } from './ethereum_chain.js'; -import { createTestnetChain } from './testnet.js'; export * from './testnet.js'; export * from './deploy_l1_contracts.js'; @@ -13,15 +12,12 @@ export * from './constants.js'; * @param rpcUrl - The rpc url of the chain or a chain identifier (e.g. 'testnet') * @param apiKey - An optional API key for the chain client. */ -export function createEthereumChain(rpcUrl: string, apiKey?: string) { - if (rpcUrl === 'testnet') { - if (apiKey === undefined || apiKey === '') { - throw new Error('API Key must be provided for aztec testnet'); - } - return createTestnetChain(apiKey!); - } +export function createEthereumChain(rpcUrl: string, chainId = 31337) { return { - chainInfo: foundry, + chainInfo: { + ...foundry, + id: chainId, + }, rpcUrl, } as EthereumChain; } From 7e9cad36407ac9e3d0e061be85f49b2b525e2702 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 15:24:29 +0000 Subject: [PATCH 62/94] fix build --- l1-contracts/REDEPLOY | 4 ++-- .../sequencer-client/src/global_variable_builder/config.ts | 4 ++-- .../src/global_variable_builder/viem-reader.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 90bef203f0ca..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ -# Append value to force redeploy -2 \ No newline at end of file +# Change value to force redeploy +1 \ No newline at end of file diff --git a/yarn-project/sequencer-client/src/global_variable_builder/config.ts b/yarn-project/sequencer-client/src/global_variable_builder/config.ts index 156b0c38c939..c64c10a1cd00 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/config.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/config.ts @@ -9,9 +9,9 @@ export interface GlobalReaderConfig { */ rpcUrl: string; /** - * The API key of the ethereum host. + * The chain ID of the ethereum host. */ - apiKey?: string; + chainId: number; /** * The deployed l1 contract addresses diff --git a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts index bb1acd8720c8..fc1fae219564 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts @@ -23,9 +23,9 @@ export class ViemReader implements L1GlobalReader { private publicClient: PublicClient; constructor(config: GlobalReaderConfig) { - const { rpcUrl, apiKey, l1Contracts } = config; + const { rpcUrl, chainId, l1Contracts } = config; - const chain = createEthereumChain(rpcUrl, apiKey); + const chain = createEthereumChain(rpcUrl, chainId); this.publicClient = createPublicClient({ chain: chain.chainInfo, From f275b027bd252507cbb2dc803e37de565b76b6c8 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 16:55:24 +0100 Subject: [PATCH 63/94] fix fn call --- l1-contracts/REDEPLOY | 2 +- yarn-project/sequencer-client/src/publisher/config.ts | 4 ++-- yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index e78fa7c2d19d..bff5f421e690 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -15,9 +15,9 @@ export interface TxSenderConfig { rpcUrl: string; /** - * The API key of the ethereum host. + * The chain ID of the ethereum host. */ - apiKey?: string; + chainId?: string; /** * The number of confirmations required. diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index c630f0436386..b733f3fdbbbf 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -46,8 +46,8 @@ export class ViemTxSender implements L1PublisherTxSender { private account: PrivateKeyAccount; constructor(config: TxSenderConfig) { - const { rpcUrl, apiKey, publisherPrivateKey, l1Contracts } = config; - const chain = createEthereumChain(rpcUrl, apiKey); + const { rpcUrl, chainId, publisherPrivateKey, l1Contracts } = config; + const chain = createEthereumChain(rpcUrl, chainId); this.account = privateKeyToAccount(publisherPrivateKey); const walletClient = createWalletClient({ account: this.account, From b25a0f51f0de41e08b1f80a48e75627cbef39582 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 9 Jul 2024 17:10:00 +0100 Subject: [PATCH 64/94] fix chainId type --- l1-contracts/REDEPLOY | 2 +- yarn-project/sequencer-client/src/publisher/config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index bff5f421e690..94a98ab1a900 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -17,7 +17,7 @@ export interface TxSenderConfig { /** * The chain ID of the ethereum host. */ - chainId?: string; + chainId?: number; /** * The number of confirmations required. From bf8742f89e2c2c650da56971c2615246a60512e8 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 08:40:07 +0000 Subject: [PATCH 65/94] remove old apiKey ref --- yarn-project/sequencer-client/src/config.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index bcf7b95c06c2..3fe6c79a1cc7 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -39,7 +39,6 @@ export function getConfigEnvVars(): SequencerClientConfig { ETHEREUM_HOST, CHAIN_ID, VERSION, - API_KEY, SEQ_REQUIRED_CONFIRMATIONS, SEQ_PUBLISH_RETRY_INTERVAL_MS, SEQ_TX_POLLING_INTERVAL_MS, @@ -85,7 +84,6 @@ export function getConfigEnvVars(): SequencerClientConfig { rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '', chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil version: VERSION ? +VERSION : 1, // 1 is our default version - apiKey: API_KEY, requiredConfirmations: SEQ_REQUIRED_CONFIRMATIONS ? +SEQ_REQUIRED_CONFIRMATIONS : 1, l1BlockPublishRetryIntervalMS: SEQ_PUBLISH_RETRY_INTERVAL_MS ? +SEQ_PUBLISH_RETRY_INTERVAL_MS : 1_000, transactionPollingIntervalMS: SEQ_TX_POLLING_INTERVAL_MS ? +SEQ_TX_POLLING_INTERVAL_MS : 1_000, From 56e02ffd77f2ebe85662f10a5b7ee06a0e44cd51 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 09:25:11 +0000 Subject: [PATCH 66/94] fix test issue --- .../end-to-end/src/composed/integration_l1_publisher.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index c797483e3724..10fd95cd5f7a 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -99,7 +99,7 @@ describe('L1Publisher integration', () => { let blockSource: MockProxy; - const chainId = createEthereumChain(config.rpcUrl, config.apiKey).chainInfo.id; + const chainId = createEthereumChain(config.rpcUrl, config.chainId).chainInfo.id; let coinbase: EthAddress; let feeRecipient: AztecAddress; @@ -151,7 +151,6 @@ describe('L1Publisher integration', () => { publisher = getL1Publisher({ rpcUrl: config.rpcUrl, - apiKey: '', requiredConfirmations: 1, l1Contracts: l1ContractAddresses, publisherPrivateKey: sequencerPK, From f31926ba74ec8e5cf5fadbcdae976f32fbce97a4 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 09:51:44 +0000 Subject: [PATCH 67/94] redeploy --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From dfc82cd9981bf8c7c85f42abccd27eb4a739d341 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 10:02:12 +0000 Subject: [PATCH 68/94] pass chainId in cli command --- .github/workflows/devnet-deploys.yml | 6 ++++-- l1-contracts/REDEPLOY | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index ac6534f0c9da..719788bec0ff 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -12,6 +12,7 @@ env: GIT_COMMIT: ${{ github.sha }} DEPLOY_TAG: devnet FILE_PATH: ./l1-contracts/addresses.txt + CHAIN_ID: 677692 # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol TF_VAR_CHAIN_ID: 677692 @@ -121,9 +122,10 @@ jobs: if: needs.build.outputs.l1_contracts_changed == 'true' || needs.build.outputs.mainnet_fork_changed == 'true' run: | docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} - docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} \ - deploy-l1-contracts -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ + -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ + -c ${{ env.CHAIN_ID }} \ | tee ${{ env.FILE_PATH }} ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From ee12c95c71d8834c1483fbd9e6d659abb2a3eaf1 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 10:14:59 +0000 Subject: [PATCH 69/94] only use chainId chainInfo --- yarn-project/ethereum/src/index.ts | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index b7641d299d72..c28fc4bc2dfb 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -12,12 +12,23 @@ export * from './constants.js'; * @param rpcUrl - The rpc url of the chain or a chain identifier (e.g. 'testnet') * @param apiKey - An optional API key for the chain client. */ -export function createEthereumChain(rpcUrl: string, chainId = 31337) { - return { - chainInfo: { - ...foundry, - id: chainId, - }, - rpcUrl, - } as EthereumChain; +export function createEthereumChain(rpcUrl: string, chainId?: number) { + if (chainId) { + return { + chainInfo: { + id: chainId, + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + }, + rpcUrl, + } as EthereumChain; + } else { + return { + chainInfo: foundry, + rpcUrl, + } as EthereumChain; + } } From 267c7674759191fac6e91c0e954b1e2c0bd31571 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 10:15:13 +0000 Subject: [PATCH 70/94] redeploy --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From a8fe490975d49830273994a4d1e43170ba191546 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 11:40:34 +0000 Subject: [PATCH 71/94] convert chainId to number in cli --- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- l1-contracts/REDEPLOY | 2 +- yarn-project/cli/src/index.ts | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index dcc9169bf935..157e4ae245bc 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -2,7 +2,7 @@ set -eum pipefail -# Replace API_KEY in nginx config +# Replace API_KEY in nginx config. echo "Replacing api key with $API_KEY in nginx config..." sed -i 's/{{API_KEY}}/'$API_KEY'/' /etc/nginx/gateway.conf diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts index 7247b724e465..e4a872ec6f50 100644 --- a/yarn-project/cli/src/index.ts +++ b/yarn-project/cli/src/index.ts @@ -90,7 +90,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { ) .action(async options => { const { deployL1Contracts } = await import('./cmds/deploy_l1_contracts.js'); - await deployL1Contracts(options.rpcUrl, options.chainId, options.privateKey, options.mnemonic, log, debugLogger); + await deployL1Contracts(options.rpcUrl, +options.chainId, options.privateKey, options.mnemonic, log, debugLogger); }); program @@ -160,7 +160,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { recipient, options.rpcUrl, options.l1RpcUrl, - options.chainId, + +options.chainId, options.mnemonic, log, debugLogger, @@ -180,7 +180,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { .addOption(pxeOption) .action(async (who, options) => { const { getL1Balance } = await import('./cmds/get_l1_balance.js'); - await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.chainId, log, debugLogger); + await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, +options.chainId, log, debugLogger); }); program @@ -670,7 +670,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { mnemonic: options.mnemonic, rpcUrl: options.rpcUrl, l1RpcUrl: options.l1RpcUrl, - chainId: options.chainId, + chainId: +options.chainId, blockNumber: options.blockNumber, log, debugLogger, From 3428f969921cc29193f36181834aa4de9b943c02 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 11:42:08 +0000 Subject: [PATCH 72/94] taint fork efs --- .github/workflows/devnet-deploys.yml | 2 +- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- l1-contracts/REDEPLOY | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 719788bec0ff..0c29172d0208 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -115,7 +115,7 @@ jobs: working-directory: ./iac/mainnet-fork/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" - terraform taint aws_ecs_service.aztec_mainnet_fork + terraform taint aws_ecs_service.aztec_mainnet_fork aws_efs_file_system.aztec_mainnet_fork_data_store terraform apply -input=false -auto-approve - name: Deploy L1 Contracts diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index 157e4ae245bc..dcc9169bf935 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -2,7 +2,7 @@ set -eum pipefail -# Replace API_KEY in nginx config. +# Replace API_KEY in nginx config echo "Replacing api key with $API_KEY in nginx config..." sed -i 's/{{API_KEY}}/'$API_KEY'/' /etc/nginx/gateway.conf diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From 7c84351289f195d38f8f764fccde3400fcde069f Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 12:07:46 +0000 Subject: [PATCH 73/94] use replace instead of taint --- .github/workflows/devnet-deploys.yml | 3 +-- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- l1-contracts/REDEPLOY | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 0c29172d0208..7f1ba0728039 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -115,8 +115,7 @@ jobs: working-directory: ./iac/mainnet-fork/terraform run: | terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" - terraform taint aws_ecs_service.aztec_mainnet_fork aws_efs_file_system.aztec_mainnet_fork_data_store - terraform apply -input=false -auto-approve + terraform apply -input=false -auto-approve -replace="aws_ecs_service.aztec_mainnet_fork" -replace="aws_efs_file_system.aztec_mainnet_fork_data_store" - name: Deploy L1 Contracts if: needs.build.outputs.l1_contracts_changed == 'true' || needs.build.outputs.mainnet_fork_changed == 'true' diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index dcc9169bf935..157e4ae245bc 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -2,7 +2,7 @@ set -eum pipefail -# Replace API_KEY in nginx config +# Replace API_KEY in nginx config. echo "Replacing api key with $API_KEY in nginx config..." sed -i 's/{{API_KEY}}/'$API_KEY'/' /etc/nginx/gateway.conf diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From 26268f85a2be83263565aed377f8820d591e1124 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 12:24:38 +0000 Subject: [PATCH 74/94] wait for fork deployment --- .github/scripts/wait_for_fork.sh | 17 +++++++++++++++++ .github/workflows/devnet-deploys.yml | 5 +++++ iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- l1-contracts/REDEPLOY | 2 +- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100755 .github/scripts/wait_for_fork.sh diff --git a/.github/scripts/wait_for_fork.sh b/.github/scripts/wait_for_fork.sh new file mode 100755 index 000000000000..c6952e9fbab4 --- /dev/null +++ b/.github/scripts/wait_for_fork.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +DEPLOY_TAG=$1 +TEST_FORK_API_KEY=$2 + +# When destroying and applying mainnet fork terraform, it may not be +# ready for a while, as it must register with DNS etc. +# This script waits on a healthy status from the fork - a valid response to the chainid request +# We retry every 20 seconds, and wait for a total of 5 minutes (15 times) +export ETHEREUM_HOST="https://$DEPLOY_TAG-mainnet-fork.aztec.network:8545/$TEST_FORK_API_KEY" + +curl -H "Content-Type: application/json" -X POST --data '{"method":"eth_chainId","params":[],"id":49,"jsonrpc":"2.0"}' \ + --connect-timeout 30 \ + --retry 15 \ + --retry-delay 20 \ + $ETHEREUM_HOST diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index 7f1ba0728039..e8fc7e167b8f 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -117,6 +117,11 @@ jobs: terraform init -input=false -backend-config="key=${{ env.DEPLOY_TAG }}/mainnet-fork" terraform apply -input=false -auto-approve -replace="aws_ecs_service.aztec_mainnet_fork" -replace="aws_efs_file_system.aztec_mainnet_fork_data_store" + - name: Wait for mainnet fork deployment + if: needs.build.outputs.mainnet_fork_changed == 'true' + run: | + ./.github/scripts/wait_for_fork.sh ${{ env.DEPLOY_TAG }} ${{ secrets.FORK_API_KEY }} + - name: Deploy L1 Contracts if: needs.build.outputs.l1_contracts_changed == 'true' || needs.build.outputs.mainnet_fork_changed == 'true' run: | diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index 157e4ae245bc..dcc9169bf935 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -2,7 +2,7 @@ set -eum pipefail -# Replace API_KEY in nginx config. +# Replace API_KEY in nginx config echo "Replacing api key with $API_KEY in nginx config..." sed -i 's/{{API_KEY}}/'$API_KEY'/' /etc/nginx/gateway.conf diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file From f284e8d9d66227f4d5ede60983b8eb234605c23e Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 13:02:04 +0000 Subject: [PATCH 75/94] unique ecs volume root_directory --- yarn-project/aztec/terraform/node/main.tf | 202 +++++++++++----------- 1 file changed, 99 insertions(+), 103 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index ea36b58f75a6..f1779ffe6a93 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -143,194 +143,190 @@ resource "aws_ecs_task_definition" "aztec-node" { name = "efs-data-store" efs_volume_configuration { file_system_id = aws_efs_file_system.node_data_store.id + root_directory = "/node-${count.index + 1}" } } - container_definitions = < Date: Wed, 10 Jul 2024 13:17:58 +0000 Subject: [PATCH 76/94] bool vars in quotes --- yarn-project/aztec/terraform/node/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index f1779ffe6a93..7f1875ee5e0c 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -277,7 +277,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { name = "P2P_ENABLED" - value = var.P2P_ENABLED + value = "${var.P2P_ENABLED}" }, { name = "CHAIN_ID" @@ -309,7 +309,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { name = "PROVER_REAL_PROOFS" - value = var.PROVING_ENABLED + value = "${var.PROVING_ENABLED}" } ] mountPoints = [ From bff5b13d2b62e4969ee59774495eb3c82d14a903 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 10 Jul 2024 13:27:36 +0000 Subject: [PATCH 77/94] use tostring --- yarn-project/aztec/terraform/node/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 7f1875ee5e0c..389508e32ba9 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -277,7 +277,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { name = "P2P_ENABLED" - value = "${var.P2P_ENABLED}" + value = tostring(var.P2P_ENABLED) }, { name = "CHAIN_ID" @@ -309,7 +309,7 @@ resource "aws_ecs_task_definition" "aztec-node" { }, { name = "PROVER_REAL_PROOFS" - value = "${var.PROVING_ENABLED}" + value = tostring(var.PROVING_ENABLED) } ] mountPoints = [ From a336b56055d6ebcc9e882a859f922ee8de2eff42 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 11 Jul 2024 13:11:18 +0000 Subject: [PATCH 78/94] fix common EFS volume --- .gitignore | 3 + yarn-project/aztec/terraform/node/main.tf | 379 ++++++++++++---------- yarn-project/cli/package.json | 3 +- 3 files changed, 204 insertions(+), 181 deletions(-) diff --git a/.gitignore b/.gitignore index 464d5e0ba9d8..71f1e37b5e27 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,6 @@ cmake-build-debug .arg .secret .bb_tmp + +# Terraform +*.tfvars \ No newline at end of file diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 389508e32ba9..3d774e55c927 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -57,7 +57,7 @@ locals { publisher_private_keys = [var.SEQ_1_PUBLISHER_PRIVATE_KEY, var.SEQ_2_PUBLISHER_PRIVATE_KEY] node_p2p_private_keys = [var.NODE_1_PRIVATE_KEY, var.NODE_2_PRIVATE_KEY] node_count = length(local.publisher_private_keys) - data_dir = "/usr/src/yarn-project/aztec/data" + data_dir = "/usr/src/yarn-project/aztec" } output "node_count" { @@ -142,190 +142,209 @@ resource "aws_ecs_task_definition" "aztec-node" { volume { name = "efs-data-store" efs_volume_configuration { + root_directory = "/" file_system_id = aws_efs_file_system.node_data_store.id - root_directory = "/node-${count.index + 1}" } } - container_definitions = jsonencode([{ - name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" - image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}" - command = ["start", "--node", "--archiver", "--sequencer", "--prover"] - essential = true - memoryReservation = 3776 - portMappings = [ - { - containerPort = 80 - }, - { - containerPort = var.NODE_P2P_TCP_PORT + count.index - protocol = "tcp" - }, - { - containerPort = var.NODE_P2P_UDP_PORT + count.index - protocol = "udp" + container_definitions = jsonencode([ + { + name = "init-container" + image = "amazonlinux:latest" + essential = false + command = ["sh", "-c", "mkdir -p ${local.data_dir}/node_${count.index + 1}"] + mountPoints = [ + { + containerPath = local.data_dir + sourceVolume = "efs-data-store" + } + ] + }, + { + name = "${var.DEPLOY_TAG}-aztec-node-${count.index + 1}" + image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}" + command = ["start", "--node", "--archiver", "--sequencer", "--prover"] + essential = true + memoryReservation = 3776 + portMappings = [ + { + containerPort = 80 + }, + { + containerPort = var.NODE_P2P_TCP_PORT + count.index + protocol = "tcp" + }, + { + containerPort = var.NODE_P2P_UDP_PORT + count.index + protocol = "udp" + } + ] + environment = [ + { + name = "NODE_ENV" + value = "production" + }, + { + name = "DEPLOY_TAG" + value = var.DEPLOY_TAG + }, + { + name = "DEPLOY_AZTEC_CONTRACTS" + value = "false" + }, + { + name = "AZTEC_PORT" + value = "80" + }, + { + name = "DEBUG" + value = "aztec:*,-json-rpc:json_proxy:*,-aztec:avm_simulator:*" + }, + { + name = "ETHEREUM_HOST" + value = "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" + }, + { + name = "DATA_DIRECTORY" + value = "${local.data_dir}_${count.index + 1}" + }, + { + name = "ARCHIVER_POLLING_INTERVAL" + value = "10000" + }, + { + name = "SEQ_RETRY_INTERVAL" + value = "10000" + }, + { + name = "SEQ_MAX_TX_PER_BLOCK" + value = var.SEQ_MAX_TX_PER_BLOCK + }, + { + name = "SEQ_MIN_TX_PER_BLOCK" + value = var.SEQ_MIN_TX_PER_BLOCK + }, + { + name = "SEQ_PUBLISHER_PRIVATE_KEY" + value = local.publisher_private_keys[count.index] + }, + { + name = "ROLLUP_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.rollup_contract_address + }, + { + name = "INBOX_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.inbox_contract_address + }, + { + name = "OUTBOX_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.outbox_contract_address + }, + { + name = "REGISTRY_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.registry_contract_address + }, + { + name = "AVAILABILITY_ORACLE_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.availability_oracle_contract_address + }, + { + name = "GAS_TOKEN_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.gas_token_contract_address + }, + { + name = "GAS_PORTAL_CONTRACT_ADDRESS" + value = data.terraform_remote_state.l1_contracts.outputs.gas_portal_contract_address + }, + { + name = "API_KEY" + value = var.API_KEY + }, + { + name = "API_PREFIX" + value = "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}" + }, + { + name = "P2P_TCP_LISTEN_ADDR" + value = "0.0.0.0:${var.NODE_P2P_TCP_PORT + count.index}" + }, + { + name = "P2P_UDP_LISTEN_ADDR" + value = "0.0.0.0:${var.NODE_P2P_UDP_PORT + count.index}" + }, + { + name = "P2P_TCP_ANNOUNCE_ADDR" + value = ":${var.NODE_P2P_TCP_PORT + count.index}" + }, + { + name = "P2P_UDP_ANNOUNCE_ADDR" + value = ":${var.NODE_P2P_UDP_PORT + count.index}" + }, + { + name = "P2P_QUERY_FOR_IP" + value = "true" + }, + { + name = "BOOTSTRAP_NODES" + value = "enr:-JO4QNvVz7yYHQ4nzZQ7JCng9LOQkDnFqeLntDEfrAAGOS_eMFWOE4ZlyjYKb3J-yCGu8xoXXEUnUqI8iTJj1K43KH0EjWF6dGVjX25ldHdvcmsBgmlkgnY0gmlwhA0pYm6Jc2VjcDI1NmsxoQLzGvsxdzM9VhPjrMnxLmMxvrEcvSg-QZq7PWXDnnIy1YN1ZHCCnjQ" + }, + { + name = "P2P_ENABLED" + value = tostring(var.P2P_ENABLED) + }, + { + name = "CHAIN_ID" + value = var.CHAIN_ID + }, + { + name = "PEER_ID_PRIVATE_KEY" + value = local.node_p2p_private_keys[count.index] + }, + { + name = "P2P_MIN_PEERS" + value = var.P2P_MIN_PEERS + }, + { + name = "P2P_MAX_PEERS" + value = var.P2P_MAX_PEERS + }, + { + name = "P2P_BLOCK_CHECK_INTERVAL_MS" + value = "1000" + }, + { + name = "P2P_PEER_CHECK_INTERVAL_MS" + value = "2000" + }, + { + name = "PROVER_AGENTS" + value = "0" + }, + { + name = "PROVER_REAL_PROOFS" + value = tostring(var.PROVING_ENABLED) + } + ] + mountPoints = [ + { + containerPath = "${local.data_dir}/node_${count.index + 1}" + sourceVolume = "efs-data-store" + } + ] + dependsOn = [ + { + containerName = "init-container" + condition = "COMPLETE" + } + ] + logConfiguration = { + logDriver = "awslogs" + options = { + "awslogs-group" = "/fargate/service/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}" + "awslogs-region" = "eu-west-2" + "awslogs-stream-prefix" = "ecs" + } } - ] - environment = [ - { - name = "NODE_ENV" - value = "production" - }, - { - name = "DEPLOY_TAG" - value = var.DEPLOY_TAG - }, - { - name = "DEPLOY_AZTEC_CONTRACTS" - value = "false" - }, - { - name = "AZTEC_PORT" - value = "80" - }, - { - name = "DEBUG" - value = "aztec:*,-json-rpc:json_proxy:*,-aztec:avm_simulator:*" - }, - { - name = "ETHEREUM_HOST" - value = "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" - }, - { - name = "DATA_DIRECTORY" - value = local.data_dir - }, - { - name = "ARCHIVER_POLLING_INTERVAL" - value = "10000" - }, - { - name = "SEQ_RETRY_INTERVAL" - value = "10000" - }, - { - name = "SEQ_MAX_TX_PER_BLOCK" - value = var.SEQ_MAX_TX_PER_BLOCK - }, - { - name = "SEQ_MIN_TX_PER_BLOCK" - value = var.SEQ_MIN_TX_PER_BLOCK - }, - { - name = "SEQ_PUBLISHER_PRIVATE_KEY" - value = local.publisher_private_keys[count.index] - }, - { - name = "ROLLUP_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.rollup_contract_address - }, - { - name = "INBOX_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.inbox_contract_address - }, - { - name = "OUTBOX_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.outbox_contract_address - }, - { - name = "REGISTRY_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.registry_contract_address - }, - { - name = "AVAILABILITY_ORACLE_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.availability_oracle_contract_address - }, - { - name = "GAS_TOKEN_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.gas_token_contract_address - }, - { - name = "GAS_PORTAL_CONTRACT_ADDRESS" - value = data.terraform_remote_state.l1_contracts.outputs.gas_portal_contract_address - }, - { - name = "API_KEY" - value = var.API_KEY - }, - { - name = "API_PREFIX" - value = "/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}/${var.API_KEY}" - }, - { - name = "P2P_TCP_LISTEN_ADDR" - value = "0.0.0.0:${var.NODE_P2P_TCP_PORT + count.index}" - }, - { - name = "P2P_UDP_LISTEN_ADDR" - value = "0.0.0.0:${var.NODE_P2P_UDP_PORT + count.index}" - }, - { - name = "P2P_TCP_ANNOUNCE_ADDR" - value = ":${var.NODE_P2P_TCP_PORT + count.index}" - }, - { - name = "P2P_UDP_ANNOUNCE_ADDR" - value = ":${var.NODE_P2P_UDP_PORT + count.index}" - }, - { - name = "P2P_QUERY_FOR_IP" - value = "true" - }, - { - name = "BOOTSTRAP_NODES" - value = "enr:-JO4QNvVz7yYHQ4nzZQ7JCng9LOQkDnFqeLntDEfrAAGOS_eMFWOE4ZlyjYKb3J-yCGu8xoXXEUnUqI8iTJj1K43KH0EjWF6dGVjX25ldHdvcmsBgmlkgnY0gmlwhA0pYm6Jc2VjcDI1NmsxoQLzGvsxdzM9VhPjrMnxLmMxvrEcvSg-QZq7PWXDnnIy1YN1ZHCCnjQ" - }, - { - name = "P2P_ENABLED" - value = tostring(var.P2P_ENABLED) - }, - { - name = "CHAIN_ID" - value = var.CHAIN_ID - }, - { - name = "PEER_ID_PRIVATE_KEY" - value = local.node_p2p_private_keys[count.index] - }, - { - name = "P2P_MIN_PEERS" - value = var.P2P_MIN_PEERS - }, - { - name = "P2P_MAX_PEERS" - value = var.P2P_MAX_PEERS - }, - { - name = "P2P_BLOCK_CHECK_INTERVAL_MS" - value = "1000" - }, - { - name = "P2P_PEER_CHECK_INTERVAL_MS" - value = "2000" - }, - { - name = "PROVER_AGENTS" - value = "0" - }, - { - name = "PROVER_REAL_PROOFS" - value = tostring(var.PROVING_ENABLED) - } - ] - mountPoints = [ - { - containerPath = local.data_dir - sourceVolume = "efs-data-store" - } - ] - logConfiguration = { - logDriver = "awslogs" - options = { - "awslogs-group" = "/fargate/service/${var.DEPLOY_TAG}/aztec-node-${count.index + 1}" - "awslogs-region" = "eu-west-2" - "awslogs-stream-prefix" = "ecs" - } - } }]) } diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index 34b2c2a91b93..dbbfcf4c594d 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -20,7 +20,8 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "start": "yarn build && node --no-warnings ./dest/bin/index.js" + "start": "yarn build && node --no-warnings ./dest/bin/index.js", + "start:debug": "node ${NODE_ARGS:-} --inspect-brk=0.0.0.0:9221 ./dest/bin/index.js" }, "inherits": [ "../package.common.json" From d0c19bc61cd5c183cc0a665f048dba5474e1d829 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 11 Jul 2024 13:23:09 +0000 Subject: [PATCH 79/94] redeploy --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From b1f496fa88c07353e92b726b71663cde4d8b4db2 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 11 Jul 2024 13:56:18 +0000 Subject: [PATCH 80/94] use descriptive option names --- .github/workflows/devnet-deploys.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index e8fc7e167b8f..905501017d12 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -127,9 +127,9 @@ jobs: run: | docker pull aztecprotocol/cli:${{ env.DEPLOY_TAG }} docker run aztecprotocol/cli:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ - -p ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ - -u https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ - -c ${{ env.CHAIN_ID }} \ + --private-key ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ + --rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ + --chain-id ${{ env.CHAIN_ID }} \ | tee ${{ env.FILE_PATH }} ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} From ad33b3a11f8356a907396894d7dd0f0ff232b258 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 11 Jul 2024 15:23:51 +0000 Subject: [PATCH 81/94] PR Fixes --- yarn-project/aztec-faucet/src/bin/index.ts | 2 -- .../aztec-node/src/aztec-node/server.test.ts | 19 ------------------- yarn-project/cli/package.json | 4 ++-- 3 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 yarn-project/aztec-node/src/aztec-node/server.test.ts diff --git a/yarn-project/aztec-faucet/src/bin/index.ts b/yarn-project/aztec-faucet/src/bin/index.ts index d433c7a6fe9d..3a73aefecd2b 100644 --- a/yarn-project/aztec-faucet/src/bin/index.ts +++ b/yarn-project/aztec-faucet/src/bin/index.ts @@ -13,7 +13,6 @@ import { privateKeyToAccount } from 'viem/accounts'; const { FAUCET_PORT = 8082, API_PREFIX = '', - API_KEY = '', RPC_URL = '', CHAIN_ID = '', PRIVATE_KEY = '', @@ -24,7 +23,6 @@ const { const logger = createDebugLogger('aztec:faucet'); const rpcUrl = RPC_URL; -const apiKey = API_KEY; const chainId = +CHAIN_ID; const privateKey: Hex = PRIVATE_KEY ? createHex(PRIVATE_KEY) : NULL_KEY; const interval = +INTERVAL; diff --git a/yarn-project/aztec-node/src/aztec-node/server.test.ts b/yarn-project/aztec-node/src/aztec-node/server.test.ts deleted file mode 100644 index 5b1ecc103f70..000000000000 --- a/yarn-project/aztec-node/src/aztec-node/server.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createEthereumChain } from '@aztec/ethereum'; -import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; - -import { type AztecNodeConfig, AztecNodeService } from '../index.js'; - -describe('aztec node service', () => { - it('fails to create Aztec Node if given incorrect chain id', async () => { - const config: Partial = { - rpcUrl: 'testnet', - chainId: 12345, // not the testnet chain id - }; - const ethereumChain = createEthereumChain(config.rpcUrl!, config.chainId); - await expect(() => - AztecNodeService.createAndSync(config as AztecNodeConfig, new NoopTelemetryClient()), - ).rejects.toThrow( - `RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`, - ); - }); -}); diff --git a/yarn-project/cli/package.json b/yarn-project/cli/package.json index dbbfcf4c594d..19ce62c4caa1 100644 --- a/yarn-project/cli/package.json +++ b/yarn-project/cli/package.json @@ -20,7 +20,7 @@ "formatting": "run -T prettier --check ./src && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests", - "start": "yarn build && node --no-warnings ./dest/bin/index.js", + "start": "node --no-warnings ./dest/bin/index.js", "start:debug": "node ${NODE_ARGS:-} --inspect-brk=0.0.0.0:9221 ./dest/bin/index.js" }, "inherits": [ @@ -107,4 +107,4 @@ "engines": { "node": ">=18" } -} +} \ No newline at end of file From 55c88fb8d67c07a0bf2c9c479e2dc57264abf330 Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 15 Jul 2024 14:31:51 +0000 Subject: [PATCH 82/94] Remove old index.ts --- l1-contracts/REDEPLOY | 2 +- yarn-project/cli/src/index.ts | 681 ---------------------------------- 2 files changed, 1 insertion(+), 682 deletions(-) delete mode 100644 yarn-project/cli/src/index.ts diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..ccf126002ba9 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 \ No newline at end of file diff --git a/yarn-project/cli/src/index.ts b/yarn-project/cli/src/index.ts deleted file mode 100644 index e4a872ec6f50..000000000000 --- a/yarn-project/cli/src/index.ts +++ /dev/null @@ -1,681 +0,0 @@ -import { Fr, PublicKeys } from '@aztec/circuits.js'; -import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; -import { fileURLToPath } from '@aztec/foundation/url'; - -import { Command as CommanderCommand, Option } from 'commander'; -import { lookup } from 'dns/promises'; -import { readFileSync } from 'fs'; -import { dirname, resolve } from 'path'; - -import { FeeOpts } from './fees.js'; -import { - parseAztecAddress, - parseBigint, - parseEthereumAddress, - parseField, - parseFieldFromHexString, - parseOptionalAztecAddress, - parseOptionalInteger, - parseOptionalLogId, - parseOptionalTxHash, - parsePartialAddress, - parsePrivateKey, - parsePublicKey, - parseTxHash, -} from './parse_args.js'; - -/** - * If we can successfully resolve 'host.docker.internal', then we are running in a container, and we should treat - * localhost as being host.docker.internal. - */ -const getLocalhost = () => - lookup('host.docker.internal') - .then(() => 'host.docker.internal') - .catch(() => 'localhost'); - -const LOCALHOST = await getLocalhost(); -const { ETHEREUM_HOST = `http://${LOCALHOST}:8545`, PRIVATE_KEY, CHAIN_ID = '31337', CLI_VERSION } = process.env; - -class Command extends CommanderCommand { - addOptions(options: Option[]) { - options.forEach(option => this.addOption(option)); - return this; - } - - override createCommand(name?: string): Command { - return new Command(name); - } -} - -/** - * Returns commander program that defines the CLI. - * @param log - Console logger. - * @param debugLogger - Debug logger. - * @returns The CLI. - */ -export function getProgram(log: LogFn, debugLogger: DebugLogger): Command { - const program = new Command(); - - const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../package.json'); - const cliVersion: string = CLI_VERSION || JSON.parse(readFileSync(packageJsonPath).toString()).version; - const logJson = (obj: object) => log(JSON.stringify(obj, null, 2)); - - program.name('aztec-cli').description('CLI for interacting with Aztec.').version(cliVersion); - - const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') - .env('PXE_URL') - .default(`http://${LOCALHOST}:8080`) - .makeOptionMandatory(true); - - const createPrivateKeyOption = (description: string, mandatory: boolean) => - new Option('-e, --private-key ', description) - .env('PRIVATE_KEY') - .argParser(parsePrivateKey) - .makeOptionMandatory(mandatory); - - program - .command('deploy-l1-contracts') - .description('Deploys all necessary Ethereum contracts for Aztec.') - .requiredOption( - '-u, --rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) - .requiredOption('-p, --private-key ', 'The private key to use for deployment', PRIVATE_KEY) - .option( - '-m, --mnemonic ', - 'The mnemonic to use in deployment', - 'test test test test test test test test test test test junk', - ) - .action(async options => { - const { deployL1Contracts } = await import('./cmds/deploy_l1_contracts.js'); - await deployL1Contracts(options.rpcUrl, +options.chainId, options.privateKey, options.mnemonic, log, debugLogger); - }); - - program - .command('deploy-l1-verifier') - .description('Deploys the rollup verifier contract') - .requiredOption( - '--eth-rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .addOption(pxeOption) - .requiredOption('-p, --private-key ', 'The private key to use for deployment', PRIVATE_KEY) - .option( - '-m, --mnemonic ', - 'The mnemonic to use in deployment', - 'test test test test test test test test test test test junk', - ) - .requiredOption('--verifier ', 'Either mock or real', 'real') - .option('--bb ', 'Path to bb binary') - .option('--bb-working-dir ', 'Path to bb working directory') - .action(async options => { - const { deployMockVerifier, deployUltraVerifier } = await import('./cmds/deploy_l1_verifier.js'); - if (options.verifier === 'mock') { - await deployMockVerifier( - options.ethRpcUrl, - options.privateKey, - options.mnemonic, - options.rpcUrl, - log, - debugLogger, - ); - } else { - await deployUltraVerifier( - options.ethRpcUrl, - options.privateKey, - options.mnemonic, - options.rpcUrl, - options.bb, - options.bbWorkingDir, - log, - debugLogger, - ); - } - }); - - program - .command('bridge-l1-gas') - .description('Mints L1 gas tokens and pushes them to L2.') - .argument('', 'The amount of gas tokens to mint and bridge.', parseBigint) - .argument('', 'Aztec address of the recipient.', parseAztecAddress) - .requiredOption( - '--l1-rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) - .option( - '-m, --mnemonic ', - 'The mnemonic to use for deriving the Ethereum address that will mint and bridge', - 'test test test test test test test test test test test junk', - ) - .addOption(pxeOption) - .action(async (amount, recipient, options) => { - const { bridgeL1Gas } = await import('./cmds/bridge_l1_gas.js'); - await bridgeL1Gas( - amount, - recipient, - options.rpcUrl, - options.l1RpcUrl, - +options.chainId, - options.mnemonic, - log, - debugLogger, - ); - }); - - program - .command('get-l1-balance') - .description('Gets the balance of gas tokens in L1 for the given Ethereum address.') - .argument('', 'Ethereum address to check.', parseEthereumAddress) - .requiredOption( - '--l1-rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) - .addOption(pxeOption) - .action(async (who, options) => { - const { getL1Balance } = await import('./cmds/get_l1_balance.js'); - await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, +options.chainId, log, debugLogger); - }); - - program - .command('generate-keys') - .summary('Generates encryption and signing private keys.') - .description('Generates and encryption and signing private key pair.') - .option( - '-m, --mnemonic', - 'An optional mnemonic string used for the private key generation. If not provided, random private key will be generated.', - ) - .action(async _options => { - const { generateKeys } = await import('./cmds/generate_private_key.js'); - const { privateEncryptionKey, privateSigningKey } = generateKeys(); - log(`Encryption Private Key: ${privateEncryptionKey}\nSigning Private key: ${privateSigningKey}\n`); - }); - - program - .command('generate-p2p-private-key') - .summary('Generates a LibP2P peer private key.') - .description('Generates a private key that can be used for running a node on a LibP2P network.') - .action(async () => { - const { generateP2PPrivateKey } = await import('./cmds/generate_p2p_private_key.js'); - await generateP2PPrivateKey(log); - }); - - program - .command('create-account') - .description( - 'Creates an aztec account that can be used for sending transactions. Registers the account on the PXE and deploys an account contract. Uses a Schnorr single-key account which uses the same key for encryption and authentication (not secure for production usage).', - ) - .summary('Creates an aztec account that can be used for sending transactions.') - .option( - '--skip-initialization', - 'Skip initializing the account contract. Useful for publicly deploying an existing account.', - ) - .option('--public-deploy', 'Publicly deploys the account and registers the class if needed.') - .addOption(createPrivateKeyOption('Private key for account. Uses random by default.', false)) - .addOption(pxeOption) - .addOptions(FeeOpts.getOptions()) - .option( - '--register-only', - 'Just register the account on the PXE. Do not deploy or initialize the account contract.', - ) - // `options.wait` is default true. Passing `--no-wait` will set it to false. - // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue - .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction') - .action(async args => { - const { createAccount } = await import('./cmds/create_account.js'); - const { rpcUrl, privateKey, wait, registerOnly, skipInitialization, publicDeploy } = args; - await createAccount( - rpcUrl, - privateKey, - registerOnly, - skipInitialization, - publicDeploy, - wait, - FeeOpts.fromCli(args, log), - debugLogger, - log, - ); - }); - - program - .command('bootstrap') - .description('Bootstrap the blockchain') - .addOption(pxeOption) - .action(async options => { - const { bootstrap } = await import('./cmds/bootstrap.js'); - await bootstrap(options.rpcUrl, log); - }); - - program - .command('deploy') - .description('Deploys a compiled Aztec.nr contract to Aztec.') - .argument( - '', - "A compiled Aztec.nr contract's artifact in JSON format or name of a contract artifact exported by @aztec/noir-contracts.js", - ) - .option('--initialize ', 'The contract initializer function to call', 'constructor') - .option('--no-initialize') - .option('-a, --args ', 'Contract constructor arguments', []) - .addOption(pxeOption) - .option( - '-k, --public-key ', - 'Optional encryption public key for this address. Set this value only if this contract is expected to receive private notes, which will be encrypted using this public key.', - parsePublicKey, - ) - .option( - '-s, --salt ', - 'Optional deployment salt as a hex string for generating the deployment address.', - parseFieldFromHexString, - ) - .option('--universal', 'Do not mix the sender address into the deployment.') - .addOption(createPrivateKeyOption("The sender's private key.", true)) - .option('--json', 'Emit output as json') - // `options.wait` is default true. Passing `--no-wait` will set it to false. - // https://github.com/tj/commander.js#other-option-types-negatable-boolean-and-booleanvalue - .option('--no-wait', 'Skip waiting for the contract to be deployed. Print the hash of deployment transaction') - .option('--class-registration', 'Register the contract class. Only has to be done once') - .option('--no-class-registration', 'Skip registering the contract class') - .option('--public-deployment', 'Deploy the public bytecode of contract') - .option('--no-public-deployment', "Skip deploying the contract's public bytecode") - .addOptions(FeeOpts.getOptions()) - .action(async (artifactPath, opts) => { - const { deploy } = await import('./cmds/deploy.js'); - const { - json, - rpcUrl, - publicKey, - args: rawArgs, - salt, - wait, - privateKey, - classRegistration, - initialize, - publicDeployment, - universal, - } = opts; - await deploy( - artifactPath, - json, - rpcUrl, - publicKey ? PublicKeys.fromString(publicKey) : undefined, - rawArgs, - salt, - privateKey, - typeof initialize === 'string' ? initialize : undefined, - !publicDeployment, - !classRegistration, - typeof initialize === 'string' ? false : initialize, - universal, - wait, - FeeOpts.fromCli(opts, log), - debugLogger, - log, - logJson, - ); - }); - - program - .command('add-contract') - .description( - 'Adds an existing contract to the PXE. This is useful if you have deployed a contract outside of the PXE and want to use it with the PXE.', - ) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address

', 'Aztec address of the contract.', parseAztecAddress) - .requiredOption('--init-hash ', 'Initialization hash', parseFieldFromHexString) - .option('--salt ', 'Optional deployment salt', parseFieldFromHexString) - .option('-p, --public-key ', 'Optional public key for this contract', parsePublicKey) - .option('--portal-address
', 'Optional address to a portal contract on L1', parseEthereumAddress) - .option('--deployer-address
', 'Optional address of the contract deployer', parseAztecAddress) - .addOption(pxeOption) - .action(async options => { - const { addContract } = await import('./cmds/add_contract.js'); - await addContract( - options.rpcUrl, - options.contractArtifact, - options.contractAddress, - options.initHash, - options.salt ?? Fr.ZERO, - options.publicKey, - options.deployerAddress, - debugLogger, - log, - ); - }); - - program - .command('get-tx') - .description('Gets the receipt for the specified transaction hash.') - .argument('', 'A transaction hash to get the receipt for.', parseTxHash) - .addOption(pxeOption) - .action(async (txHash, options) => { - const { getTx } = await import('./cmds/get_tx.js'); - await getTx(options.rpcUrl, txHash, debugLogger, log); - }); - - program - .command('get-block') - .description('Gets info for a given block or latest.') - .argument('[blockNumber]', 'Block height', parseOptionalInteger) - .option('-f, --follow', 'Keep polling for new blocks') - .addOption(pxeOption) - .action(async (blockNumber, options) => { - const { getBlock } = await import('./cmds/get_block.js'); - await getBlock(options.rpcUrl, blockNumber, options.follow, debugLogger, log); - }); - - program - .command('get-contract-data') - .description('Gets information about the Aztec contract deployed at the specified address.') - .argument('', 'Aztec address of the contract.', parseAztecAddress) - .addOption(pxeOption) - .option('-b, --include-bytecode ', "Include the contract's public function bytecode, if any.", false) - .action(async (contractAddress, options) => { - const { getContractData } = await import('./cmds/get_contract_data.js'); - await getContractData(options.rpcUrl, contractAddress, options.includeBytecode, debugLogger, log); - }); - - program - .command('get-logs') - .description('Gets all the unencrypted logs from an intersection of all the filter params.') - .option('-tx, --tx-hash ', 'A transaction hash to get the receipt for.', parseOptionalTxHash) - .option( - '-fb, --from-block ', - 'Initial block number for getting logs (defaults to 1).', - parseOptionalInteger, - ) - .option('-tb, --to-block ', 'Up to which block to fetch logs (defaults to latest).', parseOptionalInteger) - .option('-al --after-log ', 'ID of a log after which to fetch the logs.', parseOptionalLogId) - .option('-ca, --contract-address
', 'Contract address to filter logs by.', parseOptionalAztecAddress) - .addOption(pxeOption) - .option('--follow', 'If set, will keep polling for new logs until interrupted.') - .action(async ({ txHash, fromBlock, toBlock, afterLog, contractAddress, rpcUrl, follow }) => { - const { getLogs } = await import('./cmds/get_logs.js'); - await getLogs(txHash, fromBlock, toBlock, afterLog, contractAddress, rpcUrl, follow, debugLogger, log); - }); - - program - .command('register-recipient') - .description('Register a recipient in the PXE.') - .requiredOption('-a, --address ', "The account's Aztec address.", parseAztecAddress) - .requiredOption('-p, --public-key ', 'The account public key.', parsePublicKey) - .requiredOption( - '-pa, --partial-address ', - 'The partially computed address of the account contract.', - parsePartialAddress, - ) - .addOption(pxeOption) - .action(async ({ address, publicKey, partialAddress, rpcUrl }) => { - const { registerRecipient } = await import('./cmds/register_recipient.js'); - await registerRecipient(address, publicKey, partialAddress, rpcUrl, debugLogger, log); - }); - - program - .command('get-accounts') - .description('Gets all the Aztec accounts stored in the PXE.') - .addOption(pxeOption) - .option('--json', 'Emit output as json') - .action(async (options: any) => { - const { getAccounts } = await import('./cmds/get_accounts.js'); - await getAccounts(options.rpcUrl, options.json, debugLogger, log, logJson); - }); - - program - .command('get-account') - .description('Gets an account given its Aztec address.') - .argument('
', 'The Aztec address to get account for', parseAztecAddress) - .addOption(pxeOption) - .action(async (address, options) => { - const { getAccount } = await import('./cmds/get_account.js'); - await getAccount(address, options.rpcUrl, debugLogger, log); - }); - - program - .command('get-recipients') - .description('Gets all the recipients stored in the PXE.') - .addOption(pxeOption) - .action(async (options: any) => { - const { getRecipients } = await import('./cmds/get_recipients.js'); - await getRecipients(options.rpcUrl, debugLogger, log); - }); - - program - .command('get-recipient') - .description('Gets a recipient given its Aztec address.') - .argument('
', 'The Aztec address to get recipient for', parseAztecAddress) - .addOption(pxeOption) - .action(async (address, options) => { - const { getRecipient } = await import('./cmds/get_recipient.js'); - await getRecipient(address, options.rpcUrl, debugLogger, log); - }); - - program - .command('get-balance') - .description('Gets the token balance for an account. Does NOT format according to decimals.') - .argument('
', 'Aztec address to query balance for.', parseAztecAddress) - .option('-t, --token-address
', 'Token address to query balance for (defaults to gas token).') - .addOption(pxeOption) - .action(async (address, options) => { - const { getBalance } = await import('./cmds/get_balance.js'); - await getBalance(address, options.tokenAddress, options.rpcUrl, debugLogger, log); - }); - - program - .command('send') - .description('Calls a function on an Aztec contract.') - .argument('', 'Name of function to execute') - .option('-a, --args [functionArgs...]', 'Function arguments', []) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .addOption(createPrivateKeyOption("The sender's private key.", true)) - .addOption(pxeOption) - .option('--no-wait', 'Print transaction hash without waiting for it to be mined') - .addOptions(FeeOpts.getOptions()) - .action(async (functionName, options) => { - const { send } = await import('./cmds/send.js'); - await send( - functionName, - options.args, - options.contractArtifact, - options.contractAddress, - options.privateKey, - options.rpcUrl, - !options.noWait, - FeeOpts.fromCli(options, log), - debugLogger, - log, - ); - }); - - program - .command('call') - .description( - 'Simulates the execution of a view (read-only) function on a deployed contract, without modifying state.', - ) - .argument('', 'Name of function to call') - .option('-a, --args [functionArgs...]', 'Function arguments', []) - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-ca, --contract-address
', 'Aztec address of the contract.', parseAztecAddress) - .option('-f, --from ', 'Aztec address of the caller. If empty, will use the first account from RPC.') - .addOption(pxeOption) - .action(async (functionName, options) => { - const { call } = await import('./cmds/call.js'); - await call( - functionName, - options.args, - options.contractArtifact, - options.contractAddress, - options.from, - options.rpcUrl, - debugLogger, - log, - ); - }); - - program - .command('add-note') - .description('Adds a note to the database in the PXE.') - .argument('
', 'The Aztec address of the note owner.', parseAztecAddress) - .argument('', 'Aztec address of the contract.', parseAztecAddress) - .argument('', 'The storage slot of the note.', parseField) - .argument('', 'The type ID of the note.', parseField) - .argument('', 'The tx hash of the tx containing the note.', parseTxHash) - .requiredOption('-n, --note [note...]', 'The members of a Note serialized as hex strings.', []) - .addOption(pxeOption) - .action(async (address, contractAddress, storageSlot, noteTypeId, txHash, options) => { - const { addNote } = await import('./cmds/add_note.js'); - await addNote( - address, - contractAddress, - storageSlot, - noteTypeId, - txHash, - options.note, - options.rpcUrl, - debugLogger, - ); - }); - - program - .command('add-pending-shield') - .description('Adds a pending shield note to the database in the PXE.') - .argument('
', 'Aztec address of the note owner.', parseAztecAddress) - .argument('', 'Amount of the pending shield note.', parseBigint) - .requiredOption('-ca, --contract-address
', 'Aztec address of the token contract.', parseAztecAddress) - .requiredOption('-tx, --tx-hash ', 'Tx hash in which the note was created.', parseOptionalTxHash) - .requiredOption('--secret ', 'Secret used for shielding the note.', parseField) - .addOption(pxeOption) - .action(async (address, amount, options) => { - const { addPendingShield } = await import('./cmds/add_pending_shield.js'); - await addPendingShield( - address, - options.contractAddress, - amount, - options.secret, - options.txHash, - options.rpcUrl, - debugLogger, - log, - ); - }); - - // Helper for users to decode hex strings into structs if needed. - program - .command('parse-parameter-struct') - .description("Helper for parsing an encoded string into a contract's parameter struct.") - .argument('', 'The encoded hex string') - .requiredOption( - '-c, --contract-artifact ', - "A compiled Aztec.nr contract's ABI in JSON format or name of a contract ABI exported by @aztec/noir-contracts.js", - ) - .requiredOption('-p, --parameter ', 'The name of the struct parameter to decode into') - .action(async (encodedString, options) => { - const { parseParameterStruct } = await import('./cmds/parse_parameter_struct.js'); - await parseParameterStruct(encodedString, options.contractArtifact, options.parameter, log); - }); - - program - .command('block-number') - .description('Gets the current Aztec L2 block number.') - .addOption(pxeOption) - .action(async (options: any) => { - const { blockNumber } = await import('./cmds/block_number.js'); - await blockNumber(options.rpcUrl, debugLogger, log); - }); - - program - .command('example-contracts') - .description('Lists the example contracts available to deploy from @aztec/noir-contracts.js') - .action(async () => { - const { exampleContracts } = await import('./cmds/example_contracts.js'); - await exampleContracts(log); - }); - - program - .command('get-node-info') - .description('Gets the information of an aztec node at a URL.') - .addOption(pxeOption) - .action(async options => { - const { getNodeInfo } = await import('./cmds/get_node_info.js'); - await getNodeInfo(options.rpcUrl, debugLogger, log); - }); - - program - .command('get-pxe-info') - .description('Gets the information of a PXE at a URL.') - .addOption(pxeOption) - .action(async options => { - const { getPXEInfo } = await import('./cmds/get_pxe_info.js'); - await getPXEInfo(options.rpcUrl, debugLogger, log); - }); - - program - .command('inspect-contract') - .description('Shows list of external callable functions for a contract') - .argument( - '', - `A compiled Noir contract's artifact in JSON format or name of a contract artifact exported by @aztec/noir-contracts.js`, - ) - .action(async (contractArtifactFile: string) => { - const { inspectContract } = await import('./cmds/inspect_contract.js'); - await inspectContract(contractArtifactFile, debugLogger, log); - }); - - program - .command('compute-selector') - .description('Given a function signature, it computes a selector') - .argument('', 'Function signature to compute selector for e.g. foo(Field)') - .action(async (functionSignature: string) => { - const { computeSelector } = await import('./cmds/compute_selector.js'); - computeSelector(functionSignature, log); - }); - - program - .command('sequencers') - .argument('', 'Command to run: list, add, remove, who-next') - .argument('[who]', 'Who to add/remove') - .description('Manages or queries registered sequencers on the L1 rollup contract.') - .requiredOption( - '--l1-rpc-url ', - 'Url of the ethereum host. Chain identifiers localhost and testnet can be used', - ETHEREUM_HOST, - ) - .option('-c, --chain-id ', 'Chain ID for the ethereum host', CHAIN_ID) - .option( - '-m, --mnemonic ', - 'The mnemonic for the sender of the tx', - 'test test test test test test test test test test test junk', - ) - .option('--block-number ', 'Block number to query next sequencer for', parseOptionalInteger) - .addOption(pxeOption) - .action(async (command, who, options) => { - const { sequencers } = await import('./cmds/sequencers.js'); - await sequencers({ - command: command, - who, - mnemonic: options.mnemonic, - rpcUrl: options.rpcUrl, - l1RpcUrl: options.l1RpcUrl, - chainId: +options.chainId, - blockNumber: options.blockNumber, - log, - debugLogger, - }); - }); - - return program; -} From 5fe445bfe53a8b286d33ff79e7a014ee6caa4abf Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 15 Jul 2024 16:03:41 +0000 Subject: [PATCH 83/94] clarify L1 chain ID --- .github/workflows/devnet-deploys.yml | 6 ++-- aztec-up/bin/docker-compose.sandbox.yml | 6 ++-- boxes/docker-compose.yml | 6 ++-- build-system/scripts/deploy_terraform | 2 +- docker-compose.yml | 4 +-- .../sandbox_reference/sandbox-reference.md | 2 +- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- iac/mainnet-fork/terraform/main.tf | 4 +-- iac/mainnet-fork/terraform/variables.tf | 2 +- .../src/defaults/account_interface.ts | 6 ++-- yarn-project/archiver/src/archiver/config.ts | 8 ++--- yarn-project/aztec-faucet/src/bin/index.ts | 10 +++---- yarn-project/aztec-faucet/terraform/main.tf | 6 ++-- .../aztec-faucet/terraform/variables.tf | 4 +-- .../aztec-node/src/aztec-node/server.ts | 16 +++++----- .../tx_metadata_validator.test.ts | 10 +++---- .../tx_validator/tx_metadata_validator.ts | 10 +++---- .../aztec.js/src/account_manager/index.ts | 2 +- .../aztec.js/src/contract/contract.test.ts | 2 +- .../aztec.js/src/wallet/signerless_wallet.ts | 2 +- yarn-project/aztec/docker-compose.yml | 2 +- yarn-project/aztec/src/cli/texts.ts | 4 +-- yarn-project/aztec/src/sandbox.ts | 12 ++++---- yarn-project/aztec/terraform/node/main.tf | 4 +-- .../aztec/terraform/node/variables.tf | 2 +- yarn-project/cli/src/cmds/pxe/call.ts | 2 +- .../cli/src/cmds/pxe/get_node_info.ts | 2 +- yarn-project/cli/src/utils/commands.ts | 4 +-- .../scripts/docker-compose-no-sandbox.yml | 2 +- .../end-to-end/scripts/docker-compose-p2p.yml | 2 +- .../end-to-end/scripts/docker-compose.yml | 4 +-- .../src/composed/e2e_sandbox_example.test.ts | 2 +- .../composed/integration_l1_publisher.test.ts | 2 +- .../end-to-end/src/e2e_authwit.test.ts | 2 +- .../end-to-end/src/e2e_fees/fees_test.ts | 2 +- .../src/fixtures/snapshot_manager.ts | 4 +-- yarn-project/end-to-end/src/fixtures/utils.ts | 10 +++---- yarn-project/ethereum/src/index.ts | 1 - yarn-project/ethereum/src/testnet.ts | 30 ------------------- .../pxe/src/pxe_service/pxe_service.ts | 4 +-- .../src/pxe_service/test/pxe_test_suite.ts | 2 +- yarn-project/sequencer-client/src/config.ts | 6 ++-- .../src/global_variable_builder/config.ts | 2 +- .../global_variable_builder/viem-reader.ts | 2 +- .../sequencer-client/src/publisher/config.ts | 2 +- .../src/publisher/viem-tx-sender.ts | 2 +- .../types/src/interfaces/node-info.ts | 2 +- 47 files changed, 97 insertions(+), 128 deletions(-) delete mode 100644 yarn-project/ethereum/src/testnet.ts diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index f24d628a23e7..d86b19933d94 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -12,10 +12,10 @@ env: GIT_COMMIT: ${{ github.sha }} DEPLOY_TAG: devnet FILE_PATH: ./l1-contracts/addresses.txt - CHAIN_ID: 677692 + L1_CHAIN_ID: 677692 # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol - TF_VAR_CHAIN_ID: 677692 + TF_VAR_L1_CHAIN_ID: 677692 TF_VAR_BOOTNODE_1_PRIVATE_KEY: ${{ secrets.BOOTNODE_1_PRIVATE_KEY }} TF_VAR_BOOTNODE_2_PRIVATE_KEY: ${{ secrets.BOOTNODE_2_PRIVATE_KEY }} TF_VAR_SEQ_1_PUBLISHER_PRIVATE_KEY: ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} @@ -116,7 +116,7 @@ jobs: docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ --private-key ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ --rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ - --chain-id ${{ env.CHAIN_ID }} \ + --chain-id ${{ env.L1_CHAIN_ID }} \ | tee ${{ env.FILE_PATH }} ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} diff --git a/aztec-up/bin/docker-compose.sandbox.yml b/aztec-up/bin/docker-compose.sandbox.yml index 2f856a751f04..7d5cc6ebe6cb 100644 --- a/aztec-up/bin/docker-compose.sandbox.yml +++ b/aztec-up/bin/docker-compose.sandbox.yml @@ -23,7 +23,7 @@ services: DEBUG: # Loaded from the user shell if explicitly set HOST_WORKDIR: "${PWD}" # Loaded from the user shell to show log files absolute path in host ETHEREUM_HOST: ${ETHEREUM_HOST:-http://ethereum:${ANVIL_PORT:-8545}} - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 @@ -31,10 +31,10 @@ services: PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 PXE_PORT: ${PXE_PORT:-8080} - PORT: ${AZTEC_NODE_PORT:-8080} + PORT: ${AZTEC_NODE_PORT:-8080} TEST_ACCOUNTS: ${TEST_ACCOUNTS:-true} volumes: - ./log:/usr/src/yarn-project/aztec/log:rw depends_on: - ethereum - command: "start --sandbox" \ No newline at end of file + command: "start --sandbox" diff --git a/boxes/docker-compose.yml b/boxes/docker-compose.yml index c42e6dbd5d23..2ac3069334eb 100644 --- a/boxes/docker-compose.yml +++ b/boxes/docker-compose.yml @@ -6,10 +6,10 @@ services: aztec: image: aztecprotocol/aztec:${AZTEC_DOCKER_TAG:-latest} - command: 'start --sandbox' + command: "start --sandbox" environment: ETHEREUM_HOST: http://ethereum:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 @@ -29,7 +29,7 @@ services: DEBUG: "aztec:*" DEBUG_COLORS: "true" ETHEREUM_HOST: http://ethereum:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 PXE_URL: http://aztec:8080 BOX: ${BOX:-vanilla} CI: ${CI:-} diff --git a/build-system/scripts/deploy_terraform b/build-system/scripts/deploy_terraform index 5312bdec1d77..aa11408fb67a 100755 --- a/build-system/scripts/deploy_terraform +++ b/build-system/scripts/deploy_terraform @@ -29,7 +29,7 @@ export TF_VAR_DOCKERHUB_ACCOUNT=$DOCKERHUB_ACCOUNT export TF_VAR_FORK_MNEMONIC=$FORK_MNEMONIC export TF_VAR_INFURA_API_KEY=$INFURA_API_KEY export TF_VAR_API_KEY=$FORK_API_KEY -export TF_VAR_CHAIN_ID=$CHAIN_ID +export TF_VAR_L1_CHAIN_ID=$CHAIN_ID # If given a repository name, use it to construct and set/override the backend key. # Otherwise use the key as specified in the terraform. diff --git a/docker-compose.yml b/docker-compose.yml index b65e980c58d5..9a031f37e47e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: LOG_LEVEL: ${LOG_LEVEL:-info} DEBUG: ${DEBUG:-aztec:*,-json-rpc:*,-aztec:circuits:artifact_hash,-aztec:randomness_singleton} DEBUG_COLORS: 1 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 VERSION: 1 PXE_PROVER_ENABLED: ${PXE_PROVER_ENABLED:-1} PXE_DATA_DIRECTORY: /var/lib/aztec/pxe @@ -39,7 +39,7 @@ services: LOG_LEVEL: ${LOG_LEVEL:-info} DEBUG: ${DEBUG:-aztec:*,-json-rpc:*,-aztec:circuits:artifact_hash,-aztec:randomness_singleton,-aztec:avm_simulator:*} DEBUG_COLORS: 1 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 VERSION: 1 NODE_NO_WARNINGS: 1 PROVER_REAL_PROOFS: ${PROVER_REAL_PROOFS:-1} diff --git a/docs/docs/reference/sandbox_reference/sandbox-reference.md b/docs/docs/reference/sandbox_reference/sandbox-reference.md index 5e9ef0fbfbd9..ff16d411ad96 100644 --- a/docs/docs/reference/sandbox_reference/sandbox-reference.md +++ b/docs/docs/reference/sandbox_reference/sandbox-reference.md @@ -20,7 +20,7 @@ To change them, you can open `~/.aztec/docker-compose.yml` and edit them directl DEBUG=aztec:* # The level of debugging logs to be displayed. using "aztec:*" will log everything. HOST_WORKDIR='${PWD}' # The location to store log outpus. Will use ~/.aztec where the docker-compose.yml file is stored by default. ETHEREUM_HOST=http://ethereum:8545 # The Ethereum JSON RPC URL. We use an anvil instance that runs in parallel to the sandbox on docker by default. -CHAIN_ID=31337 # The Chain ID that the Ethereum host is using. +L1_CHAIN_ID=31337 # The Chain ID that the Ethereum host is using. TEST_ACCOUNTS='true' # Option to deploy 3 test account when sandbox starts. (default: true) MODE='sandbox' # Option to start the sandbox or a standalone part of the system. (default: sandbox) PXE_PORT=8080 # The port that the PXE will be listening to (default: 8080) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index dcc9169bf935..d73fb885f6cc 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -22,7 +22,7 @@ echo "result: ${MNEMONIC_STRIPPED:0:10}..." mkdir -p /data # Run anvil silently -.foundry/bin/anvil --silent --host $HOST -p $PORT -m "$MNEMONIC_STRIPPED" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >/dev/null & +.foundry/bin/anvil --silent --host $HOST -p $PORT -m "$MNEMONIC_STRIPPED" -f=https://mainnet.infura.io/v3/$INFURA_API_KEY --chain-id=$L1_CHAIN_ID --fork-block-number=15918000 --block-base-fee-per-gas=10 -s=$SNAPSHOT_FREQUENCY --state=./data/state --balance=1000000000000000000 >/dev/null & echo "Waiting for ethereum host at $ETHEREUM_HOST..." while ! curl -s $ETHEREUM_HOST >/dev/null; do sleep 1; done diff --git a/iac/mainnet-fork/terraform/main.tf b/iac/mainnet-fork/terraform/main.tf index 0b5908fc2ea7..daee91393ae5 100644 --- a/iac/mainnet-fork/terraform/main.tf +++ b/iac/mainnet-fork/terraform/main.tf @@ -132,8 +132,8 @@ resource "aws_ecs_task_definition" "aztec_mainnet_fork" { value = "${var.INFURA_API_KEY}" }, { - name = "CHAIN_ID" - value = "${var.CHAIN_ID}" + name = "L1_CHAIN_ID" + value = "${var.L1_CHAIN_ID}" }, { name = "SNAPSHOT_FREQUENCY" diff --git a/iac/mainnet-fork/terraform/variables.tf b/iac/mainnet-fork/terraform/variables.tf index 18efa1232060..7e52e53eb5c4 100644 --- a/iac/mainnet-fork/terraform/variables.tf +++ b/iac/mainnet-fork/terraform/variables.tf @@ -18,6 +18,6 @@ variable "DEPLOY_TAG" { type = string } -variable "CHAIN_ID" { +variable "L1_CHAIN_ID" { type = string } diff --git a/yarn-project/accounts/src/defaults/account_interface.ts b/yarn-project/accounts/src/defaults/account_interface.ts index 5d7fa311c6e9..db4c57dc669b 100644 --- a/yarn-project/accounts/src/defaults/account_interface.ts +++ b/yarn-project/accounts/src/defaults/account_interface.ts @@ -17,15 +17,15 @@ export class DefaultAccountInterface implements AccountInterface { constructor( private authWitnessProvider: AuthWitnessProvider, private address: CompleteAddress, - nodeInfo: Pick, + nodeInfo: Pick, ) { this.entrypoint = new DefaultAccountEntrypoint( address.address, authWitnessProvider, - nodeInfo.chainId, + nodeInfo.l1ChainId, nodeInfo.protocolVersion, ); - this.chainId = new Fr(nodeInfo.chainId); + this.chainId = new Fr(nodeInfo.l1ChainId); this.version = new Fr(nodeInfo.protocolVersion); } diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index bd7911ede144..e9f306b03740 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -23,9 +23,9 @@ export interface ArchiverConfig { apiKey?: string; /** - * The chain's ID + * The L1 chain's ID */ - chainId?: number; + l1ChainId?: number; /** * The polling interval in ms for retrieving new L2 blocks and encrypted logs. @@ -59,7 +59,7 @@ export interface ArchiverConfig { export function getConfigEnvVars(): ArchiverConfig { const { ETHEREUM_HOST, - CHAIN_ID, + L1_CHAIN_ID, ARCHIVER_POLLING_INTERVAL_MS, ARCHIVER_VIEM_POLLING_INTERVAL_MS, AVAILABILITY_ORACLE_CONTRACT_ADDRESS, @@ -88,7 +88,7 @@ export function getConfigEnvVars(): ArchiverConfig { }; return { rpcUrl: ETHEREUM_HOST || '', - chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil + l1ChainId: L1_CHAIN_ID ? +L1_CHAIN_ID : 31337, // 31337 is the default chain id for anvil archiverPollingIntervalMS: ARCHIVER_POLLING_INTERVAL_MS ? +ARCHIVER_POLLING_INTERVAL_MS : 1_000, viemPollingIntervalMS: ARCHIVER_VIEM_POLLING_INTERVAL_MS ? +ARCHIVER_VIEM_POLLING_INTERVAL_MS : 1_000, apiKey: API_KEY, diff --git a/yarn-project/aztec-faucet/src/bin/index.ts b/yarn-project/aztec-faucet/src/bin/index.ts index 3a73aefecd2b..5a787b8cf36a 100644 --- a/yarn-project/aztec-faucet/src/bin/index.ts +++ b/yarn-project/aztec-faucet/src/bin/index.ts @@ -14,7 +14,7 @@ const { FAUCET_PORT = 8082, API_PREFIX = '', RPC_URL = '', - CHAIN_ID = '', + L1_CHAIN_ID = '', PRIVATE_KEY = '', INTERVAL = '', ETH_AMOUNT = '', @@ -23,7 +23,7 @@ const { const logger = createDebugLogger('aztec:faucet'); const rpcUrl = RPC_URL; -const chainId = +CHAIN_ID; +const l1ChainId = +L1_CHAIN_ID; const privateKey: Hex = PRIVATE_KEY ? createHex(PRIVATE_KEY) : NULL_KEY; const interval = +INTERVAL; const mapping: { [key: Hex]: Date } = {}; @@ -58,7 +58,7 @@ function checkThrottle(address: Hex) { * @param address - Address to receive some ETH */ async function transferEth(address: string) { - const chain = createEthereumChain(rpcUrl, chainId); + const chain = createEthereumChain(rpcUrl, l1ChainId); const account = privateKeyToAccount(privateKey); const walletClient = createWalletClient({ @@ -112,8 +112,8 @@ function createRouter(apiPrefix: string) { async function main() { logger.info(`Setting up Aztec Faucet...`); - const chain = createEthereumChain(rpcUrl, chainId); - if (chain.chainInfo.id !== chainId) { + const chain = createEthereumChain(rpcUrl, l1ChainId); + if (chain.chainInfo.id !== l1ChainId) { throw new Error(`Incorrect chain id, expected ${chain.chainInfo.id}`); } diff --git a/yarn-project/aztec-faucet/terraform/main.tf b/yarn-project/aztec-faucet/terraform/main.tf index 2610b4a6d057..8f2bf84f8a95 100644 --- a/yarn-project/aztec-faucet/terraform/main.tf +++ b/yarn-project/aztec-faucet/terraform/main.tf @@ -36,7 +36,7 @@ data "terraform_remote_state" "aztec2_iac" { locals { api_prefix = "/${var.DEPLOY_TAG}/aztec-faucet/${var.API_KEY}" - rpc_url = "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" + rpc_url = "https://${var.DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${var.API_KEY}" } @@ -118,8 +118,8 @@ resource "aws_ecs_task_definition" "aztec-faucet" { "value": "${local.api_prefix}" }, { - "name": "CHAIN_ID", - "value": "${var.CHAIN_ID}" + "name": "L1_CHAIN_ID", + "value": "${var.L1_CHAIN_ID}" }, { "name": "PRIVATE_KEY", diff --git a/yarn-project/aztec-faucet/terraform/variables.tf b/yarn-project/aztec-faucet/terraform/variables.tf index b8e5cc7a24b5..94ad959012bf 100644 --- a/yarn-project/aztec-faucet/terraform/variables.tf +++ b/yarn-project/aztec-faucet/terraform/variables.tf @@ -6,8 +6,8 @@ variable "API_KEY" { type = string } -variable "CHAIN_ID" { - type = string +variable "L1_CHAIN_ID" { + type = string } variable "FAUCET_PRIVATE_KEY" { diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index e364df1892e9..f069de3afbd9 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -100,7 +100,7 @@ export class AztecNodeService implements AztecNode { protected readonly l1ToL2MessageSource: L1ToL2MessageSource, protected readonly worldStateSynchronizer: WorldStateSynchronizer, protected readonly sequencer: SequencerClient | undefined, - protected readonly chainId: number, + protected readonly l1ChainId: number, protected readonly version: number, protected readonly globalVariableBuilder: GlobalVariableBuilder, protected readonly merkleTreesDb: AztecKVStore, @@ -111,7 +111,7 @@ export class AztecNodeService implements AztecNode { ) { this.packageVersion = getPackageInfo().version; const message = - `Started Aztec Node against chain 0x${chainId.toString(16)} with contracts - \n` + + `Started Aztec Node against chain 0x${l1ChainId.toString(16)} with contracts - \n` + `Rollup: ${config.l1Contracts.rollupAddress.toString()}\n` + `Registry: ${config.l1Contracts.registryAddress.toString()}\n` + `Inbox: ${config.l1Contracts.inboxAddress.toString()}\n` + @@ -132,11 +132,11 @@ export class AztecNodeService implements AztecNode { storeLog = createDebugLogger('aztec:node:lmdb'), ): Promise { telemetry ??= new NoopTelemetryClient(); - const ethereumChain = createEthereumChain(config.rpcUrl, config.chainId); + const ethereumChain = createEthereumChain(config.rpcUrl, config.l1ChainId); //validate that the actual chain id matches that specified in configuration - if (config.chainId !== ethereumChain.chainInfo.id) { + if (config.l1ChainId !== ethereumChain.chainInfo.id) { throw new Error( - `RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.chainId}`, + `RPC URL configured for chain id ${ethereumChain.chainInfo.id} but expected id ${config.l1ChainId}`, ); } @@ -172,7 +172,7 @@ export class AztecNodeService implements AztecNode { const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(config) : new TestCircuitVerifier(); const txValidator = new AggregateTxValidator( - new MetadataTxValidator(config.chainId), + new MetadataTxValidator(config.l1ChainId), new TxProofValidator(proofVerifier), ); @@ -305,7 +305,7 @@ export class AztecNodeService implements AztecNode { * @returns The chain id. */ public getChainId(): Promise { - return Promise.resolve(this.chainId); + return Promise.resolve(this.l1ChainId); } public getContractClass(id: Fr): Promise { @@ -791,7 +791,7 @@ export class AztecNodeService implements AztecNode { const proofVerifier = config.realProofs ? await BBCircuitVerifier.new(newConfig) : new TestCircuitVerifier(); this.txValidator = new AggregateTxValidator( - new MetadataTxValidator(this.chainId), + new MetadataTxValidator(this.l1ChainId), new TxProofValidator(proofVerifier), ); } diff --git a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts index 9fe4555b76d8..58f40185eff0 100644 --- a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts +++ b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.test.ts @@ -4,12 +4,12 @@ import { Fr } from '@aztec/circuits.js'; import { MetadataTxValidator } from './tx_metadata_validator.js'; describe('MetadataTxValidator', () => { - let chainId: Fr; + let l1ChainId: Fr; let validator: MetadataTxValidator; beforeEach(() => { - chainId = new Fr(123); - validator = new MetadataTxValidator(chainId); + l1ChainId = new Fr(123); + validator = new MetadataTxValidator(l1ChainId); }); it('allows only transactions for the right chain', async () => { @@ -17,11 +17,11 @@ describe('MetadataTxValidator', () => { const badTxs = [mockTx(3), mockTxForRollup(4)]; goodTxs.forEach(tx => { - tx.data.constants.txContext.chainId = chainId; + tx.data.constants.txContext.chainId = l1ChainId; }); badTxs.forEach(tx => { - tx.data.constants.txContext.chainId = chainId.add(new Fr(1)); + tx.data.constants.txContext.chainId = l1ChainId.add(new Fr(1)); }); await expect(validator.validateTxs([...goodTxs, ...badTxs])).resolves.toEqual([goodTxs, badTxs]); diff --git a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts index 46c6ae0ed2fd..d6b5795722ea 100644 --- a/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts +++ b/yarn-project/aztec-node/src/aztec-node/tx_validator/tx_metadata_validator.ts @@ -4,10 +4,10 @@ import { createDebugLogger } from '@aztec/foundation/log'; export class MetadataTxValidator implements TxValidator { #log = createDebugLogger('aztec:sequencer:tx_validator:tx_metadata'); - #chainId: Fr; + #l1ChainId: Fr; - constructor(chainId: number | Fr) { - this.#chainId = new Fr(chainId); + constructor(l1ChainId: number | Fr) { + this.#l1ChainId = new Fr(l1ChainId); } validateTxs(txs: Tx[]): Promise<[validTxs: Tx[], invalidTxs: Tx[]]> { @@ -26,11 +26,11 @@ export class MetadataTxValidator implements TxValidator { } #hasCorrectChainId(tx: Tx): boolean { - if (!tx.data.constants.txContext.chainId.equals(this.#chainId)) { + if (!tx.data.constants.txContext.chainId.equals(this.#l1ChainId)) { this.#log.warn( `Rejecting tx ${Tx.getHash( tx, - )} because of incorrect chain ${tx.data.constants.txContext.chainId.toNumber()} != ${this.#chainId.toNumber()}`, + )} because of incorrect chain ${tx.data.constants.txContext.chainId.toNumber()} != ${this.#l1ChainId.toNumber()}`, ); return false; } else { diff --git a/yarn-project/aztec.js/src/account_manager/index.ts b/yarn-project/aztec.js/src/account_manager/index.ts index c33e20aa2197..7f149e8165d5 100644 --- a/yarn-project/aztec.js/src/account_manager/index.ts +++ b/yarn-project/aztec.js/src/account_manager/index.ts @@ -131,7 +131,7 @@ export class AccountManager { await this.pxe.registerAccount(this.secretKey, this.getCompleteAddress().partialAddress); - const { chainId, protocolVersion } = await this.pxe.getNodeInfo(); + const { l1ChainId: chainId, protocolVersion } = await this.pxe.getNodeInfo(); const deployWallet = new SignerlessWallet(this.pxe, new DefaultMultiCallEntrypoint(chainId, protocolVersion)); // We use a signerless wallet with the multi call entrypoint in order to make multiple calls in one go diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index 5d7413523ac2..f6801fe4ec2f 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -32,7 +32,7 @@ describe('Contract Class', () => { }; const mockNodeInfo: NodeInfo = { nodeVersion: 'vx.x.x', - chainId: 1, + l1ChainId: 1, protocolVersion: 2, l1ContractAddresses: l1Addresses, protocolContractAddresses: { diff --git a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts index f69c78d5f335..2f73cca8c270 100644 --- a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts @@ -16,7 +16,7 @@ export class SignerlessWallet extends BaseWallet { async createTxExecutionRequest(execution: ExecutionRequestInit): Promise { let entrypoint = this.entrypoint; if (!entrypoint) { - const { chainId, protocolVersion } = await this.pxe.getNodeInfo(); + const { l1ChainId: chainId, protocolVersion } = await this.pxe.getNodeInfo(); entrypoint = new DefaultEntrypoint(chainId, protocolVersion); } diff --git a/yarn-project/aztec/docker-compose.yml b/yarn-project/aztec/docker-compose.yml index 5ff460fca8ec..c6074ecff61b 100644 --- a/yarn-project/aztec/docker-compose.yml +++ b/yarn-project/aztec/docker-compose.yml @@ -22,7 +22,7 @@ services: DEBUG: # Loaded from the user shell if explicitly set HOST_WORKDIR: '${PWD}' # Loaded from the user shell to show log files absolute path in host ETHEREUM_HOST: http://ethereum:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 diff --git a/yarn-project/aztec/src/cli/texts.ts b/yarn-project/aztec/src/cli/texts.ts index a6aa1c24c32b..77f775b373d7 100644 --- a/yarn-project/aztec/src/cli/texts.ts +++ b/yarn-project/aztec/src/cli/texts.ts @@ -52,7 +52,7 @@ export const cliTexts = { 'archiverPollingIntervalMS:ARCHIVER_POLLING_INTERVAL_MS - number - The polling interval in ms for retrieving new L2 blocks and encrypted logs. Default: 1000\n' + 'viemPollingIntervalMS:ARCHIVER_VIEM_POLLING_INTERVAL_MS - number - The polling interval viem uses in ms. Default: 1000\n' + 'dataDirectory:DATA_DIRECTORY - string - Optional dir to store data. If omitted will store temporarily.\n\n' + - 'chainId:CHAIN_ID - number - The chain id of the ethereum host. Default: 31337\n' + + 'l1ChainId:L1_CHAIN_ID - number - The chain id of the ethereum host. Default: 31337\n' + contractAddresses, sequencer: 'Starts a Sequencer with options. If started additionally to --node, the Sequencer will attach to that node.\n' + @@ -60,7 +60,7 @@ export const cliTexts = { 'rcpUrl:ETHEREUM_HOST - string - The host of the Ethereum node to connect to. Default: http://localhost:8545\n' + 'minTxsPerBlock:SEQ_MIN_TXS_PER_BLOCK - number - The minimum number of transactions to include in a block. Default: 1\n' + 'maxTxsPerBlock:SEQ_MAX_TXS_PER_BLOCK - number - The maximum number of transactions to include in a block. Default: 32\n' + - 'chainId:CHAIN_ID - number - The chain id of the ethereum host. Default: 31337\n' + + 'l1ChainId:L1_CHAIN_ID - number - The chain id of the ethereum host. Default: 31337\n' + 'version:VERSION - number - The version of the Aztec rollup. Default: 1\n' + 'publisherPrivateKey:SEQ_PUBLISHER_PRIVATE_KEY - string - The private key of the publisher. If not provided, will try to infer from default foundry test accounts.\n' + 'requiredConfirmations:SEQ_REQUIRED_CONFIRMATIONS - number - The number of confirmations required before publishing a block. Default: 1\n' + diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index d79a176651fd..570b4a620ec3 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -54,13 +54,13 @@ const localAnvil = foundry; * Helper function that waits for the Ethereum RPC server to respond before deploying L1 contracts. */ async function waitThenDeploy(config: AztecNodeConfig, deployFunction: () => Promise) { - const chain = createEthereumChain(config.rpcUrl, config.chainId); + const chain = createEthereumChain(config.rpcUrl, config.l1ChainId); // wait for ETH RPC to respond to a request. const publicClient = createPublicClient({ chain: chain.chainInfo, transport: httpViemTransport(chain.rpcUrl), }); - const chainID = await retryUntil( + const l1ChainID = await retryUntil( async () => { let chainId = 0; try { @@ -75,7 +75,7 @@ async function waitThenDeploy(config: AztecNodeConfig, deployFunction: () => Pro 1, ); - if (!chainID) { + if (!l1ChainID) { throw Error(`Ethereum node unresponsive at ${chain.rpcUrl}.`); } @@ -260,15 +260,15 @@ export async function createSandbox(config: Partial = {}) { const pxe = await createAztecPXE(node); await deployCanonicalKeyRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.chainId, aztecNodeConfig.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)), ); await deployCanonicalAuthRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.chainId, aztecNodeConfig.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)), ); if (config.enableGas) { await deployCanonicalL2GasToken( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.chainId, aztecNodeConfig.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)), aztecNodeConfig.l1Contracts, ); } diff --git a/yarn-project/aztec/terraform/node/main.tf b/yarn-project/aztec/terraform/node/main.tf index 3d774e55c927..383871baadc6 100644 --- a/yarn-project/aztec/terraform/node/main.tf +++ b/yarn-project/aztec/terraform/node/main.tf @@ -293,8 +293,8 @@ resource "aws_ecs_task_definition" "aztec-node" { value = tostring(var.P2P_ENABLED) }, { - name = "CHAIN_ID" - value = var.CHAIN_ID + name = "L1_CHAIN_ID" + value = var.L1_CHAIN_ID }, { name = "PEER_ID_PRIVATE_KEY" diff --git a/yarn-project/aztec/terraform/node/variables.tf b/yarn-project/aztec/terraform/node/variables.tf index 4ffc1affa9af..90b9919a0e3d 100644 --- a/yarn-project/aztec/terraform/node/variables.tf +++ b/yarn-project/aztec/terraform/node/variables.tf @@ -14,7 +14,7 @@ variable "SEQ_2_PUBLISHER_PRIVATE_KEY" { type = string } -variable "CHAIN_ID" { +variable "L1_CHAIN_ID" { type = string default = 677692 } diff --git a/yarn-project/cli/src/cmds/pxe/call.ts b/yarn-project/cli/src/cmds/pxe/call.ts index dcc9eb750dd6..5daca1d7b27c 100644 --- a/yarn-project/cli/src/cmds/pxe/call.ts +++ b/yarn-project/cli/src/cmds/pxe/call.ts @@ -28,7 +28,7 @@ export async function call( } const client = await createCompatibleClient(rpcUrl, debugLogger); - const { chainId, protocolVersion } = await client.getNodeInfo(); + const { l1ChainId: chainId, protocolVersion } = await client.getNodeInfo(); const call = new ContractFunctionInteraction( new SignerlessWallet(client, new DefaultMultiCallEntrypoint(chainId, protocolVersion)), contractAddress, diff --git a/yarn-project/cli/src/cmds/pxe/get_node_info.ts b/yarn-project/cli/src/cmds/pxe/get_node_info.ts index 3cf45c689d65..9081d0184f7e 100644 --- a/yarn-project/cli/src/cmds/pxe/get_node_info.ts +++ b/yarn-project/cli/src/cmds/pxe/get_node_info.ts @@ -6,7 +6,7 @@ export async function getNodeInfo(rpcUrl: string, debugLogger: DebugLogger, log: const client = await createCompatibleClient(rpcUrl, debugLogger); const info = await client.getNodeInfo(); log(`Node Version: ${info.nodeVersion}`); - log(`Chain Id: ${info.chainId}`); + log(`Chain Id: ${info.l1ChainId}`); log(`Protocol Version: ${info.protocolVersion}`); log(`Rollup Address: ${info.l1ContractAddresses.rollupAddress.toString()}`); log(`Protocol Contract Addresses:`); diff --git a/yarn-project/cli/src/utils/commands.ts b/yarn-project/cli/src/utils/commands.ts index 435f70cb93ff..bee6e68e9994 100644 --- a/yarn-project/cli/src/utils/commands.ts +++ b/yarn-project/cli/src/utils/commands.ts @@ -34,8 +34,8 @@ export const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') .default(`http://${LOCALHOST}:8080`) .makeOptionMandatory(true); -export const chainIdOption = new Option('-c, --chain-id ', 'Chain ID of the ethereum host') - .env('CHAIN_ID') +export const chainIdOption = new Option('-c, --l1-chain-id ', 'Chain ID of the ethereum host') + .env('L1_CHAIN_ID') .default('31337') .argParser(value => { const parsedValue = Number(value); diff --git a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml index 221e8273b389..23353de37dce 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml @@ -20,7 +20,7 @@ services: DEBUG: ${DEBUG:-'aztec:*'} DEBUG_COLORS: 1 ETHEREUM_HOST: http://fork:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 diff --git a/yarn-project/end-to-end/scripts/docker-compose-p2p.yml b/yarn-project/end-to-end/scripts/docker-compose-p2p.yml index 369a8eca675c..788a5ad02f1e 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-p2p.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-p2p.yml @@ -28,7 +28,7 @@ services: DEBUG: ${DEBUG:-'aztec:*'} DEBUG_COLORS: 1 ETHEREUM_HOST: http://fork:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL: 500 P2P_CHECK_INTERVAL: 50 SEQ_TX_POLLING_INTERVAL: 50 diff --git a/yarn-project/end-to-end/scripts/docker-compose.yml b/yarn-project/end-to-end/scripts/docker-compose.yml index 06f72f221c41..3c9e447afbbf 100644 --- a/yarn-project/end-to-end/scripts/docker-compose.yml +++ b/yarn-project/end-to-end/scripts/docker-compose.yml @@ -20,7 +20,7 @@ services: DEBUG: 'aztec:*' DEBUG_COLORS: 1 ETHEREUM_HOST: http://fork:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 ARCHIVER_POLLING_INTERVAL_MS: 50 P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 @@ -39,7 +39,7 @@ services: DEBUG: ${DEBUG:-aztec:*} DEBUG_COLORS: 1 ETHEREUM_HOST: http://fork:8545 - CHAIN_ID: 31337 + L1_CHAIN_ID: 31337 PXE_URL: http://sandbox:8080 entrypoint: > sh -c ' diff --git a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts index 9489dcd9dafc..5ffd66872bb7 100644 --- a/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts +++ b/yarn-project/end-to-end/src/composed/e2e_sandbox_example.test.ts @@ -36,7 +36,7 @@ describe('e2e_sandbox_example', () => { // docs:end:setup expect(typeof nodeInfo.protocolVersion).toBe('number'); - expect(typeof nodeInfo.chainId).toBe('number'); + expect(typeof nodeInfo.l1ChainId).toBe('number'); expect(typeof nodeInfo.l1ContractAddresses.rollupAddress).toBe('object'); // For the sandbox quickstart we just want to show them preloaded accounts (since it is a quickstart) diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 5f846e2884d8..be08caf26187 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -96,7 +96,7 @@ describe('L1Publisher integration', () => { let blockSource: MockProxy; - const chainId = createEthereumChain(config.rpcUrl, config.chainId).chainInfo.id; + const chainId = createEthereumChain(config.rpcUrl, config.l1ChainId).chainInfo.id; let coinbase: EthAddress; let feeRecipient: AztecAddress; diff --git a/yarn-project/end-to-end/src/e2e_authwit.test.ts b/yarn-project/end-to-end/src/e2e_authwit.test.ts index ee4748632cec..a32af7b0e66b 100644 --- a/yarn-project/end-to-end/src/e2e_authwit.test.ts +++ b/yarn-project/end-to-end/src/e2e_authwit.test.ts @@ -25,7 +25,7 @@ describe('e2e_authwit_tests', () => { // docs:end:public_deploy_accounts const nodeInfo = await wallets[0].getNodeInfo(); - chainId = new Fr(nodeInfo.chainId); + chainId = new Fr(nodeInfo.l1ChainId); version = new Fr(nodeInfo.protocolVersion); auth = await AuthWitTestContract.deploy(wallets[0]).send().deployed(); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index ead26d72734e..ef1dce54c360 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -203,7 +203,7 @@ export class FeesTest { await deployCanonicalGasToken( new SignerlessWallet( context.pxe, - new DefaultMultiCallEntrypoint(context.aztecNodeConfig.chainId, context.aztecNodeConfig.version), + new DefaultMultiCallEntrypoint(context.aztecNodeConfig.l1ChainId, context.aztecNodeConfig.version), ), ); }, diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 8e982733c990..9b61cc6fdc2f 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -282,11 +282,11 @@ async function setupFromFresh(statePath: string | undefined, logger: Logger): Pr logger.verbose('Deploying key registry...'); await deployCanonicalKeyRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.chainId, aztecNodeConfig.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)), ); logger.verbose('Deploying auth registry...'); await deployCanonicalAuthRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.chainId, aztecNodeConfig.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(aztecNodeConfig.l1ChainId, aztecNodeConfig.version)), ); if (statePath) { diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 9c086c800449..243bd18ad930 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -234,14 +234,14 @@ async function setupWithRemoteEnvironment( const cheatCodes = CheatCodes.create(config.rpcUrl, pxeClient!); const teardown = () => Promise.resolve(); - const { chainId, protocolVersion } = await pxeClient.getNodeInfo(); + const { l1ChainId: chainId, protocolVersion } = await pxeClient.getNodeInfo(); // this contract might already have been deployed // the following deploying functions are idempotent await deployCanonicalKeyRegistry( new SignerlessWallet(pxeClient, new DefaultMultiCallEntrypoint(chainId, protocolVersion)), ); await deployCanonicalAuthRegistry( - new SignerlessWallet(pxeClient, new DefaultMultiCallEntrypoint(config.chainId, config.version)), + new SignerlessWallet(pxeClient, new DefaultMultiCallEntrypoint(config.l1ChainId, config.version)), ); if (enableGas) { @@ -389,18 +389,18 @@ export async function setup( logger.verbose('Deploying key registry...'); await deployCanonicalKeyRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.chainId, config.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.l1ChainId, config.version)), ); logger.verbose('Deploying auth registry...'); await deployCanonicalAuthRegistry( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.chainId, config.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.l1ChainId, config.version)), ); if (enableGas) { logger.verbose('Deploying gas token...'); await deployCanonicalGasToken( - new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.chainId, config.version)), + new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(config.l1ChainId, config.version)), ); } diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index c28fc4bc2dfb..d8d15d71ae6d 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -2,7 +2,6 @@ import { foundry } from 'viem/chains'; import { type EthereumChain } from './ethereum_chain.js'; -export * from './testnet.js'; export * from './deploy_l1_contracts.js'; export * from './l1_contract_addresses.js'; export * from './constants.js'; diff --git a/yarn-project/ethereum/src/testnet.ts b/yarn-project/ethereum/src/testnet.ts deleted file mode 100644 index c6e28871a3ef..000000000000 --- a/yarn-project/ethereum/src/testnet.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { type Chain } from 'viem'; - -import { type EthereumChain } from './ethereum_chain.js'; - -const { DEPLOY_TAG = 'aztec-dev', CHAIN_ID = 31337 } = process.env; - -export const createTestnetChain = (apiKey: string) => { - const chain: Chain = { - id: +CHAIN_ID, - name: 'testnet', - testnet: true, - nativeCurrency: { - name: 'Ether', - symbol: 'ETH', - decimals: 18, - }, - rpcUrls: { - default: { - http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], - }, - public: { - http: [`https://${DEPLOY_TAG}-mainnet-fork.aztec.network:8545/${apiKey}`], - }, - }, - }; - return { - chainInfo: chain, - rpcUrl: chain.rpcUrls.default.http[0], - } as EthereumChain; -}; diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 0891f5f84d79..1d38298b6fdf 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -118,7 +118,7 @@ export class PXEService implements PXE { await this.synchronizer.start(1, l2BlockPollingIntervalMS); await this.restoreNoteProcessors(); const info = await this.getNodeInfo(); - this.log.info(`Started PXE connected to chain ${info.chainId} version ${info.protocolVersion}`); + this.log.info(`Started PXE connected to chain ${info.l1ChainId} version ${info.protocolVersion}`); } private async restoreNoteProcessors() { @@ -616,7 +616,7 @@ export class PXEService implements PXE { const nodeInfo: NodeInfo = { nodeVersion, - chainId, + l1ChainId: chainId, protocolVersion, l1ContractAddresses: contractAddresses, protocolContractAddresses: protocolContractAddresses, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index 8a9e8bc99b35..938bf246a5e0 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -144,7 +144,7 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => it('successfully gets node info', async () => { const nodeInfo = await pxe.getNodeInfo(); expect(typeof nodeInfo.protocolVersion).toEqual('number'); - expect(typeof nodeInfo.chainId).toEqual('number'); + expect(typeof nodeInfo.l1ChainId).toEqual('number'); expect(nodeInfo.l1ContractAddresses.rollupAddress.toString()).toMatch(/0x[a-fA-F0-9]+/); }); diff --git a/yarn-project/sequencer-client/src/config.ts b/yarn-project/sequencer-client/src/config.ts index 3fe6c79a1cc7..c75517c3938a 100644 --- a/yarn-project/sequencer-client/src/config.ts +++ b/yarn-project/sequencer-client/src/config.ts @@ -16,7 +16,7 @@ import { type SequencerConfig } from './sequencer/config.js'; /** Chain configuration. */ type ChainConfig = { /** The chain id of the ethereum host. */ - chainId: number; + l1ChainId: number; /** The version of the rollup. */ version: number; }; @@ -37,7 +37,7 @@ export function getConfigEnvVars(): SequencerClientConfig { const { SEQ_PUBLISHER_PRIVATE_KEY, ETHEREUM_HOST, - CHAIN_ID, + L1_CHAIN_ID, VERSION, SEQ_REQUIRED_CONFIRMATIONS, SEQ_PUBLISH_RETRY_INTERVAL_MS, @@ -82,7 +82,7 @@ export function getConfigEnvVars(): SequencerClientConfig { return { enforceFees: ['1', 'true'].includes(ENFORCE_FEES), rpcUrl: ETHEREUM_HOST ? ETHEREUM_HOST : '', - chainId: CHAIN_ID ? +CHAIN_ID : 31337, // 31337 is the default chain id for anvil + l1ChainId: L1_CHAIN_ID ? +L1_CHAIN_ID : 31337, // 31337 is the default chain id for anvil version: VERSION ? +VERSION : 1, // 1 is our default version requiredConfirmations: SEQ_REQUIRED_CONFIRMATIONS ? +SEQ_REQUIRED_CONFIRMATIONS : 1, l1BlockPublishRetryIntervalMS: SEQ_PUBLISH_RETRY_INTERVAL_MS ? +SEQ_PUBLISH_RETRY_INTERVAL_MS : 1_000, diff --git a/yarn-project/sequencer-client/src/global_variable_builder/config.ts b/yarn-project/sequencer-client/src/global_variable_builder/config.ts index c64c10a1cd00..dcc75143eab2 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/config.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/config.ts @@ -11,7 +11,7 @@ export interface GlobalReaderConfig { /** * The chain ID of the ethereum host. */ - chainId: number; + l1ChainId: number; /** * The deployed l1 contract addresses diff --git a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts index fc1fae219564..fb134089e957 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts @@ -23,7 +23,7 @@ export class ViemReader implements L1GlobalReader { private publicClient: PublicClient; constructor(config: GlobalReaderConfig) { - const { rpcUrl, chainId, l1Contracts } = config; + const { rpcUrl, l1ChainId: chainId, l1Contracts } = config; const chain = createEthereumChain(rpcUrl, chainId); diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index 94a98ab1a900..b88c2df2285a 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -17,7 +17,7 @@ export interface TxSenderConfig { /** * The chain ID of the ethereum host. */ - chainId?: number; + l1ChainId?: number; /** * The number of confirmations required. diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index 81106f3e9acd..241fad9ef511 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -47,7 +47,7 @@ export class ViemTxSender implements L1PublisherTxSender { private account: PrivateKeyAccount; constructor(config: TxSenderConfig) { - const { rpcUrl, chainId, publisherPrivateKey, l1Contracts } = config; + const { rpcUrl, l1ChainId: chainId, publisherPrivateKey, l1Contracts } = config; const chain = createEthereumChain(rpcUrl, chainId); this.account = privateKeyToAccount(publisherPrivateKey); const walletClient = createWalletClient({ diff --git a/yarn-project/types/src/interfaces/node-info.ts b/yarn-project/types/src/interfaces/node-info.ts index 0c4250a724be..60edf9e8c6a2 100644 --- a/yarn-project/types/src/interfaces/node-info.ts +++ b/yarn-project/types/src/interfaces/node-info.ts @@ -13,7 +13,7 @@ export interface NodeInfo { /** * L1 chain id. */ - chainId: number; + l1ChainId: number; /** * Protocol version. */ From a76cb2dac886f3635bd0be88efa90931590a6a61 Mon Sep 17 00:00:00 2001 From: spypsy Date: Mon, 15 Jul 2024 17:33:00 +0000 Subject: [PATCH 84/94] don't pass secrets --- .github/workflows/devnet-deploys.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index d86b19933d94..fa3cab4637e0 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -13,6 +13,8 @@ env: DEPLOY_TAG: devnet FILE_PATH: ./l1-contracts/addresses.txt L1_CHAIN_ID: 677692 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # TF Vars TF_VAR_DOCKERHUB_ACCOUNT: aztecprotocol TF_VAR_L1_CHAIN_ID: 677692 @@ -53,8 +55,6 @@ jobs: # Run the build steps for each image with version and arch, push to dockerhub run: | earthly-ci \ - --secret AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \ - --secret AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \ --no-output --push ./yarn-project+export-aztec-arch --DIST_TAG=${{ env.DEPLOY_TAG }} - name: Check if L1 contracts need deployment From 0910078096165fd3bac780cc39bb58a640420d78 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 08:37:21 +0000 Subject: [PATCH 85/94] pass chainId in bootstrap --- yarn-project/cli/src/cmds/infrastructure/bootstrap.ts | 4 ++-- yarn-project/cli/src/cmds/infrastructure/index.ts | 7 ++++--- yarn-project/cli/src/cmds/l1/index.ts | 8 ++++---- yarn-project/cli/src/utils/commands.ts | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/yarn-project/cli/src/cmds/infrastructure/bootstrap.ts b/yarn-project/cli/src/cmds/infrastructure/bootstrap.ts index b97bac4ed5f0..0f862f8d90e9 100644 --- a/yarn-project/cli/src/cmds/infrastructure/bootstrap.ts +++ b/yarn-project/cli/src/cmds/infrastructure/bootstrap.ts @@ -9,13 +9,13 @@ const waitOpts: WaitOpts = { interval: 1, }; -export async function bootstrap(rpcUrl: string, log: LogFn) { +export async function bootstrap(rpcUrl: string, l1ChainId: number, log: LogFn) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - Importing noir-contracts.js even in devDeps results in a circular dependency error. Need to ignore because this line doesn't cause an error in a dev environment const { GasTokenContract, KeyRegistryContract } = await import('@aztec/noir-contracts.js'); const pxe = createPXEClient(rpcUrl, makeFetch([], true)); - const deployer = new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(31337, 1)); + const deployer = new SignerlessWallet(pxe, new DefaultMultiCallEntrypoint(l1ChainId, 1)); const canonicalKeyRegistry = getCanonicalKeyRegistry(); const keyRegistryDeployParams = { diff --git a/yarn-project/cli/src/cmds/infrastructure/index.ts b/yarn-project/cli/src/cmds/infrastructure/index.ts index be831e98a6ce..fb3941420da8 100644 --- a/yarn-project/cli/src/cmds/infrastructure/index.ts +++ b/yarn-project/cli/src/cmds/infrastructure/index.ts @@ -2,16 +2,17 @@ import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; import { type Command } from 'commander'; -import { ETHEREUM_HOST, chainIdOption, parseOptionalInteger, pxeOption } from '../../utils/commands.js'; +import { ETHEREUM_HOST, l1ChainIdOption, parseOptionalInteger, pxeOption } from '../../utils/commands.js'; export function injectCommands(program: Command, log: LogFn, debugLogger: DebugLogger) { program .command('bootstrap') .description('Bootstrap the blockchain') .addOption(pxeOption) + .addOption(l1ChainIdOption) .action(async options => { const { bootstrap } = await import('./bootstrap.js'); - await bootstrap(options.rpcUrl, log); + await bootstrap(options.rpcUrl, options.chainId, log); }); program @@ -31,7 +32,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL ) .option('--block-number ', 'Block number to query next sequencer for', parseOptionalInteger) .addOption(pxeOption) - .addOption(chainIdOption) + .addOption(l1ChainIdOption) .action(async (command, who, options) => { const { sequencers } = await import('./sequencers.js'); await sequencers({ diff --git a/yarn-project/cli/src/cmds/l1/index.ts b/yarn-project/cli/src/cmds/l1/index.ts index a7acb5de8ccf..1cc2b744eafb 100644 --- a/yarn-project/cli/src/cmds/l1/index.ts +++ b/yarn-project/cli/src/cmds/l1/index.ts @@ -5,7 +5,7 @@ import { type Command } from 'commander'; import { ETHEREUM_HOST, PRIVATE_KEY, - chainIdOption, + l1ChainIdOption, parseAztecAddress, parseBigint, parseEthereumAddress, @@ -27,7 +27,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL 'The mnemonic to use in deployment', 'test test test test test test test test test test test junk', ) - .addOption(chainIdOption) + .addOption(l1ChainIdOption) .action(async options => { const { deployL1Contracts } = await import('./deploy_l1_contracts.js'); await deployL1Contracts(options.rpcUrl, options.chainId, options.privateKey, options.mnemonic, log, debugLogger); @@ -92,7 +92,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL 'test test test test test test test test test test test junk', ) .addOption(pxeOption) - .addOption(chainIdOption) + .addOption(l1ChainIdOption) .action(async (amount, recipient, options) => { const { bridgeL1Gas } = await import('./bridge_l1_gas.js'); await bridgeL1Gas( @@ -117,7 +117,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL ETHEREUM_HOST, ) .addOption(pxeOption) - .addOption(chainIdOption) + .addOption(l1ChainIdOption) .action(async (who, options) => { const { getL1Balance } = await import('./get_l1_balance.js'); await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.chainId, log, debugLogger); diff --git a/yarn-project/cli/src/utils/commands.ts b/yarn-project/cli/src/utils/commands.ts index bee6e68e9994..d6ca89794199 100644 --- a/yarn-project/cli/src/utils/commands.ts +++ b/yarn-project/cli/src/utils/commands.ts @@ -34,7 +34,7 @@ export const pxeOption = new Option('-u, --rpc-url ', 'URL of the PXE') .default(`http://${LOCALHOST}:8080`) .makeOptionMandatory(true); -export const chainIdOption = new Option('-c, --l1-chain-id ', 'Chain ID of the ethereum host') +export const l1ChainIdOption = new Option('-c, --l1-chain-id ', 'Chain ID of the ethereum host') .env('L1_CHAIN_ID') .default('31337') .argParser(value => { From 04a57eef2c031d0381b46280a05bcf181caca857 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 09:01:33 +0000 Subject: [PATCH 86/94] redeploy fork, contracts --- iac/mainnet-fork/scripts/run_nginx_anvil.sh | 2 +- l1-contracts/REDEPLOY | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/iac/mainnet-fork/scripts/run_nginx_anvil.sh b/iac/mainnet-fork/scripts/run_nginx_anvil.sh index d73fb885f6cc..e7cf5d595368 100755 --- a/iac/mainnet-fork/scripts/run_nginx_anvil.sh +++ b/iac/mainnet-fork/scripts/run_nginx_anvil.sh @@ -18,7 +18,7 @@ echo "stripping double quotations from the mnemonic seed phrase: ${MNEMONIC:0:10 MNEMONIC_STRIPPED=${MNEMONIC//\"/} echo "result: ${MNEMONIC_STRIPPED:0:10}..." -# Data directory for anvil state +# Data directory for anvil state. mkdir -p /data # Run anvil silently diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index ccf126002ba9..456b5196b3d3 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 \ No newline at end of file +1 \ No newline at end of file From 2c982d60bf98e9d3454c18928e1bce26af17b6e2 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 09:45:25 +0000 Subject: [PATCH 87/94] build & deploy fork image --- .github/workflows/devnet-deploys.yml | 8 +++++++- iac/mainnet-fork/Earthfile | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index fa3cab4637e0..e40bd8de44d6 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -64,7 +64,7 @@ jobs: script: | const { execSync } = require('child_process'); const changedFiles = execSync('git diff --name-only ${{ github.event.before }} ${{ github.sha }}').toString().split('\n'); - const fileChanged = changedFiles.includes('l1-contracts/REDEPLOY'); + const fileChanged = changedFiles.some(file => file.startsWith('l1-contracts')); return fileChanged - name: Check if mainnet fork needs deployment @@ -77,6 +77,12 @@ jobs: const fileChanged = changedFiles.some(file => file.startsWith('iac/mainnet-fork')); return fileChanged + - name: Build & push mainnet fork image + if: steps.check_fork_changes.outputs.result == 'true' + run: | + earthly-ci \ + --no-output --push ./iac/mainnet-fork+export-mainnet-fork --DIST_TAG=${{ env.DEPLOY_TAG }} + terraform_deploy: runs-on: ubuntu-latest needs: build diff --git a/iac/mainnet-fork/Earthfile b/iac/mainnet-fork/Earthfile index 29370d327e86..67c0ad257d18 100644 --- a/iac/mainnet-fork/Earthfile +++ b/iac/mainnet-fork/Earthfile @@ -24,6 +24,6 @@ build: export-mainnet-fork: FROM +build - ARG DIST_TAG="aztec-dev" + ARG DIST_TAG="devnet" ARG ARCH SAVE IMAGE --push aztecprotocol/mainnet-fork:${DIST_TAG}${ARCH:+-$ARCH} From 39450a9dff22b1128dd04c856ec314b3b89a48c6 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 10:23:52 +0000 Subject: [PATCH 88/94] merge with master --- .github/workflows/publish-docs.yml | 7 +- barretenberg/.gitrepo | 4 +- barretenberg/cpp/src/barretenberg/bb/main.cpp | 1 - .../barretenberg/ecc/curves/bn254/c_bind.cpp | 19 +++++ .../relations/auxiliary_relation.hpp | 42 +++++++--- .../relations/databus_lookup_relation.hpp | 15 +++- .../delta_range_constraint_relation.hpp | 13 ++- .../relations/ecc_op_queue_relation.hpp | 17 +++- .../relations/ecc_vm/ecc_bools_relation.hpp | 11 ++- .../relations/ecc_vm/ecc_lookup_relation.hpp | 12 ++- .../relations/ecc_vm/ecc_msm_relation.hpp | 11 ++- .../ecc_vm/ecc_point_table_relation.hpp | 8 ++ .../relations/ecc_vm/ecc_set_relation.hpp | 12 ++- .../ecc_vm/ecc_transcript_relation.hpp | 11 ++- .../relations/ecc_vm/ecc_wnaf_relation.hpp | 11 ++- .../relations/elliptic_relation.hpp | 11 ++- .../relations/logderiv_lookup_relation.hpp | 24 +++++- .../relations/permutation_relation.hpp | 46 ++++++++-- .../relations/poseidon2_external_relation.hpp | 13 ++- .../relations/poseidon2_internal_relation.hpp | 13 ++- .../translator_decomposition_relation.hpp | 56 +++++++++++++ ...slator_delta_range_constraint_relation.hpp | 18 ++++ .../translator_extra_relations.hpp | 30 ++++++- .../translator_non_native_field_relation.hpp | 12 ++- .../translator_permutation_relation.hpp | 10 ++- .../relations/ultra_arithmetic_relation.hpp | 9 +- .../vm/avm_trace/avm_execution.cpp | 12 ++- .../barretenberg/vm/avm_trace/avm_trace.cpp | 26 ++++++ .../barretenberg/vm/generated/avm_prover.cpp | 46 +++++----- .../barretenberg/vm/generated/avm_prover.hpp | 1 + .../templates/circuit_builder.hpp.hbs | 1 - .../bb-pil-backend/templates/prover.cpp.hbs | 45 ++++------ .../bb-pil-backend/templates/prover.hpp.hbs | 1 + noir-projects/aztec-nr/.gitrepo | 4 +- .../shared_mutable/shared_mutable.nr | 13 ++- .../src/state_vars/shared_mutable/test.nr | 66 ++++++++++++++- .../aztec/src/test/helpers/cheatcodes.nr | 14 ++++ .../src/test/helpers/test_environment.nr | 7 +- .../src/components/tail_output_composer.nr | 42 ++-------- .../tail_output_composer/meter_gas_used.nr | 36 ++++++++ .../src/components/tail_output_validator.nr | 15 +++- .../tail_to_public_output_composer.nr | 4 +- .../meter_gas_used.nr | 31 +++---- .../split_to_public.nr | 5 +- .../tail_to_public_output_validator.nr | 16 +++- .../meter_gas_used.nr | 73 ++++++++++++++++ .../mod.nr} | 2 + .../tail_output_validator_builder/mod.nr | 23 ++++- .../validate_gas_used.nr | 73 ++++++++++++++++ .../meter_gas_used.nr | 8 +- .../mod.nr} | 0 .../split_to_public.nr | 37 ++++----- .../foundation/src/crypto/random/index.ts | 9 ++ .../foundation/src/fields/fields.test.ts | 26 +++++- yarn-project/foundation/src/fields/fields.ts | 21 +++++ .../foundation/src/fields/point.test.ts | 35 ++++++++ yarn-project/foundation/src/fields/point.ts | 83 ++++++++++++++++++- 57 files changed, 1013 insertions(+), 198 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/ecc/curves/bn254/c_bind.cpp create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{tail_output_composer_builder.nr => tail_output_composer_builder/mod.nr} (98%) create mode 100644 noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr rename noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/{tail_to_public_output_composer_builder.nr => tail_to_public_output_composer_builder/mod.nr} (100%) create mode 100644 yarn-project/foundation/src/fields/point.test.ts diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 68413b3ab33c..80a74a17fc81 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -24,17 +24,14 @@ jobs: - uses: ./.github/ci-setup-action env: DOCKERHUB_PASSWORD: "${{ secrets.DOCKERHUB_PASSWORD }}" + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} with: concurrency_key: docs-preview-${{ inputs.username || github.actor }}-x86 - timeout-minutes: 25 run: | - touch .secrets - echo "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" > .secrets - echo "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" >> .secrets - earthly-ci --no-output ./docs/+deploy-prod \ - --secret-file-path .secrets \ --NETLIFY_AUTH_TOKEN=${{ secrets.NETLIFY_AUTH_TOKEN }} \ --NETLIFY_SITE_ID=${{ secrets.NETLIFY_SITE_ID }} \ --COMMIT_TAG=${{ inputs.tag }} diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 2f0dfda7d7a7..703927395196 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = 5d27e66bd9174b90b6b6aa1e50c166ce3eec13d6 - parent = f07200c110a9cce1a2bb4a7892063acd928e86cf + commit = 9f6f0294d0b52994c7d2e57ddc1ee91e8cbbbca3 + parent = c0ff566f5d57f7d4422613d02e6e658b6e8151c5 method = merge cmdver = 0.4.6 diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index efbfd9baa847..0f7c839efd77 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -902,7 +902,6 @@ void avm_prove(const std::filesystem::path& bytecode_path, // Prove execution and return vk auto const [verification_key, proof] = avm_trace::Execution::prove(bytecode, calldata, public_inputs_vec, avm_hints); - vinfo("------- PROVING DONE -------"); // TODO(ilyas): <#4887>: Currently we only need these two parts of the vk, look into pcs_verification key reqs std::vector vk_vector = { verification_key.circuit_size, verification_key.num_public_inputs }; diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/c_bind.cpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/c_bind.cpp new file mode 100644 index 000000000000..bf0807a4e68e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/c_bind.cpp @@ -0,0 +1,19 @@ +#include "../bn254/fr.hpp" +#include "barretenberg/common/wasm_export.hpp" + +using namespace bb; + +WASM_EXPORT void bn254_fr_sqrt(uint8_t const* input, uint8_t* result) +{ + using serialize::write; + auto input_fr = from_buffer(input); + auto [is_sqr, root] = input_fr.sqrt(); + + uint8_t* is_sqrt_result_ptr = result; + uint8_t* root_result_ptr = result + 1; + + write(is_sqrt_result_ptr, is_sqr); + write(root_result_ptr, root); +} + +// NOLINTEND(cert-dcl37-c, cert-dcl51-cpp, bugprone-reserved-identifier) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp index 5f96f232cdd4..144fb1a39334 100644 --- a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp @@ -39,6 +39,21 @@ template class AuxiliaryRelationImpl { 6, // RAM consistency sub-relation 2 6 // RAM consistency sub-relation 3 }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, // auxiliary sub-relation; + 2, // ROM consistency sub-relation 1: adjacent values match if adjacent indices match and next access is a read + // operation + 2, // ROM consistency sub-relation 2: index is monotonously increasing + 3, // RAM consistency sub-relation 1: adjacent values match if adjacent indices match and next access is a read + // operation + 2, // RAM consistency sub-relation 2: index is monotonously increasing + 2 // RAM consistency sub-relation 3: next gate access type is boolean + }; static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ 1, // auxiliary sub-relation @@ -96,9 +111,13 @@ template class AuxiliaryRelationImpl { const FF& scaling_factor) { BB_OP_COUNT_TIME_NAME("Auxiliary::accumulate"); - // All subrelations have the same length so we use the same length view for all calculations - using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + // declare the accumulator of the maximum length, in non-ZK Flavors, they are of the same length, + // whereas in ZK Flavors, the accumulator corresponding to RAM consistency sub-relation 1 is the longest + using Accumulator = typename std::tuple_element_t<3, ContainerOverSubrelations>; using View = typename Accumulator::View; + // allows to re-use the values accumulated by accumulators of the sizes smaller or equal to + // the size of Accumulator declared above + using ShortView = typename std::tuple_element_t<0, ContainerOverSubrelations>::View; using ParameterView = GetParameterView; const auto& eta = ParameterView(params.eta); @@ -260,9 +279,10 @@ template class AuxiliaryRelationImpl { auto q_one_by_two_by_aux_by_scaling = q_one_by_two * q_aux_by_scaling; std::get<1>(accumulators) += - adjacent_values_match_if_adjacent_indices_match * q_one_by_two_by_aux_by_scaling; // deg 5 - std::get<2>(accumulators) += index_is_monotonically_increasing * q_one_by_two_by_aux_by_scaling; // deg 5 - auto ROM_consistency_check_identity = memory_record_check * q_one_by_two; // deg 3 or 4 + ShortView(adjacent_values_match_if_adjacent_indices_match * q_one_by_two_by_aux_by_scaling); // deg 5 + std::get<2>(accumulators) += + ShortView(index_is_monotonically_increasing * q_one_by_two_by_aux_by_scaling); // deg 5 + auto ROM_consistency_check_identity = memory_record_check * q_one_by_two; // deg 3 or 4 /** * RAM Consistency Check @@ -308,10 +328,12 @@ template class AuxiliaryRelationImpl { // Putting it all together... std::get<3>(accumulators) += adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * - q_arith_by_aux_and_scaling; // deg 5 or 6 - std::get<4>(accumulators) += index_is_monotonically_increasing * q_arith_by_aux_and_scaling; // deg 4 - std::get<5>(accumulators) += next_gate_access_type_is_boolean * q_arith_by_aux_and_scaling; // deg 4 or 6 - auto RAM_consistency_check_identity = access_check * (q_arith); // deg 3 or 5 + q_arith_by_aux_and_scaling; // deg 5 or 6 + std::get<4>(accumulators) += ShortView(index_is_monotonically_increasing * q_arith_by_aux_and_scaling); // deg 4 + std::get<5>(accumulators) += + ShortView(next_gate_access_type_is_boolean * q_arith_by_aux_and_scaling); // deg 4 or 6 + + auto RAM_consistency_check_identity = access_check * (q_arith); // deg 3 or 5 /** * RAM Timestamp Consistency Check @@ -339,7 +361,7 @@ template class AuxiliaryRelationImpl { // (deg 3 or 5) + (deg 4) + (deg 3) auto auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; auxiliary_identity *= q_aux_by_scaling; // deg 5 or 6 - std::get<0>(accumulators) += auxiliary_identity; + std::get<0>(accumulators) += ShortView(auxiliary_identity); }; }; diff --git a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp index 4d24c0baf4bd..55e9e03c64c1 100644 --- a/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/databus_lookup_relation.hpp @@ -57,6 +57,19 @@ template class DatabusLookupRelationImpl { LENGTH // log-derivative lookup argument subrelation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree, which is given by LENGTH - 1 in this case. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + LENGTH - 1, // inverse polynomial correctness subrelation + LENGTH - 1, // log-derivative lookup argument subrelation + LENGTH - 1, // inverse polynomial correctness subrelation + LENGTH - 1 // log-derivative lookup argument subrelation + }; + // The lookup subrelations are "linearly dependent" in the sense that they establish the value of a sum across the // entire execution trace rather than a per-row identity. static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { @@ -290,4 +303,4 @@ template class DatabusLookupRelationImpl { template using DatabusLookupRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp index b6f3d3e36c4c..47883138208c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/delta_range_constraint_relation.hpp @@ -13,6 +13,17 @@ template class DeltaRangeConstraintRelationImpl { 6, // range constrain sub-relation 3 6 // range constrain sub-relation 4 }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 3, // range constrain sub-relation 1 + 3, // range constrain sub-relation 2 + 3, // range constrain sub-relation 3 + 3 // range constrain sub-relation 4 + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero @@ -95,4 +106,4 @@ template class DeltaRangeConstraintRelationImpl { template using DeltaRangeConstraintRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_op_queue_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_op_queue_relation.hpp index 254057744be1..1b716d6c1470 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_op_queue_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_op_queue_relation.hpp @@ -17,6 +17,21 @@ template class EccOpQueueRelationImpl { 3, // op-queue-wire vanishes sub-relation 3 3 // op-queue-wire vanishes sub-relation 4 }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 1, // wire - op-queue-wire consistency sub-relation 1 + 1, // wire - op-queue-wire consistency sub-relation 2 + 1, // wire - op-queue-wire consistency sub-relation 3 + 1, // wire - op-queue-wire consistency sub-relation 4 + 1, // op-queue-wire vanishes sub-relation 1 + 1, // op-queue-wire vanishes sub-relation 2 + 1, // op-queue-wire vanishes sub-relation 3 + 1 // op-queue-wire vanishes sub-relation 4 + }; template inline static bool skip([[maybe_unused]] const AllEntities& in) { @@ -108,4 +123,4 @@ template class EccOpQueueRelationImpl { template using EccOpQueueRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_bools_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_bools_relation.hpp index 88d6eef5dc8c..95afbf3aca93 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_bools_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_bools_relation.hpp @@ -20,6 +20,15 @@ template class ECCVMBoolsRelationImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + }; template static void accumulate(ContainerOverSubrelations& accumulator, @@ -30,4 +39,4 @@ template class ECCVMBoolsRelationImpl { template using ECCVMBoolsRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp index fd89cbe58197..687d81d2f73b 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_lookup_relation.hpp @@ -21,6 +21,16 @@ template class ECCVMLookupRelationImpl { LENGTH, // grand product construction sub-relation LENGTH // left-shiftable polynomial sub-relation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + LENGTH - 1, // grand product construction sub-relation + LENGTH - 1 // left-shiftable polynomial sub-relation + }; static constexpr std::array SUBRELATION_LINEARLY_INDEPENDENT = { true, false }; @@ -247,4 +257,4 @@ template class ECCVMLookupRelationImpl { template using ECCVMLookupRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_msm_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_msm_relation.hpp index 51e15f608edd..e7572f4e5858 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_msm_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_msm_relation.hpp @@ -41,6 +41,15 @@ template class ECCVMMSMRelationImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; template static void accumulate(ContainerOverSubrelations& accumulator, @@ -51,4 +60,4 @@ template class ECCVMMSMRelationImpl { template using ECCVMMSMRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_point_table_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_point_table_relation.hpp index 771e54018fd2..30b4eb77c84e 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_point_table_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_point_table_relation.hpp @@ -1,3 +1,4 @@ + #pragma once #include "barretenberg/relations/relation_types.hpp" @@ -20,6 +21,13 @@ template class ECCVMPointTableRelationImpl { using FF = FF_; static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 6, 6, 6, 6, 6, 6 }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ 5, 5, 5, 5, 5, 5 }; template static void accumulate(ContainerOverSubrelations& accumulator, diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_set_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_set_relation.hpp index 2e8393cd661d..d958f7a54815 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_set_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_set_relation.hpp @@ -17,6 +17,16 @@ template class ECCVMSetRelationImpl { 21, // grand product construction sub-relation 21 // left-shiftable polynomial sub-relation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 20, // grand product construction sub-relation + 20 // left-shiftable polynomial sub-relation + }; template static Accumulator convert_to_wnaf(const auto& s0, const auto& s1) { @@ -46,4 +56,4 @@ template class ECCVMSetRelationImpl { template using ECCVMSetRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_transcript_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_transcript_relation.hpp index 215460260468..f5500649a4f4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_transcript_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_transcript_relation.hpp @@ -33,6 +33,15 @@ template class ECCVMTranscriptRelationImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + }; template static void accumulate(ContainerOverSubrelations& accumulator, @@ -55,4 +64,4 @@ template class ECCVMTranscriptRelationImpl { template using ECCVMTranscriptRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_wnaf_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_wnaf_relation.hpp index 4373d1e7f44b..b8a1e3255d58 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_wnaf_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ecc_vm/ecc_wnaf_relation.hpp @@ -38,6 +38,15 @@ template class ECCVMWnafRelationImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + }; template static void accumulate(ContainerOverSubrelations& accumulator, @@ -48,4 +57,4 @@ template class ECCVMWnafRelationImpl { template using ECCVMWnafRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp index 09ed7dd1d90f..9033179a59e2 100644 --- a/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/elliptic_relation.hpp @@ -13,6 +13,15 @@ template class EllipticRelationImpl { 6, // x-coordinate sub-relation 6, // y-coordinate sub-relation }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 3, // x-coordinate sub-relation + 3, // y-coordinate sub-relation (because of point doubling) + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero @@ -108,4 +117,4 @@ template class EllipticRelationImpl { }; template using EllipticRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp index d2cb576b575a..7e39ebc7df8f 100644 --- a/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/logderiv_lookup_relation.hpp @@ -22,6 +22,15 @@ template class LogDerivLookupRelationImpl { LENGTH, // inverse construction sub-relation LENGTH // log derivative lookup argument sub-relation }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, // inverse construction sub-relation + 3, // log derivative lookup argument sub-relation + }; // TODO(https://github.com/AztecProtocol/barretenberg/issues/1036): Scrutinize these adjustment factors. Counting // degrees suggests the first subrelation should require an adjustment of 2. @@ -128,7 +137,7 @@ template class LogDerivLookupRelationImpl { auto derived_table_entry_2 = w_2 + negative_column_2_step_size * w_2_shift; auto derived_table_entry_3 = w_3 + negative_column_3_step_size * w_3_shift; - // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. + // (w_1 + \gamma q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. // deg 2 or 3 return derived_table_entry_1 + derived_table_entry_2 * eta + derived_table_entry_3 * eta_two + table_index * eta_three; @@ -206,8 +215,14 @@ template class LogDerivLookupRelationImpl { const FF& scaling_factor) { BB_OP_COUNT_TIME_NAME("Lookup::accumulate"); - using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>; + // declare the accumulator of the maximum length, in non-ZK Flavors, they are of the same length, + // whereas in ZK Flavors, the accumulator corresponding log derivative lookup argument sub-relation is the + // longest + using Accumulator = typename std::tuple_element_t<1, ContainerOverSubrelations>; using View = typename Accumulator::View; + // allows to re-use the values accumulated by the accumulator of the size smaller than + // the size of Accumulator declared above + using ShortView = typename std::tuple_element_t<0, ContainerOverSubrelations>::View; const auto inverses = View(in.lookup_inverses); // Degree 1 const auto read_counts = View(in.lookup_read_counts); // Degree 1 @@ -221,7 +236,8 @@ template class LogDerivLookupRelationImpl { // Establish the correctness of the polynomial of inverses I. Note: inverses is computed so that the value is 0 // if !inverse_exists. // Degrees: 2 (3) 1 (2) 1 1 - std::get<0>(accumulator) += (read_term * write_term * inverses - inverse_exists) * scaling_factor; // Deg 4 (6) + std::get<0>(accumulator) += + ShortView((read_term * write_term * inverses - inverse_exists) * scaling_factor); // Deg 4 (6) // Establish validity of the read. Note: no scaling factor here since this constraint is 'linearly dependent, // i.e. enforced across the entire trace, not on a per-row basis. @@ -232,4 +248,4 @@ template class LogDerivLookupRelationImpl { template using LogDerivLookupRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp index b904fabeb956..7f5afc0b384d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/permutation_relation.hpp @@ -2,7 +2,26 @@ #include "barretenberg/relations/relation_types.hpp" namespace bb { - +/** + * @brief Ultra Permutation Relation + * + * @details The Ultra Permutation Relation is given by the equation + \f{align}{ + \left( Z_{\text{perm}}(\vec X) + L_{0}(\vec X) \right) \cdot + \left[ (w_1(\vec X) + id_1(\vec X) \cdot \beta + \gamma) \cdot (w_2(\vec X) + id_2(\vec X) \cdot \beta + \gamma) + \cdot (w_3(\vec X) + id_3(\vec X) \cdot \beta + \gamma) \cdot (w_4(\vec X) + id_4(\vec X) \cdot \beta + \gamma)\right] + &\ + - \\ + \left(Z_{\text{perm, shifted}}(\vec X) + L_{2^d-1}(\vec X) \cdot \delta_{\text{pub}} \right) \cdot + \left[ (w_1(\vec X) + \sigma_1(\vec X) \cdot \beta + \gamma) \cdot (w_2(\vec X) + \sigma_2(\vec X) \cdot \beta + + \gamma) \cdot (w_3(\vec X) + \sigma_3 (\vec X) \cdot \beta + \gamma) \cdot (w_4 (\vec X) + \sigma_4(\vec X) \cdot \beta + + \gamma)\right] &\ = 0 \f} and \f{align}{ L_{2^d-1}(\vec X)\cdot Z_{\text{perm, shifted}}(\vec X) = 0 \f} + + Here, \f$ \vec X = (X_0,\ldots, X_{d-1})\f$, where \f$ d \f$ is the log of the circuit size. + + + * @tparam FF_ + */ template class UltraPermutationRelationImpl { public: using FF = FF_; @@ -17,6 +36,16 @@ template class UltraPermutationRelationImpl { 0 // left-shiftable polynomial sub-relation }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 5, // grand product construction sub-relation + 1 // left-shiftable polynomial sub-relation + }; + /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * @@ -49,7 +78,7 @@ template class UltraPermutationRelationImpl { const auto& beta = ParameterView(params.beta); const auto& gamma = ParameterView(params.gamma); - // witness degree 4; fully degree 8 + // witness degree 4; full degree 8 return (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma); } @@ -73,7 +102,7 @@ template class UltraPermutationRelationImpl { const auto& beta = ParameterView(params.beta); const auto& gamma = ParameterView(params.gamma); - // witness degree 4; fully degree 8 + // witness degree 4; full degree 8 return (w_1 + sigma_1 * beta + gamma) * (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma) * (w_4 + sigma_4 * beta + gamma); } @@ -81,8 +110,13 @@ template class UltraPermutationRelationImpl { /** * @brief Compute contribution of the permutation relation for a given edge (internal function) * - * @details This the relation confirms faithful calculation of the grand - * product polynomial Z_perm. + * @details This relation confirms faithful calculation of the grand + * product polynomial \f$ Z_{\text{perm}}\f$. + * In Sumcheck Prover Round, this method adds to accumulators evaluations of subrelations at the point + \f$(u_0,\ldots, u_{i-1}, k, \vec\ell)\f$ for \f$ k=0,\ldots, D\f$, where \f$ \vec \ell\f$ is a point on the + Boolean hypercube \f$\{0,1\}^{d-1-i}\f$ and \f$ D \f$ is specified by the calling class. It does so by taking as + input an array of Prover Polynomials partially evaluated at the points \f$(u_0,\ldots, u_{i-1}, k, \vec\ell)\f$ and + computing point-wise evaluations of the sub-relations. \todo Protogalaxy Accumulation * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -130,4 +164,4 @@ template class UltraPermutationRelationImpl { template using UltraPermutationRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp index a14d633272f9..bb75064effad 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_external_relation.hpp @@ -12,6 +12,17 @@ template class Poseidon2ExternalRelationImpl { 7, // external poseidon2 round sub-relation for third value 7, // external poseidon2 round sub-relation for fourth value }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 5, // external poseidon2 round sub-relation for first value + 5, // external poseidon2 round sub-relation for second value + 5, // external poseidon2 round sub-relation for third value + 5, // external poseidon2 round sub-relation for fourth value + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero @@ -121,4 +132,4 @@ template class Poseidon2ExternalRelationImpl { }; template using Poseidon2ExternalRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp index 77a1f498b922..02dcfaf6192c 100644 --- a/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/poseidon2_internal_relation.hpp @@ -14,6 +14,17 @@ template class Poseidon2InternalRelationImpl { 7, // internal poseidon2 round sub-relation for third value 7, // internal poseidon2 round sub-relation for fourth value }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 5, // external poseidon2 round sub-relation for first value + 5, // external poseidon2 round sub-relation for second value + 5, // external poseidon2 round sub-relation for third value + 5, // external poseidon2 round sub-relation for fourth value + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero @@ -102,4 +113,4 @@ template class Poseidon2InternalRelationImpl { }; // namespace bb template using Poseidon2InternalRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp index a5f4956edbc5..e97869a8185d 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_decomposition_relation.hpp @@ -61,6 +61,62 @@ template class TranslatorDecompositionRelationImpl { 3, // decomposition of z1 into 2 limbs subrelation 3 // decomposition of z2 into 2 limbs subrelation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, // decomposition of P.x limb 0 into microlimbs subrelation + 2, // decomposition of P.x limb 1 into microlimbs subrelation + 2, // decomposition of P.x limb 2 into microlimbs subrelation + 2, // decomposition of P.x limb 3 into microlimbs subrelation + 2, // decomposition of P.y limb 0 into microlimbs subrelation + 2, // decomposition of P.y limb 1 into microlimbs subrelation + 2, // decomposition of P.y limb 2 into microlimbs subrelation + 2, // decomposition of P.y limb 3 into microlimbs subrelation + 2, // decomposition of z1 limb 0 into microlimbs subrelation + 2, // decomposition of z2 limb 0 into microlimbs subrelation + 2, // decomposition of z1 limb 1 into microlimbs subrelation + 2, // decomposition of z2 limb 1 into microlimbs subrelation + 2, // decomposition of accumulator limb 0 into microlimbs subrelation + 2, // decomposition of accumulator limb 1 into microlimbs subrelation + 2, // decomposition of accumulator limb 2 into microlimbs subrelation + 2, // decomposition of accumulator limb 3 into microlimbs subrelation + 2, // decomposition of quotient limb 0 into microlimbs subrelation + 2, // decomposition of quotient limb 1 into microlimbs subrelation + 2, // decomposition of quotient limb 2 into microlimbs subrelation + 2, // decomposition of quotient limb 3 into microlimbs subrelation + 2, // decomposition of low relation wide limb into microlimbs subrelation + 2, // decomposition of high relation wide limb into microlimbs subrelation + 2, // stricter constraint on highest microlimb of P.x limb 0 subrelation + 2, // stricter constraint on highest microlimb of P.x limb 1 subrelation + 2, // stricter constraint on highest microlimb of P.x limb 2 subrelation + 2, // stricter constraint on highest microlimb of P.x limb 3 subrelation + 2, // stricter constraint on highest microlimb of P.y limb 0 subrelation + 2, // stricter constraint on highest microlimb of P.y limb 1 subrelation + 2, // stricter constraint on highest microlimb of P.y limb 2 subrelation + 2, // stricter constraint on highest microlimb of P.y limb 3 subrelation + 2, // stricter constraint on highest microlimb of z1 limb 0 subrelation + 2, // stricter constraint on highest microlimb of z2 limb 0 subrelation + 2, // stricter constraint on highest microlimb of z1 limb 1 subrelation + 2, // stricter constraint on highest microlimb of z2 limb 1 subrelation + 2, // stricter constraint on highest microlimb of accumulator limb 0 subrelation + 2, // stricter constraint on highest microlimb of accumulator limb 1 subrelation + 2, // stricter constraint on highest microlimb of accumulator limb 2 subrelation + 2, // stricter constraint on highest microlimb of accumulator limb 3 subrelation + 2, // stricter constraint on highest microlimb of quotient limb 0 subrelation + 2, // stricter constraint on highest microlimb of quotient limb 1 subrelation + 2, // stricter constraint on highest microlimb of quotient limb 2 subrelation + 2, // stricter constraint on highest microlimb of quotient limb 3 subrelation + 2, // decomposition of x_lo into 2 limbs subrelation + 2, // decomposition of x_hi into 2 limbs subrelation + 2, // decomposition of y_lo into 2 limbs subrelation + 2, // decomposition of y_hi into 2 limbs subrelation + 2, // decomposition of z1 into 2 limbs subrelation + 2 // decomposition of z2 into 2 limbs subrelation + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_delta_range_constraint_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_delta_range_constraint_relation.hpp index 1515598dc883..498bd835e806 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_delta_range_constraint_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_delta_range_constraint_relation.hpp @@ -23,7 +23,25 @@ template class TranslatorDeltaRangeConstraintRelationImpl { 3 // ordered_range_constraints_4 ends with defined maximum value subrelation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 5, // ordered_range_constraints_0 step in {0,1,2,3} subrelation + 5, // ordered_range_constraints_1 step in {0,1,2,3} subrelation + 5, // ordered_range_constraints_2 step in {0,1,2,3} subrelation + 5, // ordered_range_constraints_3 step in {0,1,2,3} subrelation + 5, // ordered_range_constraints_4 step in {0,1,2,3} subrelation + 2, // ordered_range_constraints_0 ends with defined maximum value subrelation + 2, // ordered_range_constraints_1 ends with defined maximum value subrelation + 2, // ordered_range_constraints_2 ends with defined maximum value subrelation + 2, // ordered_range_constraints_3 ends with defined maximum value subrelation + 2 // ordered_range_constraints_4 ends with defined maximum value subrelation + }; /** * @brief Expression for the generalized permutation sort relation * diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp index 5e25c0eaf00d..dbc80857edd6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_extra_relations.hpp @@ -12,7 +12,15 @@ template class TranslatorOpcodeConstraintRelationImpl { static constexpr std::array SUBRELATION_PARTIAL_LENGTHS{ 7 // opcode constraint relation }; - + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 6 // opcode constraint relation + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * @@ -57,7 +65,27 @@ template class TranslatorAccumulatorTransferRelationImpl { 3 // accumulator limb 3 is equal to given result at the end of accumulation subrelation }; + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, // transfer accumulator limb 0 at even index subrelation + 2, // transfer accumulator limb 1 at even index subrelation + 2, // transfer accumulator limb 2 at even index subrelation + 2, // transfer accumulator limb 3 at even index subrelation + 2, // accumulator limb 0 is zero at the start of accumulation subrelation + 2, // accumulator limb 1 is zero at the start of accumulation subrelation + 2, // accumulator limb 2 is zero at the start of accumulation subrelation + 2, // accumulator limb 3 is zero at the start of accumulation subrelation + 2, // accumulator limb 0 is equal to given result at the end of accumulation subrelation + 2, // accumulator limb 1 is equal to given result at the end of accumulation subrelation + 2, // accumulator limb 2 is equal to given result at the end of accumulation subrelation + 2 // accumulator limb 3 is equal to given result at the end of accumulation subrelation + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp index b94fa346e979..4218c4d4c5e4 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_non_native_field_relation.hpp @@ -14,7 +14,17 @@ template class TranslatorNonNativeFieldRelationImpl { 3, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), 3 // Prime subrelation (checks result in native field) }; - + /** + * @brief For ZK-Flavors: Upper bound on the degrees of subrelations considered as polynomials only in witness +polynomials, + * i.e. all selectors and public polynomials are treated as constants. The subrelation witness degree does not + * exceed the subrelation partial degree given by SUBRELATION_PARTIAL_LENGTH - 1. + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 2, // Lower wide limb subrelation (checks result is 0 mod 2¹³⁶) + 2, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), + 2 // Prime subrelation (checks result in native field) + }; /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * diff --git a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_permutation_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_permutation_relation.hpp index b5b6f276ab54..439c17d247d6 100644 --- a/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_permutation_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/translator_vm/translator_permutation_relation.hpp @@ -13,7 +13,15 @@ template class TranslatorPermutationRelationImpl { 7, // grand product construction sub-relation 3 // left-shiftable polynomial sub-relation }; - + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ + 6, // grand product construction sub-relation + 1 // left-shiftable polynomial sub-relation + }; inline static auto& get_grand_product_polynomial(auto& in) { return in.z_perm; } inline static auto& get_shifted_grand_product_polynomial(auto& in) { return in.z_perm_shift; } diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp index 55f4a38b2112..69dfd2b9d116 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_arithmetic_relation.hpp @@ -12,6 +12,13 @@ template class UltraArithmeticRelationImpl { 5 // secondary arithmetic sub-relation }; + /** + * @brief For ZK-Flavors: The degrees of subrelations considered as polynomials only in witness polynomials, + * i.e. all selectors and public polynomials are treated as constants. + * + */ + static constexpr std::array SUBRELATION_WITNESS_DEGREES{ 2, 2 }; + /** * @brief Returns true if the contribution from all subrelations for the provided inputs is identically zero * @@ -121,4 +128,4 @@ template class UltraArithmeticRelationImpl { }; template using UltraArithmeticRelation = Relation>; -} // namespace bb +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp index 21401f2fe0a8..14a87d089c82 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_execution.cpp @@ -11,6 +11,7 @@ #include "barretenberg/vm/avm_trace/avm_trace.hpp" #include "barretenberg/vm/avm_trace/aztec_constants.hpp" #include "barretenberg/vm/avm_trace/constants.hpp" +#include "barretenberg/vm/avm_trace/stats.hpp" #include "barretenberg/vm/generated/avm_circuit_builder.hpp" #include "barretenberg/vm/generated/avm_composer.hpp" @@ -64,7 +65,9 @@ std::tuple Execution::prove(std::vector returndata; - auto trace = gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints); + std::vector trace; + AVM_TRACK_TIME("prove/gen_trace", + (trace = gen_trace(instructions, returndata, calldata, public_inputs_vec, execution_hints))); if (!avm_dump_trace_path.empty()) { info("Dumping trace as CSV to: " + avm_dump_trace_path.string()); dump_trace_as_csv(trace, avm_dump_trace_path); @@ -72,12 +75,13 @@ std::tuple Execution::prove(std::vector Execution::gen_trace(std::vector const& instructio } } - return trace_builder.finalize(); + auto trace = trace_builder.finalize(); + vinfo("Final trace size: ", trace.size()); + return trace; } } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp index eee16a419a10..292aeaea4782 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm_trace/avm_trace.cpp @@ -24,6 +24,7 @@ #include "barretenberg/vm/avm_trace/fixed_gas.hpp" #include "barretenberg/vm/avm_trace/fixed_powers.hpp" #include "barretenberg/vm/avm_trace/gadgets/avm_slice_trace.hpp" +#include "barretenberg/vm/avm_trace/stats.hpp" namespace bb::avm_trace { @@ -3772,6 +3773,31 @@ std::vector AvmTraceBuilder::finalize(uint32_t min_trace_size, bool range_c gas_trace_size + 1, KERNEL_INPUTS_LENGTH, KERNEL_OUTPUTS_LENGTH, min_trace_size, fixed_gas_table.size(), slice_trace_size, calldata.size() }; + vinfo("Trace sizes before padding:", + "\n\tmain_trace_size: ", + main_trace_size, + "\n\tmem_trace_size: ", + mem_trace_size, + "\n\talu_trace_size: ", + alu_trace_size, + "\n\trange_check_size: ", + range_check_size, + "\n\tconv_trace_size: ", + conv_trace_size, + "\n\tlookup_table_size: ", + lookup_table_size, + "\n\tsha256_trace_size: ", + sha256_trace_size, + "\n\tposeidon2_trace_size: ", + poseidon2_trace_size, + "\n\tpedersen_trace_size: ", + pedersen_trace_size, + "\n\tgas_trace_size: ", + gas_trace_size, + "\n\tfixed_gas_table_size: ", + fixed_gas_table.size(), + "\n\tslice_trace_size: ", + slice_trace_size); auto trace_size = std::max_element(trace_sizes.begin(), trace_sizes.end()); // We only need to pad with zeroes to the size to the largest trace here, pow_2 padding is handled in the diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp index 23762777a9f6..221b3cdee44c 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.cpp @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/common/constexpr_utils.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" @@ -16,27 +17,6 @@ namespace bb { using Flavor = AvmFlavor; using FF = Flavor::FF; -namespace { - -// Loops through LookupRelations and calculates the logderivatives. -// Metaprogramming is used to loop through the relations, because they are types. -template -void compute_logderivative_rel(const RelationParameters& relation_parameters, - PP& prover_polynomials, - size_t circuit_size) -{ - using Relation = std::tuple_element_t; - AVM_TRACK_TIME( - Relation::NAME + std::string("_ms"), - (compute_logderivative_inverse(prover_polynomials, relation_parameters, circuit_size))); - - if constexpr (relation_idx + 1 < std::tuple_size_v) { - compute_logderivative_rel(relation_parameters, prover_polynomials, circuit_size); - } -} - -} // namespace - /** * Create AvmProver from proving key, witness and manifest. * @@ -93,8 +73,16 @@ void AvmProver::execute_log_derivative_inverse_round() relation_parameters.gamma = gamm; auto prover_polynomials = ProverPolynomials(*key); - compute_logderivative_rel(relation_parameters, prover_polynomials, key->circuit_size); + bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { + using Relation = std::tuple_element_t; + AVM_TRACK_TIME(Relation::NAME + std::string("_ms"), + (compute_logderivative_inverse( + prover_polynomials, relation_parameters, key->circuit_size))); + }); +} +void AvmProver::execute_log_derivative_inverse_commitments_round() +{ // Commit to all logderivative inverse polynomials for (auto [commitment, key_poly] : zip_view(witness_commitments.get_derived(), key->get_derived())) { commitment = commitment_key->commit(key_poly); @@ -154,18 +142,22 @@ HonkProof AvmProver::construct_proof() execute_preamble_round(); // Compute wire commitments - execute_wire_commitments_round(); + AVM_TRACK_TIME("prove/execute_wire_commitments_round_ms", execute_wire_commitments_round()); + + // Compute sorted list accumulator + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round_ms", execute_log_derivative_inverse_round()); - // Compute sorted list accumulator and commitment - execute_log_derivative_inverse_round(); + // Compute commitments to logderivative inverse polynomials + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round_ms", + execute_log_derivative_inverse_commitments_round()); // Fiat-Shamir: alpha // Run sumcheck subprotocol. - execute_relation_check_rounds(); + AVM_TRACK_TIME("prove/execute_relation_check_rounds_ms", execute_relation_check_rounds()); // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - execute_pcs_rounds(); + AVM_TRACK_TIME("prove/execute_pcs_rounds_ms", execute_pcs_rounds()); return export_proof(); } diff --git a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp index 892b11a525ff..35d9f927cbbd 100644 --- a/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/generated/avm_prover.hpp @@ -29,6 +29,7 @@ class AvmProver { void execute_preamble_round(); void execute_wire_commitments_round(); void execute_log_derivative_inverse_round(); + void execute_log_derivative_inverse_commitments_round(); void execute_relation_check_rounds(); void execute_pcs_rounds(); diff --git a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs index 47c681dc9bd4..27ae98c74134 100644 --- a/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/circuit_builder.hpp.hbs @@ -161,7 +161,6 @@ class {{name}}CircuitBuilder { return true; } - [[nodiscard]] size_t get_num_gates() const { return rows.size(); } [[nodiscard]] size_t get_circuit_subgroup_size() const diff --git a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs index 32474b361e4e..53990fad42d2 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.cpp.hbs @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/claim.hpp" #include "barretenberg/commitment_schemes/commitment_key.hpp" +#include "barretenberg/common/constexpr_utils.hpp" #include "barretenberg/honk/proof_system/logderivative_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" #include "barretenberg/plonk_honk_shared/library/grand_product_library.hpp" @@ -16,27 +17,6 @@ namespace bb { using Flavor = {{name}}Flavor; using FF = Flavor::FF; -namespace { - -// Loops through LookupRelations and calculates the logderivatives. -// Metaprogramming is used to loop through the relations, because they are types. -template -void compute_logderivative_rel(const RelationParameters& relation_parameters, - PP& prover_polynomials, - size_t circuit_size) -{ - using Relation = std::tuple_element_t; - AVM_TRACK_TIME( - Relation::NAME + std::string("_ms"), - (compute_logderivative_inverse(prover_polynomials, relation_parameters, circuit_size))); - - if constexpr (relation_idx + 1 < std::tuple_size_v) { - compute_logderivative_rel(relation_parameters, prover_polynomials, circuit_size); - } -} - -} // namespace - /** * Create {{name}}Prover from proving key, witness and manifest. * @@ -94,8 +74,16 @@ void {{name}}Prover::execute_log_derivative_inverse_round() relation_parameters.gamma = gamm; auto prover_polynomials = ProverPolynomials(*key); - compute_logderivative_rel(relation_parameters, prover_polynomials, key->circuit_size); + bb::constexpr_for<0, std::tuple_size_v, 1>([&]() { + using Relation = std::tuple_element_t; + AVM_TRACK_TIME(Relation::NAME + std::string("_ms"), + (compute_logderivative_inverse( + prover_polynomials, relation_parameters, key->circuit_size))); + }); +} +void {{name}}Prover::execute_log_derivative_inverse_commitments_round() +{ // Commit to all logderivative inverse polynomials for (auto [commitment, key_poly] : zip_view(witness_commitments.get_derived(), key->get_derived())) { commitment = commitment_key->commit(key_poly); @@ -155,18 +143,21 @@ HonkProof {{name}}Prover::construct_proof() execute_preamble_round(); // Compute wire commitments - execute_wire_commitments_round(); + AVM_TRACK_TIME("prove/execute_wire_commitments_round_ms", execute_wire_commitments_round()); + + // Compute sorted list accumulator + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_round_ms", execute_log_derivative_inverse_round()); - // Compute sorted list accumulator and commitment - execute_log_derivative_inverse_round(); + // Compute commitments to logderivative inverse polynomials + AVM_TRACK_TIME("prove/execute_log_derivative_inverse_commitments_round_ms", execute_log_derivative_inverse_commitments_round()); // Fiat-Shamir: alpha // Run sumcheck subprotocol. - execute_relation_check_rounds(); + AVM_TRACK_TIME("prove/execute_relation_check_rounds_ms", execute_relation_check_rounds()); // Fiat-Shamir: rho, y, x, z // Execute Zeromorph multilinear PCS - execute_pcs_rounds(); + AVM_TRACK_TIME("prove/execute_pcs_rounds_ms", execute_pcs_rounds()); return export_proof(); } diff --git a/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs b/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs index 8915a9d8f29a..1ea0f4186810 100644 --- a/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/prover.hpp.hbs @@ -29,6 +29,7 @@ class {{name}}Prover { void execute_preamble_round(); void execute_wire_commitments_round(); void execute_log_derivative_inverse_round(); + void execute_log_derivative_inverse_commitments_round(); void execute_relation_check_rounds(); void execute_pcs_rounds(); diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index d2b56d88b240..e1cd01e8b218 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 = eb469c61582ec22874f0e2a0b17aee8fa01e7bde + commit = 97e1ef01e7433c582762cdd2853b8acc5f7271be method = merge cmdver = 0.4.6 - parent = f2d4ad4069c542cfc9e439a7e0bf136433271a93 + parent = b6f8f0a00ce5aea1e3fd3bf4128f3d177da20793 diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr index 2bf0d0001de8..87cd38f1b12b 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable.nr @@ -3,7 +3,7 @@ use dep::protocol_types::{ traits::{FromField, ToField} }; -use crate::context::{PrivateContext, PublicContext}; +use crate::context::{PrivateContext, PublicContext, UnconstrainedContext}; use crate::state_vars::{ storage::Storage, shared_mutable::{scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange} @@ -225,6 +225,17 @@ impl SharedMutable wher } } +impl SharedMutable where T: ToField + FromField + Eq { + unconstrained pub fn get_current_value_in_unconstrained(self) -> T { + let block_number = self.context.block_number() as u32; + self.read_value_change().get_current_at(block_number) + } + + unconstrained fn read_value_change(self) -> ScheduledValueChange { + self.context.storage_read(self.get_value_change_storage_slot()) + } +} + unconstrained fn get_public_storage_hints( address: AztecAddress, storage_slot: Field, diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr index e162a642eaae..8d5923a7f204 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/test.nr @@ -1,5 +1,5 @@ use crate::{ - context::{PublicContext, PrivateContext}, + context::{PublicContext, PrivateContext, UnconstrainedContext}, state_vars::shared_mutable::{ shared_mutable::SharedMutable, scheduled_value_change::ScheduledValueChange, scheduled_delay_change::ScheduledDelayChange @@ -33,6 +33,10 @@ fn in_private( SharedMutable::new(&mut env.private_at(historical_block_number), storage_slot) } +fn in_unconstrained(env: TestEnvironment) -> SharedMutable { + SharedMutable::new(env.unkonstrained(), storage_slot) +} + #[test] fn test_get_current_value_in_public_initial() { let env = setup(); @@ -337,3 +341,63 @@ fn test_get_current_value_in_private_bad_zero_hash_delay_hints() { let _ = state_var.get_current_value_in_private(); } + +#[test] +fn test_get_current_value_in_unconstrained_initial() { + let env = setup(); + let state_var = in_unconstrained(env); + + assert_eq(state_var.get_current_value_in_unconstrained(), zeroed()); +} + +#[test] +fn test_get_current_value_in_unconstrained_before_scheduled_change() { + let mut env = setup(); + let state_var_public = in_public(env); + + state_var_public.schedule_value_change(new_value); + + let (_, block_of_change) = state_var_public.get_scheduled_value_in_public(); + + let original_value = zeroed(); + + let mut state_var_unconstrained = in_unconstrained(env); + + // The current value has not changed + assert_eq(state_var_unconstrained.get_current_value_in_unconstrained(), original_value); + + // The current value still does not change right before the block of change + env.advance_block_to(block_of_change - 1); + + state_var_unconstrained = in_unconstrained(env); + assert_eq(state_var_unconstrained.get_current_value_in_unconstrained(), original_value); +} + +#[test] +fn test_get_current_value_in_unconstrained_at_scheduled_change() { + let mut env = setup(); + let state_var_public = in_public(env); + + state_var_public.schedule_value_change(new_value); + + let (_, block_of_change) = state_var_public.get_scheduled_value_in_public(); + + env.advance_block_to(block_of_change); + + let state_var_unconstrained = in_unconstrained(env); + assert_eq(state_var_unconstrained.get_current_value_in_unconstrained(), new_value); +} + +#[test] +fn test_get_current_value_in_unconstrained_after_scheduled_change() { + let mut env = setup(); + let state_var_public = in_public(env); + + state_var_public.schedule_value_change(new_value); + + let (_, block_of_change) = state_var_public.get_scheduled_value_in_public(); + + env.advance_block_to(block_of_change + 10); + let state_var_unconstrained = in_unconstrained(env); + assert_eq(state_var_unconstrained.get_current_value_in_unconstrained(), new_value); +} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr index 3d6b791e8334..e230ebbab672 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/cheatcodes.nr @@ -10,6 +10,14 @@ unconstrained pub fn reset() { oracle_reset(); } +unconstrained pub fn get_chain_id() -> Field { + oracle_get_chain_id() +} + +unconstrained pub fn get_version() -> Field { + oracle_get_version() +} + unconstrained pub fn get_contract_address() -> AztecAddress { oracle_get_contract_address() } @@ -112,6 +120,12 @@ unconstrained pub fn set_fn_selector(selector: FunctionSelector) { #[oracle(reset)] fn oracle_reset() {} +#[oracle(getChainId)] +fn oracle_get_chain_id() -> Field {} + +#[oracle(getVersion)] +fn oracle_get_version() -> Field {} + #[oracle(getContractAddress)] fn oracle_get_contract_address() -> AztecAddress {} diff --git a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr index b6d0cc4546a1..b6238d4e02d8 100644 --- a/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr +++ b/noir-projects/aztec-nr/aztec/src/test/helpers/test_environment.nr @@ -7,7 +7,7 @@ use dep::protocol_types::{ use crate::context::inputs::{PublicContextInputs, PrivateContextInputs}; use crate::context::{packed_returns::PackedReturns, call_interfaces::CallInterface}; -use crate::context::{PrivateContext, PublicContext, PrivateVoidCallInterface}; +use crate::context::{PrivateContext, PublicContext, UnconstrainedContext, PrivateVoidCallInterface}; use crate::test::helpers::{cheatcodes, utils::{apply_side_effects_private, Deployer, TestAccount}, keys}; use crate::keys::constants::{NULLIFIER_INDEX, INCOMING_INDEX, OUTGOING_INDEX, TAGGING_INDEX}; use crate::hash::{hash_args, hash_args_array}; @@ -56,6 +56,11 @@ impl TestEnvironment { self.private_at(cheatcodes::get_block_number()) } + // unconstrained is a key word, so we mis-spell purposefully here, like we do with contrakt + fn unkonstrained(self) -> UnconstrainedContext { + UnconstrainedContext::new() + } + fn private_at(&mut self, historical_block_number: u32) -> PrivateContext { if historical_block_number >= cheatcodes::get_block_number() { self.advance_block_to(historical_block_number + 1); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr index 50de33ebc3c3..f87036ee9d8a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer.nr @@ -1,12 +1,16 @@ -use crate::components::private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer; +mod meter_gas_used; + +use crate::components::{ + private_kernel_circuit_public_inputs_composer::PrivateKernelCircuitPublicInputsComposer, + tail_output_composer::meter_gas_used::meter_gas_used +}; use dep::types::{ abis::{ - accumulated_data::combined_accumulated_data::CombinedAccumulatedData, gas::Gas, + accumulated_data::combined_accumulated_data::CombinedAccumulatedData, kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PrivateKernelCircuitPublicInputs}, log_hash::{ScopedEncryptedLogHash, NoteLogHash, ScopedLogHash}, note_hash::ScopedNoteHash, nullifier::ScopedNullifier }, - constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, L2_GAS_PER_LOG_BYTE}, hash::{compute_tx_logs_hash, compute_tx_note_logs_hash}, messaging::l2_to_l1_message::ScopedL2ToL1Message }; @@ -45,37 +49,7 @@ impl TailOutputComposer { data.note_encrypted_log_preimages_length = source.note_encrypted_logs_hashes.storage.fold(0, |len, l: NoteLogHash| len + l.length); data.encrypted_log_preimages_length = source.encrypted_logs_hashes.storage.fold(0, |len, l: ScopedEncryptedLogHash| len + l.log_hash.length); data.unencrypted_log_preimages_length = source.unencrypted_logs_hashes.storage.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); - data.gas_used = self.meter_gas_used(data); + data.gas_used = meter_gas_used(data, self.output_composer.public_inputs.constants.tx_context.gas_settings); data } - - fn meter_gas_used(self, data: CombinedAccumulatedData) -> Gas { - let mut metered_da_bytes = 0; - let mut metered_l2_gas = 0; - - let data_builder = self.output_composer.public_inputs.end; - // IMPORTANT: Must use data_builder.__.len(), which is the the number of items pushed to the BoundedVec. - // Do not use data.__.len(), which is the array's max length. - metered_da_bytes += data_builder.note_hashes.len() * DA_BYTES_PER_FIELD; - metered_l2_gas += data_builder.note_hashes.len() * L2_GAS_PER_NOTE_HASH; - - metered_da_bytes += data_builder.nullifiers.len() * DA_BYTES_PER_FIELD; - metered_l2_gas += data_builder.nullifiers.len() * L2_GAS_PER_NULLIFIER; - - metered_da_bytes += data_builder.l2_to_l1_msgs.len() * DA_BYTES_PER_FIELD; - - metered_da_bytes += data.note_encrypted_log_preimages_length as u32; - metered_l2_gas += data.note_encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - - metered_da_bytes += data.encrypted_log_preimages_length as u32; - metered_l2_gas += data.encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - - metered_da_bytes += data.unencrypted_log_preimages_length as u32; - metered_l2_gas += data.unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - - let teardown_gas = self.output_composer.public_inputs.constants.tx_context.gas_settings.teardown_gas_limits; - Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) - + Gas::tx_overhead() - + teardown_gas - } } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr new file mode 100644 index 000000000000..e0585bd0ffe5 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_composer/meter_gas_used.nr @@ -0,0 +1,36 @@ +use dep::types::{ + abis::{ + accumulated_data::combined_accumulated_data::CombinedAccumulatedData, gas::Gas, + gas_settings::GasSettings +}, + constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, L2_GAS_PER_LOG_BYTE}, + utils::arrays::array_length +}; + +fn meter_gas_used(data: CombinedAccumulatedData, gas_settings: GasSettings) -> Gas { + let mut metered_da_bytes = 0; + let mut metered_l2_gas = 0; + + let num_note_hashes = array_length(data.note_hashes); + metered_da_bytes += num_note_hashes * DA_BYTES_PER_FIELD; + metered_l2_gas += num_note_hashes * L2_GAS_PER_NOTE_HASH; + + let num_nullifiers = array_length(data.nullifiers); + metered_da_bytes += num_nullifiers * DA_BYTES_PER_FIELD; + metered_l2_gas += num_nullifiers * L2_GAS_PER_NULLIFIER; + + let num_l2_to_l1_msgs = array_length(data.l2_to_l1_msgs); + metered_da_bytes += num_l2_to_l1_msgs * DA_BYTES_PER_FIELD; + + metered_da_bytes += data.note_encrypted_log_preimages_length as u32; + metered_l2_gas += data.note_encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; + + metered_da_bytes += data.encrypted_log_preimages_length as u32; + metered_l2_gas += data.encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; + + metered_da_bytes += data.unencrypted_log_preimages_length as u32; + metered_l2_gas += data.unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; + + let teardown_gas = gas_settings.teardown_gas_limits; + Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) + Gas::tx_overhead() + teardown_gas +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr index 135c7312a72d..7ef9a42e0762 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_output_validator.nr @@ -1,9 +1,12 @@ mod kernel_circuit_output_hints; mod validate_value_transformation; -use crate::components::tail_output_validator::{ +use crate::components::{ + tail_output_composer::meter_gas_used::meter_gas_used, + tail_output_validator::{ kernel_circuit_output_hints::{generate_kernel_circuit_output_hints, Hints}, validate_value_transformation::{validate_transformed_values, validate_value_transformation} +} }; use dep::types::{ abis::{ @@ -37,7 +40,7 @@ impl TailOutputValidator { self.validate_propagated_values(); self.validate_propagated_sorted_siloed_values(hints); self.validate_accumulated_values(hints); - self.validate_gas_limits(); + self.validate_gas_used(); } fn validate_empty_values(self) { @@ -149,7 +152,13 @@ impl TailOutputValidator { ); } - fn validate_gas_limits(self) { + fn validate_gas_used(self) { + let gas_used = meter_gas_used( + self.output.end, + self.output.constants.tx_context.gas_settings + ); + assert(self.output.end.gas_used == gas_used, "incorrect metered gas used"); + let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; assert(self.output.end.gas_used.within(limits), "The gas used exceeds the gas limits"); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr index a51363f34b60..52fdf81766b2 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer.nr @@ -34,8 +34,8 @@ impl TailToPublicOutputComposer { end_non_revertible.gas_used = meter_gas_used_non_revertible(end_non_revertible); let teardown_gas = source.constants.tx_context.gas_settings.teardown_gas_limits; end.gas_used = meter_gas_used_revertible(end, teardown_gas); - output.end_non_revertible = end_non_revertible.finish(); - output.end = end.finish(); + output.end_non_revertible = end_non_revertible; + output.end = end; output } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr index 6c85ef2e5c92..3614a49df5df 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/meter_gas_used.nr @@ -1,47 +1,50 @@ use dep::types::{ abis::{ - accumulated_data::{public_accumulated_data_builder::PublicAccumulatedDataBuilder}, gas::Gas, + accumulated_data::{public_accumulated_data_builder::PublicAccumulatedData}, gas::Gas, log_hash::{LogHash, ScopedLogHash} }, constants::{ DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, FIXED_AVM_STARTUP_L2_GAS, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, L2_GAS_PER_LOG_BYTE -} +}, + utils::arrays::array_length }; -fn meter_gas_used(data: PublicAccumulatedDataBuilder) -> Gas { +fn meter_gas_used(data: PublicAccumulatedData) -> Gas { let mut metered_da_bytes = 0; let mut metered_l2_gas = 0; - metered_da_bytes += data.note_hashes.len() * DA_BYTES_PER_FIELD; - metered_l2_gas += data.note_hashes.len() * L2_GAS_PER_NOTE_HASH; + let num_note_hashes = array_length(data.note_hashes); + metered_da_bytes += num_note_hashes * DA_BYTES_PER_FIELD; + metered_l2_gas += num_note_hashes * L2_GAS_PER_NOTE_HASH; - metered_da_bytes += data.nullifiers.len() * DA_BYTES_PER_FIELD; - metered_l2_gas += data.nullifiers.len() * L2_GAS_PER_NULLIFIER; + let num_nullifiers = array_length(data.nullifiers); + metered_da_bytes += num_nullifiers * DA_BYTES_PER_FIELD; + metered_l2_gas += num_nullifiers * L2_GAS_PER_NULLIFIER; - metered_da_bytes += data.l2_to_l1_msgs.len() * DA_BYTES_PER_FIELD; + metered_da_bytes += array_length(data.l2_to_l1_msgs) * DA_BYTES_PER_FIELD; - let note_encrypted_log_preimages_length = data.note_encrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + let note_encrypted_log_preimages_length = data.note_encrypted_logs_hashes.fold(0, |len, l: LogHash| len + l.length); metered_da_bytes += note_encrypted_log_preimages_length as u32; metered_l2_gas += note_encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - let encrypted_log_preimages_length = data.encrypted_logs_hashes.storage.fold(0, |len, l: LogHash| len + l.length); + let encrypted_log_preimages_length = data.encrypted_logs_hashes.fold(0, |len, l: LogHash| len + l.length); metered_da_bytes += encrypted_log_preimages_length as u32; metered_l2_gas += encrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - let unencrypted_log_preimages_length = data.unencrypted_logs_hashes.storage.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); + let unencrypted_log_preimages_length = data.unencrypted_logs_hashes.fold(0, |len, l: ScopedLogHash| len + l.log_hash.length); metered_da_bytes += unencrypted_log_preimages_length as u32; metered_l2_gas += unencrypted_log_preimages_length as u32 * L2_GAS_PER_LOG_BYTE; - metered_l2_gas += data.public_call_stack.len() * FIXED_AVM_STARTUP_L2_GAS; + metered_l2_gas += array_length(data.public_call_stack) * FIXED_AVM_STARTUP_L2_GAS; Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, metered_l2_gas) } -pub fn meter_gas_used_non_revertible(data: PublicAccumulatedDataBuilder) -> Gas { +pub fn meter_gas_used_non_revertible(data: PublicAccumulatedData) -> Gas { meter_gas_used(data) + Gas::tx_overhead() } -pub fn meter_gas_used_revertible(data: PublicAccumulatedDataBuilder, teardown_gas: Gas) -> Gas { +pub fn meter_gas_used_revertible(data: PublicAccumulatedData, teardown_gas: Gas) -> Gas { meter_gas_used(data) + Gas::new(teardown_gas.da_gas, teardown_gas.l2_gas) } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr index 95a11b1b631d..e6d19a486e51 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_composer/split_to_public.nr @@ -1,6 +1,7 @@ use dep::types::abis::{ accumulated_data::{ private_accumulated_data_builder::PrivateAccumulatedDataBuilder, + public_accumulated_data::PublicAccumulatedData, public_accumulated_data_builder::PublicAccumulatedDataBuilder } }; @@ -8,7 +9,7 @@ use dep::types::abis::{ pub fn split_to_public( data: PrivateAccumulatedDataBuilder, min_revertible_side_effect_counter: u32 -) -> (PublicAccumulatedDataBuilder, PublicAccumulatedDataBuilder) { +) -> (PublicAccumulatedData, PublicAccumulatedData) { assert(min_revertible_side_effect_counter != 0, "min_revertible_side_effect_counter must not be 0"); let mut non_revertible_builder = PublicAccumulatedDataBuilder::empty(); @@ -106,5 +107,5 @@ pub fn split_to_public( } } - (non_revertible_builder, revertible_builder) + (non_revertible_builder.finish(), revertible_builder.finish()) } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr index dcbf1722b4f6..ece36c83ad04 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/components/tail_to_public_output_validator.nr @@ -2,6 +2,7 @@ mod tail_to_public_output_hints; use crate::components::{ tail_output_validator::validate_value_transformation::{validate_transformed_values, validate_value_transformation}, + tail_to_public_output_composer::meter_gas_used::{meter_gas_used_non_revertible, meter_gas_used_revertible}, tail_to_public_output_validator::tail_to_public_output_hints::{generate_tail_to_public_output_hints, TailToPublicOutputHints} }; use dep::types::{ @@ -33,7 +34,7 @@ impl TailToPublicOutputValidator { self.validate_empty_values(); self.validate_propagated_values(); self.validate_propagated_sorted_siloed_values(hints); - self.validate_gas_limits(); + self.validate_gas_used(); } fn validate_empty_values(self) { @@ -180,7 +181,18 @@ impl TailToPublicOutputValidator { ) } - fn validate_gas_limits(self) { + fn validate_gas_used(self) { + let gas_used = meter_gas_used_non_revertible(self.output.end_non_revertible); + assert( + self.output.end_non_revertible.gas_used == gas_used, "incorrect metered non-revertible gas used" + ); + + let gas_used = meter_gas_used_revertible( + self.output.end, + self.output.constants.tx_context.gas_settings.teardown_gas_limits + ); + assert(self.output.end.gas_used == gas_used, "incorrect metered revertible gas used"); + let limits = self.previous_kernel.constants.tx_context.gas_settings.gas_limits; let total_gas_used = self.output.end_non_revertible.gas_used + self.output.end.gas_used; assert(total_gas_used.within(limits), "The gas used exceeds the gas limits"); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr new file mode 100644 index 000000000000..4450cb2cd2fa --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/meter_gas_used.nr @@ -0,0 +1,73 @@ +use crate::components::tail_output_composer::meter_gas_used::meter_gas_used; +use dep::types::{ + abis::gas::Gas, + constants::{DA_BYTES_PER_FIELD, DA_GAS_PER_BYTE, L2_GAS_PER_NOTE_HASH, L2_GAS_PER_NULLIFIER, L2_GAS_PER_LOG_BYTE}, + tests::fixture_builder::FixtureBuilder +}; + +fn new_builder() -> FixtureBuilder { + let mut builder = FixtureBuilder::new(); + builder.tx_context.gas_settings.teardown_gas_limits = Gas::new(12, 345); + builder +} + +#[test] +fn meter_gas_used_empty_succeeds() { + let builder = new_builder(); + let data = builder.to_combined_accumulated_data(); + let gas_settings = builder.tx_context.gas_settings; + let gas = meter_gas_used(data, gas_settings); + assert_eq(gas, Gas::tx_overhead() + gas_settings.teardown_gas_limits); +} + +#[test] +fn meter_gas_used_everything_succeeds() { + let mut builder = new_builder(); + let mut metered_da_bytes = 0; + let mut computed_l2_gas = 0; + + builder.append_note_hashes(4); + metered_da_bytes += 4 * DA_BYTES_PER_FIELD; + computed_l2_gas += 4 * L2_GAS_PER_NOTE_HASH; + + builder.append_nullifiers(3); + metered_da_bytes += 3 * DA_BYTES_PER_FIELD; + computed_l2_gas += 3 * L2_GAS_PER_NULLIFIER; + + builder.append_l2_to_l1_msgs(1); + metered_da_bytes += 1 * DA_BYTES_PER_FIELD; + + builder.add_note_encrypted_log_hash(1001, 12, 0); + metered_da_bytes += 12; + computed_l2_gas += 12 * L2_GAS_PER_LOG_BYTE; + + builder.add_note_encrypted_log_hash(1002, 8, 0); + metered_da_bytes += 8; + computed_l2_gas += 8 * L2_GAS_PER_LOG_BYTE; + + builder.add_note_encrypted_log_hash(1003, 20, 0); + metered_da_bytes += 20; + computed_l2_gas += 20 * L2_GAS_PER_LOG_BYTE; + + builder.add_encrypted_log_hash(2001, 2); + metered_da_bytes += 2; + computed_l2_gas += 2 * L2_GAS_PER_LOG_BYTE; + + builder.add_encrypted_log_hash(2002, 6); + metered_da_bytes += 6; + computed_l2_gas += 6 * L2_GAS_PER_LOG_BYTE; + + builder.add_unencrypted_log_hash(3001, 51); + metered_da_bytes += 51; + computed_l2_gas += 51 * L2_GAS_PER_LOG_BYTE; + + let data = builder.to_combined_accumulated_data(); + let gas_settings = builder.tx_context.gas_settings; + let gas = meter_gas_used(data, gas_settings); + + assert_eq( + gas, Gas::new(metered_da_bytes * DA_GAS_PER_BYTE, computed_l2_gas) + + Gas::tx_overhead() + + gas_settings.teardown_gas_limits + ); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr similarity index 98% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr index b73651287517..0bdc19122bd9 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_composer_builder/mod.nr @@ -1,3 +1,5 @@ +mod meter_gas_used; + use crate::components::tail_output_composer::TailOutputComposer; use dep::types::{abis::kernel_circuit_public_inputs::KernelCircuitPublicInputs, tests::fixture_builder::FixtureBuilder}; diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr index 6baadc391fbc..524e283b332d 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/mod.nr @@ -1,10 +1,14 @@ mod validate_accumulated_values; mod validate_empty_values; +mod validate_gas_used; mod validate_propagated_sorted_siloed_values; mod validate_propagated_values; -use crate::components::tail_output_validator::TailOutputValidator; -use dep::types::tests::fixture_builder::FixtureBuilder; +use crate::components::{tail_output_composer::meter_gas_used::meter_gas_used, tail_output_validator::TailOutputValidator}; +use dep::types::{ + abis::{gas_settings::GasSettings, kernel_circuit_public_inputs::KernelCircuitPublicInputs}, + tests::fixture_builder::FixtureBuilder +}; struct TailOutputValidatorBuilder { output: FixtureBuilder, @@ -15,13 +19,26 @@ impl TailOutputValidatorBuilder { pub fn new() -> Self { let mut output = FixtureBuilder::new(); let mut previous_kernel = FixtureBuilder::new(); + output.tx_context.gas_settings = GasSettings::default(); + previous_kernel.tx_context.gas_settings = GasSettings::default(); output.set_first_nullifier(); previous_kernel.set_first_nullifier(); TailOutputValidatorBuilder { output, previous_kernel } } + pub fn export_output(self) -> KernelCircuitPublicInputs { + let mut output = self.output.to_kernel_circuit_public_inputs(); + output.end.gas_used = meter_gas_used(output.end, output.constants.tx_context.gas_settings); + output + } + pub fn validate(self) { - let output = self.output.to_kernel_circuit_public_inputs(); + let output = self.export_output(); + let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); + TailOutputValidator::new(output, previous_kernel).validate(); + } + + pub fn validate_with_output(self, output: KernelCircuitPublicInputs) { let previous_kernel = self.previous_kernel.to_private_kernel_circuit_public_inputs(); TailOutputValidator::new(output, previous_kernel).validate(); } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr new file mode 100644 index 000000000000..de9c3b78ff9f --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_output_validator_builder/validate_gas_used.nr @@ -0,0 +1,73 @@ +use crate::tests::tail_output_validator_builder::TailOutputValidatorBuilder; + +impl TailOutputValidatorBuilder { + pub fn new_with_data() -> Self { + let mut builder = TailOutputValidatorBuilder::new(); + + builder.previous_kernel.append_note_hashes(3); + builder.output.append_siloed_note_hashes(3); + + builder.previous_kernel.append_note_encrypted_log_hashes(3); + builder.output.append_note_encrypted_log_hashes(3); + builder.output.hash_note_encrypted_log_hashes(); + + builder + } +} + +#[test] +fn validate_gas_used_succeeds() { + let builder = TailOutputValidatorBuilder::new_with_data(); + let output = builder.export_output(); + builder.validate_with_output(output); +} + +#[test(should_fail_with="incorrect metered gas used")] +fn validate_gas_used_wrong_da_gas_fails() { + let builder = TailOutputValidatorBuilder::new_with_data(); + let mut output = builder.export_output(); + + // Tweak the da gas in the output to be a wrong value. + output.end.gas_used.da_gas += 1; + + builder.validate_with_output(output); +} + +#[test(should_fail_with="incorrect metered gas used")] +fn validate_gas_used_wrong_l2_gas_fails() { + let builder = TailOutputValidatorBuilder::new_with_data(); + let mut output = builder.export_output(); + + // Tweak the l2 gas in the output to be a wrong value. + output.end.gas_used.l2_gas += 1; + + builder.validate_with_output(output); +} + +#[test(should_fail_with="The gas used exceeds the gas limits")] +fn validate_gas_used_exceed_da_limit_fails() { + let mut builder = TailOutputValidatorBuilder::new_with_data(); + let mut output = builder.export_output(); + + let gas_used = output.end.gas_used.da_gas; + // Tweak the da gas limit to be less than the gas used. + output.constants.tx_context.gas_settings.gas_limits.da_gas = gas_used - 1; + // Constants must match. + builder.previous_kernel.tx_context.gas_settings.gas_limits.da_gas = gas_used - 1; + + builder.validate_with_output(output); +} + +#[test(should_fail_with="The gas used exceeds the gas limits")] +fn validate_gas_used_exceed_l2_limit_fails() { + let mut builder = TailOutputValidatorBuilder::new_with_data(); + let mut output = builder.export_output(); + + let gas_used = output.end.gas_used.l2_gas; + // Tweak the l2 gas limit to be less than the gas used. + output.constants.tx_context.gas_settings.gas_limits.l2_gas = gas_used - 1; + // Constants must match. + builder.previous_kernel.tx_context.gas_settings.gas_limits.l2_gas = gas_used - 1; + + builder.validate_with_output(output); +} diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr index bab21a8b0906..8dec06d95c77 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/meter_gas_used.nr @@ -11,7 +11,7 @@ use dep::types::{ #[test] fn meter_gas_used_non_revertible_empty_succeeds() { let builder = FixtureBuilder::new(); - let data = builder.to_public_accumulated_data_builder(); + let data = builder.to_public_accumulated_data(); let gas = meter_gas_used_non_revertible(data); assert_eq(gas, Gas::tx_overhead()); } @@ -32,7 +32,7 @@ fn meter_gas_used_non_revertible_everything_succeeds() { builder.append_public_call_requests(2); builder.end_setup(); - let data = builder.to_public_accumulated_data_builder(); + let data = builder.to_public_accumulated_data(); let gas = meter_gas_used_non_revertible(data); let total_num_side_effects = 4 + 3 + 1; @@ -51,7 +51,7 @@ fn meter_gas_used_non_revertible_everything_succeeds() { #[test] fn meter_gas_used_revertible_empty_succeeds() { let builder = FixtureBuilder::new(); - let data = builder.to_public_accumulated_data_builder(); + let data = builder.to_public_accumulated_data(); let teardown_gas = Gas::new(42, 17); let gas = meter_gas_used_revertible(data, teardown_gas); assert_eq(gas, teardown_gas); @@ -73,7 +73,7 @@ fn meter_gas_used_revertible_everything_succeeds() { builder.append_public_call_requests(2); builder.end_setup(); - let data = builder.to_public_accumulated_data_builder(); + let data = builder.to_public_accumulated_data(); let teardown_gas = Gas::new(42, 17); let gas = meter_gas_used_revertible(data, teardown_gas); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr similarity index 100% rename from noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder.nr rename to noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/mod.nr diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr index d87bdfb6b700..8998a01e387a 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/tests/tail_to_public_output_composer_builder/split_to_public.nr @@ -31,56 +31,47 @@ fn split_to_public_succeeds() { // note_hashes let expected = combined_data.note_hashes; + assert_array_eq(non_revertible.note_hashes, [expected[0], expected[1]]); assert_array_eq( - non_revertible.note_hashes.storage, - [expected[0], expected[1]] - ); - assert_array_eq( - revertible.note_hashes.storage, + revertible.note_hashes, [expected[2], expected[3], expected[4]] ); // nullifiers let expected = combined_data.nullifiers; - assert_array_eq(non_revertible.nullifiers.storage, [expected[0], expected[1]]); - assert_array_eq(revertible.nullifiers.storage, [expected[2]]); + assert_array_eq(non_revertible.nullifiers, [expected[0], expected[1]]); + assert_array_eq(revertible.nullifiers, [expected[2]]); // l2_to_l1_msgs let expected = combined_data.l2_to_l1_msgs; - assert_array_eq(non_revertible.l2_to_l1_msgs.storage, [expected[0]]); - assert_array_eq(revertible.l2_to_l1_msgs.storage, [expected[1]]); + assert_array_eq(non_revertible.l2_to_l1_msgs, [expected[0]]); + assert_array_eq(revertible.l2_to_l1_msgs, [expected[1]]); // note_encrypted_logs_hashes let expected = combined_data.note_encrypted_logs_hashes; assert_array_eq( - non_revertible.note_encrypted_logs_hashes.storage, + non_revertible.note_encrypted_logs_hashes, [expected[0], expected[1], expected[2]] ); - assert_array_eq(revertible.note_encrypted_logs_hashes.storage, [expected[3]]); + assert_array_eq(revertible.note_encrypted_logs_hashes, [expected[3]]); // encrypted_logs_hashes let expected = combined_data.encrypted_logs_hashes; assert_array_eq( - non_revertible.encrypted_logs_hashes.storage, + non_revertible.encrypted_logs_hashes, [expected[0], expected[1]] ); - assert_array_eq( - revertible.encrypted_logs_hashes.storage, - [expected[2], expected[3]] - ); + assert_array_eq(revertible.encrypted_logs_hashes, [expected[2], expected[3]]); // unencrypted_logs_hashes let expected = combined_data.unencrypted_logs_hashes; - assert_array_eq(non_revertible.unencrypted_logs_hashes.storage, [expected[0]]); - assert_array_eq(revertible.unencrypted_logs_hashes.storage, [expected[1]]); + assert_array_eq(non_revertible.unencrypted_logs_hashes, [expected[0]]); + assert_array_eq(revertible.unencrypted_logs_hashes, [expected[1]]); // public_call_stack let expected = combined_data.public_call_stack; - assert_array_eq(non_revertible.public_call_stack.storage, [expected[0]]); - assert_array_eq( - revertible.public_call_stack.storage, - [expected[1], expected[2]] - ); + assert_array_eq(non_revertible.public_call_stack, [expected[0]]); + assert_array_eq(revertible.public_call_stack, [expected[1], expected[2]]); } #[test(should_fail_with="min_revertible_side_effect_counter must not be 0")] diff --git a/yarn-project/foundation/src/crypto/random/index.ts b/yarn-project/foundation/src/crypto/random/index.ts index a64dc4f4a957..76ee5a9a6a9b 100644 --- a/yarn-project/foundation/src/crypto/random/index.ts +++ b/yarn-project/foundation/src/crypto/random/index.ts @@ -74,3 +74,12 @@ export const randomBigInt = (max: bigint) => { const randomBigInt = BigInt(`0x${randomBuffer.toString('hex')}`); // Convert buffer to a large integer. return randomBigInt % max; // Use modulo to ensure the result is less than max. }; + +/** + * Generate a random boolean value. + * @returns A random boolean value. + */ +export const randomBoolean = () => { + const randomByte = randomBytes(1)[0]; // Generate a single random byte. + return randomByte % 2 === 0; // Use modulo to determine if the byte is even or odd. +}; diff --git a/yarn-project/foundation/src/fields/fields.test.ts b/yarn-project/foundation/src/fields/fields.test.ts index 2f8686bb4c5b..f07db9fe8992 100644 --- a/yarn-project/foundation/src/fields/fields.test.ts +++ b/yarn-project/foundation/src/fields/fields.test.ts @@ -109,7 +109,7 @@ describe('Bn254 arithmetic', () => { expect(actual).toEqual(expected); }); - it('High Bonudary', () => { + it('High Boundary', () => { // -1 - (-1) = 0 const a = new Fr(Fr.MODULUS - 1n); const b = new Fr(Fr.MODULUS - 1n); @@ -184,6 +184,30 @@ describe('Bn254 arithmetic', () => { }); }); + describe('Square root', () => { + it.each([ + [new Fr(0), 0n], + [new Fr(4), 2n], + [new Fr(9), 3n], + [new Fr(16), 4n], + ])('Should return the correct square root for %p', (input, expected) => { + const actual = input.sqrt()!.toBigInt(); + + // The square root can be either the expected value or the modulus - expected value + const isValid = actual == expected || actual == Fr.MODULUS - expected; + + expect(isValid).toBeTruthy(); + }); + + it('Should return the correct square root for random value', () => { + const a = Fr.random(); + const squared = a.mul(a); + + const actual = squared.sqrt(); + expect(actual!.mul(actual!)).toEqual(squared); + }); + }); + describe('Comparison', () => { it.each([ [new Fr(5), new Fr(10), -1], diff --git a/yarn-project/foundation/src/fields/fields.ts b/yarn-project/foundation/src/fields/fields.ts index 436003adbfda..5fa3c9cac295 100644 --- a/yarn-project/foundation/src/fields/fields.ts +++ b/yarn-project/foundation/src/fields/fields.ts @@ -1,3 +1,5 @@ +import { BarretenbergSync } from '@aztec/bb.js'; + import { inspect } from 'util'; import { toBigIntBE, toBufferBE } from '../bigint-buffer/index.js'; @@ -280,6 +282,25 @@ export class Fr extends BaseField { return new Fr(this.toBigInt() / rhs.toBigInt()); } + /** + * Computes a square root of the field element. + * @returns A square root of the field element (null if it does not exist). + */ + sqrt(): Fr | null { + const wasm = BarretenbergSync.getSingleton().getWasm(); + wasm.writeMemory(0, this.toBuffer()); + wasm.call('bn254_fr_sqrt', 0, Fr.SIZE_IN_BYTES); + const isSqrtBuf = Buffer.from(wasm.getMemorySlice(Fr.SIZE_IN_BYTES, Fr.SIZE_IN_BYTES + 1)); + const isSqrt = isSqrtBuf[0] === 1; + if (!isSqrt) { + // Field element is not a quadratic residue mod p so it has no square root. + return null; + } + + const rootBuf = Buffer.from(wasm.getMemorySlice(Fr.SIZE_IN_BYTES + 1, Fr.SIZE_IN_BYTES * 2 + 1)); + return Fr.fromBuffer(rootBuf); + } + toJSON() { return { type: 'Fr', diff --git a/yarn-project/foundation/src/fields/point.test.ts b/yarn-project/foundation/src/fields/point.test.ts new file mode 100644 index 000000000000..6fa64160b414 --- /dev/null +++ b/yarn-project/foundation/src/fields/point.test.ts @@ -0,0 +1,35 @@ +import { Fr } from './fields.js'; +import { Point } from './point.js'; + +describe('Point', () => { + it('converts to and from x and sign of y coordinate', () => { + const p = new Point( + new Fr(0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1n), + new Fr(0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6n), + false, + ); + + const [x, sign] = p.toXAndSign(); + const p2 = Point.fromXAndSign(x, sign); + + expect(p.equals(p2)).toBeTruthy(); + }); + + it('creates a valid random point', () => { + expect(Point.random().isOnGrumpkin()).toBeTruthy(); + }); + + it('converts to and from buffer', () => { + const p = Point.random(); + const p2 = Point.fromBuffer(p.toBuffer()); + + expect(p.equals(p2)).toBeTruthy(); + }); + + it('converts to and from compressed buffer', () => { + const p = Point.random(); + const p2 = Point.fromCompressedBuffer(p.toCompressedBuffer()); + + expect(p.equals(p2)).toBeTruthy(); + }); +}); diff --git a/yarn-project/foundation/src/fields/point.ts b/yarn-project/foundation/src/fields/point.ts index 26c84d88ec06..3bcf4a00ede1 100644 --- a/yarn-project/foundation/src/fields/point.ts +++ b/yarn-project/foundation/src/fields/point.ts @@ -1,4 +1,4 @@ -import { poseidon2Hash } from '../crypto/index.js'; +import { poseidon2Hash, randomBoolean } from '../crypto/index.js'; import { BufferReader, FieldReader, serializeToBuffer } from '../serialize/index.js'; import { Fr } from './fields.js'; @@ -10,6 +10,7 @@ import { Fr } from './fields.js'; export class Point { static ZERO = new Point(Fr.ZERO, Fr.ZERO, false); static SIZE_IN_BYTES = Fr.SIZE_IN_BYTES * 2; + static COMPRESSED_SIZE_IN_BYTES = Fr.SIZE_IN_BYTES + 1; /** Used to differentiate this class from AztecAddress */ public readonly kind = 'point'; @@ -37,8 +38,17 @@ export class Point { * @returns A randomly generated Point instance. */ static random() { - // TODO make this return an actual point on curve. - return new Point(Fr.random(), Fr.random(), false); + while (true) { + try { + return Point.fromXAndSign(Fr.random(), randomBoolean()); + } catch (e: any) { + if (!(e instanceof NotOnCurveError)) { + throw e; + } + // The random point is not on the curve - we try again + continue; + } + } } /** @@ -53,6 +63,18 @@ export class Point { return new this(Fr.fromBuffer(reader), Fr.fromBuffer(reader), false); } + /** + * Create a Point instance from a compressed buffer. + * The input 'buffer' should have exactly 33 bytes representing the x coordinate and the sign of the y coordinate. + * + * @param buffer - The buffer containing the x coordinate and the sign of the y coordinate. + * @returns A Point instance. + */ + static fromCompressedBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return this.fromXAndSign(Fr.fromBuffer(reader), reader.readBoolean()); + } + /** * Create a Point instance from a hex-encoded string. * The input 'address' should be prefixed with '0x' or not, and have exactly 128 hex characters representing the x and y coordinates. @@ -78,6 +100,46 @@ export class Point { return new this(reader.readField(), reader.readField(), reader.readBoolean()); } + /** + * Uses the x coordinate and isPositive flag (+/-) to reconstruct the point. + * @dev The y coordinate can be derived from the x coordinate and the "sign" flag by solving the grumpkin curve + * equation for y. + * @param x - The x coordinate of the point + * @param sign - The "sign" of the y coordinate - note that this is not a sign as is known in integer arithmetic. + * Instead it is a boolean flag that determines whether the y coordinate is <= (Fr.MODULUS - 1) / 2 + * @returns The point as an array of 2 fields + */ + static fromXAndSign(x: Fr, sign: boolean) { + // Calculate y^2 = x^3 - 17 + const ySquared = x.square().mul(x).sub(new Fr(17)); + + // Calculate the square root of ySquared + const y = ySquared.sqrt(); + + // If y is null, the x-coordinate is not on the curve + if (y === null) { + throw new NotOnCurveError(); + } + + const yPositiveBigInt = y.toBigInt() > (Fr.MODULUS - 1n) / 2n ? Fr.MODULUS - y.toBigInt() : y.toBigInt(); + const yNegativeBigInt = Fr.MODULUS - yPositiveBigInt; + + // Choose the positive or negative root based on isPositive + const finalY = sign ? new Fr(yPositiveBigInt) : new Fr(yNegativeBigInt); + + // Create and return the new Point + return new this(x, finalY, false); + } + + /** + * Returns the x coordinate and the sign of the y coordinate. + * @dev The y sign can be determined by checking if the y coordinate is greater than half of the modulus. + * @returns The x coordinate and the sign of the y coordinate. + */ + toXAndSign(): [Fr, boolean] { + return [this.x, this.y.toBigInt() <= (Fr.MODULUS - 1n) / 2n]; + } + /** * Returns the contents of the point as BigInts. * @returns The point as BigInts @@ -111,6 +173,14 @@ export class Point { return buf; } + /** + * Converts the Point instance to a compressed Buffer representation of the coordinates. + * @returns A Buffer representation of the Point instance + */ + toCompressedBuffer() { + return serializeToBuffer(this.toXAndSign()); + } + /** * Convert the Point instance to a hexadecimal string representation. * The output string is prefixed with '0x' and consists of exactly 128 hex characters, @@ -194,3 +264,10 @@ export function isPoint(obj: object): obj is Point { const point = obj as Point; return point.kind === 'point' && point.x !== undefined && point.y !== undefined; } + +class NotOnCurveError extends Error { + constructor() { + super('The given x-coordinate is not on the Grumpkin curve'); + this.name = 'NotOnCurveError'; + } +} From 770fe026de8bb0b2117776e8e9c69494fe7f1084 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 10:25:19 +0000 Subject: [PATCH 89/94] fix chain-id arg --- .github/workflows/devnet-deploys.yml | 2 +- l1-contracts/REDEPLOY | 2 +- yarn-project/cli/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/devnet-deploys.yml b/.github/workflows/devnet-deploys.yml index e40bd8de44d6..fef1b0d382ae 100644 --- a/.github/workflows/devnet-deploys.yml +++ b/.github/workflows/devnet-deploys.yml @@ -122,7 +122,7 @@ jobs: docker run aztecprotocol/aztec:${{ env.DEPLOY_TAG }} deploy-l1-contracts \ --private-key ${{ secrets.SEQ_1_PUBLISHER_PRIVATE_KEY }} \ --rpc-url https://${{ env.DEPLOY_TAG }}-mainnet-fork.aztec.network:8545/${{ secrets.FORK_API_KEY }} \ - --chain-id ${{ env.L1_CHAIN_ID }} \ + --l1-chain-id ${{ env.L1_CHAIN_ID }} \ | tee ${{ env.FILE_PATH }} ./.github/scripts/extract_l1_addresses.sh ${{ env.FILE_PATH }} diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index 456b5196b3d3..bf96116ff778 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -1 \ No newline at end of file +2 diff --git a/yarn-project/cli/README.md b/yarn-project/cli/README.md index d4876845942c..0ed38b953054 100644 --- a/yarn-project/cli/README.md +++ b/yarn-project/cli/README.md @@ -69,7 +69,7 @@ aztec-cli deploy-l1-contracts [rpcUrl] [options] Options: -- `-a, --chain-id `: Chain ID for the Ethereum host. +- `-a, --l1-chain-id `: Chain ID for the Ethereum host. - `-p, --private-key `: The private key to use for deployment. - `-m, --mnemonic `: The mnemonic to use in deployment. Default: `test test test test test test test test test test test junk`. From 1c300acdce2327b4756e688da612d96fba8340d3 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 10:44:43 +0000 Subject: [PATCH 90/94] redeploy --- l1-contracts/REDEPLOY | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/REDEPLOY b/l1-contracts/REDEPLOY index bf96116ff778..595f09288f85 100644 --- a/l1-contracts/REDEPLOY +++ b/l1-contracts/REDEPLOY @@ -1,2 +1,2 @@ # Change value to force redeploy -2 +1 From d1b7029aea5f11e3eb66925d5da39a63ffb8973a Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 11:08:29 +0000 Subject: [PATCH 91/94] fix options.l1ChainId --- yarn-project/cli/src/cmds/infrastructure/index.ts | 4 ++-- yarn-project/cli/src/cmds/l1/index.ts | 13 ++++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/yarn-project/cli/src/cmds/infrastructure/index.ts b/yarn-project/cli/src/cmds/infrastructure/index.ts index fb3941420da8..4e035b128401 100644 --- a/yarn-project/cli/src/cmds/infrastructure/index.ts +++ b/yarn-project/cli/src/cmds/infrastructure/index.ts @@ -12,7 +12,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL .addOption(l1ChainIdOption) .action(async options => { const { bootstrap } = await import('./bootstrap.js'); - await bootstrap(options.rpcUrl, options.chainId, log); + await bootstrap(options.rpcUrl, options.l1ChainId, log); }); program @@ -41,7 +41,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL mnemonic: options.mnemonic, rpcUrl: options.rpcUrl, l1RpcUrl: options.l1RpcUrl, - chainId: options.chainId ?? '', + chainId: options.l1ChainId, blockNumber: options.blockNumber, log, debugLogger, diff --git a/yarn-project/cli/src/cmds/l1/index.ts b/yarn-project/cli/src/cmds/l1/index.ts index 1cc2b744eafb..c9a276cfd952 100644 --- a/yarn-project/cli/src/cmds/l1/index.ts +++ b/yarn-project/cli/src/cmds/l1/index.ts @@ -30,7 +30,14 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL .addOption(l1ChainIdOption) .action(async options => { const { deployL1Contracts } = await import('./deploy_l1_contracts.js'); - await deployL1Contracts(options.rpcUrl, options.chainId, options.privateKey, options.mnemonic, log, debugLogger); + await deployL1Contracts( + options.rpcUrl, + options.l1ChainId, + options.privateKey, + options.mnemonic, + log, + debugLogger, + ); }); program @@ -100,7 +107,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL recipient, options.rpcUrl, options.l1RpcUrl, - options.chainId, + options.l1ChainId, options.mnemonic, log, debugLogger, @@ -120,7 +127,7 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: DebugL .addOption(l1ChainIdOption) .action(async (who, options) => { const { getL1Balance } = await import('./get_l1_balance.js'); - await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.chainId, log, debugLogger); + await getL1Balance(who, options.rpcUrl, options.l1RpcUrl, options.l1ChainId, log, debugLogger); }); return program; From e165800e999dea885e6c18b758fa503a3815b89d Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 11:59:47 +0000 Subject: [PATCH 92/94] ensure number chainId --- yarn-project/aztec/src/cli/cli.ts | 7 +++---- yarn-project/ethereum/src/index.ts | 8 +++++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/yarn-project/aztec/src/cli/cli.ts b/yarn-project/aztec/src/cli/cli.ts index 87595ed3b42d..03b79596915c 100644 --- a/yarn-project/aztec/src/cli/cli.ts +++ b/yarn-project/aztec/src/cli/cli.ts @@ -41,7 +41,6 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge let services: ServerList = []; if (options.sandbox) { - // If no CLI arguments were provided, run aztec full node for sandbox usage. userLog(`${splash}\n${github}\n\n`); userLog(`Setting up Aztec Sandbox, please stand by...`); const { aztecNodeConfig, node, pxe, stop } = await createSandbox({ @@ -108,12 +107,12 @@ export function injectAztecCommands(program: Command, userLog: LogFn, debugLogge program.addHelpText( 'after', ` - + Additional commands: - test [options]: starts a dockerized TXE node via + test [options]: starts a dockerized TXE node via $ aztec start --txe - then runs + then runs $ aztec-nargo test --silence-warnings --use-legacy --oracle-resolver= [options] `, ); diff --git a/yarn-project/ethereum/src/index.ts b/yarn-project/ethereum/src/index.ts index d8d15d71ae6d..2734f978dfca 100644 --- a/yarn-project/ethereum/src/index.ts +++ b/yarn-project/ethereum/src/index.ts @@ -11,7 +11,13 @@ export * from './constants.js'; * @param rpcUrl - The rpc url of the chain or a chain identifier (e.g. 'testnet') * @param apiKey - An optional API key for the chain client. */ -export function createEthereumChain(rpcUrl: string, chainId?: number) { +export function createEthereumChain(rpcUrl: string, _chainId: number | string) { + let chainId: number; + if (typeof _chainId === 'string') { + chainId = +_chainId; + } else { + chainId = _chainId; + } if (chainId) { return { chainInfo: { From 9ec7eee9ba76e334af17f0974c53b51518b737fb Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 12:05:32 +0000 Subject: [PATCH 93/94] fix req chainId --- yarn-project/archiver/src/archiver/archiver.ts | 2 +- yarn-project/archiver/src/archiver/config.ts | 2 +- yarn-project/sequencer-client/src/publisher/config.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index d599e1c1e19d..51f4ad4f1675 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -109,7 +109,7 @@ export class Archiver implements ArchiveSource { telemetry: TelemetryClient, blockUntilSynced = true, ): Promise { - const chain = createEthereumChain(config.rpcUrl); + const chain = createEthereumChain(config.rpcUrl, config.l1ChainId); const publicClient = createPublicClient({ chain: chain.chainInfo, transport: http(chain.rpcUrl), diff --git a/yarn-project/archiver/src/archiver/config.ts b/yarn-project/archiver/src/archiver/config.ts index e9f306b03740..362d472f20f6 100644 --- a/yarn-project/archiver/src/archiver/config.ts +++ b/yarn-project/archiver/src/archiver/config.ts @@ -25,7 +25,7 @@ export interface ArchiverConfig { /** * The L1 chain's ID */ - l1ChainId?: number; + l1ChainId: number; /** * The polling interval in ms for retrieving new L2 blocks and encrypted logs. diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index b88c2df2285a..1292ae65d124 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -17,7 +17,7 @@ export interface TxSenderConfig { /** * The chain ID of the ethereum host. */ - l1ChainId?: number; + l1ChainId: number; /** * The number of confirmations required. From cd61415431343ec0207f04d0c88efe4c854b9e3c Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 16 Jul 2024 12:12:44 +0000 Subject: [PATCH 94/94] missing config val --- .../end-to-end/src/composed/integration_l1_publisher.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index edf4586c2f4d..548265fc8952 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -152,6 +152,7 @@ describe('L1Publisher integration', () => { l1Contracts: l1ContractAddresses, publisherPrivateKey: sequencerPK, l1BlockPublishRetryIntervalMS: 100, + l1ChainId: 31337, }); coinbase = config.coinbase || EthAddress.random();